Add 'sdk/java-v2/' from commit '55f103e336ca9fb8bf1720d2ef4ee8dd4e221118'
[arvados.git] / tools / arvbox / bin / arvbox
1 #!/bin/sh
2 # Copyright (C) The Arvados Authors. All rights reserved.
3 #
4 # SPDX-License-Identifier: AGPL-3.0
5
6 set -e
7
8 if ! test -d /sys/fs/cgroup ; then
9      echo "Arvbox requires cgroups to be mounted at /sys/fs/cgroup in order to use"
10      echo "Docker-in-Docker.  Older operating systems that put cgroups in other"
11      echo "places (such as /cgroup) are not supported."
12      exit 1
13 fi
14
15 if ! which docker >/dev/null 2>/dev/null ; then
16   echo "Arvbox requires Docker.  To install, run the following command as root:"
17   echo "curl -sSL https://get.docker.com/ | sh"
18   exit 1
19 fi
20
21 if test -z "$ARVBOX_DOCKER" ; then
22     if which greadlink >/dev/null 2>/dev/null ; then
23         ARVBOX_DOCKER=$(greadlink -f $(dirname $0)/../lib/arvbox/docker)
24     else
25         ARVBOX_DOCKER=$(readlink -f $(dirname $0)/../lib/arvbox/docker)
26     fi
27 fi
28
29 if test -z "$ARVBOX_CONTAINER" ; then
30     ARVBOX_CONTAINER=arvbox
31 fi
32
33 if test -z "$ARVBOX_BASE" ; then
34     ARVBOX_BASE="$HOME/.arvbox"
35 fi
36
37 if test -z "$ARVBOX_DATA" ; then
38     ARVBOX_DATA="$ARVBOX_BASE/$ARVBOX_CONTAINER"
39 fi
40
41 if test -z "$ARVADOS_ROOT" ; then
42     ARVADOS_ROOT="$ARVBOX_DATA/arvados"
43 fi
44
45 if test -z "$SSO_ROOT" ; then
46     SSO_ROOT="$ARVBOX_DATA/sso-devise-omniauth-provider"
47 fi
48
49 if test -z "$COMPOSER_ROOT" ; then
50     COMPOSER_ROOT="$ARVBOX_DATA/composer"
51 fi
52
53 if test -z "$WORKBENCH2_ROOT" ; then
54     WORKBENCH2_ROOT="$ARVBOX_DATA/workbench2"
55 fi
56
57 PG_DATA="$ARVBOX_DATA/postgres"
58 VAR_DATA="$ARVBOX_DATA/var"
59 PASSENGER="$ARVBOX_DATA/passenger"
60 GEMS="$ARVBOX_DATA/gems"
61 PIPCACHE="$ARVBOX_DATA/pip"
62 NPMCACHE="$ARVBOX_DATA/npm"
63 GOSTUFF="$ARVBOX_DATA/gopath"
64 RLIBS="$ARVBOX_DATA/Rlibs"
65
66 getip() {
67     docker inspect $ARVBOX_CONTAINER | grep \"IPAddress\" | head -n1 | tr -d ' ":,\n' | cut -c10-
68 }
69
70 gethost() {
71     set +e
72     OVERRIDE=$(docker exec -i $ARVBOX_CONTAINER cat /var/run/localip_override 2>/dev/null)
73     CODE=$?
74     set -e
75     if test "$CODE" = 0 ; then
76        echo $OVERRIDE
77     else
78         getip
79     fi
80 }
81
82 getclusterid() {
83     docker exec $ARVBOX_CONTAINER cat /var/lib/arvados/api_uuid_prefix
84 }
85
86 updateconf() {
87     if test -f ~/.config/arvados/$ARVBOX_CONTAINER.conf ; then
88         sed "s/ARVADOS_API_HOST=.*/ARVADOS_API_HOST=$(gethost):8000/" <$HOME/.config/arvados/$ARVBOX_CONTAINER.conf >$HOME/.config/arvados/$ARVBOX_CONTAINER.conf.tmp
89         mv ~/.config/arvados/$ARVBOX_CONTAINER.conf.tmp ~/.config/arvados/$ARVBOX_CONTAINER.conf
90     else
91         mkdir -p $HOME/.config/arvados
92         cat >$HOME/.config/arvados/$ARVBOX_CONTAINER.conf <<EOF
93 ARVADOS_API_HOST=$(gethost):8000
94 ARVADOS_API_TOKEN=
95 ARVADOS_API_HOST_INSECURE=true
96 EOF
97     fi
98 }
99
100 wait_for_arvbox() {
101     FF=/tmp/arvbox-fifo-$$
102     mkfifo $FF
103     docker logs -f $ARVBOX_CONTAINER > $FF &
104     LOGPID=$!
105     while read line ; do
106         if echo $line | grep "ok: down: ready:" >/dev/null ; then
107             kill $LOGPID
108         else
109             echo $line
110         fi
111     done < $FF
112     rm $FF
113     echo
114     if test -n "$localip" ; then
115         echo "export ARVADOS_API_HOST=$localip:8000"
116     else
117         echo "export ARVADOS_API_HOST=$(gethost):8000"
118     fi
119 }
120
121 run() {
122     CONFIG=$1
123     TAG=$2
124
125     shift
126
127     need_setup=1
128
129     if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
130         if test "$CONFIG" = test ; then
131             need_setup=0
132         else
133             echo "Container $ARVBOX_CONTAINER is already running"
134             exit 0
135         fi
136     fi
137
138     if test $need_setup = 1 ; then
139         if docker ps -a | grep -E "$ARVBOX_CONTAINER$" -q ; then
140             echo "Container $ARVBOX_CONTAINER already exists but is not running; use restart or reboot"
141             exit 1
142         fi
143     fi
144
145     if test -n "$TAG"
146     then
147         if test $(echo $TAG | cut -c1-1) != '-' ; then
148             TAG=":$TAG"
149             shift
150         else
151             unset TAG
152         fi
153     fi
154
155     if echo "$CONFIG" | grep '^public' ; then
156         if test -n "$ARVBOX_PUBLISH_IP" ; then
157             localip=$ARVBOX_PUBLISH_IP
158         else
159             defaultdev=$(/sbin/ip route|awk '/default/ { print $5 }')
160             localip=$(ip addr show $defaultdev | grep 'inet ' | sed 's/ *inet \(.*\)\/.*/\1/')
161         fi
162         iptemp=$(tempfile)
163         echo $localip > $iptemp
164         chmod og+r $iptemp
165         PUBLIC="--volume=$iptemp:/var/run/localip_override
166               --publish=443:443
167               --publish=3001:3001
168               --publish=8000:8000
169               --publish=8900:8900
170               --publish=9001:9001
171               --publish=9002:9002
172               --publish=25100:25100
173               --publish=25107:25107
174               --publish=25108:25108
175               --publish=8001:8001
176               --publish=8002:8002"
177     else
178         PUBLIC=""
179     fi
180
181     if echo "$CONFIG" | grep 'demo$' ; then
182         if test -d "$ARVBOX_DATA" ; then
183             echo "It looks like you already have a development container named $ARVBOX_CONTAINER."
184             echo "Set ARVBOX_CONTAINER to set a different name for your demo container"
185             exit 1
186         fi
187
188         if ! (docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q) ; then
189             docker create -v /var/lib/postgresql -v /var/lib/arvados --name $ARVBOX_CONTAINER-data arvados/arvbox-demo /bin/true
190         fi
191
192         docker run \
193                --detach \
194                --name=$ARVBOX_CONTAINER \
195                --privileged \
196                --volumes-from $ARVBOX_CONTAINER-data \
197                $PUBLIC \
198                arvados/arvbox-demo$TAG
199         updateconf
200         wait_for_arvbox
201     else
202         mkdir -p "$PG_DATA" "$VAR_DATA" "$PASSENGER" "$GEMS" "$PIPCACHE" "$NPMCACHE" "$GOSTUFF" "$RLIBS"
203
204
205         if ! test -d "$ARVADOS_ROOT" ; then
206             git clone https://github.com/curoverse/arvados.git "$ARVADOS_ROOT"
207         fi
208         if ! test -d "$SSO_ROOT" ; then
209             git clone https://github.com/curoverse/sso-devise-omniauth-provider.git "$SSO_ROOT"
210         fi
211         if ! test -d "$COMPOSER_ROOT" ; then
212             git clone https://github.com/curoverse/composer.git "$COMPOSER_ROOT"
213         fi
214         if ! test -d "$WORKBENCH2_ROOT" ; then
215             git clone https://github.com/curoverse/arvados-workbench2.git "$WORKBENCH2_ROOT"
216         fi
217
218         if test "$CONFIG" = test ; then
219
220             mkdir -p $VAR_DATA/test
221
222             if test "$need_setup" = 1 ; then
223                 docker run \
224                        --detach \
225                        --name=$ARVBOX_CONTAINER \
226                        --privileged \
227                        "--volume=$ARVADOS_ROOT:/usr/src/arvados:rw" \
228                        "--volume=$SSO_ROOT:/usr/src/sso:rw" \
229                        "--volume=$COMPOSER_ROOT:/usr/src/composer:rw" \
230                        "--volume=$WORKBENCH2_ROOT:/usr/src/workbench2:rw" \
231                        "--volume=$PG_DATA:/var/lib/postgresql:rw" \
232                        "--volume=$VAR_DATA:/var/lib/arvados:rw" \
233                        "--volume=$PASSENGER:/var/lib/passenger:rw" \
234                        "--volume=$GEMS:/var/lib/gems:rw" \
235                        "--volume=$PIPCACHE:/var/lib/pip:rw" \
236                        "--volume=$NPMCACHE:/var/lib/npm:rw" \
237                        "--volume=$GOSTUFF:/var/lib/gopath:rw" \
238                        "--volume=$RLIBS:/var/lib/Rlibs:rw" \
239                        "--env=SVDIR=/etc/test-service" \
240                        arvados/arvbox-dev$TAG
241
242                 docker exec -ti \
243                        $ARVBOX_CONTAINER \
244                        /usr/local/lib/arvbox/runsu.sh \
245                        /usr/local/lib/arvbox/waitforpostgres.sh
246
247                 docker exec -ti \
248                        $ARVBOX_CONTAINER \
249                        /usr/local/lib/arvbox/runsu.sh \
250                        /var/lib/arvbox/service/sso/run-service --only-setup
251
252                 docker exec -ti \
253                        $ARVBOX_CONTAINER \
254                        /usr/local/lib/arvbox/runsu.sh \
255                        /var/lib/arvbox/service/api/run-service --only-setup
256             fi
257
258             docker exec -ti \
259                    $ARVBOX_CONTAINER \
260                    /usr/local/lib/arvbox/runsu.sh \
261                    /usr/src/arvados/build/run-tests.sh \
262                    --temp /var/lib/arvados/test \
263                    WORKSPACE=/usr/src/arvados \
264                    GEM_HOME=/var/lib/gems \
265                    "$@"
266         elif echo "$CONFIG" | grep 'dev$' ; then
267             docker run \
268                    --detach \
269                    --name=$ARVBOX_CONTAINER \
270                    --privileged \
271                    "--volume=$ARVADOS_ROOT:/usr/src/arvados:rw" \
272                    "--volume=$SSO_ROOT:/usr/src/sso:rw" \
273                    "--volume=$COMPOSER_ROOT:/usr/src/composer:rw" \
274                    "--volume=$WORKBENCH2_ROOT:/usr/src/workbench2:rw" \
275                    "--volume=$PG_DATA:/var/lib/postgresql:rw" \
276                    "--volume=$VAR_DATA:/var/lib/arvados:rw" \
277                    "--volume=$PASSENGER:/var/lib/passenger:rw" \
278                    "--volume=$GEMS:/var/lib/gems:rw" \
279                    "--volume=$PIPCACHE:/var/lib/pip:rw" \
280                    "--volume=$NPMCACHE:/var/lib/npm:rw" \
281                    "--volume=$GOSTUFF:/var/lib/gopath:rw" \
282                    "--volume=$RLIBS:/var/lib/Rlibs:rw" \
283                    $PUBLIC \
284                    arvados/arvbox-dev$TAG
285             updateconf
286             wait_for_arvbox
287             echo "The Arvados source code is checked out at: $ARVADOS_ROOT"
288             echo "The Arvados testing root certificate is $VAR_DATA/root-cert.pem"
289         else
290             echo "Unknown configuration '$CONFIG'"
291         fi
292     fi
293 }
294
295 stop() {
296     if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
297         docker stop $ARVBOX_CONTAINER
298     fi
299
300     VOLUMES=--volumes=true
301     if docker ps -a --filter "status=created" | grep -E "$ARVBOX_CONTAINER$" -q ; then
302         docker rm $VOLUMES $ARVBOX_CONTAINER
303     fi
304     if docker ps -a --filter "status=exited" | grep -E "$ARVBOX_CONTAINER$" -q ; then
305         docker rm $VOLUMES $ARVBOX_CONTAINER
306     fi
307 }
308
309 build() {
310     if ! test -f "$ARVBOX_DOCKER/Dockerfile.base" ;  then
311         echo "Could not find Dockerfile (expected it at $ARVBOX_DOCKER/Dockerfile.base)"
312         exit 1
313     fi
314     if docker --version |grep " 1\.[0-9]\." ; then
315         # Docker version prior 1.10 require -f flag
316         # -f flag removed in Docker 1.12
317         FORCE=-f
318     fi
319     GITHEAD=$(cd $ARVBOX_DOCKER && git log --format=%H -n1 HEAD)
320     docker build --build-arg=arvados_version=$GITHEAD $NO_CACHE -t arvados/arvbox-base:$GITHEAD -f "$ARVBOX_DOCKER/Dockerfile.base" "$ARVBOX_DOCKER"
321     docker tag $FORCE arvados/arvbox-base:$GITHEAD arvados/arvbox-base:latest
322     if test "$1" = localdemo -o "$1" = publicdemo ; then
323         docker build $NO_CACHE -t arvados/arvbox-demo:$GITHEAD -f "$ARVBOX_DOCKER/Dockerfile.demo" "$ARVBOX_DOCKER"
324         docker tag $FORCE arvados/arvbox-demo:$GITHEAD arvados/arvbox-demo:latest
325     else
326         docker build $NO_CACHE -t arvados/arvbox-dev:$GITHEAD -f "$ARVBOX_DOCKER/Dockerfile.dev" "$ARVBOX_DOCKER"
327         docker tag $FORCE arvados/arvbox-dev:$GITHEAD arvados/arvbox-dev:latest
328     fi
329 }
330
331 check() {
332     case "$1" in
333         localdemo|publicdemo|dev|publicdev|test)
334             true
335             ;;
336         *)
337             echo "Argument to $subcmd must be one of localdemo, publicdemo, dev, publicdev, test"
338             exit 1
339         ;;
340     esac
341 }
342
343 subcmd="$1"
344 if test -n "$subcmd" ; then
345     shift
346 fi
347 case "$subcmd" in
348     build)
349         check $@
350         build $@
351         ;;
352
353     rebuild)
354         check $@
355         NO_CACHE=--no-cache build $@
356         ;;
357
358     start|run)
359         check $@
360         run $@
361         ;;
362
363     sh*)
364         exec docker exec -ti \
365                -e LINES=$(tput lines) \
366                -e COLUMNS=$(tput cols) \
367                -e TERM=$TERM \
368                -e GEM_HOME=/var/lib/gems \
369                $ARVBOX_CONTAINER /bin/bash
370         ;;
371
372     pipe)
373         exec docker exec -i $ARVBOX_CONTAINER /usr/bin/env GEM_HOME=/var/lib/gems /bin/bash -
374         ;;
375
376     stop)
377         stop
378         ;;
379
380     restart)
381         check $@
382         stop
383         run $@
384         ;;
385
386     reboot)
387         check $@
388         stop
389         build $@
390         run $@
391         ;;
392
393     ip)
394         getip
395         ;;
396
397     host)
398         gethost
399         ;;
400
401     open)
402         exec xdg-open http://$(gethost)
403         ;;
404
405     status)
406         echo "Container: $ARVBOX_CONTAINER"
407         if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
408             echo "Cluster id: $(getclusterid)"
409             echo "Status: running"
410             echo "Container IP: $(getip)"
411             echo "Published host: $(gethost)"
412         else
413             echo "Status: not running"
414         fi
415         if test -d "$ARVBOX_DATA" ; then
416             echo "Data: $ARVBOX_DATA"
417         elif docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q ; then
418             echo "Data: $ARVBOX_CONTAINER-data"
419         else
420             echo "Data: none"
421         fi
422         ;;
423
424     reset|destroy)
425         stop
426         if test -d "$ARVBOX_DATA" ; then
427             if test "$subcmd" = destroy ; then
428                 if test "$1" != -f ; then
429                     echo "WARNING!  This will delete your entire arvbox ($ARVBOX_DATA)."
430                     echo "Use destroy -f if you really mean it."
431                     exit 1
432                 fi
433                 set -x
434                 rm -rf "$ARVBOX_DATA"
435             else
436                 if test "$1" != -f ; then
437                     echo "WARNING!  This will delete your arvbox data ($ARVBOX_DATA)."
438                     echo "Code and downloaded packages will be preserved."
439                     echo "Use reset -f if you really mean it."
440                     exit 1
441                 fi
442                 set -x
443                 rm -rf "$ARVBOX_DATA/postgres"
444                 rm -rf "$ARVBOX_DATA/var"
445             fi
446         else
447             if test "$1" != -f ; then
448                 echo "WARNING!  This will delete your data container $ARVBOX_CONTAINER-data.  Use -f if you really mean it."
449                 exit 1
450             fi
451             set -x
452             docker rm "$ARVBOX_CONTAINER-data"
453         fi
454         ;;
455
456     log)
457         if test -n "$1" ; then
458             exec docker exec -ti -e LINES=$(tput lines) -e COLUMNS=$(tput cols) -e TERM=$TERM $ARVBOX_CONTAINER less --follow-name -R +GF "/etc/service/$1/log/main/current"
459         else
460             exec docker exec -ti $ARVBOX_CONTAINER tail $(docker exec -ti $ARVBOX_CONTAINER find -L /etc -path '/etc/service/*/log/main/current' -printf " %p")
461         fi
462         ;;
463
464     cat)
465         if test -n "$1" ; then
466             exec docker exec $ARVBOX_CONTAINER cat "$@"
467         else
468             echo "Usage: $0 $subcmd <files>"
469         fi
470         ;;
471
472     ls)
473         exec docker exec -ti $ARVBOX_CONTAINER /usr/bin/env TERM=$TERM ls "$@"
474         ;;
475
476     sv)
477         if test -n "$1" -a -n "$2" ; then
478             exec docker exec $ARVBOX_CONTAINER sv "$@"
479         else
480             echo "Usage: $0 $subcmd <start|stop|restart> <service>"
481             echo "Available services:"
482             exec docker execa $ARVBOX_CONTAINER ls /etc/service
483         fi
484         ;;
485
486     clone)
487         if test -n "$2" ; then
488             cp -r "$ARVBOX_BASE/$1" "$ARVBOX_BASE/$2"
489             echo "Created new arvbox $2"
490             echo "export ARVBOX_CONTAINER=$2"
491         else
492             echo "clone <from> <to>   clone an arvbox"
493             echo "available arvboxes: $(ls $ARVBOX_BASE)"
494         fi
495         ;;
496
497     *)
498         echo "Arvados-in-a-box                      http://arvados.org"
499         echo
500         echo "build   <config>      build arvbox Docker image"
501         echo "rebuild <config>      build arvbox Docker image, no layer cache"
502         echo "start|run <config> [tag]  start $ARVBOX_CONTAINER container"
503         echo "open       open arvbox workbench in a web browser"
504         echo "shell      enter arvbox shell"
505         echo "ip         print arvbox docker container ip address"
506         echo "host       print arvbox published host"
507         echo "status     print some information about current arvbox"
508         echo "stop       stop arvbox container"
509         echo "restart <config>  stop, then run again"
510         echo "reboot  <config>  stop, build arvbox Docker image, run"
511         echo "reset      delete arvbox arvados data (be careful!)"
512         echo "destroy    delete all arvbox code and data (be careful!)"
513         echo "log <service> tail log of specified service"
514         echo "ls <options>  list directories inside arvbox"
515         echo "cat <files>   get contents of files inside arvbox"
516         echo "pipe       run a bash script piped in from stdin"
517         echo "sv <start|stop|restart> <service> change state of service inside arvbox"
518         echo "clone <from> <to>   clone an arvbox"
519         ;;
520 esac