CWL spec -> CWL standards
[arvados.git] / tools / arvbox / bin / arvbox
1 #!/bin/bash
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     set +e
23     if which greadlink >/dev/null 2>/dev/null ; then
24         ARVBOX_DOCKER=$(greadlink -f $(dirname $0)/../lib/arvbox/docker)
25     else
26         ARVBOX_DOCKER=$(readlink -f $(dirname $0)/../lib/arvbox/docker)
27     fi
28     set -e
29 fi
30
31 if test -z "$ARVBOX_CONTAINER" ; then
32     ARVBOX_CONTAINER=arvbox
33 fi
34
35 if test -z "$ARVBOX_BASE" ; then
36     ARVBOX_BASE="$HOME/.arvbox"
37 fi
38
39 if test -z "$ARVBOX_DATA" ; then
40     ARVBOX_DATA="$ARVBOX_BASE/$ARVBOX_CONTAINER"
41 fi
42
43 if test -z "$ARVADOS_ROOT" ; then
44     ARVADOS_ROOT="$ARVBOX_DATA/arvados"
45 fi
46
47 if test -z "$SSO_ROOT" ; then
48     SSO_ROOT="$ARVBOX_DATA/sso-devise-omniauth-provider"
49 fi
50
51 if test -z "$COMPOSER_ROOT" ; then
52     COMPOSER_ROOT="$ARVBOX_DATA/composer"
53 fi
54
55 if test -z "$WORKBENCH2_ROOT" ; then
56     WORKBENCH2_ROOT="$ARVBOX_DATA/workbench2"
57 fi
58
59 PG_DATA="$ARVBOX_DATA/postgres"
60 VAR_DATA="$ARVBOX_DATA/var"
61 PASSENGER="$ARVBOX_DATA/passenger"
62 GEMS="$ARVBOX_DATA/gems"
63 PIPCACHE="$ARVBOX_DATA/pip"
64 NPMCACHE="$ARVBOX_DATA/npm"
65 GOSTUFF="$ARVBOX_DATA/gopath"
66 RLIBS="$ARVBOX_DATA/Rlibs"
67
68 getip() {
69     docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $ARVBOX_CONTAINER
70 }
71
72 gethost() {
73     set +e
74     OVERRIDE=$(docker exec -i $ARVBOX_CONTAINER cat /var/run/localip_override 2>/dev/null)
75     CODE=$?
76     set -e
77     if test "$CODE" = 0 ; then
78        echo $OVERRIDE
79     else
80         getip
81     fi
82 }
83
84 getclusterid() {
85     docker exec $ARVBOX_CONTAINER cat /var/lib/arvados/api_uuid_prefix
86 }
87
88 updateconf() {
89     if test -f ~/.config/arvados/$ARVBOX_CONTAINER.conf ; then
90         sed "s/ARVADOS_API_HOST=.*/ARVADOS_API_HOST=$(gethost):8000/" <$HOME/.config/arvados/$ARVBOX_CONTAINER.conf >$HOME/.config/arvados/$ARVBOX_CONTAINER.conf.tmp
91         mv ~/.config/arvados/$ARVBOX_CONTAINER.conf.tmp ~/.config/arvados/$ARVBOX_CONTAINER.conf
92     else
93         mkdir -p $HOME/.config/arvados
94         cat >$HOME/.config/arvados/$ARVBOX_CONTAINER.conf <<EOF
95 ARVADOS_API_HOST=$(gethost):8000
96 ARVADOS_API_TOKEN=
97 ARVADOS_API_HOST_INSECURE=true
98 EOF
99     fi
100 }
101
102 wait_for_arvbox() {
103     FF=/tmp/arvbox-fifo-$$
104     mkfifo $FF
105     docker logs -f $ARVBOX_CONTAINER > $FF &
106     LOGPID=$!
107     while read line ; do
108         if [[ $line =~ "ok: down: ready:" ]] ; then
109             kill $LOGPID
110             set +e
111             wait $LOGPID 2>/dev/null
112             set -e
113         else
114             echo $line
115         fi
116     done < $FF
117     rm $FF
118     echo
119     if test -n "$localip" ; then
120         echo "export ARVADOS_API_HOST=$localip:8000"
121     else
122         echo "export ARVADOS_API_HOST=$(gethost):8000"
123     fi
124 }
125
126 docker_run_dev() {
127     docker run \
128            "--volume=$ARVADOS_ROOT:/usr/src/arvados:rw" \
129            "--volume=$SSO_ROOT:/usr/src/sso:rw" \
130            "--volume=$COMPOSER_ROOT:/usr/src/composer:rw" \
131            "--volume=$WORKBENCH2_ROOT:/usr/src/workbench2:rw" \
132            "--volume=$PG_DATA:/var/lib/postgresql:rw" \
133            "--volume=$VAR_DATA:/var/lib/arvados:rw" \
134            "--volume=$PASSENGER:/var/lib/passenger:rw" \
135            "--volume=$GEMS:/var/lib/gems:rw" \
136            "--volume=$PIPCACHE:/var/lib/pip:rw" \
137            "--volume=$NPMCACHE:/var/lib/npm:rw" \
138            "--volume=$GOSTUFF:/var/lib/gopath:rw" \
139            "--volume=$RLIBS:/var/lib/Rlibs:rw" \
140            --label "org.arvados.arvbox_config=$CONFIG" \
141            "$@"
142 }
143
144 running_config() {
145     docker inspect $ARVBOX_CONTAINER -f '{{index .Config.Labels "org.arvados.arvbox_config"}}'
146 }
147
148 run() {
149     CONFIG=$1
150     TAG=$2
151
152     shift
153
154     need_setup=1
155
156     if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
157         if [[ $(running_config) != "$CONFIG" ]] ; then
158             echo "Container $ARVBOX_CONTAINER is '$(running_config)' config but requested '$CONFIG'; use restart or reboot"
159             return 1
160         fi
161         if test "$CONFIG" = test -o "$CONFIG" = devenv ; then
162             need_setup=0
163         else
164             echo "Container $ARVBOX_CONTAINER is already running"
165             return 0
166         fi
167     fi
168
169     if test $need_setup = 1 ; then
170         if docker ps -a | grep -E "$ARVBOX_CONTAINER$" -q ; then
171             echo "Container $ARVBOX_CONTAINER already exists but is not running; use restart or reboot"
172             return 1
173         fi
174     fi
175
176     if test -n "$TAG"
177     then
178         if test $(echo $TAG | cut -c1-1) != '-' ; then
179             TAG=":$TAG"
180             shift
181         else
182             if [[ $TAG = '-' ]] ; then
183                 shift
184             fi
185             unset TAG
186         fi
187     fi
188
189     if [[ "$CONFIG" =~ ^public ]] ; then
190         if test -n "$ARVBOX_PUBLISH_IP" ; then
191             localip=$ARVBOX_PUBLISH_IP
192         else
193             defaultdev=$(/sbin/ip route|awk '/default/ { print $5 }')
194             localip=$(ip addr show $defaultdev | grep 'inet ' | sed 's/ *inet \(.*\)\/.*/\1/')
195         fi
196         echo "Public arvbox will use address $localip"
197         iptemp=$(tempfile)
198         echo $localip > $iptemp
199         chmod og+r $iptemp
200         PUBLIC="--volume=$iptemp:/var/run/localip_override
201               --publish=443:443
202               --publish=3001:3001
203               --publish=8000:8000
204               --publish=8900:8900
205               --publish=9000:9000
206               --publish=9002:9002
207               --publish=25101:25101
208               --publish=8001:8001
209               --publish=8002:8002"
210     else
211         PUBLIC=""
212     fi
213
214     if [[ "$CONFIG" =~ demo$ ]] ; then
215         if test -d "$ARVBOX_DATA" ; then
216             echo "It looks like you already have a development container named $ARVBOX_CONTAINER."
217             echo "Set environment variable ARVBOX_CONTAINER to set a different name for your demo container"
218             exit 1
219         fi
220
221         if ! (docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q) ; then
222             docker create -v /var/lib/postgresql -v /var/lib/arvados --name $ARVBOX_CONTAINER-data arvados/arvbox-demo /bin/true
223         fi
224
225         docker run \
226                --detach \
227                --name=$ARVBOX_CONTAINER \
228                --privileged \
229                --volumes-from $ARVBOX_CONTAINER-data \
230                --label "org.arvados.arvbox_config=$CONFIG" \
231                $PUBLIC \
232                arvados/arvbox-demo$TAG
233         updateconf
234         wait_for_arvbox
235     else
236         mkdir -p "$PG_DATA" "$VAR_DATA" "$PASSENGER" "$GEMS" "$PIPCACHE" "$NPMCACHE" "$GOSTUFF" "$RLIBS"
237
238         if ! test -d "$ARVADOS_ROOT" ; then
239             git clone https://github.com/arvados/arvados.git "$ARVADOS_ROOT"
240         fi
241         if ! test -d "$SSO_ROOT" ; then
242             git clone https://github.com/arvados/sso-devise-omniauth-provider.git "$SSO_ROOT"
243         fi
244         if ! test -d "$COMPOSER_ROOT" ; then
245             git clone https://github.com/arvados/composer.git "$COMPOSER_ROOT"
246             git -C "$COMPOSER_ROOT" checkout arvados-fork
247             git -C "$COMPOSER_ROOT" pull
248         fi
249         if ! test -d "$WORKBENCH2_ROOT" ; then
250             git clone https://github.com/arvados/arvados-workbench2.git "$WORKBENCH2_ROOT"
251         fi
252
253         if [[ "$CONFIG" = test ]] ; then
254
255             mkdir -p $VAR_DATA/test
256
257             if test "$need_setup" = 1 ; then
258                 docker_run_dev \
259                        --detach \
260                        --name=$ARVBOX_CONTAINER \
261                        --privileged \
262                        "--env=SVDIR=/etc/test-service" \
263                        arvados/arvbox-dev$TAG
264
265                 docker exec -ti \
266                        $ARVBOX_CONTAINER \
267                        /usr/local/lib/arvbox/runsu.sh \
268                        /usr/local/lib/arvbox/waitforpostgres.sh
269
270                 docker exec -ti \
271                        $ARVBOX_CONTAINER \
272                        /usr/local/lib/arvbox/runsu.sh \
273                        /var/lib/arvbox/service/sso/run-service --only-setup
274
275                 docker exec -ti \
276                        $ARVBOX_CONTAINER \
277                        /usr/local/lib/arvbox/runsu.sh \
278                        /var/lib/arvbox/service/api/run-service --only-setup
279             fi
280
281             interactive=""
282             if [[ -z "$@" ]] ; then
283                 interactive=--interactive
284             fi
285
286             docker exec -ti \
287                    -e LINES=$(tput lines) \
288                    -e COLUMNS=$(tput cols) \
289                    -e TERM=$TERM \
290                    -e WORKSPACE=/usr/src/arvados \
291                    -e GEM_HOME=/var/lib/gems \
292                    -e CONFIGSRC=/var/lib/arvados/run_tests \
293                    $ARVBOX_CONTAINER \
294                    /usr/local/lib/arvbox/runsu.sh \
295                    /usr/src/arvados/build/run-tests.sh \
296                    --temp /var/lib/arvados/test \
297                    $interactive \
298                    "$@"
299         elif [[ "$CONFIG" = devenv ]] ; then
300             if [[ $need_setup = 1 ]] ; then
301                 docker_run_dev \
302                     --detach \
303                     --name=${ARVBOX_CONTAINER} \
304                     "--env=SVDIR=/etc/devenv-service" \
305                     "--volume=$HOME:$HOME:rw" \
306                     --volume=/tmp/.X11-unix:/tmp/.X11-unix:rw \
307                     arvados/arvbox-dev$TAG
308             fi
309             exec docker exec --interactive --tty \
310                  -e LINES=$(tput lines) \
311                  -e COLUMNS=$(tput cols) \
312                  -e TERM=$TERM \
313                  -e "ARVBOX_HOME=$HOME" \
314                  -e "DISPLAY=$DISPLAY" \
315                  --workdir=$PWD \
316                  ${ARVBOX_CONTAINER} \
317                  /usr/local/lib/arvbox/devenv.sh "$@"
318         elif [[ "$CONFIG" =~ dev$ ]] ; then
319             docker_run_dev \
320                    --detach \
321                    --name=$ARVBOX_CONTAINER \
322                    --privileged \
323                    $PUBLIC \
324                    arvados/arvbox-dev$TAG
325             updateconf
326             wait_for_arvbox
327             echo "The Arvados source code is checked out at: $ARVADOS_ROOT"
328             echo "The Arvados testing root certificate is $VAR_DATA/root-cert.pem"
329         else
330             echo "Unknown configuration '$CONFIG'"
331         fi
332     fi
333 }
334
335 update() {
336     CONFIG=$1
337     TAG=$2
338
339     if test -n "$TAG"
340     then
341         if test $(echo $TAG | cut -c1-1) != '-' ; then
342             TAG=":$TAG"
343             shift
344         else
345             unset TAG
346         fi
347     fi
348
349     if echo "$CONFIG" | grep 'demo$' ; then
350         docker pull arvados/arvbox-demo$TAG
351     else
352         docker pull arvados/arvbox-dev$TAG
353     fi
354 }
355
356 stop() {
357     if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
358         docker stop $ARVBOX_CONTAINER
359     fi
360
361     VOLUMES=--volumes=true
362     if docker ps -a --filter "status=created" | grep -E "$ARVBOX_CONTAINER$" -q ; then
363         docker rm $VOLUMES $ARVBOX_CONTAINER
364     fi
365     if docker ps -a --filter "status=exited" | grep -E "$ARVBOX_CONTAINER$" -q ; then
366         docker rm $VOLUMES $ARVBOX_CONTAINER
367     fi
368 }
369
370 build() {
371     if ! test -f "$ARVBOX_DOCKER/Dockerfile.base" ;  then
372         echo "Could not find Dockerfile (expected it at $ARVBOX_DOCKER/Dockerfile.base)"
373         exit 1
374     fi
375     if docker --version |grep " 1\.[0-9]\." ; then
376         # Docker version prior 1.10 require -f flag
377         # -f flag removed in Docker 1.12
378         FORCE=-f
379     fi
380     GITHEAD=$(cd $ARVBOX_DOCKER && git log --format=%H -n1 HEAD)
381     docker build --build-arg=arvados_version=$GITHEAD $NO_CACHE -t arvados/arvbox-base:$GITHEAD -f "$ARVBOX_DOCKER/Dockerfile.base" "$ARVBOX_DOCKER"
382     docker tag $FORCE arvados/arvbox-base:$GITHEAD arvados/arvbox-base:latest
383     if test "$1" = localdemo -o "$1" = publicdemo ; then
384         docker build $NO_CACHE -t arvados/arvbox-demo:$GITHEAD -f "$ARVBOX_DOCKER/Dockerfile.demo" "$ARVBOX_DOCKER"
385         docker tag $FORCE arvados/arvbox-demo:$GITHEAD arvados/arvbox-demo:latest
386     else
387         docker build $NO_CACHE -t arvados/arvbox-dev:$GITHEAD -f "$ARVBOX_DOCKER/Dockerfile.dev" "$ARVBOX_DOCKER"
388         docker tag $FORCE arvados/arvbox-dev:$GITHEAD arvados/arvbox-dev:latest
389     fi
390 }
391
392 check() {
393     case "$1" in
394         localdemo|publicdemo|dev|publicdev|test|devenv)
395             true
396             ;;
397         *)
398             echo "Argument to $subcmd must be one of localdemo, publicdemo, dev, publicdev, test, devenv"
399             exit 1
400         ;;
401     esac
402 }
403
404 subcmd="$1"
405 if test -n "$subcmd" ; then
406     shift
407 fi
408 case "$subcmd" in
409     build)
410         check $@
411         build $@
412         ;;
413
414     rebuild)
415         check $@
416         NO_CACHE=--no-cache build $@
417         ;;
418
419     start|run)
420         check $@
421         run $@
422         ;;
423
424     sh*)
425         exec docker exec --interactive --tty \
426                -e LINES=$(tput lines) \
427                -e COLUMNS=$(tput cols) \
428                -e TERM=$TERM \
429                -e GEM_HOME=/var/lib/gems \
430                $ARVBOX_CONTAINER /bin/bash
431         ;;
432
433     ash*)
434         exec docker exec --interactive --tty \
435                -e LINES=$(tput lines) \
436                -e COLUMNS=$(tput cols) \
437                -e TERM=$TERM \
438                -e GEM_HOME=/var/lib/gems \
439                -u arvbox \
440                -w /usr/src/arvados \
441                $ARVBOX_CONTAINER /bin/bash --login
442         ;;
443
444     pipe)
445         exec docker exec -i $ARVBOX_CONTAINER /usr/bin/env GEM_HOME=/var/lib/gems /bin/bash -
446         ;;
447
448     stop)
449         stop
450         ;;
451
452     restart)
453         check $@
454         stop
455         run $@
456         ;;
457
458     reboot)
459         check $@
460         stop
461         build $@
462         run $@
463         ;;
464
465     update)
466         check $@
467         stop
468         update $@
469         run $@
470         ;;
471
472     ip)
473         getip
474         ;;
475
476     host)
477         gethost
478         ;;
479
480     open)
481         exec xdg-open http://$(gethost)
482         ;;
483
484     status)
485         echo "Container: $ARVBOX_CONTAINER"
486         if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
487             echo "Cluster id: $(getclusterid)"
488             echo "Status: running"
489             echo "Container IP: $(getip)"
490             echo "Published host: $(gethost)"
491         else
492             echo "Status: not running"
493         fi
494         if test -d "$ARVBOX_DATA" ; then
495             echo "Data: $ARVBOX_DATA"
496         elif docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q ; then
497             echo "Data: $ARVBOX_CONTAINER-data"
498         else
499             echo "Data: none"
500         fi
501         ;;
502
503     reset|destroy)
504         stop
505         if test -d "$ARVBOX_DATA" ; then
506             if test "$subcmd" = destroy ; then
507                 if test "$1" != -f ; then
508                     echo "WARNING!  This will delete your entire arvbox ($ARVBOX_DATA)."
509                     echo "Use destroy -f if you really mean it."
510                     exit 1
511                 fi
512                 set -x
513                 rm -rf "$ARVBOX_DATA"
514             else
515                 if test "$1" != -f ; then
516                     echo "WARNING!  This will delete your arvbox data ($ARVBOX_DATA)."
517                     echo "Code and downloaded packages will be preserved."
518                     echo "Use reset -f if you really mean it."
519                     exit 1
520                 fi
521                 set -x
522                 rm -rf "$ARVBOX_DATA/postgres"
523                 rm -rf "$ARVBOX_DATA/var"
524             fi
525         else
526             if test "$1" != -f ; then
527                 echo "WARNING!  This will delete your data container $ARVBOX_CONTAINER-data.  Use -f if you really mean it."
528                 exit 1
529             fi
530             set -x
531             docker rm "$ARVBOX_CONTAINER-data"
532         fi
533         ;;
534
535     log)
536         if test -n "$1" ; then
537             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"
538         else
539             exec docker exec -ti $ARVBOX_CONTAINER tail $(docker exec -ti $ARVBOX_CONTAINER find -L /etc -path '/etc/service/*/log/main/current' -printf " %p")
540         fi
541         ;;
542
543     cat)
544         if test -n "$1" ; then
545             exec docker exec $ARVBOX_CONTAINER cat "$@"
546         else
547             echo "Usage: $0 $subcmd <files>"
548         fi
549         ;;
550
551     ls)
552         exec docker exec -ti $ARVBOX_CONTAINER /usr/bin/env TERM=$TERM ls "$@"
553         ;;
554
555     sv)
556         if test -n "$1" -a -n "$2" ; then
557             exec docker exec $ARVBOX_CONTAINER sv "$@"
558         else
559             echo "Usage: $0 $subcmd <start|stop|restart> <service>"
560             echo "Available services:"
561             exec docker execa $ARVBOX_CONTAINER ls /etc/service
562         fi
563         ;;
564
565     clone)
566         if test -n "$2" ; then
567             mkdir -p "$ARVBOX_BASE/$2"
568             cp -a "$ARVBOX_BASE/$1/passenger" \
569                "$ARVBOX_BASE/$1/gems" \
570                "$ARVBOX_BASE/$1/pip" \
571                "$ARVBOX_BASE/$1/npm" \
572                "$ARVBOX_BASE/$1/gopath" \
573                "$ARVBOX_BASE/$1/Rlibs" \
574                "$ARVBOX_BASE/$1/arvados" \
575                "$ARVBOX_BASE/$1/sso-devise-omniauth-provider" \
576                "$ARVBOX_BASE/$1/composer" \
577                "$ARVBOX_BASE/$1/workbench2" \
578                "$ARVBOX_BASE/$2"
579             echo "Created new arvbox $2"
580             echo "export ARVBOX_CONTAINER=$2"
581         else
582             echo "clone <from> <to>   clone an arvbox"
583             echo "available arvboxes: $(ls $ARVBOX_BASE)"
584         fi
585         ;;
586
587     root-cert)
588         CERT=$PWD/${ARVBOX_CONTAINER}-root-cert.crt
589         if test -n "$1" ; then
590             CERT="$1"
591         fi
592         docker exec $ARVBOX_CONTAINER cat /var/lib/arvados/root-cert.pem > "$CERT"
593         echo "Certificate copied to $CERT"
594         ;;
595
596     psql)
597         exec docker exec -ti $ARVBOX_CONTAINER bash -c 'PGPASSWORD=$(cat /var/lib/arvados/api_database_pw) exec psql --dbname=arvados_development --host=localhost --username=arvados'
598         ;;
599
600     checkpoint)
601         exec docker exec -ti $ARVBOX_CONTAINER bash -c 'PGPASSWORD=$(cat /var/lib/arvados/api_database_pw) exec pg_dump --host=localhost --username=arvados --clean arvados_development > /var/lib/arvados/checkpoint.sql'
602         ;;
603
604     restore)
605         exec docker exec -ti $ARVBOX_CONTAINER bash -c 'PGPASSWORD=$(cat /var/lib/arvados/api_database_pw) exec psql --dbname=arvados_development --host=localhost --username=arvados --quiet --file=/var/lib/arvados/checkpoint.sql'
606         ;;
607
608     hotreset)
609         exec docker exec -i $ARVBOX_CONTAINER /usr/bin/env GEM_HOME=/var/lib/gems /bin/bash - <<EOF
610 sv stop api
611 sv stop controller
612 sv stop websockets
613 sv stop keepstore0
614 sv stop keepstore1
615 sv stop keepproxy
616 cd /usr/src/arvados/services/api
617 export RAILS_ENV=development
618 bundle exec rake db:drop
619 rm /var/lib/arvados/api_database_setup
620 rm /var/lib/arvados/superuser_token
621 rm /var/lib/arvados/keep0-uuid
622 rm /var/lib/arvados/keep1-uuid
623 rm /var/lib/arvados/keepproxy-uuid
624 sv start api
625 sv start controller
626 sv start websockets
627 sv restart keepstore0
628 sv restart keepstore1
629 sv restart keepproxy
630 EOF
631         ;;
632
633     *)
634         echo "Arvados-in-a-box             https://doc.arvados.org/install/arvbox.html"
635         echo
636         echo "start|run <config> [tag]   start $ARVBOX_CONTAINER container"
637         echo "stop               stop arvbox container"
638         echo "restart <config>   stop, then run again"
639         echo "status             print some information about current arvbox"
640         echo "ip                 print arvbox docker container ip address"
641         echo "host               print arvbox published host"
642         echo "shell              enter shell as root"
643         echo "ashell             enter shell as 'arvbox'"
644         echo "psql               enter postgres console"
645         echo "open               open arvbox workbench in a web browser"
646         echo "root-cert          get copy of root certificate"
647         echo "update  <config>   stop, pull latest image, run"
648         echo "build   <config>   build arvbox Docker image"
649         echo "reboot  <config>   stop, build arvbox Docker image, run"
650         echo "rebuild <config>   build arvbox Docker image, no layer cache"
651         echo "checkpoint         create database backup"
652         echo "restore            restore checkpoint"
653         echo "hotreset           reset database and restart API without restarting container"
654         echo "reset              delete arvbox arvados data (be careful!)"
655         echo "destroy            delete all arvbox code and data (be careful!)"
656         echo "log <service>      tail log of specified service"
657         echo "ls <options>       list directories inside arvbox"
658         echo "cat <files>        get contents of files inside arvbox"
659         echo "pipe               run a bash script piped in from stdin"
660         echo "sv <start|stop|restart> <service> "
661         echo "                   change state of service inside arvbox"
662         echo "clone <from> <to>  clone dev arvbox"
663         ;;
664 esac