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