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 if test -z "$ARVADOS_BRANCH" ; then
59 if test -z "$WORKBENCH2_BRANCH" ; then
60 WORKBENCH2_BRANCH=main
63 # Update this to the docker tag for the version on releases.
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 GEM_HOME="/var/lib/arvados/lib/ruby/gems/2.7.0"
78 docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $ARVBOX_CONTAINER
83 OVERRIDE=$(docker exec -i $ARVBOX_CONTAINER cat /var/run/localip_override 2>/dev/null)
86 if test "$CODE" = 0 ; then
94 docker exec $ARVBOX_CONTAINER cat $ARVADOS_CONTAINER_PATH/api_uuid_prefix
98 if test -f ~/.config/arvados/$ARVBOX_CONTAINER.conf ; then
99 sed "s/ARVADOS_API_HOST=.*/ARVADOS_API_HOST=$(gethost):8000/" <$HOME/.config/arvados/$ARVBOX_CONTAINER.conf >$HOME/.config/arvados/$ARVBOX_CONTAINER.conf.tmp
100 mv ~/.config/arvados/$ARVBOX_CONTAINER.conf.tmp ~/.config/arvados/$ARVBOX_CONTAINER.conf
102 mkdir -p $HOME/.config/arvados
103 cat >$HOME/.config/arvados/$ARVBOX_CONTAINER.conf <<EOF
104 ARVADOS_API_HOST=$(gethost):8000
106 ARVADOS_API_HOST_INSECURE=true
112 docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py $ARVADOS_CONTAINER_PATH/cluster_config.yml $(getclusterid) list
116 FF=/tmp/arvbox-fifo-$$
118 docker logs -f $ARVBOX_CONTAINER > $FF &
121 if [[ $line =~ "ok: down: ready:" ]] ; then
124 wait $LOGPID 2>/dev/null
132 if test -n "$localip" ; then
133 echo "export ARVADOS_API_HOST=$localip:8000"
135 echo "export ARVADOS_API_HOST=$(gethost):8000"
141 "--volume=$ARVADOS_ROOT:/usr/src/arvados:rw" \
142 "--volume=$COMPOSER_ROOT:/usr/src/composer:rw" \
143 "--volume=$WORKBENCH2_ROOT:/usr/src/workbench2:rw" \
144 "--volume=$PG_DATA:/var/lib/postgresql:rw" \
145 "--volume=$VAR_DATA:$ARVADOS_CONTAINER_PATH:rw" \
146 "--volume=$PASSENGER:/var/lib/passenger:rw" \
147 "--volume=$GEMS:$GEM_HOME:rw" \
148 "--volume=$PIPCACHE:/var/lib/pip:rw" \
149 "--volume=$NPMCACHE:/var/lib/npm:rw" \
150 "--volume=$GOSTUFF:/var/lib/gopath:rw" \
151 "--volume=$RLIBS:/var/lib/Rlibs:rw" \
152 --label "org.arvados.arvbox_config=$CONFIG" \
157 docker inspect $ARVBOX_CONTAINER -f '{{index .Config.Labels "org.arvados.arvbox_config"}}'
168 if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
169 if [[ $(running_config) != "$CONFIG" ]] ; then
170 echo "Container $ARVBOX_CONTAINER is '$(running_config)' config but requested '$CONFIG'; use restart or reboot"
173 if test "$CONFIG" = test -o "$CONFIG" = devenv ; then
176 echo "Container $ARVBOX_CONTAINER is already running"
181 if test $need_setup = 1 ; then
182 if docker ps -a | grep -E "$ARVBOX_CONTAINER$" -q ; then
183 echo "Container $ARVBOX_CONTAINER already exists but is not running; use restart or reboot"
190 if test $(echo $TAG | cut -c1-1) != '-' ; then
194 if [[ $TAG = '-' ]] ; then
201 if test -z "$TAG" -a -n "$DEFAULT_TAG"; then
205 if [[ "$CONFIG" =~ ^public ]] ; then
206 if test -n "$ARVBOX_PUBLISH_IP" ; then
207 localip=$ARVBOX_PUBLISH_IP
209 defaultdev=$(/sbin/ip route|awk '/default/ { print $5 }')
210 localip=$(ip addr show $defaultdev | grep 'inet ' | sed 's/ *inet \(.*\)\/.*/\1/')
212 echo "Public arvbox will use address $localip"
214 echo $localip > $iptemp
216 PUBLIC="--volume=$iptemp:/var/run/localip_override
224 --publish=25101:25101
228 --publish=45000-45020:45000-45020"
233 if [[ "$CONFIG" =~ demo$ ]] ; then
234 if test -d "$ARVBOX_DATA" ; then
235 echo "It looks like you already have a development container named $ARVBOX_CONTAINER."
236 echo "Set environment variable ARVBOX_CONTAINER to set a different name for your demo container"
240 if ! (docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q) ; then
241 docker create -v /var/lib/postgresql -v $ARVADOS_CONTAINER_PATH --name $ARVBOX_CONTAINER-data arvados/arvbox-demo /bin/true
246 --name=$ARVBOX_CONTAINER \
248 --volumes-from $ARVBOX_CONTAINER-data \
249 --label "org.arvados.arvbox_config=$CONFIG" \
251 arvados/arvbox-demo$TAG
255 mkdir -p "$PG_DATA" "$VAR_DATA" "$PASSENGER" "$GEMS" "$PIPCACHE" "$NPMCACHE" "$GOSTUFF" "$RLIBS"
257 if ! test -d "$ARVADOS_ROOT" ; then
258 git clone https://git.arvados.org/arvados.git "$ARVADOS_ROOT"
259 git -C "$ARVADOS_ROOT" checkout $ARVADOS_BRANCH
261 if ! test -d "$COMPOSER_ROOT" ; then
262 git clone https://github.com/arvados/composer.git "$COMPOSER_ROOT"
263 git -C "$COMPOSER_ROOT" checkout arvados-fork
265 if ! test -d "$WORKBENCH2_ROOT" ; then
266 git clone https://git.arvados.org/arvados-workbench2.git "$WORKBENCH2_ROOT"
267 git -C "$ARVADOS_ROOT" checkout $WORKBENCH2_BRANCH
270 if [[ "$CONFIG" = test ]] ; then
272 mkdir -p $VAR_DATA/test
274 if test "$need_setup" = 1 ; then
277 --name=$ARVBOX_CONTAINER \
279 "--env=SVDIR=/etc/test-service" \
280 arvados/arvbox-dev$TAG
284 /usr/local/lib/arvbox/runsu.sh \
285 /usr/local/lib/arvbox/waitforpostgres.sh
289 if [[ -z "$@" ]] ; then
290 interactive=--interactive
294 -e LINES=$(tput lines) \
295 -e COLUMNS=$(tput cols) \
297 -e WORKSPACE=/usr/src/arvados \
298 -e GEM_HOME=$GEM_HOME \
299 -e CONFIGSRC=$ARVADOS_CONTAINER_PATH/run_tests \
301 /usr/local/lib/arvbox/runsu.sh \
302 /usr/src/arvados/build/run-tests.sh \
303 --temp $ARVADOS_CONTAINER_PATH/test \
306 elif [[ "$CONFIG" = devenv ]] ; then
307 if [[ $need_setup = 1 ]] ; then
310 --name=${ARVBOX_CONTAINER} \
311 "--env=SVDIR=/etc/devenv-service" \
312 "--volume=$HOME:$HOME:rw" \
313 --volume=/tmp/.X11-unix:/tmp/.X11-unix:rw \
314 arvados/arvbox-dev$TAG
316 exec docker exec --interactive --tty \
317 -e LINES=$(tput lines) \
318 -e COLUMNS=$(tput cols) \
320 -e "ARVBOX_HOME=$HOME" \
321 -e "DISPLAY=$DISPLAY" \
323 ${ARVBOX_CONTAINER} \
324 /usr/local/lib/arvbox/devenv.sh "$@"
325 elif [[ "$CONFIG" =~ dev$ ]] ; then
328 --name=$ARVBOX_CONTAINER \
331 arvados/arvbox-dev$TAG
334 echo "The Arvados source code is checked out at: $ARVADOS_ROOT"
335 echo "The Arvados testing root certificate is $VAR_DATA/root-cert.pem"
336 if [[ "$(listusers)" =~ ^\{\} ]] ; then
337 echo "No users defined, use 'arvbox adduser' to add user logins"
339 echo "Use 'arvbox listusers' to see user logins"
342 echo "Unknown configuration '$CONFIG'"
353 if test $(echo $TAG | cut -c1-1) != '-' ; then
361 if echo "$CONFIG" | grep 'demo$' ; then
362 docker pull arvados/arvbox-demo$TAG
364 docker pull arvados/arvbox-dev$TAG
369 if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
370 docker stop $ARVBOX_CONTAINER
373 VOLUMES=--volumes=true
374 if docker ps -a --filter "status=created" | grep -E "$ARVBOX_CONTAINER$" -q ; then
375 docker rm $VOLUMES $ARVBOX_CONTAINER
377 if docker ps -a --filter "status=exited" | grep -E "$ARVBOX_CONTAINER$" -q ; then
378 docker rm $VOLUMES $ARVBOX_CONTAINER
383 export DOCKER_BUILDKIT=1
384 if ! test -f "$ARVBOX_DOCKER/Dockerfile.base" ; then
385 echo "Could not find Dockerfile (expected it at $ARVBOX_DOCKER/Dockerfile.base)"
388 if docker --version |grep " 1\.[0-9]\." ; then
389 # Docker version prior 1.10 require -f flag
390 # -f flag removed in Docker 1.12
393 GITHEAD=$(cd $ARVBOX_DOCKER && git log --format=%H -n1 HEAD)
396 if which greadlink >/dev/null 2>/dev/null ; then
397 LOCAL_ARVADOS_ROOT=$(greadlink -f $(dirname $0)/../../../)
399 LOCAL_ARVADOS_ROOT=$(readlink -f $(dirname $0)/../../../)
403 # Get the go version we should use for bootstrapping
404 GO_VERSION=`grep 'const goversion =' $LOCAL_ARVADOS_ROOT/lib/install/deps.go |awk -F'"' '{print $2}'`
406 if test "$1" = localdemo -o "$1" = publicdemo ; then
412 if test "$ARVADOS_BRANCH" = "main" ; then
413 ARVADOS_BRANCH=$GITHEAD
416 docker build --build-arg=BUILDTYPE=$BUILDTYPE $NO_CACHE \
417 --build-arg=go_version=$GO_VERSION \
418 --build-arg=arvados_version=$ARVADOS_BRANCH \
419 --build-arg=workbench2_version=$WORKBENCH2_BRANCH \
420 --build-arg=workdir=/tools/arvbox/lib/arvbox/docker \
421 -t arvados/arvbox-base:$GITHEAD \
422 -f "$ARVBOX_DOCKER/Dockerfile.base" \
423 "$LOCAL_ARVADOS_ROOT"
424 docker tag $FORCE arvados/arvbox-base:$GITHEAD arvados/arvbox-base:latest
425 docker build $NO_CACHE \
426 --build-arg=go_version=$GO_VERSION \
427 --build-arg=arvados_version=$ARVADOS_BRANCH \
428 --build-arg=workbench2_version=$WORKBENCH2_BRANCH \
429 -t arvados/arvbox-$BUILDTYPE:$GITHEAD \
430 -f "$ARVBOX_DOCKER/Dockerfile.$BUILDTYPE" \
432 docker tag $FORCE arvados/arvbox-$BUILDTYPE:$GITHEAD arvados/arvbox-$BUILDTYPE:latest
437 localdemo|publicdemo|dev|publicdev|test|devenv)
441 echo "Argument to $subcmd must be one of localdemo, publicdemo, dev, publicdev, test, devenv"
448 if test -n "$subcmd" ; then
459 NO_CACHE=--no-cache build $@
468 exec docker exec --interactive --tty \
469 -e LINES=$(tput lines) \
470 -e COLUMNS=$(tput cols) \
472 -e GEM_HOME=$GEM_HOME \
473 $ARVBOX_CONTAINER /bin/bash
477 exec docker exec --interactive --tty \
478 -e LINES=$(tput lines) \
479 -e COLUMNS=$(tput cols) \
481 -e GEM_HOME=$GEM_HOME \
483 -w /usr/src/arvados \
484 $ARVBOX_CONTAINER /bin/bash --login
488 exec docker exec -i $ARVBOX_CONTAINER /usr/bin/env GEM_HOME=$GEM_HOME /bin/bash -
524 exec xdg-open http://$(gethost)
528 echo "Container: $ARVBOX_CONTAINER"
529 if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
530 echo "Cluster id: $(getclusterid)"
531 echo "Status: running"
532 echo "Container IP: $(getip)"
533 echo "Published host: $(gethost)"
534 echo "Workbench: https://$(gethost)"
536 echo "Status: not running"
538 if test -d "$ARVBOX_DATA" ; then
539 echo "Data: $ARVBOX_DATA"
540 elif docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q ; then
541 echo "Data: $ARVBOX_CONTAINER-data"
549 if test -d "$ARVBOX_DATA" ; then
550 if test "$subcmd" = destroy ; then
551 if test "$1" != -f ; then
552 echo "WARNING! This will delete your entire arvbox ($ARVBOX_DATA)."
553 echo "Use destroy -f if you really mean it."
557 chmod -R u+w "$ARVBOX_DATA"
558 rm -rf "$ARVBOX_DATA"
560 if test "$1" != -f ; then
561 echo "WARNING! This will delete your arvbox data ($ARVBOX_DATA)."
562 echo "Code and downloaded packages will be preserved."
563 echo "Use reset -f if you really mean it."
567 rm -rf "$ARVBOX_DATA/postgres"
568 rm -rf "$ARVBOX_DATA/var"
571 if test "$1" != -f ; then
572 echo "WARNING! This will delete your data container $ARVBOX_CONTAINER-data. Use -f if you really mean it."
576 docker rm "$ARVBOX_CONTAINER-data"
581 if test -n "$1" ; then
582 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"
584 exec docker exec -ti $ARVBOX_CONTAINER tail $(docker exec -ti $ARVBOX_CONTAINER find -L /etc -path '/etc/service/*/log/main/current' -printf " %p")
589 if test -n "$1" ; then
590 exec docker exec $ARVBOX_CONTAINER cat "$@"
592 echo "Usage: $0 $subcmd <files>"
597 exec docker exec -ti $ARVBOX_CONTAINER /usr/bin/env TERM=$TERM ls "$@"
601 if test -n "$1" -a -n "$2" ; then
602 exec docker exec $ARVBOX_CONTAINER sv "$@"
604 echo "Usage: $0 $subcmd <start|stop|restart> <service>"
605 echo "Available services:"
606 exec docker exec $ARVBOX_CONTAINER ls /etc/service
611 if test -n "$2" ; then
612 mkdir -p "$ARVBOX_BASE/$2"
613 cp -a "$ARVBOX_BASE/$1/passenger" \
614 "$ARVBOX_BASE/$1/gems" \
615 "$ARVBOX_BASE/$1/pip" \
616 "$ARVBOX_BASE/$1/npm" \
617 "$ARVBOX_BASE/$1/gopath" \
618 "$ARVBOX_BASE/$1/Rlibs" \
619 "$ARVBOX_BASE/$1/arvados" \
620 "$ARVBOX_BASE/$1/composer" \
621 "$ARVBOX_BASE/$1/workbench2" \
623 echo "Created new arvbox $2"
624 echo "export ARVBOX_CONTAINER=$2"
626 echo "clone <from> <to> clone an arvbox"
627 echo "available arvboxes: $(ls $ARVBOX_BASE)"
632 CERT=$PWD/${ARVBOX_CONTAINER}-root-cert.crt
633 if test -n "$1" ; then
636 docker exec $ARVBOX_CONTAINER cat $ARVADOS_CONTAINER_PATH/root-cert.pem > "$CERT"
637 echo "Certificate copied to $CERT"
641 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'
645 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'
649 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'
653 exec docker exec -i $ARVBOX_CONTAINER /usr/bin/env GEM_HOME=$GEM_HOME /bin/bash - <<EOF
660 cd /usr/src/arvados/services/api
661 export DISABLE_DATABASE_ENVIRONMENT_CHECK=1
662 export RAILS_ENV=development
663 flock $GEM_HOME/gems.lock bin/bundle exec rake db:drop
664 rm $ARVADOS_CONTAINER_PATH/api_database_setup
665 rm $ARVADOS_CONTAINER_PATH/superuser_token
669 sv restart keepstore0
670 sv restart keepstore1
676 if [[ -n "$2" ]] ; then
677 docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py $ARVADOS_CONTAINER_PATH/cluster_config.yml.override $(getclusterid) add $@
678 docker exec $ARVBOX_CONTAINER sv restart controller
680 echo "Usage: adduser <username> <email> [password]"
685 if [[ -n "$1" ]] ; then
686 docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py $ARVADOS_CONTAINER_PATH/cluster_config.yml.override $(getclusterid) remove $@
687 docker exec $ARVBOX_CONTAINER sv restart controller
689 echo "Usage: removeuser <username>"
698 echo "Arvados-in-a-box https://doc.arvados.org/install/arvbox.html"
700 echo "start|run <config> [tag] start $ARVBOX_CONTAINER container"
701 echo "stop stop arvbox container"
702 echo "restart <config> stop, then run again"
703 echo "status print some information about current arvbox"
704 echo "ip print arvbox docker container ip address"
705 echo "host print arvbox published host"
706 echo "shell enter shell as root"
707 echo "ashell enter shell as 'arvbox'"
708 echo "psql enter postgres console"
709 echo "open open arvbox workbench in a web browser"
710 echo "root-cert get copy of root certificate"
711 echo "update <config> stop, pull latest image, run"
712 echo "build <config> build arvbox Docker image"
713 echo "reboot <config> stop, build arvbox Docker image, run"
714 echo "rebuild <config> build arvbox Docker image, no layer cache"
715 echo "checkpoint create database backup"
716 echo "restore restore checkpoint"
717 echo "hotreset reset database and restart API without restarting container"
718 echo "reset delete arvbox arvados data (be careful!)"
719 echo "destroy delete all arvbox code and data (be careful!)"
720 echo "log <service> tail log of specified service"
721 echo "ls <options> list directories inside arvbox"
722 echo "cat <files> get contents of files inside arvbox"
723 echo "pipe run a bash script piped in from stdin"
724 echo "sv <start|stop|restart> <service> "
725 echo " change state of service inside arvbox"
726 echo "clone <from> <to> clone dev arvbox"
727 echo "adduser <username> <email> [password]"
728 echo " add a user login"
729 echo "removeuser <username>"
730 echo " remove user login"
731 echo "listusers list user logins"