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