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
253 git -C "$ARVADOS_ROOT" pull
255 if ! test -d "$COMPOSER_ROOT" ; then
256 git clone https://github.com/arvados/composer.git "$COMPOSER_ROOT"
257 git -C "$COMPOSER_ROOT" checkout arvados-fork
258 git -C "$COMPOSER_ROOT" pull
260 if ! test -d "$WORKBENCH2_ROOT" ; then
261 git clone https://git.arvados.org/arvados-workbench2.git "$WORKBENCH2_ROOT"
262 git -C "$ARVADOS_ROOT" checkout $WORKBENCH2_BRANCH
263 git -C "$ARVADOS_ROOT" pull
266 if [[ "$CONFIG" = test ]] ; then
268 mkdir -p $VAR_DATA/test
270 if test "$need_setup" = 1 ; then
273 --name=$ARVBOX_CONTAINER \
275 "--env=SVDIR=/etc/test-service" \
276 arvados/arvbox-dev$TAG
280 /usr/local/lib/arvbox/runsu.sh \
281 /usr/local/lib/arvbox/waitforpostgres.sh
285 if [[ -z "$@" ]] ; then
286 interactive=--interactive
290 -e LINES=$(tput lines) \
291 -e COLUMNS=$(tput cols) \
293 -e WORKSPACE=/usr/src/arvados \
294 -e GEM_HOME=$GEM_HOME \
295 -e CONFIGSRC=$ARVADOS_CONTAINER_PATH/run_tests \
297 /usr/local/lib/arvbox/runsu.sh \
298 /usr/src/arvados/build/run-tests.sh \
299 --temp $ARVADOS_CONTAINER_PATH/test \
302 elif [[ "$CONFIG" = devenv ]] ; then
303 if [[ $need_setup = 1 ]] ; then
306 --name=${ARVBOX_CONTAINER} \
307 "--env=SVDIR=/etc/devenv-service" \
308 "--volume=$HOME:$HOME:rw" \
309 --volume=/tmp/.X11-unix:/tmp/.X11-unix:rw \
310 arvados/arvbox-dev$TAG
312 exec docker exec --interactive --tty \
313 -e LINES=$(tput lines) \
314 -e COLUMNS=$(tput cols) \
316 -e "ARVBOX_HOME=$HOME" \
317 -e "DISPLAY=$DISPLAY" \
319 ${ARVBOX_CONTAINER} \
320 /usr/local/lib/arvbox/devenv.sh "$@"
321 elif [[ "$CONFIG" =~ dev$ ]] ; then
324 --name=$ARVBOX_CONTAINER \
327 arvados/arvbox-dev$TAG
330 echo "The Arvados source code is checked out at: $ARVADOS_ROOT"
331 echo "The Arvados testing root certificate is $VAR_DATA/root-cert.pem"
332 if [[ "$(listusers)" =~ ^\{\} ]] ; then
333 echo "No users defined, use 'arvbox adduser' to add user logins"
335 echo "Use 'arvbox listusers' to see user logins"
338 echo "Unknown configuration '$CONFIG'"
349 if test $(echo $TAG | cut -c1-1) != '-' ; then
357 if echo "$CONFIG" | grep 'demo$' ; then
358 docker pull arvados/arvbox-demo$TAG
360 docker pull arvados/arvbox-dev$TAG
365 if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
366 docker stop $ARVBOX_CONTAINER
369 VOLUMES=--volumes=true
370 if docker ps -a --filter "status=created" | grep -E "$ARVBOX_CONTAINER$" -q ; then
371 docker rm $VOLUMES $ARVBOX_CONTAINER
373 if docker ps -a --filter "status=exited" | grep -E "$ARVBOX_CONTAINER$" -q ; then
374 docker rm $VOLUMES $ARVBOX_CONTAINER
379 export DOCKER_BUILDKIT=1
380 if ! test -f "$ARVBOX_DOCKER/Dockerfile.base" ; then
381 echo "Could not find Dockerfile (expected it at $ARVBOX_DOCKER/Dockerfile.base)"
384 if docker --version |grep " 1\.[0-9]\." ; then
385 # Docker version prior 1.10 require -f flag
386 # -f flag removed in Docker 1.12
389 GITHEAD=$(cd $ARVBOX_DOCKER && git log --format=%H -n1 HEAD)
392 if which greadlink >/dev/null 2>/dev/null ; then
393 LOCAL_ARVADOS_ROOT=$(greadlink -f $(dirname $0)/../../../)
395 LOCAL_ARVADOS_ROOT=$(readlink -f $(dirname $0)/../../../)
399 if test "$1" = localdemo -o "$1" = publicdemo ; then
405 if test "$ARVADOS_BRANCH" = "main" ; then
406 ARVADOS_BRANCH=$GITHEAD
409 docker build --build-arg=BUILDTYPE=$BUILDTYPE $NO_CACHE \
410 --build-arg=arvados_version=$ARVADOS_BRANCH \
411 --build-arg=workbench2_version=$WORKBENCH2_BRANCH \
412 --build-arg=workdir=/tools/arvbox/lib/arvbox/docker \
413 -t arvados/arvbox-base:$GITHEAD \
414 -f "$ARVBOX_DOCKER/Dockerfile.base" \
415 "$LOCAL_ARVADOS_ROOT"
416 docker tag $FORCE arvados/arvbox-base:$GITHEAD arvados/arvbox-base:latest
417 docker build $NO_CACHE \
418 --build-arg=arvados_version=$ARVADOS_BRANCH \
419 --build-arg=workbench2_version=$WORKBENCH2_BRANCH \
420 -t arvados/arvbox-$BUILDTYPE:$GITHEAD \
421 -f "$ARVBOX_DOCKER/Dockerfile.$BUILDTYPE" \
423 docker tag $FORCE arvados/arvbox-$BUILDTYPE:$GITHEAD arvados/arvbox-$BUILDTYPE:latest
428 localdemo|publicdemo|dev|publicdev|test|devenv)
432 echo "Argument to $subcmd must be one of localdemo, publicdemo, dev, publicdev, test, devenv"
439 if test -n "$subcmd" ; then
450 NO_CACHE=--no-cache build $@
459 exec docker exec --interactive --tty \
460 -e LINES=$(tput lines) \
461 -e COLUMNS=$(tput cols) \
463 -e GEM_HOME=$GEM_HOME \
464 $ARVBOX_CONTAINER /bin/bash
468 exec docker exec --interactive --tty \
469 -e LINES=$(tput lines) \
470 -e COLUMNS=$(tput cols) \
472 -e GEM_HOME=$GEM_HOME \
474 -w /usr/src/arvados \
475 $ARVBOX_CONTAINER /bin/bash --login
479 exec docker exec -i $ARVBOX_CONTAINER /usr/bin/env GEM_HOME=$GEM_HOME /bin/bash -
515 exec xdg-open http://$(gethost)
519 echo "Container: $ARVBOX_CONTAINER"
520 if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
521 echo "Cluster id: $(getclusterid)"
522 echo "Status: running"
523 echo "Container IP: $(getip)"
524 echo "Published host: $(gethost)"
526 echo "Status: not running"
528 if test -d "$ARVBOX_DATA" ; then
529 echo "Data: $ARVBOX_DATA"
530 elif docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q ; then
531 echo "Data: $ARVBOX_CONTAINER-data"
539 if test -d "$ARVBOX_DATA" ; then
540 if test "$subcmd" = destroy ; then
541 if test "$1" != -f ; then
542 echo "WARNING! This will delete your entire arvbox ($ARVBOX_DATA)."
543 echo "Use destroy -f if you really mean it."
547 chmod -R u+w "$ARVBOX_DATA"
548 rm -rf "$ARVBOX_DATA"
550 if test "$1" != -f ; then
551 echo "WARNING! This will delete your arvbox data ($ARVBOX_DATA)."
552 echo "Code and downloaded packages will be preserved."
553 echo "Use reset -f if you really mean it."
557 rm -rf "$ARVBOX_DATA/postgres"
558 rm -rf "$ARVBOX_DATA/var"
561 if test "$1" != -f ; then
562 echo "WARNING! This will delete your data container $ARVBOX_CONTAINER-data. Use -f if you really mean it."
566 docker rm "$ARVBOX_CONTAINER-data"
571 if test -n "$1" ; then
572 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"
574 exec docker exec -ti $ARVBOX_CONTAINER tail $(docker exec -ti $ARVBOX_CONTAINER find -L /etc -path '/etc/service/*/log/main/current' -printf " %p")
579 if test -n "$1" ; then
580 exec docker exec $ARVBOX_CONTAINER cat "$@"
582 echo "Usage: $0 $subcmd <files>"
587 exec docker exec -ti $ARVBOX_CONTAINER /usr/bin/env TERM=$TERM ls "$@"
591 if test -n "$1" -a -n "$2" ; then
592 exec docker exec $ARVBOX_CONTAINER sv "$@"
594 echo "Usage: $0 $subcmd <start|stop|restart> <service>"
595 echo "Available services:"
596 exec docker exec $ARVBOX_CONTAINER ls /etc/service
601 if test -n "$2" ; then
602 mkdir -p "$ARVBOX_BASE/$2"
603 cp -a "$ARVBOX_BASE/$1/passenger" \
604 "$ARVBOX_BASE/$1/gems" \
605 "$ARVBOX_BASE/$1/pip" \
606 "$ARVBOX_BASE/$1/npm" \
607 "$ARVBOX_BASE/$1/gopath" \
608 "$ARVBOX_BASE/$1/Rlibs" \
609 "$ARVBOX_BASE/$1/arvados" \
610 "$ARVBOX_BASE/$1/composer" \
611 "$ARVBOX_BASE/$1/workbench2" \
613 echo "Created new arvbox $2"
614 echo "export ARVBOX_CONTAINER=$2"
616 echo "clone <from> <to> clone an arvbox"
617 echo "available arvboxes: $(ls $ARVBOX_BASE)"
622 CERT=$PWD/${ARVBOX_CONTAINER}-root-cert.crt
623 if test -n "$1" ; then
626 docker exec $ARVBOX_CONTAINER cat $ARVADOS_CONTAINER_PATH/root-cert.pem > "$CERT"
627 echo "Certificate copied to $CERT"
631 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'
635 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'
639 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'
643 exec docker exec -i $ARVBOX_CONTAINER /usr/bin/env GEM_HOME=$GEM_HOME /bin/bash - <<EOF
650 cd /usr/src/arvados/services/api
651 export DISABLE_DATABASE_ENVIRONMENT_CHECK=1
652 export RAILS_ENV=development
653 flock $GEM_HOME/gems.lock bin/bundle exec rake db:drop
654 rm $ARVADOS_CONTAINER_PATH/api_database_setup
655 rm $ARVADOS_CONTAINER_PATH/superuser_token
659 sv restart keepstore0
660 sv restart keepstore1
666 if [[ -n "$2" ]] ; then
667 docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py $ARVADOS_CONTAINER_PATH/cluster_config.yml.override $(getclusterid) add $@
668 docker exec $ARVBOX_CONTAINER sv restart controller
670 echo "Usage: adduser <username> <email> [password]"
675 if [[ -n "$1" ]] ; then
676 docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py $ARVADOS_CONTAINER_PATH/cluster_config.yml.override $(getclusterid) remove $@
677 docker exec $ARVBOX_CONTAINER sv restart controller
679 echo "Usage: removeuser <username>"
688 echo "Arvados-in-a-box https://doc.arvados.org/install/arvbox.html"
690 echo "start|run <config> [tag] start $ARVBOX_CONTAINER container"
691 echo "stop stop arvbox container"
692 echo "restart <config> stop, then run again"
693 echo "status print some information about current arvbox"
694 echo "ip print arvbox docker container ip address"
695 echo "host print arvbox published host"
696 echo "shell enter shell as root"
697 echo "ashell enter shell as 'arvbox'"
698 echo "psql enter postgres console"
699 echo "open open arvbox workbench in a web browser"
700 echo "root-cert get copy of root certificate"
701 echo "update <config> stop, pull latest image, run"
702 echo "build <config> build arvbox Docker image"
703 echo "reboot <config> stop, build arvbox Docker image, run"
704 echo "rebuild <config> build arvbox Docker image, no layer cache"
705 echo "checkpoint create database backup"
706 echo "restore restore checkpoint"
707 echo "hotreset reset database and restart API without restarting container"
708 echo "reset delete arvbox arvados data (be careful!)"
709 echo "destroy delete all arvbox code and data (be careful!)"
710 echo "log <service> tail log of specified service"
711 echo "ls <options> list directories inside arvbox"
712 echo "cat <files> get contents of files inside arvbox"
713 echo "pipe run a bash script piped in from stdin"
714 echo "sv <start|stop|restart> <service> "
715 echo " change state of service inside arvbox"
716 echo "clone <from> <to> clone dev arvbox"
717 echo "adduser <username> <email> [password]"
718 echo " add a user login"
719 echo "removeuser <username>"
720 echo " remove user login"
721 echo "listusers list user logins"