Merge branch '16856-acr-disable-color' closes #16856
[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=4202:4202
210               --publish=45000-45020:45000-45020"
211     else
212         PUBLIC=""
213     fi
214
215     if [[ "$CONFIG" =~ demo$ ]] ; then
216         if test -d "$ARVBOX_DATA" ; then
217             echo "It looks like you already have a development container named $ARVBOX_CONTAINER."
218             echo "Set environment variable ARVBOX_CONTAINER to set a different name for your demo container"
219             exit 1
220         fi
221
222         if ! (docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q) ; then
223             docker create -v /var/lib/postgresql -v /var/lib/arvados --name $ARVBOX_CONTAINER-data arvados/arvbox-demo /bin/true
224         fi
225
226         docker run \
227                --detach \
228                --name=$ARVBOX_CONTAINER \
229                --privileged \
230                --volumes-from $ARVBOX_CONTAINER-data \
231                --label "org.arvados.arvbox_config=$CONFIG" \
232                $PUBLIC \
233                arvados/arvbox-demo$TAG
234         updateconf
235         wait_for_arvbox
236     else
237         mkdir -p "$PG_DATA" "$VAR_DATA" "$PASSENGER" "$GEMS" "$PIPCACHE" "$NPMCACHE" "$GOSTUFF" "$RLIBS"
238
239         if ! test -d "$ARVADOS_ROOT" ; then
240             git clone https://git.arvados.org/arvados.git "$ARVADOS_ROOT"
241         fi
242         if ! test -d "$COMPOSER_ROOT" ; then
243             git clone https://github.com/arvados/composer.git "$COMPOSER_ROOT"
244             git -C "$COMPOSER_ROOT" checkout arvados-fork
245             git -C "$COMPOSER_ROOT" pull
246         fi
247         if ! test -d "$WORKBENCH2_ROOT" ; then
248             git clone https://git.arvados.org/arvados-workbench2.git "$WORKBENCH2_ROOT"
249         fi
250
251         if [[ "$CONFIG" = test ]] ; then
252
253             mkdir -p $VAR_DATA/test
254
255             if test "$need_setup" = 1 ; then
256                 docker_run_dev \
257                        --detach \
258                        --name=$ARVBOX_CONTAINER \
259                        --privileged \
260                        "--env=SVDIR=/etc/test-service" \
261                        arvados/arvbox-dev$TAG
262
263                 docker exec -ti \
264                        $ARVBOX_CONTAINER \
265                        /usr/local/lib/arvbox/runsu.sh \
266                        /usr/local/lib/arvbox/waitforpostgres.sh
267
268                 docker exec -ti \
269                        $ARVBOX_CONTAINER \
270                        /usr/local/lib/arvbox/runsu.sh \
271                        /var/lib/arvbox/service/api/run-service --only-setup
272             fi
273
274             interactive=""
275             if [[ -z "$@" ]] ; then
276                 interactive=--interactive
277             fi
278
279             docker exec -ti \
280                    -e LINES=$(tput lines) \
281                    -e COLUMNS=$(tput cols) \
282                    -e TERM=$TERM \
283                    -e WORKSPACE=/usr/src/arvados \
284                    -e GEM_HOME=/var/lib/gems \
285                    -e CONFIGSRC=/var/lib/arvados/run_tests \
286                    $ARVBOX_CONTAINER \
287                    /usr/local/lib/arvbox/runsu.sh \
288                    /usr/src/arvados/build/run-tests.sh \
289                    --temp /var/lib/arvados/test \
290                    $interactive \
291                    "$@"
292         elif [[ "$CONFIG" = devenv ]] ; then
293             if [[ $need_setup = 1 ]] ; then
294                     docker_run_dev \
295                     --detach \
296                     --name=${ARVBOX_CONTAINER} \
297                     "--env=SVDIR=/etc/devenv-service" \
298                         "--volume=$HOME:$HOME:rw" \
299                     --volume=/tmp/.X11-unix:/tmp/.X11-unix:rw \
300                         arvados/arvbox-dev$TAG
301             fi
302                 exec docker exec --interactive --tty \
303                      -e LINES=$(tput lines) \
304                      -e COLUMNS=$(tput cols) \
305                      -e TERM=$TERM \
306                      -e "ARVBOX_HOME=$HOME" \
307                      -e "DISPLAY=$DISPLAY" \
308                      --workdir=$PWD \
309                  ${ARVBOX_CONTAINER} \
310                      /usr/local/lib/arvbox/devenv.sh "$@"
311         elif [[ "$CONFIG" =~ dev$ ]] ; then
312             docker_run_dev \
313                    --detach \
314                    --name=$ARVBOX_CONTAINER \
315                    --privileged \
316                    $PUBLIC \
317                    arvados/arvbox-dev$TAG
318             updateconf
319             wait_for_arvbox
320             echo "The Arvados source code is checked out at: $ARVADOS_ROOT"
321             echo "The Arvados testing root certificate is $VAR_DATA/root-cert.pem"
322             if [[ "$(listusers)" =~ ^\{\} ]] ; then
323                 echo "No users defined, use 'arvbox adduser' to add user logins"
324             else
325                 echo "Use 'arvbox listusers' to see user logins"
326             fi
327         else
328             echo "Unknown configuration '$CONFIG'"
329         fi
330     fi
331 }
332
333 update() {
334     CONFIG=$1
335     TAG=$2
336
337     if test -n "$TAG"
338     then
339         if test $(echo $TAG | cut -c1-1) != '-' ; then
340             TAG=":$TAG"
341             shift
342         else
343             unset TAG
344         fi
345     fi
346
347     if echo "$CONFIG" | grep 'demo$' ; then
348         docker pull arvados/arvbox-demo$TAG
349     else
350         docker pull arvados/arvbox-dev$TAG
351     fi
352 }
353
354 stop() {
355     if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
356         docker stop $ARVBOX_CONTAINER
357     fi
358
359     VOLUMES=--volumes=true
360     if docker ps -a --filter "status=created" | grep -E "$ARVBOX_CONTAINER$" -q ; then
361         docker rm $VOLUMES $ARVBOX_CONTAINER
362     fi
363     if docker ps -a --filter "status=exited" | grep -E "$ARVBOX_CONTAINER$" -q ; then
364         docker rm $VOLUMES $ARVBOX_CONTAINER
365     fi
366 }
367
368 build() {
369     if ! test -f "$ARVBOX_DOCKER/Dockerfile.base" ;  then
370         echo "Could not find Dockerfile (expected it at $ARVBOX_DOCKER/Dockerfile.base)"
371         exit 1
372     fi
373     if docker --version |grep " 1\.[0-9]\." ; then
374         # Docker version prior 1.10 require -f flag
375         # -f flag removed in Docker 1.12
376         FORCE=-f
377     fi
378     GITHEAD=$(cd $ARVBOX_DOCKER && git log --format=%H -n1 HEAD)
379     docker build --build-arg=arvados_version=$GITHEAD $NO_CACHE -t arvados/arvbox-base:$GITHEAD -f "$ARVBOX_DOCKER/Dockerfile.base" "$ARVBOX_DOCKER"
380     docker tag $FORCE arvados/arvbox-base:$GITHEAD arvados/arvbox-base:latest
381     if test "$1" = localdemo -o "$1" = publicdemo ; then
382         docker build $NO_CACHE -t arvados/arvbox-demo:$GITHEAD -f "$ARVBOX_DOCKER/Dockerfile.demo" "$ARVBOX_DOCKER"
383         docker tag $FORCE arvados/arvbox-demo:$GITHEAD arvados/arvbox-demo:latest
384     else
385         docker build $NO_CACHE -t arvados/arvbox-dev:$GITHEAD -f "$ARVBOX_DOCKER/Dockerfile.dev" "$ARVBOX_DOCKER"
386         docker tag $FORCE arvados/arvbox-dev:$GITHEAD arvados/arvbox-dev:latest
387     fi
388 }
389
390 check() {
391     case "$1" in
392         localdemo|publicdemo|dev|publicdev|test|devenv)
393             true
394             ;;
395         *)
396             echo "Argument to $subcmd must be one of localdemo, publicdemo, dev, publicdev, test, devenv"
397             exit 1
398         ;;
399     esac
400 }
401
402 subcmd="$1"
403 if test -n "$subcmd" ; then
404     shift
405 fi
406 case "$subcmd" in
407     build)
408         check $@
409         build $@
410         ;;
411
412     rebuild)
413         check $@
414         NO_CACHE=--no-cache build $@
415         ;;
416
417     start|run)
418         check $@
419         run $@
420         ;;
421
422     sh*)
423         exec docker exec --interactive --tty \
424                -e LINES=$(tput lines) \
425                -e COLUMNS=$(tput cols) \
426                -e TERM=$TERM \
427                -e GEM_HOME=/var/lib/gems \
428                $ARVBOX_CONTAINER /bin/bash
429         ;;
430
431     ash*)
432         exec docker exec --interactive --tty \
433                -e LINES=$(tput lines) \
434                -e COLUMNS=$(tput cols) \
435                -e TERM=$TERM \
436                -e GEM_HOME=/var/lib/gems \
437                -u arvbox \
438                -w /usr/src/arvados \
439                $ARVBOX_CONTAINER /bin/bash --login
440         ;;
441
442     pipe)
443         exec docker exec -i $ARVBOX_CONTAINER /usr/bin/env GEM_HOME=/var/lib/gems /bin/bash -
444         ;;
445
446     stop)
447         stop
448         ;;
449
450     restart)
451         check $@
452         stop
453         run $@
454         ;;
455
456     reboot)
457         check $@
458         stop
459         build $@
460         run $@
461         ;;
462
463     update)
464         check $@
465         stop
466         update $@
467         run $@
468         ;;
469
470     ip)
471         getip
472         ;;
473
474     host)
475         gethost
476         ;;
477
478     open)
479         exec xdg-open http://$(gethost)
480         ;;
481
482     status)
483         echo "Container: $ARVBOX_CONTAINER"
484         if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
485             echo "Cluster id: $(getclusterid)"
486             echo "Status: running"
487             echo "Container IP: $(getip)"
488             echo "Published host: $(gethost)"
489         else
490             echo "Status: not running"
491         fi
492         if test -d "$ARVBOX_DATA" ; then
493             echo "Data: $ARVBOX_DATA"
494         elif docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q ; then
495             echo "Data: $ARVBOX_CONTAINER-data"
496         else
497             echo "Data: none"
498         fi
499         ;;
500
501     reset|destroy)
502         stop
503         if test -d "$ARVBOX_DATA" ; then
504             if test "$subcmd" = destroy ; then
505                 if test "$1" != -f ; then
506                     echo "WARNING!  This will delete your entire arvbox ($ARVBOX_DATA)."
507                     echo "Use destroy -f if you really mean it."
508                     exit 1
509                 fi
510                 set -x
511                 chmod -R u+w "$ARVBOX_DATA"
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/composer" \
575                "$ARVBOX_BASE/$1/workbench2" \
576                "$ARVBOX_BASE/$2"
577             echo "Created new arvbox $2"
578             echo "export ARVBOX_CONTAINER=$2"
579         else
580             echo "clone <from> <to>   clone an arvbox"
581             echo "available arvboxes: $(ls $ARVBOX_BASE)"
582         fi
583         ;;
584
585     root-cert)
586         CERT=$PWD/${ARVBOX_CONTAINER}-root-cert.crt
587         if test -n "$1" ; then
588             CERT="$1"
589         fi
590         docker exec $ARVBOX_CONTAINER cat /var/lib/arvados/root-cert.pem > "$CERT"
591         echo "Certificate copied to $CERT"
592         ;;
593
594     psql)
595         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'
596         ;;
597
598     checkpoint)
599         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'
600         ;;
601
602     restore)
603         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'
604         ;;
605
606     hotreset)
607         exec docker exec -i $ARVBOX_CONTAINER /usr/bin/env GEM_HOME=/var/lib/gems /bin/bash - <<EOF
608 sv stop api
609 sv stop controller
610 sv stop websockets
611 sv stop keepstore0
612 sv stop keepstore1
613 sv stop keepproxy
614 cd /usr/src/arvados/services/api
615 export DISABLE_DATABASE_ENVIRONMENT_CHECK=1
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     adduser)
633         docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py /var/lib/arvados/cluster_config.yml.override $(getclusterid) add $@
634         docker exec $ARVBOX_CONTAINER sv restart controller
635         ;;
636
637     removeuser)
638         docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py /var/lib/arvados/cluster_config.yml.override $(getclusterid) remove $@
639         docker exec $ARVBOX_CONTAINER sv restart controller
640         ;;
641
642     listusers)
643         listusers
644         ;;
645
646     *)
647         echo "Arvados-in-a-box             https://doc.arvados.org/install/arvbox.html"
648         echo
649         echo "start|run <config> [tag]   start $ARVBOX_CONTAINER container"
650         echo "stop               stop arvbox container"
651         echo "restart <config>   stop, then run again"
652         echo "status             print some information about current arvbox"
653         echo "ip                 print arvbox docker container ip address"
654         echo "host               print arvbox published host"
655         echo "shell              enter shell as root"
656         echo "ashell             enter shell as 'arvbox'"
657         echo "psql               enter postgres console"
658         echo "open               open arvbox workbench in a web browser"
659         echo "root-cert          get copy of root certificate"
660         echo "update  <config>   stop, pull latest image, run"
661         echo "build   <config>   build arvbox Docker image"
662         echo "reboot  <config>   stop, build arvbox Docker image, run"
663         echo "rebuild <config>   build arvbox Docker image, no layer cache"
664         echo "checkpoint         create database backup"
665         echo "restore            restore checkpoint"
666         echo "hotreset           reset database and restart API without restarting container"
667         echo "reset              delete arvbox arvados data (be careful!)"
668         echo "destroy            delete all arvbox code and data (be careful!)"
669         echo "log <service>      tail log of specified service"
670         echo "ls <options>       list directories inside arvbox"
671         echo "cat <files>        get contents of files inside arvbox"
672         echo "pipe               run a bash script piped in from stdin"
673         echo "sv <start|stop|restart> <service> "
674         echo "                   change state of service inside arvbox"
675         echo "clone <from> <to>  clone dev arvbox"
676         echo "adduser <username> <email>"
677         echo "                   add a user login"
678         echo "removeuser <username>"
679         echo "                   remove user login"
680         echo "listusers          list user logins"
681         ;;
682 esac