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