3 changed files with 143 additions and 39 deletions
@ -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 |
@ -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 |
@ -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 |
Loading…
Reference in new issue