--- /dev/null
+#!/bin/bash
+#
+# Boot up subhost as if a vitual machine.
+#
+# There is already an existing network namespace of the right name,
+# and there are one or more disks at /opt/subhost/$NAME/disk$i
+
+#set -x
+
+: ${NAME=$1}
+: ${NSNAME=$NAME}
+: ${SUBHOST=/opt/subhost/$NAME}
+: ${TARGET=$SUBHOST/live}
+: ${INITRD=$SUBHOST/initrd.gz}
+: ${CONFIG=$SUBHOST/config}
+
+[ -r "$CONFIG" ] && . $CONFIG
+
+# Generate a mac address for given arguments pass through 40-bit b2sum
+# and with 02: prefix.
+macaddr() {
+ local V="$(b2sum -l 40 <<< "$*" )"
+ V="$( sed 's/\(..\)/\1:/g' <<< "${V}aaaaaaaaaa")"
+ echo "02:${V:0:14}"
+}
+
+# Setup the subhost network namespace and link up the host side
+setup_cables() {
+ E=0
+ [ -e /var/run/netns/$NSNAME ] || ip netns add $NSNAME
+ for BRIDGE in ${BRIDGES[@]} ; do
+ IF=$NAME$E
+ B=( ${BRIDGE/:/ } )
+ BRIDGE="${B[0]}"
+ MAC="${B[1]}"
+ [ -z "$MAC" ] && MAC="$(macaddr "$(hostname)" "$NAME" "$IF")"
+ brctl show $BRIDGE >& /dev/null || brctl addbr $BRIDGE
+ 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
+}
+
+# loopdev path -- Make a named device node for a loop device
+copyloop() {
+ local MKNOD="mknod $(basename $2) b $(stat -c "%t %T" $1)"
+ if [ -e "$2" ] ; then
+ rm -f $2
+ else
+ mkdir -p $(dirname $2)
+ fi
+ ( cd $(dirname $2) && $MKNOD )
+}
+
+# diskid image partition# -- set up parition device node
+mkdevnode() {
+ local LOOP="$(losetup -j "$3" | sed 's/:.*//')"
+ [ -z "$LOOP" ] && LOOP="$(losetup -f --show "$3")"
+ grep -q $TARGET /proc/mounts || \
+ mount ${LOOP}p$2 $TARGET
+ copyloop $LOOP $TARGET/dev/$1
+ copyloop ${LOOP}p$2 $TARGET/dev/$1$2
+}
+
+# Setup device nodes for VM loopbacks according to $DISKS
+setup_rootfs() {
+ for DISK in ${DISKS[@]} ; do
+ D=( $(echo $DISK | tr : ' ') )
+ case "${D[0]}" in
+ vd*|sd*)
+ mkdevnode "${D[@]}"
+ ;;
+ *)
+ echo "Unknown disk type ${D[0]}" >&2
+ exit 1
+ ;;
+ esac
+ done
+}
+
+# Change $TARGET/dev/console
+setup_console() {
+ local SCRIPT=$$
+ CONSOLE=$TARGET/dev/console
+ rm -f $CONSOLE
+ ln -s $(tty) $CONSOLE
+}
+
+setup_cables
+setup_rootfs
+setup_console || exit 1
+
+# Install the current subhost-init startup script
+cp -p $(realpath $(dirname $0))/subhost-init startup $TARGET/
+
+######################################################################
+# Run the subhost
+ip netns exec $NSNAME unshare --fork --pid --mount-proc --kill-child \
+ --uts --ipc --mount --cgroup chroot $TARGET /startup
+######################################################################
+
+# Cleanup on exit
+umount $TARGET
+ip netns del $NSNAME
+true
+++ /dev/null
-#!/bin/bash
-#
-# This is a script to run at startup of a bespoke sub-host
-
-NOW=$(date +"%Y%m%d-%H%M%S")
-
-{
- echo "Startup at $NOW"
- set -x
-
- mkdir -p /dev/pts /dev/shm /run
- [ -f /proc/mounts ] || mount -t proc proc /proc
- if ! grep "^none /run tmpfs" /proc/mounts ; then
- mount -t tmpfs -osize=80M none /run
- mount -t tmpfs -osize=20M none /dev/shm
- mount -t devpts none /dev/pts
- mount -t sysfs none /sys
- mkdir -p /run/lock /run/user
- fi
-
- {
- # Restart auto interfaces
- for IF in $(grep "^auto" /etc/network/interfaces) ; do
- [ -e "/sys/class/net/$IF" ] || continue
- ifdown $IF
- ifup $IF
- done
-
- # Restart services
- SERVICES=( )
- for S in ${SERVICES[@]} ; do
- service $S restart
- done
- } &
- NETPID=$!
-
-} |& tee /var/log/startup-$NOW.log
-
-exec /bin/bash
--- /dev/null
+#!/bin/bash
+#
+# This is a script to run at startup of a bespoke sub-host
+
+date +"subhost startup at %Y%m%d-%H%M%S"
+
+mkdir -p /dev/pts /dev/shm /run
+[ -f /proc/mounts ] || mount -t proc proc /proc
+if ! grep "^none /run tmpfs" /proc/mounts ; then
+ mount -t tmpfs -osize=80M none /run
+ mount -t tmpfs -osize=20M none /dev/shm
+ mount -t devpts none /dev/pts
+ mount -t sysfs none /sys
+ mkdir -p /run/lock /run/user
+fi
+
+if grep -q ' / ext4 rw,' /proc/mounts ; then
+ ##
+ ## Here's the "pretend init"
+ ##
+
+ zombie() {
+ wait
+ true # echo "zombie return $?" >&2
+ }
+ trap "zombie" 17 # SIGCHILD
+
+ /etc/init.d/rc S < /dev/null
+ /etc/init.d/rc 2 < /dev/null
+ SUBHOSTCTL=/run/initctl
+ mkfifo $SUBHOSTCTL
+ exec cat < $SUBHOSTCTL
+ #exec /bin/bash -i
+else
+ echo "** The root filesystem is read-only; EXITING" >&2
+ exit 1
+fi