use ifup for bridge-less cable; allow UPPER scripting for image file root; allow...
[rrq/overlay-boot.git] / functions
1 # This file implements common functions for all boot methods
2
3 die() {
4     echo "$*" >&2
5     exit 1
6 }
7
8 # grab and set a configuration variable
9 # $1 = variable, [ $2 = default .. error otherwise ]
10 config() {
11     eval $1="$(sed "/^$1=.*/{s|^$1=||;b};d" $CONFIG)"
12     [ -z "$(eval echo "\$$1")" ] || return 0
13     [ $# -lt 2 ] && die "Missing $1=... in $CONFIG"
14     eval $1="'$2'"
15     eval echo "$1=\$$1"
16 }
17
18 # Unless the subhost already has a private /etc/network/interfaces,
19 # install an "empty" one
20 setup_networking() {
21     [ -r $UPPER/etc/network/interfaces ] && return 0
22     [ "$UPPER/etc/network" = "/etc/network" ] && exit 1
23     mkdir -p $UPPER/etc/network
24     cat <<EOF > $UPPER/etc/network/interfaces
25 # Generated for $NAME subhost
26 auto lo
27 iface lo inet loopback
28 EOF
29     return 1
30 }
31
32 # Setup the network namespace for the given $CABLES
33 # $1=netns ( $2="br=mac" .. )
34 setup_veth_cables() {
35     local NETNS BR IF MAC C i ADD
36     NETNS="$1"
37     shift 1
38     i=0
39     ADD=false
40     setup_networking || ADD=true
41     for C in "$@" ; do
42         IF=$NETNS$i
43         MAC="${C#*=}"
44         [ -z "$MAC" ] || MAC="address $MAC"
45         ip link add $IF type veth peer name eth$i $MAC netns $NETNS
46         ip link set $IF up
47         $ADD && cat <<EOF >> $UPPER/etc/network/interfaces
48
49 auto eth$i
50 iface eth$i inet manual
51 EOF
52         BR="${C%=*}"
53         if [ -z "$BR" ] ; then
54             ip link set $IF
55             ifup $IF
56         else
57             brctl addif $BR $IF
58         fi
59         i=$((i+1))
60     done
61 }
62
63 # (name live system root work)
64 # Set up an overlay fmr $name on $live, with a new tmpfs on its /run,
65 # and "install" a "reaper" as the upcoming pid 1
66 setup_overlay() {
67     local LIVE="$2" LOWER="$3" UPPER="$4" ROOT
68
69     if grep -q "$1 $2" /proc/mounts ; then
70         die "$1 is already mounted"
71     fi
72
73     if [ -f "${UPPER%% *}" ] ; then
74         if [ -x "${UPPER%% *}" ] ; then
75             echo "${UPPER%% *} appears to be executable" >&2
76             # Giving a program/script as UPPER= asks for running this
77             # first, to make a root filesystem available. The script takes
78             # ACTION "setup" and "teardown", and on "setup" it must tell
79             # where the ROOT is set up.
80             ROOT="$(env ACTION=setup $UPPER)"
81             if [ ! -d "$ROOT" ] ; then
82                 # setup failed
83                 die "root setup failed: $UPPER"
84             fi
85             UPPER="$ROOT"
86             ## Now falling down to "normal overlay" setup
87         else
88             die "${UPPER%% *} (root setup program/script) is not executable"
89         fi
90     fi
91
92     # LIVE is the same as LOWER then skip the overlay; just assume
93     # a proper chroot system exists at LIVE.
94     if [ "$LIVE" != "$LOWER" ] ; then
95         # setup $UPPER/run
96         mkdir -p "$UPPER/run"
97         mount -t tmpfs -osize=100M tmpfs "$UPPER/run"
98         mkdir -p "$UPPER/run/lock"
99         # setup $UPPER/dev
100         mkdir -p "$UPPER/dev"
101         mount -t tmpfs -osize=100M tmpfs "$UPPER/dev"
102         mknod -m 622 "$UPPER/dev/console" c 5 1
103         mknod -m 666 "$UPPER/dev/null" c 1 3
104         mknod -m 666 "$UPPER/dev/zero" c 1 5
105         mknod -m 666 "$UPPER/dev/ptmx" c 5 2
106         mknod -m 666 "$UPPER/dev/tty" c 5 0
107         mknod -m 444 "$UPPER/dev/random" c 1 8
108         mknod -m 444 "$UPPER/dev/urandom" c 1 9
109         chown root:tty "$UPPER/dev/console"
110         chown root:tty "$UPPER/dev/ptmx"
111         chown root:tty "$UPPER/dev/tty"
112         ln -sTf /proc/self/fd "$UPPER/dev/fd"
113         ln -sTf /proc/self/fd/0 "$UPPER/dev/stdin"
114         ln -sTf /proc/self/fd/1 "$UPPER/dev/stdout"
115         ln -sTf /proc/self/fd/2 "$UPPER/dev/stderr"
116         ln -sTf /proc/kcore "$UPPER/dev/core"
117         mkdir "$UPPER/dev/shm"
118         mkdir "$UPPER/dev/pts"
119         chmod 1777 "$UPPER/dev/shm"
120
121         OLY="-olowerdir=$3,upperdir=$UPPER,workdir=$5"
122         if mount -t overlay "$OLY" $1 $2 ; then
123             : # all good
124         else
125             umount -R "$UPPER/dev"
126             umount "$UPPER/run"
127             die "Cannot set up the overlay mount $2"
128         fi
129     fi
130
131     echo "Installing $OVERLAYDIR/reaper to $LIVE/.reaper"
132     cp -p $OVERLAYDIR/reaper $LIVE/.reaper
133 }
134
135 start_services() {
136     for S in "$@" ; do
137         service $S start
138     done
139 }
140
141 # find the upperdir option for an overlay mount line
142 getupper() {
143     sed 's/.*upperdir=\([^,]*\).*/\1/'
144 }
145
146 # Check if $1 is "live" and echo the
147 # unshare and reaper process pids
148 is_live() {
149     local NAME=$1
150     local USPID="$(pgrep -f "unshare.* $NAME ")"
151     [ -z "$USPID" ] && return 1
152     echo $USPID $(pgrep -f ".reaper $NAME")
153 }
154
155 list_running() {
156     for C in $(pgrep -a overlay-boot | awk '{print $4}') ; do
157         eval NAME="$(sed "/^NAME=.*/{s|^NAME=||;b};d" $C)"
158         [ -z "$NAME" ] && NAME=$(basename $C .conf)
159         echo $NAME
160     done
161 }