documenting prtend boot variant
[rrq/subhost.git] / pretend-boot
1 #!/bin/bash
2 #
3 # Boot up subhost as if a vitual machine.
4 #
5 # There is already an existing network namespace of the right name,
6 # and there are one or more disks at /opt/subhost/$NAME/disk$i
7
8 #set -x
9
10 : ${NAME=$1}
11 : ${NSNAME=$NAME}
12 : ${SUBHOST=/opt/subhost/$NAME}
13 : ${TARGET=$SUBHOST/live}
14 : ${INITRD=$SUBHOST/initrd.gz}
15 : ${CONFIG=$SUBHOST/config}
16
17 [ -r "$CONFIG" ] && . $CONFIG
18
19 # Generate a mac address for given arguments pass through 40-bit b2sum
20 # and with 02: prefix.
21 macaddr() {
22     local V="$(b2sum -l 40 <<< "$*" )"
23     V="$( sed 's/\(..\)/\1:/g' <<< "${V}aaaaaaaaaa")"
24     echo "02:${V:0:14}"
25 }
26
27 # Setup the subhost network namespace and link up the host side
28 setup_cables() {
29     E=0
30     [ -e /var/run/netns/$NSNAME ] || ip netns add $NSNAME
31     for BRIDGE in ${BRIDGES[@]} ; do
32         IF=$NAME$E
33         B=( ${BRIDGE/:/ } )
34         BRIDGE="${B[0]}"
35         MAC="${B[1]}"
36         [ -z "$MAC" ] && MAC="$(macaddr "$(hostname)" "$NAME" "$IF")"
37         brctl show $BRIDGE >& /dev/null || brctl addbr $BRIDGE
38         ip link add $IF type veth peer name eth$E address $MAC netns $NSNAME 
39         ip link set $IF up
40         [ -n "$BRIDGE" ] && brctl addif $BRIDGE $IF
41         E=$((E+1))
42     done
43 }
44
45 # loopdev path -- Make a named device node for a loop device
46 copyloop() {
47     local MKNOD="mknod $(basename $2) b $(stat -c "%t %T" $1)"
48     if [ -e "$2" ] ; then
49         rm -f $2
50     else
51         mkdir -p $(dirname $2)
52     fi
53     ( cd $(dirname $2) && $MKNOD )
54 }
55
56 # diskid image partition# -- set up parition device node
57 mkdevnode() {
58     local LOOP="$(losetup -j "$3" | sed 's/:.*//')"
59     [ -z "$LOOP" ] && LOOP="$(losetup -f --show "$3")"
60     grep -q $TARGET /proc/mounts || \
61         mount ${LOOP}p$2 $TARGET
62     copyloop $LOOP $TARGET/dev/$1
63     copyloop ${LOOP}p$2 $TARGET/dev/$1$2
64 }
65
66 # Setup device nodes for VM loopbacks according to $DISKS
67 setup_rootfs() {
68     for DISK in ${DISKS[@]} ; do
69         D=( $(echo $DISK | tr : ' ') )
70         case "${D[0]}" in
71             vd*|sd*)
72                 mkdevnode "${D[@]}"
73                 ;;
74             *)
75                 echo "Unknown disk type ${D[0]}" >&2
76                 exit 1
77                 ;;
78         esac
79     done
80 }
81
82 # Change $TARGET/dev/console 
83 setup_console() {
84     local SCRIPT=$$
85     CONSOLE=$TARGET/dev/console
86     rm -f $CONSOLE
87     ln -s $(tty) $CONSOLE
88 }
89
90 setup_cables
91 setup_rootfs
92 setup_console || exit 1
93
94 # Install the current subhost-init startup script
95 cp -p $(realpath $(dirname $0))/subhost-init startup $TARGET/
96
97 ######################################################################
98 # Run the subhost
99 ip netns exec $NSNAME unshare --fork --pid --mount-proc --kill-child \
100      --uts --ipc --mount --cgroup chroot $TARGET /startup
101 ######################################################################
102
103 # Cleanup on exit
104 umount $TARGET
105 ip netns del $NSNAME
106 true