284f0ef5d72a8816d388c84699ebbdb49e8b3e75
[arvados-dev.git] / 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 "$ARVADOS_DEV_ROOT" ; then
43     ARVADOS_DEV_ROOT="$ARVBOX_DATA/arvados-dev"
44 fi
45
46 if test -z "$SSO_ROOT" ; then
47     SSO_ROOT="$ARVBOX_DATA/sso-devise-omniauth-provider"
48 fi
49
50 PG_DATA="$ARVBOX_DATA/postgres"
51 VAR_DATA="$ARVBOX_DATA/var"
52 PASSENGER="$ARVBOX_DATA/passenger"
53 GEMS="$ARVBOX_DATA/gems"
54
55 getip() {
56     docker inspect $ARVBOX_CONTAINER | grep \"IPAddress\" | head -n1 | tr -d ' ":,\n' | cut -c10-
57 }
58
59 updateconf() {
60     if test -f ~/.config/arvados/$ARVBOX_CONTAINER.conf ; then
61         sed "s/ARVADOS_API_HOST=.*/ARVADOS_API_HOST=$(getip):8000/" <$HOME/.config/arvados/$ARVBOX_CONTAINER.conf >$HOME/.config/arvados/$ARVBOX_CONTAINER.conf.tmp
62         mv ~/.config/arvados/$ARVBOX_CONTAINER.conf.tmp ~/.config/arvados/$ARVBOX_CONTAINER.conf
63     else
64         mkdir -p $HOME/.config/arvados
65         cat >$HOME/.config/arvados/$ARVBOX_CONTAINER.conf <<EOF
66 ARVADOS_API_HOST=$(getip):8000
67 ARVADOS_API_TOKEN=
68 ARVADOS_API_HOST_INSECURE=true
69 EOF
70     fi
71 }
72
73 wait_for_arvbox() {
74     FF=/tmp/arvbox-fifo-$$
75     mkfifo $FF
76     docker logs -f $ARVBOX_CONTAINER > $FF &
77     LOGPID=$!
78     while read line ; do
79         echo $line
80         if echo $line | grep "Workbench is running at" >/dev/null ; then
81             kill $LOGPID
82         fi
83     done < $FF
84     rm $FF
85     echo
86     if test -n "$localip" ; then
87         echo "export ARVADOS_API_HOST=$localip:8000"
88     else
89         echo "export ARVADOS_API_HOST=$(getip):8000"
90     fi
91 }
92
93 run() {
94     if docker ps -a | grep -E "$ARVBOX_CONTAINER$" -q ; then
95         echo "Container $ARVBOX_CONTAINER is already running, use stop, restart or reboot"
96         exit 0
97     fi
98
99     if echo "$1" | grep '^public' ; then
100         if test -n "$ARVBOX_PUBLISH_IP" ; then
101             localip=$ARVBOX_PUBLISH_IP
102         else
103             defaultdev=$(/sbin/ip route|awk '/default/ { print $5 }')
104             localip=$(ip addr show $defaultdev | grep 'inet ' | sed 's/ *inet \(.*\)\/.*/\1/')
105         fi
106         iptemp=$(tempfile)
107         echo $localip > $iptemp
108         chmod og+r $iptemp
109         PUBLIC="--volume=$iptemp:/var/run/localip_override
110               --publish=80:80
111               --publish=8000:8000
112               --publish=8900:8900
113               --publish=9001:9001
114               --publish=9002:9002
115               --publish=25100:25100
116               --publish=25107:25107
117               --publish=25108:25108
118               --publish=8001:8001"
119     else
120         PUBLIC=""
121     fi
122
123     if echo "$1" | grep 'demo$' ; then
124         if test -d "$ARVBOX_DATA" ; then
125             echo "It looks like you already have a development container named $ARVBOX_CONTAINER."
126             echo "Set ARVBOX_CONTAINER to set a different name for your demo container"
127             exit 1
128         fi
129
130         if ! (docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q) ; then
131             docker create -v /var/lib/postgresql -v /var/lib/arvados --name $ARVBOX_CONTAINER-data arvados/arvbox-demo /bin/true
132         fi
133
134         docker run \
135                --detach \
136                --name=$ARVBOX_CONTAINER \
137                --privileged \
138                --volumes-from $ARVBOX_CONTAINER-data \
139                $PUBLIC \
140                arvados/arvbox-demo
141         updateconf
142         wait_for_arvbox
143     else
144         mkdir -p "$PG_DATA" "$VAR_DATA" "$PASSENGER" "$GEMS"
145
146         if ! test -d "$ARVADOS_ROOT" ; then
147             git clone https://github.com/curoverse/arvados.git "$ARVADOS_ROOT"
148         fi
149         if ! test -d "$SSO_ROOT" ; then
150             git clone https://github.com/curoverse/sso-devise-omniauth-provider.git "$SSO_ROOT"
151         fi
152
153         if test "$1" = test ; then
154             shift
155
156             if ! test -d "$ARVADOS_DEV_ROOT" ; then
157                 git clone https://github.com/curoverse/arvados-dev.git "$ARVADOS_DEV_ROOT"
158             fi
159
160             mkdir -p $VAR_DATA/test
161
162             docker run \
163                    --detach \
164                    --name=$ARVBOX_CONTAINER \
165                    --privileged \
166                    "--volume=$ARVADOS_ROOT:/usr/src/arvados:rw" \
167                    "--volume=$ARVADOS_DEV_ROOT:/usr/src/arvados-dev:rw" \
168                    "--volume=$SSO_ROOT:/usr/src/sso:rw" \
169                    "--volume=$PG_DATA:/var/lib/postgresql:rw" \
170                    "--volume=$VAR_DATA:/var/lib/arvados:rw" \
171                    "--volume=$PASSENGER:/var/lib/passenger:rw" \
172                    "--volume=$GEMS:/var/lib/gems:rw" \
173                    arvados/arvbox-dev \
174                    /usr/local/bin/runsvinit -svdir=/etc/test-service
175
176             docker exec -ti \
177                     $ARVBOX_CONTAINER \
178                     /usr/local/lib/arvbox/runsu.sh \
179                     /usr/local/lib/arvbox/waitforpostgres.sh
180
181             docker exec -ti \
182                    $ARVBOX_CONTAINER \
183                    /usr/local/lib/arvbox/runsu.sh \
184                    /usr/local/lib/arvbox/service/sso/run-service --only-setup
185
186             docker exec -ti \
187                    $ARVBOX_CONTAINER \
188                    /usr/local/lib/arvbox/runsu.sh \
189                    /usr/local/lib/arvbox/service/api/run-service --only-setup
190
191             docker exec -ti \
192                    $ARVBOX_CONTAINER \
193                    /usr/local/lib/arvbox/runsu.sh \
194                    /usr/src/arvados-dev/jenkins/run-tests.sh \
195                    --temp /var/lib/arvados/test \
196                    WORKSPACE=/usr/src/arvados \
197                    GEM_HOME=/var/lib/gems \
198                    "$@"
199         else
200             docker run \
201                    --detach \
202                    --name=$ARVBOX_CONTAINER \
203                    --privileged \
204                    "--volume=$ARVADOS_ROOT:/usr/src/arvados:rw" \
205                    "--volume=$SSO_ROOT:/usr/src/sso:rw" \
206                    "--volume=$PG_DATA:/var/lib/postgresql:rw" \
207                    "--volume=$VAR_DATA:/var/lib/arvados:rw" \
208                    "--volume=$PASSENGER:/var/lib/passenger:rw" \
209                    "--volume=$GEMS:/var/lib/gems:rw" \
210                    $PUBLIC \
211                    arvados/arvbox-dev
212             updateconf
213             wait_for_arvbox
214             echo "The Arvados source code is checked out at: $ARVADOS_ROOT"
215         fi
216     fi
217 }
218
219 stop() {
220     if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
221         docker stop $ARVBOX_CONTAINER
222     fi
223
224     VOLUMES=--volumes=true
225     if docker ps -a --filter "status=created" | grep -E "$ARVBOX_CONTAINER$" -q ; then
226         docker rm $VOLUMES $ARVBOX_CONTAINER
227     fi
228     if docker ps -a --filter "status=exited" | grep -E "$ARVBOX_CONTAINER$" -q ; then
229         docker rm $VOLUMES $ARVBOX_CONTAINER
230     fi
231 }
232
233 build() {
234     if ! test -f "$ARVBOX_DOCKER/Dockerfile.base" ;  then
235         echo "Could not find Dockerfile ($ARVBOX_DOCKER/Dockerfile.base)"
236         exit 1
237     fi
238     docker build -t arvados/arvbox-base -f "$ARVBOX_DOCKER/Dockerfile.base" "$ARVBOX_DOCKER"
239     if test "$1" = localdemo -o "$1" = publicdemo ; then
240         docker build -t arvados/arvbox-demo -f "$ARVBOX_DOCKER/Dockerfile.demo" "$ARVBOX_DOCKER"
241     else
242         docker build -t arvados/arvbox-dev -f "$ARVBOX_DOCKER/Dockerfile.dev" "$ARVBOX_DOCKER"
243     fi
244 }
245
246 check() {
247     case "$1" in
248         localdemo|publicdemo|dev|publicdev|test)
249             true
250             ;;
251         *)
252             echo "Argument to $subcmd must be one of localdemo, publicdemo, dev, publicdev, test"
253             exit 1
254         ;;
255     esac
256 }
257
258 subcmd="$1"
259 if test -n "$subcmd" ; then
260     shift
261 fi
262 case "$subcmd" in
263     build)
264         check $@
265         build $@
266         ;;
267
268     start|run)
269         check $@
270         run $@
271         ;;
272
273     sh*)
274         docker exec -ti $ARVBOX_CONTAINER /usr/bin/env TERM=$TERM GEM_HOME=/var/lib/gems /bin/bash
275         ;;
276
277     stop)
278         stop
279         ;;
280
281     restart)
282         check $@
283         stop
284         run $@
285         ;;
286
287     reboot)
288         check $@
289         stop
290         build $@
291         run $@
292         ;;
293
294     ip|open)
295         if test "$subcmd" = 'ip' ; then
296             echo $(getip)
297         else
298             xdg-open http://$(getip)
299         fi
300         ;;
301
302     reset|destroy)
303         stop
304         if test -d "$ARVBOX_DATA" ; then
305             if test "$subcmd" = destroy ; then
306                 if test "$1" != -f ; then
307                     echo "WARNING!  This will delete your entire arvbox ($ARVBOX_DATA)."
308                     echo "Use destroy -f if you really mean it."
309                     exit 1
310                 fi
311                 rm -rf "$ARVBOX_DATA"
312             else
313                 if test "$1" != -f ; then
314                     echo "WARNING!  This will delete your arvbox data ($ARVBOX_DATA)."
315                     echo "Code and downloaded packages will be preserved."
316                     echo "Use reset -f if you really mean it."
317                     exit 1
318                 fi
319                 rm -rf "$ARVBOX_DATA/postgres"
320                 rm -rf "$ARVBOX_DATA/var"
321             fi
322         else
323             if test "$1" != -f ; then
324                 echo "WARNING!  This will delete your data container $ARVBOX_CONTAINER-data.  Use -f if you really mean it."
325                 exit 1
326             fi
327             docker rm "$ARVBOX_CONTAINER-data"
328         fi
329         ;;
330
331     log|svrestart)
332         if test -n "$1" ; then
333             if test "$subcmd" = log ; then
334                 docker exec -ti $ARVBOX_CONTAINER /usr/bin/env TERM=$TERM less --follow-name +GF "/etc/service/$1/log/main/current"
335             fi
336             if test "$subcmd" = svrestart ; then
337                 docker exec -ti $ARVBOX_CONTAINER sv restart "$1"
338                 docker exec -ti $ARVBOX_CONTAINER sv restart ready
339             fi
340         else
341             echo "Usage: $0 $subcmd <service>"
342             echo "Available services:"
343             docker exec -ti $ARVBOX_CONTAINER ls /etc/service
344         fi
345         ;;
346
347     clone)
348         if test -n "$2" ; then
349             cp -r "$ARVBOX_BASE/$1" "$ARVBOX_BASE/$2"
350             echo "Created new arvbox $2"
351             echo "export ARVBOX_CONTAINER=$2"
352         else
353             echo "clone <from> <to>   clone an arvbox"
354             echo "available arvboxes: $(ls $ARVBOX_BASE)"
355         fi
356         ;;
357
358     *)
359         echo "Arvados-in-a-box"
360         echo
361         echo "$(basename $0) (build|start|run|open|shell|ip|stop|reboot|reset|destroy|log|svrestart)"
362         echo
363         echo "build <config>      build arvbox Docker image"
364         echo "start|run <config>  start $ARVBOX_CONTAINER container"
365         echo "open       open arvbox workbench in a web browser"
366         echo "shell      enter arvbox shell"
367         echo "ip         print arvbox ip address"
368         echo "stop       stop arvbox container"
369         echo "restart <config>  stop, then run again"
370         echo "reboot  <config>  stop, build arvbox Docker image, run"
371         echo "reset      delete arvbox arvados data (be careful!)"
372         echo "destroy    delete all arvbox code and data (be careful!)"
373         echo "log       <service> tail log of specified service"
374         echo "svrestart <service> restart specified service inside arvbox"
375         echo "clone <from> <to>   clone an arvbox"
376         ;;
377 esac