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 "$ARVADOS_BRANCH" ; then
51 # Update this to the docker tag for the version on releases.
54 PG_DATA="$ARVBOX_DATA/postgres"
55 VAR_DATA="$ARVBOX_DATA/var"
56 PASSENGER="$ARVBOX_DATA/passenger"
57 GEMS="$ARVBOX_DATA/gems"
58 PIPCACHE="$ARVBOX_DATA/pip"
59 NPMCACHE="$ARVBOX_DATA/npm"
60 GOSTUFF="$ARVBOX_DATA/gopath"
61 RLIBS="$ARVBOX_DATA/Rlibs"
62 ARVADOS_CONTAINER_PATH="/var/lib/arvados-arvbox"
65 docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $ARVBOX_CONTAINER
70 OVERRIDE=$(docker exec -i $ARVBOX_CONTAINER cat /var/run/localip_override 2>/dev/null)
73 if test "$CODE" = 0 ; then
81 docker exec $ARVBOX_CONTAINER cat $ARVADOS_CONTAINER_PATH/api_uuid_prefix
85 if test -f ~/.config/arvados/$ARVBOX_CONTAINER.conf ; then
86 sed "s/ARVADOS_API_HOST=.*/ARVADOS_API_HOST=$(gethost):8000/" <$HOME/.config/arvados/$ARVBOX_CONTAINER.conf >$HOME/.config/arvados/$ARVBOX_CONTAINER.conf.tmp
87 mv ~/.config/arvados/$ARVBOX_CONTAINER.conf.tmp ~/.config/arvados/$ARVBOX_CONTAINER.conf
89 mkdir -p $HOME/.config/arvados
90 cat >$HOME/.config/arvados/$ARVBOX_CONTAINER.conf <<EOF
91 ARVADOS_API_HOST=$(gethost):8000
93 ARVADOS_API_HOST_INSECURE=true
99 docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py $ARVADOS_CONTAINER_PATH/cluster_config.yml $(getclusterid) list
103 FF=/tmp/arvbox-fifo-$$
105 docker logs -f $ARVBOX_CONTAINER > $FF &
108 if [[ $line =~ "ok: down: ready:" ]] ; then
111 wait $LOGPID 2>/dev/null
119 if test -n "$localip" ; then
120 echo "export ARVADOS_API_HOST=$localip:8000"
122 echo "export ARVADOS_API_HOST=$(gethost):8000"
128 "--volume=$ARVADOS_ROOT:/usr/src/arvados:rw" \
129 "--volume=$PG_DATA:/var/lib/postgresql:rw" \
130 "--volume=$VAR_DATA:$ARVADOS_CONTAINER_PATH:rw" \
131 "--volume=$PASSENGER:/var/lib/passenger:rw" \
132 "--volume=$GEMS:/var/lib/arvados-arvbox/.gem:rw" \
133 "--volume=$PIPCACHE:/var/lib/pip:rw" \
134 "--volume=$NPMCACHE:/var/lib/npm:rw" \
135 "--volume=$GOSTUFF:/var/lib/gopath:rw" \
136 "--volume=$RLIBS:/var/lib/Rlibs:rw" \
137 --label "org.arvados.arvbox_config=$CONFIG" \
142 docker inspect $ARVBOX_CONTAINER -f '{{index .Config.Labels "org.arvados.arvbox_config"}}'
153 if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
154 if [[ $(running_config) != "$CONFIG" ]] ; then
155 echo "Container $ARVBOX_CONTAINER is '$(running_config)' config but requested '$CONFIG'; use restart or reboot"
158 if test "$CONFIG" = test -o "$CONFIG" = devenv ; then
161 echo "Container $ARVBOX_CONTAINER is already running"
166 if test $need_setup = 1 ; then
167 if docker ps -a | grep -E "$ARVBOX_CONTAINER$" -q ; then
168 echo "Container $ARVBOX_CONTAINER already exists but is not running; use restart or reboot"
175 if test $(echo $TAG | cut -c1-1) != '-' ; then
179 if [[ $TAG = '-' ]] ; then
186 if test -z "$TAG" -a -n "$DEFAULT_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
209 --publish=25101:25101
213 --publish=45000-45020:45000-45020"
218 if [[ "$CONFIG" =~ demo$ ]] ; then
219 if test -d "$ARVBOX_DATA" ; then
220 echo "It looks like you already have a development container named $ARVBOX_CONTAINER."
221 echo "Set environment variable ARVBOX_CONTAINER to set a different name for your demo container"
225 if ! (docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q) ; then
226 docker create -v /var/lib/postgresql -v $ARVADOS_CONTAINER_PATH --name $ARVBOX_CONTAINER-data arvados/arvbox-demo$TAG /bin/true
231 --name=$ARVBOX_CONTAINER \
233 --volumes-from $ARVBOX_CONTAINER-data \
234 --label "org.arvados.arvbox_config=$CONFIG" \
236 arvados/arvbox-demo$TAG
240 mkdir -p "$PG_DATA" "$VAR_DATA" "$PASSENGER" "$GEMS" "$PIPCACHE" "$NPMCACHE" "$GOSTUFF" "$RLIBS"
242 if ! test -d "$ARVADOS_ROOT" ; then
243 git clone https://git.arvados.org/arvados.git "$ARVADOS_ROOT"
244 git -C "$ARVADOS_ROOT" checkout $ARVADOS_BRANCH
247 if [[ "$CONFIG" = test ]] ; then
249 mkdir -p $VAR_DATA/test
251 if test "$need_setup" = 1 ; then
254 --name=$ARVBOX_CONTAINER \
256 "--env=SVDIR=/etc/test-service" \
257 arvados/arvbox-dev$TAG
261 /usr/local/lib/arvbox/runsu.sh \
262 /usr/local/lib/arvbox/waitforpostgres.sh
266 if [[ -z "$@" ]] ; then
267 interactive=--interactive
271 -e LINES=$(tput lines) \
272 -e COLUMNS=$(tput cols) \
274 -e WORKSPACE=/usr/src/arvados \
275 -e CONFIGSRC=$ARVADOS_CONTAINER_PATH/run_tests \
277 /usr/local/lib/arvbox/runsu.sh \
278 /usr/src/arvados/build/run-tests.sh \
279 --temp $ARVADOS_CONTAINER_PATH/test \
282 elif [[ "$CONFIG" = devenv ]] ; then
283 if [[ $need_setup = 1 ]] ; then
286 --name=${ARVBOX_CONTAINER} \
287 "--env=SVDIR=/etc/devenv-service" \
288 "--volume=$HOME:$HOME:rw" \
289 --volume=/tmp/.X11-unix:/tmp/.X11-unix:rw \
290 arvados/arvbox-dev$TAG
292 exec docker exec --interactive --tty \
293 -e LINES=$(tput lines) \
294 -e COLUMNS=$(tput cols) \
296 -e "ARVBOX_HOME=$HOME" \
297 -e "DISPLAY=$DISPLAY" \
299 ${ARVBOX_CONTAINER} \
300 /usr/local/lib/arvbox/devenv.sh "$@"
301 elif [[ "$CONFIG" =~ dev$ ]] ; then
304 --name=$ARVBOX_CONTAINER \
307 arvados/arvbox-dev$TAG
310 echo "The Arvados source code is checked out at: $ARVADOS_ROOT"
311 echo "The Arvados testing root certificate is $VAR_DATA/root-cert.pem"
312 if [[ "$(listusers)" =~ ^\{\} ]] ; then
313 echo "No users defined, use 'arvbox adduser' to add user logins"
315 echo "Use 'arvbox listusers' to see user logins"
318 echo "Unknown configuration '$CONFIG'"
329 if test $(echo $TAG | cut -c1-1) != '-' ; then
337 if echo "$CONFIG" | grep 'demo$' ; then
338 docker pull arvados/arvbox-demo$TAG
340 docker pull arvados/arvbox-dev$TAG
345 if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
346 docker stop $ARVBOX_CONTAINER
349 VOLUMES=--volumes=true
350 if docker ps -a --filter "status=created" | grep -E "$ARVBOX_CONTAINER$" -q ; then
351 docker rm $VOLUMES $ARVBOX_CONTAINER
353 if docker ps -a --filter "status=exited" | grep -E "$ARVBOX_CONTAINER$" -q ; then
354 docker rm $VOLUMES $ARVBOX_CONTAINER
359 export DOCKER_BUILDKIT=1
360 if ! test -f "$ARVBOX_DOCKER/Dockerfile.base" ; then
361 echo "Could not find Dockerfile (expected it at $ARVBOX_DOCKER/Dockerfile.base)"
364 if docker --version |grep " 1\.[0-9]\." ; then
365 # Docker version prior 1.10 require -f flag
366 # -f flag removed in Docker 1.12
369 GITHEAD=$(cd $ARVBOX_DOCKER && git log --format=%H -n1 HEAD)
372 if which greadlink >/dev/null 2>/dev/null ; then
373 LOCAL_ARVADOS_ROOT=$(greadlink -f $(dirname $0)/../../../)
375 LOCAL_ARVADOS_ROOT=$(readlink -f $(dirname $0)/../../../)
379 # Get the go version we should use for bootstrapping
380 GO_VERSION=`grep 'const goversion =' $LOCAL_ARVADOS_ROOT/lib/install/deps.go |awk -F'"' '{print $2}'`
382 if test "$1" = localdemo -o "$1" = publicdemo ; then
388 if test "$ARVADOS_BRANCH" = "main" ; then
389 ARVADOS_BRANCH=$GITHEAD
392 docker build --build-arg=BUILDTYPE=$BUILDTYPE $NO_CACHE \
393 --build-arg=go_version=$GO_VERSION \
394 --build-arg=arvados_version=$ARVADOS_BRANCH \
395 --build-arg=workdir=/tools/arvbox/lib/arvbox/docker \
396 -t arvados/arvbox-base:$GITHEAD \
397 -f "$ARVBOX_DOCKER/Dockerfile.base" \
398 "$LOCAL_ARVADOS_ROOT"
399 docker tag $FORCE arvados/arvbox-base:$GITHEAD arvados/arvbox-base:latest
400 docker build $NO_CACHE \
401 --build-arg=go_version=$GO_VERSION \
402 --build-arg=arvados_version=$ARVADOS_BRANCH \
403 -t arvados/arvbox-$BUILDTYPE:$GITHEAD \
404 -f "$ARVBOX_DOCKER/Dockerfile.$BUILDTYPE" \
406 docker tag $FORCE arvados/arvbox-$BUILDTYPE:$GITHEAD arvados/arvbox-$BUILDTYPE:latest
411 localdemo|publicdemo|dev|publicdev|test|devenv)
415 echo "Argument to $subcmd must be one of localdemo, publicdemo, dev, publicdev, test, devenv"
420 user_watches=$(/usr/sbin/sysctl fs.inotify.max_user_watches)
421 [[ $user_watches =~ fs.inotify.max_user_watches\ =\ ([0-9]+) ]] && value=${BASH_REMATCH[1]}
422 if [[ "$value" -lt 256000 ]] ; then
423 echo "Not enough file system listeners ($value), to fix this run:"
424 echo "sudo sh -c 'echo fs.inotify.max_user_watches=524288 >> /etc/sysctl.d/local.conf && sysctl --system'"
430 if test -n "$subcmd" ; then
441 NO_CACHE=--no-cache build $@
450 exec docker exec --interactive --tty \
451 -e LINES=$(tput lines) \
452 -e COLUMNS=$(tput cols) \
454 $ARVBOX_CONTAINER /bin/bash
458 exec docker exec --interactive --tty \
459 -e LINES=$(tput lines) \
460 -e COLUMNS=$(tput cols) \
463 -w /usr/src/arvados \
464 $ARVBOX_CONTAINER /bin/bash --login
468 exec docker exec -i $ARVBOX_CONTAINER /usr/bin/env /bin/bash -
504 exec xdg-open http://$(gethost)
508 echo "Container: $ARVBOX_CONTAINER"
509 if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
510 echo "Cluster id: $(getclusterid)"
511 echo "Status: running"
512 echo "Container IP: $(getip)"
513 echo "Published host: $(gethost)"
514 echo "Workbench: https://$(gethost)"
516 echo "Status: not running"
518 if test -d "$ARVBOX_DATA" ; then
519 echo "Data: $ARVBOX_DATA"
520 elif docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q ; then
521 echo "Data: $ARVBOX_CONTAINER-data"
529 if test -d "$ARVBOX_DATA" ; then
530 if test "$subcmd" = destroy ; then
531 if test "$1" != -f ; then
532 echo "WARNING! This will delete your entire arvbox ($ARVBOX_DATA)."
533 echo "Use destroy -f if you really mean it."
537 chmod -R u+w "$ARVBOX_DATA"
538 rm -rf "$ARVBOX_DATA"
540 if test "$1" != -f ; then
541 echo "WARNING! This will delete your arvbox data ($ARVBOX_DATA)."
542 echo "Code and downloaded packages will be preserved."
543 echo "Use reset -f if you really mean it."
547 rm -rf "$ARVBOX_DATA/postgres"
548 rm -rf "$ARVBOX_DATA/var"
551 if test "$1" != -f ; then
552 echo "WARNING! This will delete your data container $ARVBOX_CONTAINER-data. Use -f if you really mean it."
556 docker rm "$ARVBOX_CONTAINER-data"
561 if test -n "$1" ; then
562 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"
564 exec docker exec -ti $ARVBOX_CONTAINER tail $(docker exec -ti $ARVBOX_CONTAINER find -L /etc -path '/etc/service/*/log/main/current' -printf " %p")
569 if test -n "$1" ; then
570 exec docker exec $ARVBOX_CONTAINER cat "$@"
572 echo "Usage: $0 $subcmd <files>"
577 exec docker exec -ti $ARVBOX_CONTAINER /usr/bin/env TERM=$TERM ls "$@"
581 if test -n "$1" -a -n "$2" ; then
582 exec docker exec $ARVBOX_CONTAINER sv "$@"
584 echo "Usage: $0 $subcmd <start|stop|restart> <service>"
585 echo "Available services:"
586 exec docker exec $ARVBOX_CONTAINER ls /etc/service
591 if test -n "$2" ; then
592 mkdir -p "$ARVBOX_BASE/$2"
593 cp -a "$ARVBOX_BASE/$1/passenger" \
594 "$ARVBOX_BASE/$1/gems" \
595 "$ARVBOX_BASE/$1/pip" \
596 "$ARVBOX_BASE/$1/npm" \
597 "$ARVBOX_BASE/$1/gopath" \
598 "$ARVBOX_BASE/$1/Rlibs" \
599 "$ARVBOX_BASE/$1/arvados" \
601 echo "Created new arvbox $2"
602 echo "export ARVBOX_CONTAINER=$2"
604 echo "clone <from> <to> clone an arvbox"
605 echo "available arvboxes: $(ls $ARVBOX_BASE)"
610 CERT=$PWD/${ARVBOX_CONTAINER}-root-cert.crt
611 if test -n "$1" ; then
614 docker exec $ARVBOX_CONTAINER cat $ARVADOS_CONTAINER_PATH/root-cert.pem > "$CERT"
615 echo "Certificate copied to $CERT"
619 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'
623 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'
627 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'
631 exec docker exec -i $ARVBOX_CONTAINER /usr/bin/env /bin/bash - <<EOF
638 cd /usr/src/arvados/services/api
639 export DISABLE_DATABASE_ENVIRONMENT_CHECK=1
640 export RAILS_ENV=development
641 export GEM_HOME=/var/lib/arvados-arvbox/.gem
643 bin/bundle exec rake db:drop
644 rm $ARVADOS_CONTAINER_PATH/api_database_setup
645 rm $ARVADOS_CONTAINER_PATH/superuser_token
649 sv restart keepstore0
650 sv restart keepstore1
656 if [[ -n "$2" ]] ; then
657 docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py $ARVADOS_CONTAINER_PATH/cluster_config.yml.override $(getclusterid) add $@
658 docker exec $ARVBOX_CONTAINER sv restart controller
660 echo "Usage: adduser <username> <email> [password]"
665 if [[ -n "$1" ]] ; then
666 docker exec -ti $ARVBOX_CONTAINER /usr/local/lib/arvbox/edit_users.py $ARVADOS_CONTAINER_PATH/cluster_config.yml.override $(getclusterid) remove $@
667 docker exec $ARVBOX_CONTAINER sv restart controller
669 echo "Usage: removeuser <username>"
678 echo "Arvados-in-a-box https://doc.arvados.org/install/arvbox.html"
680 echo "start|run <config> [tag] start $ARVBOX_CONTAINER container"
681 echo "stop stop arvbox container"
682 echo "restart <config> stop, then run again"
683 echo "status print some information about current arvbox"
684 echo "ip print arvbox docker container ip address"
685 echo "host print arvbox published host"
686 echo "shell enter shell as root"
687 echo "ashell enter shell as 'arvbox'"
688 echo "psql enter postgres console"
689 echo "open open arvbox workbench in a web browser"
690 echo "root-cert get copy of root certificate"
691 echo "update <config> stop, pull latest image, run"
692 echo "build <config> build arvbox Docker image"
693 echo "reboot <config> stop, build arvbox Docker image, run"
694 echo "rebuild <config> build arvbox Docker image, no layer cache"
695 echo "checkpoint create database backup"
696 echo "restore restore checkpoint"
697 echo "hotreset reset database and restart API without restarting container"
698 echo "reset delete arvbox arvados data (be careful!)"
699 echo "destroy delete all arvbox code and data (be careful!)"
700 echo "log <service> tail log of specified service"
701 echo "ls <options> list directories inside arvbox"
702 echo "cat <files> get contents of files inside arvbox"
703 echo "pipe run a bash script piped in from stdin"
704 echo "sv <start|stop|restart> <service> "
705 echo " change state of service inside arvbox"
706 echo "clone <from> <to> clone dev arvbox"
707 echo "adduser <username> <email> [password]"
708 echo " add a user login"
709 echo "removeuser <username>"
710 echo " remove user login"
711 echo "listusers list user logins"