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 PG_DATA="$ARVBOX_DATA/postgres"
64 VAR_DATA="$ARVBOX_DATA/var"
65 PASSENGER="$ARVBOX_DATA/passenger"
66 GEMS="$ARVBOX_DATA/gems"
67 PIPCACHE="$ARVBOX_DATA/pip"
68 NPMCACHE="$ARVBOX_DATA/npm"
69 GOSTUFF="$ARVBOX_DATA/gopath"
70 RLIBS="$ARVBOX_DATA/Rlibs"
71 ARVADOS_CONTAINER_PATH="/var/lib/arvados-arvbox"
72 GEM_HOME="/var/lib/arvados/lib/ruby/gems/2.7.0"
75 docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $ARVBOX_CONTAINER
80 OVERRIDE=$(docker exec -i $ARVBOX_CONTAINER cat /var/run/localip_override 2>/dev/null)
83 if test "$CODE" = 0 ; then
91 docker exec $ARVBOX_CONTAINER cat $ARVADOS_CONTAINER_PATH/api_uuid_prefix
95 if test -f ~/.config/arvados/$ARVBOX_CONTAINER.conf ; then
96 sed "s/ARVADOS_API_HOST=.*/ARVADOS_API_HOST=$(gethost):8000/" <$HOME/.config/arvados/$ARVBOX_CONTAINER.conf >$HOME/.config/arvados/$ARVBOX_CONTAINER.conf.tmp
97 mv ~/.config/arvados/$ARVBOX_CONTAINER.conf.tmp ~/.config/arvados/$ARVBOX_CONTAINER.conf
99 mkdir -p $HOME/.config/arvados
100 cat >$HOME/.config/arvados/$ARVBOX_CONTAINER.conf <<EOF
101 ARVADOS_API_HOST=$(gethost):8000
103 ARVADOS_API_HOST_INSECURE=true
109 docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py $ARVADOS_CONTAINER_PATH/cluster_config.yml $(getclusterid) list
113 FF=/tmp/arvbox-fifo-$$
115 docker logs -f $ARVBOX_CONTAINER > $FF &
118 if [[ $line =~ "ok: down: ready:" ]] ; then
121 wait $LOGPID 2>/dev/null
129 if test -n "$localip" ; then
130 echo "export ARVADOS_API_HOST=$localip:8000"
132 echo "export ARVADOS_API_HOST=$(gethost):8000"
138 "--volume=$ARVADOS_ROOT:/usr/src/arvados:rw" \
139 "--volume=$COMPOSER_ROOT:/usr/src/composer:rw" \
140 "--volume=$WORKBENCH2_ROOT:/usr/src/workbench2:rw" \
141 "--volume=$PG_DATA:/var/lib/postgresql:rw" \
142 "--volume=$VAR_DATA:$ARVADOS_CONTAINER_PATH:rw" \
143 "--volume=$PASSENGER:/var/lib/passenger:rw" \
144 "--volume=$GEMS:$GEM_HOME:rw" \
145 "--volume=$PIPCACHE:/var/lib/pip:rw" \
146 "--volume=$NPMCACHE:/var/lib/npm:rw" \
147 "--volume=$GOSTUFF:/var/lib/gopath:rw" \
148 "--volume=$RLIBS:/var/lib/Rlibs:rw" \
149 --label "org.arvados.arvbox_config=$CONFIG" \
154 docker inspect $ARVBOX_CONTAINER -f '{{index .Config.Labels "org.arvados.arvbox_config"}}'
165 if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
166 if [[ $(running_config) != "$CONFIG" ]] ; then
167 echo "Container $ARVBOX_CONTAINER is '$(running_config)' config but requested '$CONFIG'; use restart or reboot"
170 if test "$CONFIG" = test -o "$CONFIG" = devenv ; then
173 echo "Container $ARVBOX_CONTAINER is already running"
178 if test $need_setup = 1 ; then
179 if docker ps -a | grep -E "$ARVBOX_CONTAINER$" -q ; then
180 echo "Container $ARVBOX_CONTAINER already exists but is not running; use restart or reboot"
187 if test $(echo $TAG | cut -c1-1) != '-' ; then
191 if [[ $TAG = '-' ]] ; then
198 if [[ "$CONFIG" =~ ^public ]] ; then
199 if test -n "$ARVBOX_PUBLISH_IP" ; then
200 localip=$ARVBOX_PUBLISH_IP
202 defaultdev=$(/sbin/ip route|awk '/default/ { print $5 }')
203 localip=$(ip addr show $defaultdev | grep 'inet ' | sed 's/ *inet \(.*\)\/.*/\1/')
205 echo "Public arvbox will use address $localip"
207 echo $localip > $iptemp
209 PUBLIC="--volume=$iptemp:/var/run/localip_override
217 --publish=25101:25101
221 --publish=45000-45020:45000-45020"
226 if [[ "$CONFIG" =~ demo$ ]] ; then
227 if test -d "$ARVBOX_DATA" ; then
228 echo "It looks like you already have a development container named $ARVBOX_CONTAINER."
229 echo "Set environment variable ARVBOX_CONTAINER to set a different name for your demo container"
233 if ! (docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q) ; then
234 docker create -v /var/lib/postgresql -v $ARVADOS_CONTAINER_PATH --name $ARVBOX_CONTAINER-data arvados/arvbox-demo /bin/true
239 --name=$ARVBOX_CONTAINER \
241 --volumes-from $ARVBOX_CONTAINER-data \
242 --label "org.arvados.arvbox_config=$CONFIG" \
244 arvados/arvbox-demo$TAG
248 mkdir -p "$PG_DATA" "$VAR_DATA" "$PASSENGER" "$GEMS" "$PIPCACHE" "$NPMCACHE" "$GOSTUFF" "$RLIBS"
250 if ! test -d "$ARVADOS_ROOT" ; then
251 git clone https://git.arvados.org/arvados.git "$ARVADOS_ROOT"
252 git -C "$ARVADOS_ROOT" checkout $ARVADOS_BRANCH
254 if ! test -d "$COMPOSER_ROOT" ; then
255 git clone https://github.com/arvados/composer.git "$COMPOSER_ROOT"
256 git -C "$COMPOSER_ROOT" checkout arvados-fork
258 if ! test -d "$WORKBENCH2_ROOT" ; then
259 git clone https://git.arvados.org/arvados-workbench2.git "$WORKBENCH2_ROOT"
260 git -C "$ARVADOS_ROOT" checkout $WORKBENCH2_BRANCH
263 if [[ "$CONFIG" = test ]] ; then
265 mkdir -p $VAR_DATA/test
267 if test "$need_setup" = 1 ; then
270 --name=$ARVBOX_CONTAINER \
272 "--env=SVDIR=/etc/test-service" \
273 arvados/arvbox-dev$TAG
277 /usr/local/lib/arvbox/runsu.sh \
278 /usr/local/lib/arvbox/waitforpostgres.sh
282 if [[ -z "$@" ]] ; then
283 interactive=--interactive
287 -e LINES=$(tput lines) \
288 -e COLUMNS=$(tput cols) \
290 -e WORKSPACE=/usr/src/arvados \
291 -e GEM_HOME=$GEM_HOME \
292 -e CONFIGSRC=$ARVADOS_CONTAINER_PATH/run_tests \
294 /usr/local/lib/arvbox/runsu.sh \
295 /usr/src/arvados/build/run-tests.sh \
296 --temp $ARVADOS_CONTAINER_PATH/test \
299 elif [[ "$CONFIG" = devenv ]] ; then
300 if [[ $need_setup = 1 ]] ; then
303 --name=${ARVBOX_CONTAINER} \
304 "--env=SVDIR=/etc/devenv-service" \
305 "--volume=$HOME:$HOME:rw" \
306 --volume=/tmp/.X11-unix:/tmp/.X11-unix:rw \
307 arvados/arvbox-dev$TAG
309 exec docker exec --interactive --tty \
310 -e LINES=$(tput lines) \
311 -e COLUMNS=$(tput cols) \
313 -e "ARVBOX_HOME=$HOME" \
314 -e "DISPLAY=$DISPLAY" \
316 ${ARVBOX_CONTAINER} \
317 /usr/local/lib/arvbox/devenv.sh "$@"
318 elif [[ "$CONFIG" =~ dev$ ]] ; then
321 --name=$ARVBOX_CONTAINER \
324 arvados/arvbox-dev$TAG
327 echo "The Arvados source code is checked out at: $ARVADOS_ROOT"
328 echo "The Arvados testing root certificate is $VAR_DATA/root-cert.pem"
329 if [[ "$(listusers)" =~ ^\{\} ]] ; then
330 echo "No users defined, use 'arvbox adduser' to add user logins"
332 echo "Use 'arvbox listusers' to see user logins"
335 echo "Unknown configuration '$CONFIG'"
346 if test $(echo $TAG | cut -c1-1) != '-' ; then
354 if echo "$CONFIG" | grep 'demo$' ; then
355 docker pull arvados/arvbox-demo$TAG
357 docker pull arvados/arvbox-dev$TAG
362 if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
363 docker stop $ARVBOX_CONTAINER
366 VOLUMES=--volumes=true
367 if docker ps -a --filter "status=created" | grep -E "$ARVBOX_CONTAINER$" -q ; then
368 docker rm $VOLUMES $ARVBOX_CONTAINER
370 if docker ps -a --filter "status=exited" | grep -E "$ARVBOX_CONTAINER$" -q ; then
371 docker rm $VOLUMES $ARVBOX_CONTAINER
376 export DOCKER_BUILDKIT=1
377 if ! test -f "$ARVBOX_DOCKER/Dockerfile.base" ; then
378 echo "Could not find Dockerfile (expected it at $ARVBOX_DOCKER/Dockerfile.base)"
381 if docker --version |grep " 1\.[0-9]\." ; then
382 # Docker version prior 1.10 require -f flag
383 # -f flag removed in Docker 1.12
386 GITHEAD=$(cd $ARVBOX_DOCKER && git log --format=%H -n1 HEAD)
389 if which greadlink >/dev/null 2>/dev/null ; then
390 LOCAL_ARVADOS_ROOT=$(greadlink -f $(dirname $0)/../../../)
392 LOCAL_ARVADOS_ROOT=$(readlink -f $(dirname $0)/../../../)
396 if test "$1" = localdemo -o "$1" = publicdemo ; then
402 if test "$ARVADOS_BRANCH" = "main" ; then
403 ARVADOS_BRANCH=$GITHEAD
406 docker build --build-arg=BUILDTYPE=$BUILDTYPE $NO_CACHE \
407 --build-arg=arvados_version=$ARVADOS_BRANCH \
408 --build-arg=workbench2_version=$WORKBENCH2_BRANCH \
409 --build-arg=workdir=/tools/arvbox/lib/arvbox/docker \
410 -t arvados/arvbox-base:$GITHEAD \
411 -f "$ARVBOX_DOCKER/Dockerfile.base" \
412 "$LOCAL_ARVADOS_ROOT"
413 docker tag $FORCE arvados/arvbox-base:$GITHEAD arvados/arvbox-base:latest
414 docker build $NO_CACHE \
415 --build-arg=arvados_version=$ARVADOS_BRANCH \
416 --build-arg=workbench2_version=$WORKBENCH2_BRANCH \
417 -t arvados/arvbox-$BUILDTYPE:$GITHEAD \
418 -f "$ARVBOX_DOCKER/Dockerfile.$BUILDTYPE" \
420 docker tag $FORCE arvados/arvbox-$BUILDTYPE:$GITHEAD arvados/arvbox-$BUILDTYPE:latest
425 localdemo|publicdemo|dev|publicdev|test|devenv)
429 echo "Argument to $subcmd must be one of localdemo, publicdemo, dev, publicdev, test, devenv"
436 if test -n "$subcmd" ; then
447 NO_CACHE=--no-cache build $@
456 exec docker exec --interactive --tty \
457 -e LINES=$(tput lines) \
458 -e COLUMNS=$(tput cols) \
460 -e GEM_HOME=$GEM_HOME \
461 $ARVBOX_CONTAINER /bin/bash
465 exec docker exec --interactive --tty \
466 -e LINES=$(tput lines) \
467 -e COLUMNS=$(tput cols) \
469 -e GEM_HOME=$GEM_HOME \
471 -w /usr/src/arvados \
472 $ARVBOX_CONTAINER /bin/bash --login
476 exec docker exec -i $ARVBOX_CONTAINER /usr/bin/env GEM_HOME=$GEM_HOME /bin/bash -
512 exec xdg-open http://$(gethost)
516 echo "Container: $ARVBOX_CONTAINER"
517 if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
518 echo "Cluster id: $(getclusterid)"
519 echo "Status: running"
520 echo "Container IP: $(getip)"
521 echo "Published host: $(gethost)"
523 echo "Status: not running"
525 if test -d "$ARVBOX_DATA" ; then
526 echo "Data: $ARVBOX_DATA"
527 elif docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q ; then
528 echo "Data: $ARVBOX_CONTAINER-data"
536 if test -d "$ARVBOX_DATA" ; then
537 if test "$subcmd" = destroy ; then
538 if test "$1" != -f ; then
539 echo "WARNING! This will delete your entire arvbox ($ARVBOX_DATA)."
540 echo "Use destroy -f if you really mean it."
544 chmod -R u+w "$ARVBOX_DATA"
545 rm -rf "$ARVBOX_DATA"
547 if test "$1" != -f ; then
548 echo "WARNING! This will delete your arvbox data ($ARVBOX_DATA)."
549 echo "Code and downloaded packages will be preserved."
550 echo "Use reset -f if you really mean it."
554 rm -rf "$ARVBOX_DATA/postgres"
555 rm -rf "$ARVBOX_DATA/var"
558 if test "$1" != -f ; then
559 echo "WARNING! This will delete your data container $ARVBOX_CONTAINER-data. Use -f if you really mean it."
563 docker rm "$ARVBOX_CONTAINER-data"
568 if test -n "$1" ; then
569 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"
571 exec docker exec -ti $ARVBOX_CONTAINER tail $(docker exec -ti $ARVBOX_CONTAINER find -L /etc -path '/etc/service/*/log/main/current' -printf " %p")
576 if test -n "$1" ; then
577 exec docker exec $ARVBOX_CONTAINER cat "$@"
579 echo "Usage: $0 $subcmd <files>"
584 exec docker exec -ti $ARVBOX_CONTAINER /usr/bin/env TERM=$TERM ls "$@"
588 if test -n "$1" -a -n "$2" ; then
589 exec docker exec $ARVBOX_CONTAINER sv "$@"
591 echo "Usage: $0 $subcmd <start|stop|restart> <service>"
592 echo "Available services:"
593 exec docker exec $ARVBOX_CONTAINER ls /etc/service
598 if test -n "$2" ; then
599 mkdir -p "$ARVBOX_BASE/$2"
600 cp -a "$ARVBOX_BASE/$1/passenger" \
601 "$ARVBOX_BASE/$1/gems" \
602 "$ARVBOX_BASE/$1/pip" \
603 "$ARVBOX_BASE/$1/npm" \
604 "$ARVBOX_BASE/$1/gopath" \
605 "$ARVBOX_BASE/$1/Rlibs" \
606 "$ARVBOX_BASE/$1/arvados" \
607 "$ARVBOX_BASE/$1/composer" \
608 "$ARVBOX_BASE/$1/workbench2" \
610 echo "Created new arvbox $2"
611 echo "export ARVBOX_CONTAINER=$2"
613 echo "clone <from> <to> clone an arvbox"
614 echo "available arvboxes: $(ls $ARVBOX_BASE)"
619 CERT=$PWD/${ARVBOX_CONTAINER}-root-cert.crt
620 if test -n "$1" ; then
623 docker exec $ARVBOX_CONTAINER cat $ARVADOS_CONTAINER_PATH/root-cert.pem > "$CERT"
624 echo "Certificate copied to $CERT"
628 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'
632 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'
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 --quiet --file=$ARVADOS_CONTAINER_PATH/checkpoint.sql'
640 exec docker exec -i $ARVBOX_CONTAINER /usr/bin/env GEM_HOME=$GEM_HOME /bin/bash - <<EOF
647 cd /usr/src/arvados/services/api
648 export DISABLE_DATABASE_ENVIRONMENT_CHECK=1
649 export RAILS_ENV=development
650 flock $GEM_HOME/gems.lock bin/bundle exec rake db:drop
651 rm $ARVADOS_CONTAINER_PATH/api_database_setup
652 rm $ARVADOS_CONTAINER_PATH/superuser_token
656 sv restart keepstore0
657 sv restart keepstore1
663 if [[ -n "$2" ]] ; then
664 docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py $ARVADOS_CONTAINER_PATH/cluster_config.yml.override $(getclusterid) add $@
665 docker exec $ARVBOX_CONTAINER sv restart controller
667 echo "Usage: adduser <username> <email> [password]"
672 if [[ -n "$1" ]] ; then
673 docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py $ARVADOS_CONTAINER_PATH/cluster_config.yml.override $(getclusterid) remove $@
674 docker exec $ARVBOX_CONTAINER sv restart controller
676 echo "Usage: removeuser <username>"
685 echo "Arvados-in-a-box https://doc.arvados.org/install/arvbox.html"
687 echo "start|run <config> [tag] start $ARVBOX_CONTAINER container"
688 echo "stop stop arvbox container"
689 echo "restart <config> stop, then run again"
690 echo "status print some information about current arvbox"
691 echo "ip print arvbox docker container ip address"
692 echo "host print arvbox published host"
693 echo "shell enter shell as root"
694 echo "ashell enter shell as 'arvbox'"
695 echo "psql enter postgres console"
696 echo "open open arvbox workbench in a web browser"
697 echo "root-cert get copy of root certificate"
698 echo "update <config> stop, pull latest image, run"
699 echo "build <config> build arvbox Docker image"
700 echo "reboot <config> stop, build arvbox Docker image, run"
701 echo "rebuild <config> build arvbox Docker image, no layer cache"
702 echo "checkpoint create database backup"
703 echo "restore restore checkpoint"
704 echo "hotreset reset database and restart API without restarting container"
705 echo "reset delete arvbox arvados data (be careful!)"
706 echo "destroy delete all arvbox code and data (be careful!)"
707 echo "log <service> tail log of specified service"
708 echo "ls <options> list directories inside arvbox"
709 echo "cat <files> get contents of files inside arvbox"
710 echo "pipe run a bash script piped in from stdin"
711 echo "sv <start|stop|restart> <service> "
712 echo " change state of service inside arvbox"
713 echo "clone <from> <to> clone dev arvbox"
714 echo "adduser <username> <email> [password]"
715 echo " add a user login"
716 echo "removeuser <username>"
717 echo " remove user login"
718 echo "listusers list user logins"