From: Ralph Ronnquist Date: Thu, 3 Mar 2022 04:47:50 +0000 (+1100) Subject: tarting subhost almost as if booted X-Git-Url: https://git.rrq.au/?a=commitdiff_plain;h=1ac9828de4fad474b1a286fb62d43685c7fc9ac1;p=rrq%2Fsubhost.git tarting subhost almost as if booted --- diff --git a/pretend-boot b/pretend-boot new file mode 100755 index 0000000..1eaf034 --- /dev/null +++ b/pretend-boot @@ -0,0 +1,106 @@ +#!/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 diff --git a/startup b/startup deleted file mode 100755 index dd07b98..0000000 --- a/startup +++ /dev/null @@ -1,39 +0,0 @@ -#!/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 diff --git a/subhost-init b/subhost-init new file mode 100755 index 0000000..6fbb25d --- /dev/null +++ b/subhost-init @@ -0,0 +1,37 @@ +#!/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