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