initial
authorRalph Ronnquist <ralph.ronnquist@gmail.com>
Sun, 20 Mar 2022 05:53:39 +0000 (16:53 +1100)
committerRalph Ronnquist <ralph.ronnquist@gmail.com>
Sun, 20 Mar 2022 05:53:39 +0000 (16:53 +1100)
functions [new file with mode: 0644]
olle/olle.conf [new file with mode: 0644]
overlay-boot [new file with mode: 0755]
overlay-go [new file with mode: 0755]

diff --git a/functions b/functions
new file mode 100644 (file)
index 0000000..1d52d74
--- /dev/null
+++ b/functions
@@ -0,0 +1,84 @@
+# This file implements common functions for all boot methods
+
+die() {
+    echo "$*" >&2
+    exit 1
+}
+
+# grab and set a configuration variable
+# $1 = variable, [ $2 = default .. error otherwise ]
+config() {
+    eval $1="$(sed "/^$1=.*/{s|^$1=||;b};d" $CONFIG)"
+    [ -z "$(eval echo "\$$1")" ] || return 0
+    [ $# -lt 2 ] && die "Missing $1=... in $CONFIG"
+    eval $1="'$2'"
+    eval echo "$1=\$$1"
+}
+
+# Unless the subhost already has a private /etc/network/interfaces,
+# install an "empty" one
+setup_networking() {
+    [ -r $UPPER/etc/network/interfaces ] && return 0
+    [ "$UPPER/etc/network" = "/etc/network" ] && exit 1
+    mkdir -p $UPPER/etc/network
+    cat <<EOF > $UPPER/etc/network/interfaces
+# Generated for $NAME subhost
+auto lo
+iface lo inet loopback
+EOF
+    return 1
+}
+
+# Setup the network namespace for the given $CABLES
+# $1=netns ( $2="br=mac" .. )
+setup_veth_cables() {
+    local NETNS BR IF MAC C i ADD
+    NETNS="$1"
+    shift 1
+    i=0
+    ADD=false
+    setup_networking || ADD=true
+    for C in "$@" ; do
+       IF=$NETNS$i
+       MAC="${C#*=}"
+       [ -z "$MAC" ] || MAC="address $MAC"
+       ip link add $IF type veth peer name eth$i $MAC netns $NETNS
+       ip link set $IF up
+       $ADD && cat <<EOF >> $UPPER/etc/network/interfaces
+
+auto eth$i
+iface eth$i inet manual
+EOF
+       BR="${C%=*}"
+       [ -z "$BR" ] || brctl addif $BR $IF
+       i=$((i+1))
+    done
+}
+
+REAPER=$(dirname $(realpath $0))/reaper/reaper
+# (name live system root work)
+# Set up an overlay fmr $name on $live, with a new tmpfs on its /run,
+# and "install" a "reaper" as the upcoming pid 1
+setup_overlay() {
+    set -x
+    mkdir -p $4/run
+    mount -t tmpfs -osize=100M tmpfs $4/run
+    mkdir -p $4/run/lock
+    grep -q "$1 $2" /proc/mounts || \
+       mount -t overlay -olowerdir=$3,upperdir=$4,workdir=$5 $1 $2 || \
+       die "Cannot set up the overlay mount $2"
+    mount --bind $4/run $2/run
+    cp $REAPER $LIVE/.reaper
+}
+
+
+# Check if $SRV is "live" ; will 
+is_live() {
+    pgrep -f ".reaper $SRV" > /dev/null
+}
+
+start_services() {
+    for S in "$@" ; do
+       service $S start
+    done
+}
diff --git a/olle/olle.conf b/olle/olle.conf
new file mode 100644 (file)
index 0000000..71b86ef
--- /dev/null
@@ -0,0 +1,10 @@
+NAME=olle
+BASE=olle
+CABLES=homenet=
+#LOG=/tmp/oly-olle.log
+#LIVE=olle/live
+#UPPER=olle/root"
+#WORK=olle/work"
+LOWER=/
+#START=networking ssh
+#SUBSHELL=/bin/sh
diff --git a/overlay-boot b/overlay-boot
new file mode 100755 (executable)
index 0000000..239ae1c
--- /dev/null
@@ -0,0 +1,60 @@
+#!/bin/sh
+#
+# This boot method runs a service subhost with a root filesystem that
+# is an overlay of the subhost's root and an OS root. The service
+# subhost is defined by a configuration file named on teh command line
+
+[ $(id -u) = 0 ] || exec sudo $0 $@
+
+. $(dirname $(realpath $0))/functions
+
+CONFIG="$1"
+[ -r "$CONFIG" ] || die "Missing configuration $CONFIG"
+
+config NAME $(basename $1 .${1##*.})
+config LOG /tmp/oly-$NAME.log
+
+if [ -z "$UNSHARED" ] ; then
+    # Pre-unsharing:
+    #
+    # Create the network namespace for the subhost, then trigger
+    # detached re-run with unshared mount namespace
+    [ -r /run/netns/$NAME ] || ip netns add $NAME
+    exec env UNSHARED=yes unshare -m $0 $@ > $LOG 2>&1 &
+    echo "Logging to $LOG" >&2
+    exit 0
+fi
+
+config BASE
+config LIVE "$BASE/live"
+config UPPER "$BASE/root"
+config WORK "$BASE/work"
+config LOWER "/"
+config CABLES ""
+config START "networking ssh"
+config SUBSHELL /bin/sh
+config STOP ""
+
+# Setup virtual cabling and subhost's /etc/network/interfaces
+setup_veth_cables $NAME $CABLES
+
+# Set up the mount for this subhost, including a new tmpfs on its /run
+echo setup_overlay "$NAME" "$LIVE" "$LOWER" "$UPPER" "$WORK"
+setup_overlay "$NAME" "$LIVE" "$LOWER" "$UPPER" "$WORK"
+
+exithandler() {
+    ip netns del $NAME
+    umount -R "$LIVE"
+}
+trap "exithandler" 0
+
+CMD="unshare -fp --mount-proc ip netns exec $NAME chroot $LIVE /bin/sh"
+echo "$CMD"
+cat <<EOF | $CMD
+set -x
+mount --bind $UPPER/run /run
+for srv in $START ; do service \$srv start ; done
+exec /.reaper $NAME
+EOF
+echo "EXITED $CMD"
+#echo "$STOP" | ip netns exec $NAME chroot $LIVE $SUBSHELL
diff --git a/overlay-go b/overlay-go
new file mode 100755 (executable)
index 0000000..dd557d8
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/sh
+set -x
+X="$(pgrep -f ".reaper $1")"
+grep -q "^proc " /proc/$X/mounts || \
+    sudo nsenter -t "$X" -m -p -r -w mount -t proc proc /proc
+ROOT="$(sudo nsenter -t "$X" -m -p -r -w mount | \
+            awk -v S="$1" '$1==S{print $3;exit;}')"
+sudo nsenter -t "$X" -n -m -p -r -w -u -C /bin/bash