+#!/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