Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download
Views: 39489
1
#!/usr/bin/env python
2
3
import argparse, os, sys, time
4
5
SRC = os.path.split(os.path.realpath(__file__))[0]
6
7
# Only use sudo if not running as root already (this avoids having to install sudo)
8
import getpass
9
if getpass.getuser() != 'root':
10
SUDO = "sudo "
11
else:
12
SUDO = ""
13
14
def nice():
15
try:
16
import psutil # not available by default (e.g., when building with docker)
17
os.nice(10)
18
psutil.Process(os.getpid()).ionice(ioclass=psutil.IOPRIO_CLASS_IDLE)
19
except:
20
print "WARNING: psutil not available so not re-nicing build of webapp"
21
22
def cmd(s):
23
t0 = time.time()
24
os.chdir(SRC)
25
s = "umask 022; " + s
26
print s
27
if os.system(s):
28
sys.exit(1)
29
print "TOTAL TIME: %.1f seconds"%(time.time() - t0)
30
31
def thread_map(callable, inputs, nb_threads=None):
32
if len(inputs) == 0:
33
return []
34
from multiprocessing.pool import ThreadPool
35
if not nb_threads:
36
nb_threads = min(50, len(inputs))
37
tp = ThreadPool(nb_threads)
38
return tp.map(callable, inputs)
39
40
def pull():
41
cmd("git pull")
42
43
def install_pyutil():
44
cmd(SUDO+"pip2 install --upgrade ./smc_pyutil")
45
46
def install_sagews():
47
if os.system('which sage') == 0:
48
cmd("sage -pip install --upgrade ./smc_sagews")
49
cmd(SUDO+"pip2 install --upgrade ./smc_sagews") # as a fallback
50
51
def install_project():
52
# unsafe-perm below is needed so can build C code as root
53
def f(m):
54
cmd(SUDO+"npm --loglevel=warn --unsafe-perm=true install --upgrade %s -g"%m)
55
thread_map(f, './smc-util ./smc-util-node ./smc-project ./smc-webapp coffee-script forever'.split())
56
57
# UGLY; hard codes the path -- TODO: fix at some point.
58
cmd("cd /usr/lib/node_modules/smc-project/jupyter && %s npm --loglevel=warn install --unsafe-perm=true --upgrade"%SUDO)
59
60
# Pre-compile everything to Javascript, so that loading is much faster and more efficient.
61
# This can easily save more than 2 seconds, given how big things have got.
62
cmd("cd /usr/lib/node_modules && coffee -c smc-util smc-util-node smc-webapp smc-project smc-project/jupyter smc-webapp/jupyter")
63
64
def install_hub():
65
for path in ['.', 'smc-util', 'smc-util-node', 'smc-hub']:
66
cmd("cd %s; npm --loglevel=warn install"%path)
67
68
def install_webapp(*args):
69
nice()
70
action = args[0].action if args else 'build'
71
nothing = True
72
73
if 'build' in action:
74
cmd("cd examples && make")
75
for path in ['.', 'smc-util', 'smc-util-node', 'smc-webapp', 'smc-webapp/jupyter']:
76
cmd("cd %s; npm --loglevel=warn install"%path)
77
# react static step must come *before* webpack step
78
cmd("update_react_static")
79
# update primus - so client has it.
80
install_primus()
81
# update term.js
82
cmd("cd webapp-lib/term; ./compile")
83
wtype = 'debug' if args[0].debug else 'production'
84
if args[0].debug:
85
wtype = 'debug'
86
est = 1
87
else:
88
wtype = 'production'
89
est = 5
90
print("Building {wtype} webpack -- this should take up to {est} minutes".format(wtype=wtype, est=est))
91
cmd("npm --loglevel=warn run webpack-{wtype}".format(wtype=wtype))
92
nothing = False
93
94
if 'pull' == action:
95
cmd("webapp-control.sh pull")
96
nothing = False
97
98
if 'push' in action:
99
cmd("webapp-control.sh push")
100
nothing = False
101
102
if 'clean' == action:
103
cmd("webapp-control.sh clean")
104
nothing = False
105
106
# some fallback check, just in case ...
107
if nothing:
108
raise ValueError("action %s unknown" % action)
109
110
def install_primus():
111
# The rm works around a bug in npm...
112
cmd("cd smc-hub && rm -rf node_modules/primus node_modules/engine.io && npm --loglevel=warn install primus engine.io && cd .. && webapp-lib/primus/update_primus")
113
114
def install_all(compute=False, web=False):
115
if compute or web:
116
install_hub() # also contains compute server right now (will refactor later)
117
if compute:
118
install_pyutil()
119
install_sagews()
120
install_project()
121
if web:
122
install_webapp()
123
124
def main():
125
parser = argparse.ArgumentParser(description="Install components of CoCalc into the system")
126
subparsers = parser.add_subparsers(help='sub-command help')
127
128
parser_pull = subparsers.add_parser('pull', help='pull latest version of code from github')
129
parser_pull.set_defaults(func = lambda *args: pull())
130
131
parser_hub = subparsers.add_parser('hub', help='install/update any node.js dependencies for smc-[util/util*/hub]')
132
parser_hub.set_defaults(func = lambda *args: install_hub())
133
134
parser_webapp = subparsers.add_parser('webapp', help='install/update any node.js dependencies for smc-[util*/webapp] and use webpack to build production js (takes several minutes!)')
135
parser_webapp.add_argument('action', help='either "build" the webapp or "pull/push" compiled files from a repository -- see scripts/webapp-control.sh how this works', choices=['build', 'pull', 'push', 'build-push', 'clean'])
136
parser_webapp.add_argument("--debug", action="store_true", help="if set, build debug version of code (rather than production)")
137
parser_webapp.set_defaults(func = install_webapp)
138
139
parser_primus = subparsers.add_parser('primus', help='update client-side primus websocket code')
140
parser_primus.set_defaults(func = lambda *args: install_primus())
141
142
parser_pyutil = subparsers.add_parser('pyutil', help='install smc_pyutil package system-wide (requires sudo)')
143
parser_pyutil.set_defaults(func = lambda *args: install_pyutil())
144
145
parser_sagews = subparsers.add_parser('sagews', help='install sagews server into sage install')
146
parser_sagews.add_argument("--sage", help="/path/to/sage (default: 'sage')", default='sage', type=str)
147
parser_sagews.set_defaults(func = lambda *args: install_sagews())
148
149
parser_project = subparsers.add_parser('project', help='install project server code system-wide')
150
parser_project.set_defaults(func = lambda *args: install_project())
151
152
parser_all = subparsers.add_parser('all', help='install all code that makes sense for the selected classes of servers; use "./install.py all --compute" for compute node and "./install.py all --web" for a web node')
153
parser_all.add_argument("--compute", default=False, action="store_const", const=True)
154
parser_all.add_argument("--web", default=False, action="store_const", const=True)
155
parser_all.set_defaults(func = lambda args: install_all(compute=args.compute, web=args.web))
156
157
args = parser.parse_args()
158
args.func(args)
159
160
if __name__ == "__main__":
161
main()
162
163