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"
77 docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $ARVBOX_CONTAINER
82 OVERRIDE=$(docker exec -i $ARVBOX_CONTAINER cat /var/run/localip_override 2>/dev/null)
85 if test "$CODE" = 0 ; then
93 docker exec $ARVBOX_CONTAINER cat $ARVADOS_CONTAINER_PATH/api_uuid_prefix
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
101 mkdir -p $HOME/.config/arvados
102 cat >$HOME/.config/arvados/$ARVBOX_CONTAINER.conf <<EOF
103 ARVADOS_API_HOST=$(gethost):8000
105 ARVADOS_API_HOST_INSECURE=true
111 docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py $ARVADOS_CONTAINER_PATH/cluster_config.yml $(getclusterid) list
115 FF=/tmp/arvbox-fifo-$$
117 docker logs -f $ARVBOX_CONTAINER > $FF &
120 if [[ $line =~ "ok: down: ready:" ]] ; then
123 wait $LOGPID 2>/dev/null
131 if test -n "$localip" ; then
132 echo "export ARVADOS_API_HOST=$localip:8000"
134 echo "export ARVADOS_API_HOST=$(gethost):8000"
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=$PIPCACHE:/var/lib/pip:rw" \
147 "--volume=$NPMCACHE:/var/lib/npm:rw" \
148 "--volume=$GOSTUFF:/var/lib/gopath:rw" \
149 "--volume=$RLIBS:/var/lib/Rlibs:rw" \
150 --label "org.arvados.arvbox_config=$CONFIG" \
155 docker inspect $ARVBOX_CONTAINER -f '{{index .Config.Labels "org.arvados.arvbox_config"}}'
166 if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
167 if [[ $(running_config) != "$CONFIG" ]] ; then
168 echo "Container $ARVBOX_CONTAINER is '$(running_config)' config but requested '$CONFIG'; use restart or reboot"
171 if test "$CONFIG" = test -o "$CONFIG" = devenv ; then
174 echo "Container $ARVBOX_CONTAINER is already running"
179 if test $need_setup = 1 ; then
180 if docker ps -a | grep -E "$ARVBOX_CONTAINER$" -q ; then
181 echo "Container $ARVBOX_CONTAINER already exists but is not running; use restart or reboot"
188 if test $(echo $TAG | cut -c1-1) != '-' ; then
192 if [[ $TAG = '-' ]] ; then
199 if test -z "$TAG" -a -n "$DEFAULT_TAG"; then
203 if [[ "$CONFIG" =~ ^public ]] ; then
204 if test -n "$ARVBOX_PUBLISH_IP" ; then
205 localip=$ARVBOX_PUBLISH_IP
207 defaultdev=$(/sbin/ip route|awk '/default/ { print $5 }')
208 localip=$(ip addr show $defaultdev | grep 'inet ' | sed 's/ *inet \(.*\)\/.*/\1/')
210 echo "Public arvbox will use address $localip"
212 echo $localip > $iptemp
214 PUBLIC="--volume=$iptemp:/var/run/localip_override
222 --publish=25101:25101
226 --publish=45000-45020:45000-45020"
231 if [[ "$CONFIG" =~ demo$ ]] ; then
232 if test -d "$ARVBOX_DATA" ; then
233 echo "It looks like you already have a development container named $ARVBOX_CONTAINER."
234 echo "Set environment variable ARVBOX_CONTAINER to set a different name for your demo container"
238 if ! (docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q) ; then
239 docker create -v /var/lib/postgresql -v $ARVADOS_CONTAINER_PATH --name $ARVBOX_CONTAINER-data arvados/arvbox-demo /bin/true
244 --name=$ARVBOX_CONTAINER \
246 --volumes-from $ARVBOX_CONTAINER-data \
247 --label "org.arvados.arvbox_config=$CONFIG" \
249 arvados/arvbox-demo$TAG
253 mkdir -p "$PG_DATA" "$VAR_DATA" "$PASSENGER" "$GEMS" "$PIPCACHE" "$NPMCACHE" "$GOSTUFF" "$RLIBS"
255 if ! test -d "$ARVADOS_ROOT" ; then
256 git clone https://git.arvados.org/arvados.git "$ARVADOS_ROOT"
257 git -C "$ARVADOS_ROOT" checkout $ARVADOS_BRANCH
259 if ! test -d "$COMPOSER_ROOT" ; then
260 git clone https://github.com/arvados/composer.git "$COMPOSER_ROOT"
261 git -C "$COMPOSER_ROOT" checkout arvados-fork
263 if ! test -d "$WORKBENCH2_ROOT" ; then
264 git clone https://git.arvados.org/arvados-workbench2.git "$WORKBENCH2_ROOT"
265 git -C "$ARVADOS_ROOT" checkout $WORKBENCH2_BRANCH
268 if [[ "$CONFIG" = test ]] ; then
270 mkdir -p $VAR_DATA/test
272 if test "$need_setup" = 1 ; then
275 --name=$ARVBOX_CONTAINER \
277 "--env=SVDIR=/etc/test-service" \
278 arvados/arvbox-dev$TAG
282 /usr/local/lib/arvbox/runsu.sh \
283 /usr/local/lib/arvbox/waitforpostgres.sh
287 if [[ -z "$@" ]] ; then
288 interactive=--interactive
292 -e LINES=$(tput lines) \
293 -e COLUMNS=$(tput cols) \
295 -e WORKSPACE=/usr/src/arvados \
296 -e CONFIGSRC=$ARVADOS_CONTAINER_PATH/run_tests \
298 /usr/local/lib/arvbox/runsu.sh \
299 /usr/src/arvados/build/run-tests.sh \
300 --temp $ARVADOS_CONTAINER_PATH/test \
303 elif [[ "$CONFIG" = devenv ]] ; then
304 if [[ $need_setup = 1 ]] ; then
307 --name=${ARVBOX_CONTAINER} \
308 "--env=SVDIR=/etc/devenv-service" \
309 "--volume=$HOME:$HOME:rw" \
310 --volume=/tmp/.X11-unix:/tmp/.X11-unix:rw \
311 arvados/arvbox-dev$TAG
313 exec docker exec --interactive --tty \
314 -e LINES=$(tput lines) \
315 -e COLUMNS=$(tput cols) \
317 -e "ARVBOX_HOME=$HOME" \
318 -e "DISPLAY=$DISPLAY" \
320 ${ARVBOX_CONTAINER} \
321 /usr/local/lib/arvbox/devenv.sh "$@"
322 elif [[ "$CONFIG" =~ dev$ ]] ; then
325 --name=$ARVBOX_CONTAINER \
328 arvados/arvbox-dev$TAG
331 echo "The Arvados source code is checked out at: $ARVADOS_ROOT"
332 echo "The Arvados testing root certificate is $VAR_DATA/root-cert.pem"
333 if [[ "$(listusers)" =~ ^\{\} ]] ; then
334 echo "No users defined, use 'arvbox adduser' to add user logins"
336 echo "Use 'arvbox listusers' to see user logins"
339 echo "Unknown configuration '$CONFIG'"
350 if test $(echo $TAG | cut -c1-1) != '-' ; then
358 if echo "$CONFIG" | grep 'demo$' ; then
359 docker pull arvados/arvbox-demo$TAG
361 docker pull arvados/arvbox-dev$TAG
366 if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
367 docker stop $ARVBOX_CONTAINER
370 VOLUMES=--volumes=true
371 if docker ps -a --filter "status=created" | grep -E "$ARVBOX_CONTAINER$" -q ; then
372 docker rm $VOLUMES $ARVBOX_CONTAINER
374 if docker ps -a --filter "status=exited" | grep -E "$ARVBOX_CONTAINER$" -q ; then
375 docker rm $VOLUMES $ARVBOX_CONTAINER
380 export DOCKER_BUILDKIT=1
381 if ! test -f "$ARVBOX_DOCKER/Dockerfile.base" ; then
382 echo "Could not find Dockerfile (expected it at $ARVBOX_DOCKER/Dockerfile.base)"
385 if docker --version |grep " 1\.[0-9]\." ; then
386 # Docker version prior 1.10 require -f flag
387 # -f flag removed in Docker 1.12
390 GITHEAD=$(cd $ARVBOX_DOCKER && git log --format=%H -n1 HEAD)
393 if which greadlink >/dev/null 2>/dev/null ; then
394 LOCAL_ARVADOS_ROOT=$(greadlink -f $(dirname $0)/../../../)
396 LOCAL_ARVADOS_ROOT=$(readlink -f $(dirname $0)/../../../)
400 # Get the go version we should use for bootstrapping
401 GO_VERSION=`grep 'const goversion =' $LOCAL_ARVADOS_ROOT/lib/install/deps.go |awk -F'"' '{print $2}'`
403 if test "$1" = localdemo -o "$1" = publicdemo ; then
409 if test "$ARVADOS_BRANCH" = "main" ; then
410 ARVADOS_BRANCH=$GITHEAD
413 docker build --build-arg=BUILDTYPE=$BUILDTYPE $NO_CACHE \
414 --build-arg=go_version=$GO_VERSION \
415 --build-arg=arvados_version=$ARVADOS_BRANCH \
416 --build-arg=workbench2_version=$WORKBENCH2_BRANCH \
417 --build-arg=workdir=/tools/arvbox/lib/arvbox/docker \
418 -t arvados/arvbox-base:$GITHEAD \
419 -f "$ARVBOX_DOCKER/Dockerfile.base" \
420 "$LOCAL_ARVADOS_ROOT"
421 docker tag $FORCE arvados/arvbox-base:$GITHEAD arvados/arvbox-base:latest
422 docker build $NO_CACHE \
423 --build-arg=go_version=$GO_VERSION \
424 --build-arg=arvados_version=$ARVADOS_BRANCH \
425 --build-arg=workbench2_version=$WORKBENCH2_BRANCH \
426 -t arvados/arvbox-$BUILDTYPE:$GITHEAD \
427 -f "$ARVBOX_DOCKER/Dockerfile.$BUILDTYPE" \
429 docker tag $FORCE arvados/arvbox-$BUILDTYPE:$GITHEAD arvados/arvbox-$BUILDTYPE:latest
434 localdemo|publicdemo|dev|publicdev|test|devenv)
438 echo "Argument to $subcmd must be one of localdemo, publicdemo, dev, publicdev, test, devenv"
445 if test -n "$subcmd" ; then
456 NO_CACHE=--no-cache build $@
465 exec docker exec --interactive --tty \
466 -e LINES=$(tput lines) \
467 -e COLUMNS=$(tput cols) \
469 $ARVBOX_CONTAINER /bin/bash
473 exec docker exec --interactive --tty \
474 -e LINES=$(tput lines) \
475 -e COLUMNS=$(tput cols) \
478 -w /usr/src/arvados \
479 $ARVBOX_CONTAINER /bin/bash --login
483 exec docker exec -i $ARVBOX_CONTAINER /usr/bin/env /bin/bash -
519 exec xdg-open http://$(gethost)
523 echo "Container: $ARVBOX_CONTAINER"
524 if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
525 echo "Cluster id: $(getclusterid)"
526 echo "Status: running"
527 echo "Container IP: $(getip)"
528 echo "Published host: $(gethost)"
529 echo "Workbench: https://$(gethost)"
531 echo "Status: not running"
533 if test -d "$ARVBOX_DATA" ; then
534 echo "Data: $ARVBOX_DATA"
535 elif docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q ; then
536 echo "Data: $ARVBOX_CONTAINER-data"
544 if test -d "$ARVBOX_DATA" ; then
545 if test "$subcmd" = destroy ; then
546 if test "$1" != -f ; then
547 echo "WARNING! This will delete your entire arvbox ($ARVBOX_DATA)."
548 echo "Use destroy -f if you really mean it."
552 chmod -R u+w "$ARVBOX_DATA"
553 rm -rf "$ARVBOX_DATA"
555 if test "$1" != -f ; then
556 echo "WARNING! This will delete your arvbox data ($ARVBOX_DATA)."
557 echo "Code and downloaded packages will be preserved."
558 echo "Use reset -f if you really mean it."
562 rm -rf "$ARVBOX_DATA/postgres"
563 rm -rf "$ARVBOX_DATA/var"
566 if test "$1" != -f ; then
567 echo "WARNING! This will delete your data container $ARVBOX_CONTAINER-data. Use -f if you really mean it."
571 docker rm "$ARVBOX_CONTAINER-data"
576 if test -n "$1" ; then
577 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 exec docker exec -ti $ARVBOX_CONTAINER tail $(docker exec -ti $ARVBOX_CONTAINER find -L /etc -path '/etc/service/*/log/main/current' -printf " %p")
584 if test -n "$1" ; then
585 exec docker exec $ARVBOX_CONTAINER cat "$@"
587 echo "Usage: $0 $subcmd <files>"
592 exec docker exec -ti $ARVBOX_CONTAINER /usr/bin/env TERM=$TERM ls "$@"
596 if test -n "$1" -a -n "$2" ; then
597 exec docker exec $ARVBOX_CONTAINER sv "$@"
599 echo "Usage: $0 $subcmd <start|stop|restart> <service>"
600 echo "Available services:"
601 exec docker exec $ARVBOX_CONTAINER ls /etc/service
606 if test -n "$2" ; then
607 mkdir -p "$ARVBOX_BASE/$2"
608 cp -a "$ARVBOX_BASE/$1/passenger" \
609 "$ARVBOX_BASE/$1/gems" \
610 "$ARVBOX_BASE/$1/pip" \
611 "$ARVBOX_BASE/$1/npm" \
612 "$ARVBOX_BASE/$1/gopath" \
613 "$ARVBOX_BASE/$1/Rlibs" \
614 "$ARVBOX_BASE/$1/arvados" \
615 "$ARVBOX_BASE/$1/composer" \
616 "$ARVBOX_BASE/$1/workbench2" \
618 echo "Created new arvbox $2"
619 echo "export ARVBOX_CONTAINER=$2"
621 echo "clone <from> <to> clone an arvbox"
622 echo "available arvboxes: $(ls $ARVBOX_BASE)"
627 CERT=$PWD/${ARVBOX_CONTAINER}-root-cert.crt
628 if test -n "$1" ; then
631 docker exec $ARVBOX_CONTAINER cat $ARVADOS_CONTAINER_PATH/root-cert.pem > "$CERT"
632 echo "Certificate copied to $CERT"
636 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'
640 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'
644 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'
648 exec docker exec -i $ARVBOX_CONTAINER /usr/bin/env /bin/bash - <<EOF
655 cd /usr/src/arvados/services/api
656 export DISABLE_DATABASE_ENVIRONMENT_CHECK=1
657 export RAILS_ENV=development
658 bin/bundle exec rake db:drop
659 rm $ARVADOS_CONTAINER_PATH/api_database_setup
660 rm $ARVADOS_CONTAINER_PATH/superuser_token
664 sv restart keepstore0
665 sv restart keepstore1
671 if [[ -n "$2" ]] ; then
672 docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py $ARVADOS_CONTAINER_PATH/cluster_config.yml.override $(getclusterid) add $@
673 docker exec $ARVBOX_CONTAINER sv restart controller
675 echo "Usage: adduser <username> <email> [password]"
680 if [[ -n "$1" ]] ; then
681 docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py $ARVADOS_CONTAINER_PATH/cluster_config.yml.override $(getclusterid) remove $@
682 docker exec $ARVBOX_CONTAINER sv restart controller
684 echo "Usage: removeuser <username>"
693 echo "Arvados-in-a-box https://doc.arvados.org/install/arvbox.html"
695 echo "start|run <config> [tag] start $ARVBOX_CONTAINER container"
696 echo "stop stop arvbox container"
697 echo "restart <config> stop, then run again"
698 echo "status print some information about current arvbox"
699 echo "ip print arvbox docker container ip address"
700 echo "host print arvbox published host"
701 echo "shell enter shell as root"
702 echo "ashell enter shell as 'arvbox'"
703 echo "psql enter postgres console"
704 echo "open open arvbox workbench in a web browser"
705 echo "root-cert get copy of root certificate"
706 echo "update <config> stop, pull latest image, run"
707 echo "build <config> build arvbox Docker image"
708 echo "reboot <config> stop, build arvbox Docker image, run"
709 echo "rebuild <config> build arvbox Docker image, no layer cache"
710 echo "checkpoint create database backup"
711 echo "restore restore checkpoint"
712 echo "hotreset reset database and restart API without restarting container"
713 echo "reset delete arvbox arvados data (be careful!)"
714 echo "destroy delete all arvbox code and data (be careful!)"
715 echo "log <service> tail log of specified service"
716 echo "ls <options> list directories inside arvbox"
717 echo "cat <files> get contents of files inside arvbox"
718 echo "pipe run a bash script piped in from stdin"
719 echo "sv <start|stop|restart> <service> "
720 echo " change state of service inside arvbox"
721 echo "clone <from> <to> clone dev arvbox"
722 echo "adduser <username> <email> [password]"
723 echo " add a user login"
724 echo "removeuser <username>"
725 echo " remove user login"
726 echo "listusers list user logins"