4 changed files with 162 additions and 0 deletions
@ -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 |
|||
} |
@ -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 |
@ -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 |
@ -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 |
Loading…
Reference in new issue