10231: update crunchrun to pass Container.RuntimeConstraints.KeepCacheRAM as file...
[arvados.git] / tools / arvbox / bin / arvbox
1 #!/bin/sh
2
3 set -e
4
5 if ! test -d /sys/fs/cgroup ; then
6      echo "Arvbox requires cgroups to be mounted at /sys/fs/cgroup in order to use"
7      echo "Docker-in-Docker.  Older operating systems that put cgroups in other"
8      echo "places (such as /cgroup) are not supported."
9      exit 1
10 fi
11
12 if ! which docker >/dev/null 2>/dev/null ; then
13   echo "Arvbox requires Docker.  To install, run the following command as root:"
14   echo "curl -sSL https://get.docker.com/ | sh"
15   exit 1
16 fi
17
18 if test -z "$ARVBOX_DOCKER" ; then
19     if which greadlink >/dev/null 2>/dev/null ; then
20         ARVBOX_DOCKER=$(greadlink -f $(dirname $0)/../lib/arvbox/docker)
21     else
22         ARVBOX_DOCKER=$(readlink -f $(dirname $0)/../lib/arvbox/docker)
23     fi
24 fi
25
26 if test -z "$ARVBOX_CONTAINER" ; then
27     ARVBOX_CONTAINER=arvbox
28 fi
29
30 if test -z "$ARVBOX_BASE" ; then
31     ARVBOX_BASE="$HOME/.arvbox"
32 fi
33
34 if test -z "$ARVBOX_DATA" ; then
35     ARVBOX_DATA="$ARVBOX_BASE/$ARVBOX_CONTAINER"
36 fi
37
38 if test -z "$ARVADOS_ROOT" ; then
39     ARVADOS_ROOT="$ARVBOX_DATA/arvados"
40 fi
41
42 if test -z "$SSO_ROOT" ; then
43     SSO_ROOT="$ARVBOX_DATA/sso-devise-omniauth-provider"
44 fi
45
46 PG_DATA="$ARVBOX_DATA/postgres"
47 VAR_DATA="$ARVBOX_DATA/var"
48 PASSENGER="$ARVBOX_DATA/passenger"
49 GEMS="$ARVBOX_DATA/gems"
50 PIPCACHE="$ARVBOX_DATA/pip"
51 GOSTUFF="$ARVBOX_DATA/gopath"
52
53 getip() {
54     docker inspect $ARVBOX_CONTAINER | grep \"IPAddress\" | head -n1 | tr -d ' ":,\n' | cut -c10-
55 }
56
57 gethost() {
58     set +e
59     OVERRIDE=$(docker exec -i $ARVBOX_CONTAINER cat /var/run/localip_override 2>/dev/null)
60     CODE=$?
61     set -e
62     if test "$CODE" = 0 ; then
63        echo $OVERRIDE
64     else
65         getip
66     fi
67 }
68
69 updateconf() {
70     if test -f ~/.config/arvados/$ARVBOX_CONTAINER.conf ; then
71         sed "s/ARVADOS_API_HOST=.*/ARVADOS_API_HOST=$(gethost):8000/" <$HOME/.config/arvados/$ARVBOX_CONTAINER.conf >$HOME/.config/arvados/$ARVBOX_CONTAINER.conf.tmp
72         mv ~/.config/arvados/$ARVBOX_CONTAINER.conf.tmp ~/.config/arvados/$ARVBOX_CONTAINER.conf
73     else
74         mkdir -p $HOME/.config/arvados
75         cat >$HOME/.config/arvados/$ARVBOX_CONTAINER.conf <<EOF
76 ARVADOS_API_HOST=$(gethost):8000
77 ARVADOS_API_TOKEN=
78 ARVADOS_API_HOST_INSECURE=true
79 EOF
80     fi
81 }
82
83 wait_for_arvbox() {
84     FF=/tmp/arvbox-fifo-$$
85     mkfifo $FF
86     docker logs -f $ARVBOX_CONTAINER > $FF &
87     LOGPID=$!
88     while read line ; do
89         echo $line
90         if echo $line | grep "Workbench is running at" >/dev/null ; then
91             kill $LOGPID
92         fi
93     done < $FF
94     rm $FF
95     echo
96     if test -n "$localip" ; then
97         echo "export ARVADOS_API_HOST=$localip:8000"
98     else
99         echo "export ARVADOS_API_HOST=$(gethost):8000"
100     fi
101 }
102
103 run() {
104     CONFIG=$1
105     TAG=$2
106
107     shift
108
109     if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
110         echo "Container $ARVBOX_CONTAINER is already running"
111         exit 0
112     fi
113
114     if docker ps -a | grep -E "$ARVBOX_CONTAINER$" -q ; then
115         echo "Container $ARVBOX_CONTAINER already exists but is not running; use restart or rebuild"
116         exit 1
117     fi
118
119     if test ! -z "$TAG"
120     then
121         if test $(echo $TAG | cut -c1-1) != '-' ; then
122             TAG=":$TAG"
123             shift
124         else
125             unset TAG
126         fi
127     fi
128
129     if echo "$CONFIG" | grep '^public' ; then
130         if test -n "$ARVBOX_PUBLISH_IP" ; then
131             localip=$ARVBOX_PUBLISH_IP
132         else
133             defaultdev=$(/sbin/ip route|awk '/default/ { print $5 }')
134             localip=$(ip addr show $defaultdev | grep 'inet ' | sed 's/ *inet \(.*\)\/.*/\1/')
135         fi
136         iptemp=$(tempfile)
137         echo $localip > $iptemp
138         chmod og+r $iptemp
139         PUBLIC="--volume=$iptemp:/var/run/localip_override
140               --publish=80:80
141               --publish=8000:8000
142               --publish=8900:8900
143               --publish=9001:9001
144               --publish=9002:9002
145               --publish=25100:25100
146               --publish=25107:25107
147               --publish=25108:25108
148               --publish=8001:8001
149               --publish=8002:8002"
150     else
151         PUBLIC=""
152     fi
153
154     if echo "$CONFIG" | grep 'demo$' ; then
155         if test -d "$ARVBOX_DATA" ; then
156             echo "It looks like you already have a development container named $ARVBOX_CONTAINER."
157             echo "Set ARVBOX_CONTAINER to set a different name for your demo container"
158             exit 1
159         fi
160
161         if ! (docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q) ; then
162             docker create -v /var/lib/postgresql -v /var/lib/arvados --name $ARVBOX_CONTAINER-data arvados/arvbox-demo /bin/true
163         fi
164
165         docker run \
166                --detach \
167                --name=$ARVBOX_CONTAINER \
168                --privileged \
169                --volumes-from $ARVBOX_CONTAINER-data \
170                $PUBLIC \
171                arvados/arvbox-demo$TAG
172         updateconf
173         wait_for_arvbox
174     else
175         mkdir -p "$PG_DATA" "$VAR_DATA" "$PASSENGER" "$GEMS" "$PIPCACHE" "$GOSTUFF"
176
177
178         if ! test -d "$ARVADOS_ROOT" ; then
179             git clone https://github.com/curoverse/arvados.git "$ARVADOS_ROOT"
180         fi
181         if ! test -d "$SSO_ROOT" ; then
182             git clone https://github.com/curoverse/sso-devise-omniauth-provider.git "$SSO_ROOT"
183         fi
184
185         if test "$CONFIG" = test ; then
186
187             mkdir -p $VAR_DATA/test
188
189             docker run \
190                    --detach \
191                    --name=$ARVBOX_CONTAINER \
192                    --privileged \
193                    "--volume=$ARVADOS_ROOT:/usr/src/arvados:rw" \
194                    "--volume=$SSO_ROOT:/usr/src/sso:rw" \
195                    "--volume=$PG_DATA:/var/lib/postgresql:rw" \
196                    "--volume=$VAR_DATA:/var/lib/arvados:rw" \
197                    "--volume=$PASSENGER:/var/lib/passenger:rw" \
198                    "--volume=$GEMS:/var/lib/gems:rw" \
199                    "--volume=$PIPCACHE:/var/lib/pip:rw" \
200                    "--volume=$GOSTUFF:/var/lib/gopath:rw" \
201                    arvados/arvbox-dev$TAG \
202                    /usr/local/bin/runsvinit -svdir=/etc/test-service
203
204             docker exec -ti \
205                     $ARVBOX_CONTAINER \
206                     /usr/local/lib/arvbox/runsu.sh \
207                     /usr/local/lib/arvbox/waitforpostgres.sh
208
209             docker exec -ti \
210                    $ARVBOX_CONTAINER \
211                    /usr/local/lib/arvbox/runsu.sh \
212                    /var/lib/arvbox/service/sso/run-service --only-setup
213
214             docker exec -ti \
215                    $ARVBOX_CONTAINER \
216                    /usr/local/lib/arvbox/runsu.sh \
217                    /var/lib/arvbox/service/api/run-service --only-setup
218
219             docker exec -ti \
220                    $ARVBOX_CONTAINER \
221                    /usr/local/lib/arvbox/runsu.sh \
222                    /usr/src/arvados/build/run-tests.sh \
223                    --temp /var/lib/arvados/test \
224                    WORKSPACE=/usr/src/arvados \
225                    GEM_HOME=/var/lib/gems \
226                    "$@"
227         elif echo "$CONFIG" | grep 'dev$' ; then
228             docker run \
229                    --detach \
230                    --name=$ARVBOX_CONTAINER \
231                    --privileged \
232                    "--volume=$ARVADOS_ROOT:/usr/src/arvados:rw" \
233                    "--volume=$SSO_ROOT:/usr/src/sso:rw" \
234                    "--volume=$PG_DATA:/var/lib/postgresql:rw" \
235                    "--volume=$VAR_DATA:/var/lib/arvados:rw" \
236                    "--volume=$PASSENGER:/var/lib/passenger:rw" \
237                    "--volume=$GEMS:/var/lib/gems:rw" \
238                    "--volume=$PIPCACHE:/var/lib/pip:rw" \
239                    "--volume=$GOSTUFF:/var/lib/gopath:rw" \
240                    $PUBLIC \
241                    arvados/arvbox-dev$TAG
242             updateconf
243             wait_for_arvbox
244             echo "The Arvados source code is checked out at: $ARVADOS_ROOT"
245         else
246             echo "Unknown configuration '$CONFIG'"
247         fi
248     fi
249 }
250
251 stop() {
252     if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
253         docker stop $ARVBOX_CONTAINER
254     fi
255
256     VOLUMES=--volumes=true
257     if docker ps -a --filter "status=created" | grep -E "$ARVBOX_CONTAINER$" -q ; then
258         docker rm $VOLUMES $ARVBOX_CONTAINER
259     fi
260     if docker ps -a --filter "status=exited" | grep -E "$ARVBOX_CONTAINER$" -q ; then
261         docker rm $VOLUMES $ARVBOX_CONTAINER
262     fi
263 }
264
265 build() {
266     if ! test -f "$ARVBOX_DOCKER/Dockerfile.base" ;  then
267         echo "Could not find Dockerfile (expected it at $ARVBOX_DOCKER/Dockerfile.base)"
268         exit 1
269     fi
270     GITHEAD=$(cd $ARVBOX_DOCKER && git log --format=%H -n1 HEAD)
271     docker build --build-arg=arvados_version=$GITHEAD $NO_CACHE -t arvados/arvbox-base:$GITHEAD -f "$ARVBOX_DOCKER/Dockerfile.base" "$ARVBOX_DOCKER"
272     if docker --version |grep " 1\.[0-9]\." ; then
273         # Docker version prior 1.10 require -f flag
274         # -f flag removed in Docker 1.12
275         FORCE=-f
276     fi
277     if test "$1" = localdemo -o "$1" = publicdemo ; then
278         docker build $NO_CACHE -t arvados/arvbox-demo:$GITHEAD -f "$ARVBOX_DOCKER/Dockerfile.demo" "$ARVBOX_DOCKER"
279         docker tag $FORCE arvados/arvbox-demo:$GITHEAD arvados/arvbox-demo:latest
280     else
281         docker build $NO_CACHE -t arvados/arvbox-dev:$GITHEAD -f "$ARVBOX_DOCKER/Dockerfile.dev" "$ARVBOX_DOCKER"
282         docker tag $FORCE arvados/arvbox-dev:$GITHEAD arvados/arvbox-dev:latest
283     fi
284 }
285
286 check() {
287     case "$1" in
288         localdemo|publicdemo|dev|publicdev|test)
289             true
290             ;;
291         *)
292             echo "Argument to $subcmd must be one of localdemo, publicdemo, dev, publicdev, test"
293             exit 1
294         ;;
295     esac
296 }
297
298 subcmd="$1"
299 if test -n "$subcmd" ; then
300     shift
301 fi
302 case "$subcmd" in
303     build)
304         check $@
305         build $@
306         ;;
307
308     rebuild)
309         check $@
310         NO_CACHE=--no-cache build $@
311         ;;
312
313     start|run)
314         check $@
315         run $@
316         ;;
317
318     sh*)
319         exec docker exec -ti $ARVBOX_CONTAINER /usr/bin/env TERM=$TERM GEM_HOME=/var/lib/gems /bin/bash
320         ;;
321
322     pipe)
323         exec docker exec -i $ARVBOX_CONTAINER /usr/bin/env GEM_HOME=/var/lib/gems /bin/bash -
324         ;;
325
326     stop)
327         stop
328         ;;
329
330     restart)
331         check $@
332         stop
333         run $@
334         ;;
335
336     reboot)
337         check $@
338         stop
339         build $@
340         run $@
341         ;;
342
343     ip)
344         getip
345         ;;
346
347     host)
348         gethost
349         ;;
350
351     open)
352         exec xdg-open http://$(gethost)
353         ;;
354
355     status)
356         echo "Selected: $ARVBOX_CONTAINER"
357         if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
358             echo "Status: running"
359             echo "Container IP: $(getip)"
360             echo "Published host: $(gethost)"
361         else
362             echo "Status: not running"
363         fi
364         if test -d "$ARVBOX_DATA" ; then
365             echo "Data: $ARVBOX_DATA"
366         elif docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q ; then
367             echo "Data: $ARVBOX_CONTAINER-data"
368         else
369             echo "Data: none"
370         fi
371         ;;
372
373     reset|destroy)
374         stop
375         if test -d "$ARVBOX_DATA" ; then
376             if test "$subcmd" = destroy ; then
377                 if test "$1" != -f ; then
378                     echo "WARNING!  This will delete your entire arvbox ($ARVBOX_DATA)."
379                     echo "Use destroy -f if you really mean it."
380                     exit 1
381                 fi
382                 set -x
383                 rm -rf "$ARVBOX_DATA"
384             else
385                 if test "$1" != -f ; then
386                     echo "WARNING!  This will delete your arvbox data ($ARVBOX_DATA)."
387                     echo "Code and downloaded packages will be preserved."
388                     echo "Use reset -f if you really mean it."
389                     exit 1
390                 fi
391                 set -x
392                 rm -rf "$ARVBOX_DATA/postgres"
393                 rm -rf "$ARVBOX_DATA/var"
394             fi
395         else
396             if test "$1" != -f ; then
397                 echo "WARNING!  This will delete your data container $ARVBOX_CONTAINER-data.  Use -f if you really mean it."
398                 exit 1
399             fi
400             set -x
401             docker rm "$ARVBOX_CONTAINER-data"
402         fi
403         ;;
404
405     log)
406         if test -n "$1" ; then
407             exec docker exec -ti $ARVBOX_CONTAINER /usr/bin/env TERM=$TERM less --follow-name -R +GF "/etc/service/$1/log/main/current"
408         else
409             exec docker exec -ti $ARVBOX_CONTAINER /usr/bin/env TERM=$TERM tail $(docker exec -ti $ARVBOX_CONTAINER find -L /etc -path '/etc/service/*/log/main/current' -printf " %p")
410         fi
411         ;;
412
413     cat)
414         if test -n "$1" ; then
415             exec docker exec $ARVBOX_CONTAINER cat "$@"
416         else
417             echo "Usage: $0 $subcmd <files>"
418         fi
419         ;;
420
421     ls)
422         exec docker exec -ti $ARVBOX_CONTAINER /usr/bin/env TERM=$TERM ls "$@"
423         ;;
424
425     sv)
426         if test -n "$1" -a -n "$2" ; then
427             exec docker exec -ti $ARVBOX_CONTAINER sv "$@"
428         else
429             echo "Usage: $0 $subcmd <start|stop|restart> <service>"
430             echo "Available services:"
431             exec docker exec -ti $ARVBOX_CONTAINER ls /etc/service
432         fi
433         ;;
434
435     clone)
436         if test -n "$2" ; then
437             cp -r "$ARVBOX_BASE/$1" "$ARVBOX_BASE/$2"
438             echo "Created new arvbox $2"
439             echo "export ARVBOX_CONTAINER=$2"
440         else
441             echo "clone <from> <to>   clone an arvbox"
442             echo "available arvboxes: $(ls $ARVBOX_BASE)"
443         fi
444         ;;
445
446     *)
447         echo "Arvados-in-a-box                      http://arvados.org"
448         echo
449         echo "build   <config>      build arvbox Docker image"
450         echo "rebuild <config>      build arvbox Docker image, no layer cache"
451         echo "start|run <config> [tag]  start $ARVBOX_CONTAINER container"
452         echo "open       open arvbox workbench in a web browser"
453         echo "shell      enter arvbox shell"
454         echo "ip         print arvbox docker container ip address"
455         echo "host       print arvbox published host"
456         echo "status     print some information about current arvbox"
457         echo "stop       stop arvbox container"
458         echo "restart <config>  stop, then run again"
459         echo "reboot  <config>  stop, build arvbox Docker image, run"
460         echo "reset      delete arvbox arvados data (be careful!)"
461         echo "destroy    delete all arvbox code and data (be careful!)"
462         echo "log <service> tail log of specified service"
463         echo "ls <options>  list directories inside arvbox"
464         echo "cat <files>   get contents of files inside arvbox"
465         echo "pipe       run a bash script piped in from stdin"
466         echo "sv <start|stop|restart> <service> change state of service inside arvbox"
467         echo "clone <from> <to>   clone an arvbox"
468         ;;
469 esac