Minor correction, with explicit chroot (as required in beowulf)
[rrq/subhost.git] / control
diff --git a/control b/control
index 28a4d2c0d99d9fb2653b4c49d8e1d78d4100595a..f5831a267f8842a3d1090dece847d4d2501648c4 100755 (executable)
--- a/control
+++ b/control
@@ -6,6 +6,8 @@
 # $2 = the sub-host to start or stop
 # $3... = the optional chroot-ed command (/startup by default)
 
+set -x
+
 SCRIPT=$0
 CMD=$1
 NAME=$2
@@ -18,59 +20,102 @@ usage() {
 
 [ -z "$NAME" ] && usage
 
-: ${ATTIC=/opt/srv}
-: ${BRIDGE=srv_br}
-: ${TARGET=/srv/$NAME}
-: ${LOWER=$ATTIC/daedalus.fs}
-: ${IMAGE=$ATTIC/$NAME/$NAME.img}
-: ${UPPER=$ATTIC/$NAME/root}
-: ${WORK=$ATTIC/$NAME/work}
-: ${MOUNT=$ATTIC/$NAME/mnt}
+: ${SUBHOST=/opt/subhost}
+: ${OSROOT=}
+: ${TOP=$SUBHOST/$NAME}
+: ${TARGET=$TOP/live}
+: ${IMAGE=$TOP/$NAME.img}
+: ${UPPER=$TOP/root}
+: ${WORK=$TOP/work}
+: ${MOUNT=$TOP/mnt}
 : ${NSNAME=$NAME}
-: ${NETH=1}
+: ${BRIDGES=lan_br}
+: ${CONFIG=$TOP/config}
+
+[ -e "$CONFIG" ] && . "$CONFIG"
 
+cd "$SUBHOST" || exit 1
+
+# Create a simple overlay subhost without its own image file
 create_subhost() {
     mkdir -p $TARGET $MOUNT $UPPER $WORK
+    [ -d "$OSROOT" ] || OSROOT=$SUBHOST/chimaera/base
+    [ -e $CONFIG ] || cat <<EOF > "$CONFIG"
+# Subhost $NAME is an autogenerated overlay subhost with shared filesystem
+OSROOT="$OSROOT"
+BRIDGES="$BRIDGES"
+EOF
 }
 
-setup_network() {
-    if [ -n "$BRIDGE" ] ; then
-       brctl show $BRIDGE >& /dev/null || brctl addbr $BRIDGE
-    fi
+# map a string into a hexadecimal number with 10-digits by folding the given string into 9-digit ascii-code numbers and adding them
+hexfoldsum() {
+    local V
+    V="$(b2sum -l 40 <<< "$1" | sed 's/\(..\)/\1:/g')"
+    echo "02:${V:0:14}"
+}
 
+# Generate a mac address for given interface by passing hostname,
+# subhost name and interface through 40-bit b2sum and with 02: prefix.
+macaddr() {
+    local V="$(b2sum -l 40 <<< "$(hostname)$NAME$1" | sed 's/\(..\)/\1:/g')"
+    echo "02:${V:0:14}"
+}
+
+# setup the subhost network namespace and link up the host side
+setup_network() {
     E=0
     ip netns add $NSNAME
-    for I in $(eval echo "{1..$NETH}") ; do
+    for BRIDGE in ${BRIDGES[@]} ; do
+       brctl show $BRIDGE >& /dev/null || brctl addbr $BRIDGE
        IF=$NAME$E
-       ip link add $IF type veth peer name eth$E netns $NSNAME
+       MAC=$(macaddr $IF)
+       ip link add $IF type veth peer name eth$E address $MAC netns $NSNAME 
        ip link set $IF up
        [ -n "$BRIDGE" ] && brctl addif $BRIDGE $IF
        E=$((E+1))
     done
 }
 
+# check if $1 is mounted
+is_mounted() {
+    grep -qE "^[^ ]+ $1 " /proc/mounts
+}
+
+# Setup or re-setup the subhost filesystem
 setup_rootfs() {
-    if [ -e "$IMAGE" ] ; then
-       mount $IMAGE $MOUNT || exit 1
-       LOWER=$MOUNT/root
-       WORK=$MOUNT/work
+    if is_mounted $TARGET ; then
+       mount -oremount $TARGET
+    else
+       if [ -e "$IMAGE" ] ; then
+           # $IMAGE is either an image file or a link to a partition,
+           # with /root and /work in it.
+           is_mounted $MOUNT || mount $IMAGE $MOUNT || exit 1
+           UPPER=$MOUNT/root
+           WORK=$MOUNT/work
+       fi
+       if [ -z "$OSROOT" ] ; then
+           # No overlay
+           mount --rbind $UPPER $TARGET
+       else
+           # overlay of $UPPER (+$WORK) over $OSROOT onto $TARGET
+           mount -t overlay $NAME \
+                 -olowerdir=$OSROOT,upperdir=$UPPER,workdir=$WORK \
+                 $TARGET
+       fi
     fi
-    mount -t overlay $NAME -olowerdir=$LOWER,upperdir=$UPPER,workdir=$WORK \
-         $TARGET
 }
 
 case "$CMD" in
     start)
-       cd "$ATTIC" || exit 1
        [ -e "/run/netns/$NSNAME" ] || setup_network
        [ -d "$MOUNT" ] || create_subhost
-       grep -q "^$NAME $TARGET overlay" /proc/mounts || setup_rootfs
+       setup_rootfs
        START=/bin/bash
        [ -x $TARGET/startup ] && START=/startup
        exec ip netns exec $NSNAME unshare \
             --fork --pid --mount-proc --kill-child \
             --uts --ipc --mount --cgroup \
-            "--root=$TARGET" $START
+            chroot $TARGET $START
        ;;
     stop)
        umount $TARGET