2 # Copyright (C) The Arvados Authors. All rights reserved.
4 # SPDX-License-Identifier: AGPL-3.0
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."
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"
21 if test -z "$ARVBOX_DOCKER" ; then
23 if which greadlink >/dev/null 2>/dev/null ; then
24 ARVBOX_DOCKER=$(greadlink -f $(dirname $0)/../lib/arvbox/docker)
26 ARVBOX_DOCKER=$(readlink -f $(dirname $0)/../lib/arvbox/docker)
31 if test -z "$ARVBOX_CONTAINER" ; then
32 ARVBOX_CONTAINER=arvbox
35 if test -z "$ARVBOX_BASE" ; then
36 ARVBOX_BASE="$HOME/.arvbox"
39 if test -z "$ARVBOX_DATA" ; then
40 ARVBOX_DATA="$ARVBOX_BASE/$ARVBOX_CONTAINER"
43 if test -z "$ARVADOS_ROOT" ; then
44 ARVADOS_ROOT="$ARVBOX_DATA/arvados"
47 if test -z "$COMPOSER_ROOT" ; then
48 COMPOSER_ROOT="$ARVBOX_DATA/composer"
51 if test -z "$WORKBENCH2_ROOT" ; then
52 WORKBENCH2_ROOT="$ARVBOX_DATA/workbench2"
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 ARVADOS_CONTAINER_PATH="/var/lib/arvados-arvbox"
64 GEM_HOME="/var/lib/arvados/lib/ruby/gems/2.5.0"
67 docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $ARVBOX_CONTAINER
72 OVERRIDE=$(docker exec -i $ARVBOX_CONTAINER cat /var/run/localip_override 2>/dev/null)
75 if test "$CODE" = 0 ; then
83 docker exec $ARVBOX_CONTAINER cat $ARVADOS_CONTAINER_PATH/api_uuid_prefix
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
91 mkdir -p $HOME/.config/arvados
92 cat >$HOME/.config/arvados/$ARVBOX_CONTAINER.conf <<EOF
93 ARVADOS_API_HOST=$(gethost):8000
95 ARVADOS_API_HOST_INSECURE=true
101 docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py $ARVADOS_CONTAINER_PATH/cluster_config.yml $(getclusterid) list
105 FF=/tmp/arvbox-fifo-$$
107 docker logs -f $ARVBOX_CONTAINER > $FF &
110 if [[ $line =~ "ok: down: ready:" ]] ; then
113 wait $LOGPID 2>/dev/null
121 if test -n "$localip" ; then
122 echo "export ARVADOS_API_HOST=$localip:8000"
124 echo "export ARVADOS_API_HOST=$(gethost):8000"
130 "--volume=$ARVADOS_ROOT:/usr/src/arvados:rw" \
131 "--volume=$COMPOSER_ROOT:/usr/src/composer:rw" \
132 "--volume=$WORKBENCH2_ROOT:/usr/src/workbench2:rw" \
133 "--volume=$PG_DATA:/var/lib/postgresql:rw" \
134 "--volume=$VAR_DATA:$ARVADOS_CONTAINER_PATH:rw" \
135 "--volume=$PASSENGER:/var/lib/passenger:rw" \
136 "--volume=$GEMS:$GEM_HOME:rw" \
137 "--volume=$PIPCACHE:/var/lib/pip:rw" \
138 "--volume=$NPMCACHE:/var/lib/npm:rw" \
139 "--volume=$GOSTUFF:/var/lib/gopath:rw" \
140 "--volume=$RLIBS:/var/lib/Rlibs:rw" \
141 --label "org.arvados.arvbox_config=$CONFIG" \
146 docker inspect $ARVBOX_CONTAINER -f '{{index .Config.Labels "org.arvados.arvbox_config"}}'
157 if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
158 if [[ $(running_config) != "$CONFIG" ]] ; then
159 echo "Container $ARVBOX_CONTAINER is '$(running_config)' config but requested '$CONFIG'; use restart or reboot"
162 if test "$CONFIG" = test -o "$CONFIG" = devenv ; then
165 echo "Container $ARVBOX_CONTAINER is already running"
170 if test $need_setup = 1 ; then
171 if docker ps -a | grep -E "$ARVBOX_CONTAINER$" -q ; then
172 echo "Container $ARVBOX_CONTAINER already exists but is not running; use restart or reboot"
179 if test $(echo $TAG | cut -c1-1) != '-' ; then
183 if [[ $TAG = '-' ]] ; then
190 if [[ "$CONFIG" =~ ^public ]] ; then
191 if test -n "$ARVBOX_PUBLISH_IP" ; then
192 localip=$ARVBOX_PUBLISH_IP
194 defaultdev=$(/sbin/ip route|awk '/default/ { print $5 }')
195 localip=$(ip addr show $defaultdev | grep 'inet ' | sed 's/ *inet \(.*\)\/.*/\1/')
197 echo "Public arvbox will use address $localip"
199 echo $localip > $iptemp
201 PUBLIC="--volume=$iptemp:/var/run/localip_override
208 --publish=25101:25101
212 --publish=45000-45020:45000-45020"
217 if [[ "$CONFIG" =~ demo$ ]] ; then
218 if test -d "$ARVBOX_DATA" ; then
219 echo "It looks like you already have a development container named $ARVBOX_CONTAINER."
220 echo "Set environment variable ARVBOX_CONTAINER to set a different name for your demo container"
224 if ! (docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q) ; then
225 docker create -v /var/lib/postgresql -v $ARVADOS_CONTAINER_PATH --name $ARVBOX_CONTAINER-data arvados/arvbox-demo /bin/true
230 --name=$ARVBOX_CONTAINER \
232 --volumes-from $ARVBOX_CONTAINER-data \
233 --label "org.arvados.arvbox_config=$CONFIG" \
235 arvados/arvbox-demo$TAG
239 mkdir -p "$PG_DATA" "$VAR_DATA" "$PASSENGER" "$GEMS" "$PIPCACHE" "$NPMCACHE" "$GOSTUFF" "$RLIBS"
241 if ! test -d "$ARVADOS_ROOT" ; then
242 git clone https://git.arvados.org/arvados.git "$ARVADOS_ROOT"
244 if ! test -d "$COMPOSER_ROOT" ; then
245 git clone https://github.com/arvados/composer.git "$COMPOSER_ROOT"
246 git -C "$COMPOSER_ROOT" checkout arvados-fork
247 git -C "$COMPOSER_ROOT" pull
249 if ! test -d "$WORKBENCH2_ROOT" ; then
250 git clone https://git.arvados.org/arvados-workbench2.git "$WORKBENCH2_ROOT"
253 if [[ "$CONFIG" = test ]] ; then
255 mkdir -p $VAR_DATA/test
257 if test "$need_setup" = 1 ; then
260 --name=$ARVBOX_CONTAINER \
262 "--env=SVDIR=/etc/test-service" \
263 arvados/arvbox-dev$TAG
267 /usr/local/lib/arvbox/runsu.sh \
268 /usr/local/lib/arvbox/waitforpostgres.sh
272 if [[ -z "$@" ]] ; then
273 interactive=--interactive
277 -e LINES=$(tput lines) \
278 -e COLUMNS=$(tput cols) \
280 -e WORKSPACE=/usr/src/arvados \
281 -e GEM_HOME=$GEM_HOME \
282 -e CONFIGSRC=$ARVADOS_CONTAINER_PATH/run_tests \
284 /usr/local/lib/arvbox/runsu.sh \
285 /usr/src/arvados/build/run-tests.sh \
286 --temp $ARVADOS_CONTAINER_PATH/test \
289 elif [[ "$CONFIG" = devenv ]] ; then
290 if [[ $need_setup = 1 ]] ; then
293 --name=${ARVBOX_CONTAINER} \
294 "--env=SVDIR=/etc/devenv-service" \
295 "--volume=$HOME:$HOME:rw" \
296 --volume=/tmp/.X11-unix:/tmp/.X11-unix:rw \
297 arvados/arvbox-dev$TAG
299 exec docker exec --interactive --tty \
300 -e LINES=$(tput lines) \
301 -e COLUMNS=$(tput cols) \
303 -e "ARVBOX_HOME=$HOME" \
304 -e "DISPLAY=$DISPLAY" \
306 ${ARVBOX_CONTAINER} \
307 /usr/local/lib/arvbox/devenv.sh "$@"
308 elif [[ "$CONFIG" =~ dev$ ]] ; then
311 --name=$ARVBOX_CONTAINER \
314 arvados/arvbox-dev$TAG
317 echo "The Arvados source code is checked out at: $ARVADOS_ROOT"
318 echo "The Arvados testing root certificate is $VAR_DATA/root-cert.pem"
319 if [[ "$(listusers)" =~ ^\{\} ]] ; then
320 echo "No users defined, use 'arvbox adduser' to add user logins"
322 echo "Use 'arvbox listusers' to see user logins"
325 echo "Unknown configuration '$CONFIG'"
336 if test $(echo $TAG | cut -c1-1) != '-' ; then
344 if echo "$CONFIG" | grep 'demo$' ; then
345 docker pull arvados/arvbox-demo$TAG
347 docker pull arvados/arvbox-dev$TAG
352 if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
353 docker stop $ARVBOX_CONTAINER
356 VOLUMES=--volumes=true
357 if docker ps -a --filter "status=created" | grep -E "$ARVBOX_CONTAINER$" -q ; then
358 docker rm $VOLUMES $ARVBOX_CONTAINER
360 if docker ps -a --filter "status=exited" | grep -E "$ARVBOX_CONTAINER$" -q ; then
361 docker rm $VOLUMES $ARVBOX_CONTAINER
366 export DOCKER_BUILDKIT=1
367 if ! test -f "$ARVBOX_DOCKER/Dockerfile.base" ; then
368 echo "Could not find Dockerfile (expected it at $ARVBOX_DOCKER/Dockerfile.base)"
371 if docker --version |grep " 1\.[0-9]\." ; then
372 # Docker version prior 1.10 require -f flag
373 # -f flag removed in Docker 1.12
376 GITHEAD=$(cd $ARVBOX_DOCKER && git log --format=%H -n1 HEAD)
377 if test "$1" = localdemo -o "$1" = publicdemo ; then
379 if which greadlink >/dev/null 2>/dev/null ; then
380 ARVADOS_ROOT=$(greadlink -f $(dirname $0)/../../../)
382 ARVADOS_ROOT=$(readlink -f $(dirname $0)/../../../)
385 docker build --build-arg=BUILDTYPE=demo $NO_CACHE --build-arg=arvados_version=$GITHEAD --build-arg=workdir=/tools/arvbox/lib/arvbox/docker -t arvados/arvbox-base:$GITHEAD -f "$ARVBOX_DOCKER/Dockerfile.base" "$ARVADOS_ROOT"
386 docker tag $FORCE arvados/arvbox-base:$GITHEAD arvados/arvbox-base:latest
387 docker build $NO_CACHE -t arvados/arvbox-demo:$GITHEAD -f "$ARVBOX_DOCKER/Dockerfile.demo" "$ARVBOX_DOCKER"
388 docker tag $FORCE arvados/arvbox-demo:$GITHEAD arvados/arvbox-demo:latest
390 if ! test -d "$ARVADOS_ROOT" ; then
391 git clone https://git.arvados.org/arvados.git "$ARVADOS_ROOT"
393 docker build --build-arg=BUILDTYPE=dev $NO_CACHE --build-arg=arvados_version=$GITHEAD --build-arg=workdir=/tools/arvbox/lib/arvbox/docker -t arvados/arvbox-base:$GITHEAD -f "$ARVBOX_DOCKER/Dockerfile.base" "$ARVADOS_ROOT"
394 docker tag $FORCE arvados/arvbox-base:$GITHEAD arvados/arvbox-base:latest
395 docker build $NO_CACHE -t arvados/arvbox-dev:$GITHEAD -f "$ARVBOX_DOCKER/Dockerfile.dev" "$ARVBOX_DOCKER"
396 docker tag $FORCE arvados/arvbox-dev:$GITHEAD arvados/arvbox-dev:latest
402 localdemo|publicdemo|dev|publicdev|test|devenv)
406 echo "Argument to $subcmd must be one of localdemo, publicdemo, dev, publicdev, test, devenv"
413 if test -n "$subcmd" ; then
424 NO_CACHE=--no-cache build $@
433 exec docker exec --interactive --tty \
434 -e LINES=$(tput lines) \
435 -e COLUMNS=$(tput cols) \
437 -e GEM_HOME=$GEM_HOME \
438 $ARVBOX_CONTAINER /bin/bash
442 exec docker exec --interactive --tty \
443 -e LINES=$(tput lines) \
444 -e COLUMNS=$(tput cols) \
446 -e GEM_HOME=$GEM_HOME \
448 -w /usr/src/arvados \
449 $ARVBOX_CONTAINER /bin/bash --login
453 exec docker exec -i $ARVBOX_CONTAINER /usr/bin/env GEM_HOME=$GEM_HOME /bin/bash -
489 exec xdg-open http://$(gethost)
493 echo "Container: $ARVBOX_CONTAINER"
494 if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
495 echo "Cluster id: $(getclusterid)"
496 echo "Status: running"
497 echo "Container IP: $(getip)"
498 echo "Published host: $(gethost)"
500 echo "Status: not running"
502 if test -d "$ARVBOX_DATA" ; then
503 echo "Data: $ARVBOX_DATA"
504 elif docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q ; then
505 echo "Data: $ARVBOX_CONTAINER-data"
513 if test -d "$ARVBOX_DATA" ; then
514 if test "$subcmd" = destroy ; then
515 if test "$1" != -f ; then
516 echo "WARNING! This will delete your entire arvbox ($ARVBOX_DATA)."
517 echo "Use destroy -f if you really mean it."
521 chmod -R u+w "$ARVBOX_DATA"
522 rm -rf "$ARVBOX_DATA"
524 if test "$1" != -f ; then
525 echo "WARNING! This will delete your arvbox data ($ARVBOX_DATA)."
526 echo "Code and downloaded packages will be preserved."
527 echo "Use reset -f if you really mean it."
531 rm -rf "$ARVBOX_DATA/postgres"
532 rm -rf "$ARVBOX_DATA/var"
535 if test "$1" != -f ; then
536 echo "WARNING! This will delete your data container $ARVBOX_CONTAINER-data. Use -f if you really mean it."
540 docker rm "$ARVBOX_CONTAINER-data"
545 if test -n "$1" ; then
546 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"
548 exec docker exec -ti $ARVBOX_CONTAINER tail $(docker exec -ti $ARVBOX_CONTAINER find -L /etc -path '/etc/service/*/log/main/current' -printf " %p")
553 if test -n "$1" ; then
554 exec docker exec $ARVBOX_CONTAINER cat "$@"
556 echo "Usage: $0 $subcmd <files>"
561 exec docker exec -ti $ARVBOX_CONTAINER /usr/bin/env TERM=$TERM ls "$@"
565 if test -n "$1" -a -n "$2" ; then
566 exec docker exec $ARVBOX_CONTAINER sv "$@"
568 echo "Usage: $0 $subcmd <start|stop|restart> <service>"
569 echo "Available services:"
570 exec docker execa $ARVBOX_CONTAINER ls /etc/service
575 if test -n "$2" ; then
576 mkdir -p "$ARVBOX_BASE/$2"
577 cp -a "$ARVBOX_BASE/$1/passenger" \
578 "$ARVBOX_BASE/$1/gems" \
579 "$ARVBOX_BASE/$1/pip" \
580 "$ARVBOX_BASE/$1/npm" \
581 "$ARVBOX_BASE/$1/gopath" \
582 "$ARVBOX_BASE/$1/Rlibs" \
583 "$ARVBOX_BASE/$1/arvados" \
584 "$ARVBOX_BASE/$1/composer" \
585 "$ARVBOX_BASE/$1/workbench2" \
587 echo "Created new arvbox $2"
588 echo "export ARVBOX_CONTAINER=$2"
590 echo "clone <from> <to> clone an arvbox"
591 echo "available arvboxes: $(ls $ARVBOX_BASE)"
596 CERT=$PWD/${ARVBOX_CONTAINER}-root-cert.crt
597 if test -n "$1" ; then
600 docker exec $ARVBOX_CONTAINER cat $ARVADOS_CONTAINER_PATH/root-cert.pem > "$CERT"
601 echo "Certificate copied to $CERT"
605 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'
609 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'
613 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'
617 exec docker exec -i $ARVBOX_CONTAINER /usr/bin/env GEM_HOME=$GEM_HOME /bin/bash - <<EOF
624 cd /usr/src/arvados/services/api
625 export DISABLE_DATABASE_ENVIRONMENT_CHECK=1
626 export RAILS_ENV=development
627 bundle exec rake db:drop
628 rm $ARVADOS_CONTAINER_PATH/api_database_setup
629 rm $ARVADOS_CONTAINER_PATH/superuser_token
630 rm $ARVADOS_CONTAINER_PATH/keep0-uuid
631 rm $ARVADOS_CONTAINER_PATH/keep1-uuid
632 rm $ARVADOS_CONTAINER_PATH/keepproxy-uuid
636 sv restart keepstore0
637 sv restart keepstore1
643 docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py $ARVADOS_CONTAINER_PATH/cluster_config.yml.override $(getclusterid) add $@
644 docker exec $ARVBOX_CONTAINER sv restart controller
648 docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py $ARVADOS_CONTAINER_PATH/cluster_config.yml.override $(getclusterid) remove $@
649 docker exec $ARVBOX_CONTAINER sv restart controller
657 echo "Arvados-in-a-box https://doc.arvados.org/install/arvbox.html"
659 echo "start|run <config> [tag] start $ARVBOX_CONTAINER container"
660 echo "stop stop arvbox container"
661 echo "restart <config> stop, then run again"
662 echo "status print some information about current arvbox"
663 echo "ip print arvbox docker container ip address"
664 echo "host print arvbox published host"
665 echo "shell enter shell as root"
666 echo "ashell enter shell as 'arvbox'"
667 echo "psql enter postgres console"
668 echo "open open arvbox workbench in a web browser"
669 echo "root-cert get copy of root certificate"
670 echo "update <config> stop, pull latest image, run"
671 echo "build <config> build arvbox Docker image"
672 echo "reboot <config> stop, build arvbox Docker image, run"
673 echo "rebuild <config> build arvbox Docker image, no layer cache"
674 echo "checkpoint create database backup"
675 echo "restore restore checkpoint"
676 echo "hotreset reset database and restart API without restarting container"
677 echo "reset delete arvbox arvados data (be careful!)"
678 echo "destroy delete all arvbox code and data (be careful!)"
679 echo "log <service> tail log of specified service"
680 echo "ls <options> list directories inside arvbox"
681 echo "cat <files> get contents of files inside arvbox"
682 echo "pipe run a bash script piped in from stdin"
683 echo "sv <start|stop|restart> <service> "
684 echo " change state of service inside arvbox"
685 echo "clone <from> <to> clone dev arvbox"
686 echo "adduser <username> <email>"
687 echo " add a user login"
688 echo "removeuser <username>"
689 echo " remove user login"
690 echo "listusers list user logins"