patching the vref images was buggy
[vserver-reference.git] / initscripts / lxc-sliceimage
1 #!/bin/bash
2 #
3 # chkconfig: 345 20 80
4 # description: Create BTRFS subvolumes for LXC reference images.
5 #
6 # Thierry Parmentelat <thierry.parmentelat@inria.fr>
7 # Copyright (C) 2012 INRIA
8 #
9
10 # not needed -- Source function library
11 #. /etc/init.d/functions
12
13 # a f>=18 root context won't have /bin nor /sbin in its path, which is where
14 # chkconfig is located on f<=14 images
15 export PATH=$PATH:/bin:/sbin
16
17 # This is where sliceimage(s) store their reference images
18 sliceimage_dir=/vservers/.vref
19 sliceimage_stubs=/vservers/.vstub
20 lxc_dir=/vservers/.lvref
21 tmp_dir=/vservers/.ltmp
22
23 # Check if we are in the build environment
24 function check_node () {
25     mount | grep -q 'planetlab-vservers' || exit 0
26     [ -d $sliceimage_dir ] || { echo "No sliceimage installed" ; exit 1; }
27 }
28
29 function start () {
30
31     check_node
32     
33     mkdir -p $lxc_dir
34
35     slicefamilies=$(cd $sliceimage_dir ; ls )
36
37     for slicefamily in $slicefamilies; do
38         # initialize if needed
39         [ -d $lxc_dir/$slicefamily ] || btrfs subvolume create $lxc_dir/$slicefamily
40         # xxx what is that ?
41         #btrfs subvolume create $lxc_dir/lxc-squeeze-x86_64
42         # copy the slice image into the btrfs ?
43         rsync -a --delete $sliceimage_dir/$slicefamily/ $lxc_dir/$slicefamily/
44         # tmp -- should very probably be done at build time
45         patch_lvref $lxc_dir/$slicefamily
46     done
47
48     # create ref images from stubs
49     unfold_system_slices
50 }
51
52 function status () {
53     echo -n "Checking node .. "
54     check_node
55     echo OK
56     echo "From installed sliceimage variants"
57     ls $sliceimage_dir
58     echo "Exported to lxc"
59     ls $lxc_dir
60 }
61
62 # beware that patch_lvref_systemd will return early on non systemd-powered images
63 function patch_lvref () {
64     rootfs=$1; shift
65     
66     # Allow a user who logins via ssh to sudo
67     chroot $rootfs sed -i 's/^Defaults\ *requiretty/\#&/' /etc/sudoers
68     # Allow to login at virsh console. loginuid.so doen't work in the absence of auditd
69     # which cannot run inside a container.
70     chroot $rootfs sed -i 's/^.*loginuid.so.*$/\#&/' /etc/pam.d/login
71     # Enable eth0 on bootup
72     cat <<EOF > $rootfs/etc/sysconfig/network-scripts/ifcfg-eth0
73 DEVICE=eth0
74 BOOTPROTO=dhcp
75 ONBOOT=yes
76 EOF
77     # Tweak sshd configuration
78     chroot $rootfs sed -i 's/^UsePAM\ *yes/\#&/' /etc/ssh/sshd_config
79     # commenting out the defaults in the file is not enough, need to explicitly set these to no
80     chroot $rootfs sed -i 's/^GSSAPIAuthentication.*$/GSSAPIAuthentication no/' /etc/ssh/sshd_config
81     chroot $rootfs sed -i 's/^PasswordAuthentication.*$/PasswordAuthentication no/' /etc/ssh/sshd_config
82     # Allow root to login at virsh console
83     echo "pts/0" >> $rootfs/etc/securetty
84     # our image does not have NetworkManager, only network, and it is off by default
85     chroot $rootfs chkconfig network on
86
87     # this will run only if the rootfs seems to be systemd-based
88     patch_lvref_systemd $rootfs
89 }
90
91 # inspired from https://gist.github.com/1142202
92 ETC=/etc/systemd/system
93 LIB=/lib/systemd/system
94 function patch_lvref_systemd () {
95     rootfs=$1; shift
96
97     # this applies to systemd only
98     [ -d $rootfs/$LIB ] || return
99
100     # sliceimage comes with graphical.target as default
101     chroot $rootfs ln -sf $LIB/multi-user.target $ETC/default.target
102     # sysinit.target seems to stick on boot, so disable it. However, we need
103     # systemd-tmpfiles-setup.service that was started by the dependency of
104     # sysinit.target to boot up correctly, so start it instead.
105     chroot $rootfs cp $LIB/basic.target $ETC/basic.target
106     chroot $rootfs sed -i 's/sysinit.target/systemd-tmpfiles-setup.service/' $ETC/basic.target
107     # Stop starting sysinit.target. Symlinking one to /dev/null is a standard way
108     # to disable a target (or a service and others).
109     chroot $rootfs ln -s /dev/null $ETC/sysinit.target
110     # It also a cause of stuck on boot
111     chroot $rootfs ln -s /dev/null $ETC/udev-settle.service
112     # It prevents systemd-tmpfiles-setup.service from starting
113     chroot $rootfs ln -s /dev/null $ETC/fedora-readonly.service
114     # Libvirt lxc provides only tty1
115     chroot $rootfs rm -f $ETC/getty.target.wants/getty\@tty{2,3,4,5,6}.service
116     # It launches sulogin on console(tty1) but it interferes getty@tty1
117     chroot $rootfs ln -s /dev/null $ETC/console-shell.service
118     # Workarounds for libvirt 0.9.4. Without this, getty@tty1 doen't launch
119     # because a trigger event on tty1 doesn't happen.
120     chroot $rootfs cp $LIB/getty\@.service $ETC/getty\@.service
121     chroot $rootfs sed -i 's/^BindTo/\#&/' $ETC/getty\@.service
122     chroot $rootfs ln -sf $ETC/getty\@.service $ETC/getty.target.wants/getty\@tty1.service
123
124 }
125
126 function unfold_system_slices () {
127     for clonedstamp in $sliceimage_stubs/*/*.cloned; do
128         unfold_system_slice_from_cloned $clonedstamp
129     done
130 }
131
132 function unfold_system_slice_from_cloned () {
133     clonedstamp=$1; shift
134     # e.g. NAME=planetflow
135     NAME=$(basename $clonedstamp .cloned)
136     DIR=$(dirname $clonedstamp)
137     # e.g. SLICEFAMILY=planetlab-f8-i386
138     SLICEFAMILY=$(cat $clonedstamp)
139     # deduce the actual name used in .vref by replacing the first part of slice-family 
140     # (pldistro) with the slice name
141     # e.g. VREFNAME=planetflow-f8-i386
142     VREFNAME=$(echo $SLICEFAMILY | sed -e "s,^[^-]*-,$NAME-,")
143
144     VREFPATH="$lxc_dir/$VREFNAME"
145
146     # do not redo existing vref's unless force is mentioned
147     [ -z "$FORCE" -a -d "$VREFPATH" ] && continue
148     [ -z "$FORCE" ] && message=Building
149     [ -n "$FORCE" ] && message=Force-building
150
151     # Copy base reference image
152     echo -n $"$message slice image for $NAME in $VREFNAME: "
153
154     # build the systemslice from the one it was originally cloned from
155     FAMILYREF="$lxc_dir/$SLICEFAMILY"
156     if [ ! -d "$FAMILYREF" ] ; then
157         echo system slice from $clonedstamp - could not find reference $FAMILYREF - skipped
158         return
159     fi
160     
161     # safe side
162     mkdir -p "$lxc_dir"
163     # cleanup reference image if already exists
164     [ -d "$VREFPATH" ] && btrfs subvolume delete "$VREFPATH"
165     # extra safe
166     [ -d "$VREFPATH" ] && rm -rf "$VREFPATH"
167
168     # clone subvolume
169     btrfs subvolume snapshot $FAMILYREF $VREFPATH
170     
171     # merge the stub with the reference to get the system slice
172     (cd "$DIR/$NAME"/ && find . | cpio -m -d -u -p "$VREFPATH"/) || \
173         { echo "Could not apply stub $DIR/$NAME - skipping $clonedstamp" ; btrfs subvolume delete "$VREFPATH" ; return ; }
174
175     # Clean RPM state
176     rm -f "$VREFPATH/var/lib/rpm/__db"*
177
178     echo Done
179 }
180
181 case "$1" in
182     start|restart|reload)       start ; exit 0 ;;
183     status)                     status ; exit 0 ;;
184     stop)                       exit 0 ;;
185     *)  echo $"Usage: $0 {start|stop|status}"
186         exit 1
187         ;;
188 esac
189