patching the vref images was buggy
[sliceimage.git] / initscripts / lxc-sliceimage
index e17f838..3bf56ab 100755 (executable)
@@ -1,14 +1,24 @@
 #!/bin/bash
+#
 # chkconfig: 345 20 80
 # description: Create BTRFS subvolumes for LXC reference images.
 #
+# Thierry Parmentelat <thierry.parmentelat@inria.fr>
+# Copyright (C) 2012 INRIA
+#
 
 # not needed -- Source function library
 #. /etc/init.d/functions
 
+# a f>=18 root context won't have /bin nor /sbin in its path, which is where
+# chkconfig is located on f<=14 images
+export PATH=$PATH:/bin:/sbin
+
 # This is where sliceimage(s) store their reference images
 sliceimage_dir=/vservers/.vref
+sliceimage_stubs=/vservers/.vstub
 lxc_dir=/vservers/.lvref
+tmp_dir=/vservers/.ltmp
 
 # Check if we are in the build environment
 function check_node () {
@@ -30,8 +40,13 @@ function start () {
         # xxx what is that ?
        #btrfs subvolume create $lxc_dir/lxc-squeeze-x86_64
         # copy the slice image into the btrfs ?
-       rsync -av $sliceimage_dir/$slicefamily/ $lxc_dir/$slicefamily/
+       rsync -a --delete $sliceimage_dir/$slicefamily/ $lxc_dir/$slicefamily/
+       # tmp -- should very probably be done at build time
+       patch_lvref $lxc_dir/$slicefamily
     done
+
+    # create ref images from stubs
+    unfold_system_slices
 }
 
 function status () {
@@ -44,6 +59,125 @@ function status () {
     ls $lxc_dir
 }
 
+# beware that patch_lvref_systemd will return early on non systemd-powered images
+function patch_lvref () {
+    rootfs=$1; shift
+    
+    # Allow a user who logins via ssh to sudo
+    chroot $rootfs sed -i 's/^Defaults\ *requiretty/\#&/' /etc/sudoers
+    # Allow to login at virsh console. loginuid.so doen't work in the absence of auditd
+    # which cannot run inside a container.
+    chroot $rootfs sed -i 's/^.*loginuid.so.*$/\#&/' /etc/pam.d/login
+    # Enable eth0 on bootup
+    cat <<EOF > $rootfs/etc/sysconfig/network-scripts/ifcfg-eth0
+DEVICE=eth0
+BOOTPROTO=dhcp
+ONBOOT=yes
+EOF
+    # Tweak sshd configuration
+    chroot $rootfs sed -i 's/^UsePAM\ *yes/\#&/' /etc/ssh/sshd_config
+    # commenting out the defaults in the file is not enough, need to explicitly set these to no
+    chroot $rootfs sed -i 's/^GSSAPIAuthentication.*$/GSSAPIAuthentication no/' /etc/ssh/sshd_config
+    chroot $rootfs sed -i 's/^PasswordAuthentication.*$/PasswordAuthentication no/' /etc/ssh/sshd_config
+    # Allow root to login at virsh console
+    echo "pts/0" >> $rootfs/etc/securetty
+    # our image does not have NetworkManager, only network, and it is off by default
+    chroot $rootfs chkconfig network on
+
+    # this will run only if the rootfs seems to be systemd-based
+    patch_lvref_systemd $rootfs
+}
+
+# inspired from https://gist.github.com/1142202
+ETC=/etc/systemd/system
+LIB=/lib/systemd/system
+function patch_lvref_systemd () {
+    rootfs=$1; shift
+
+    # this applies to systemd only
+    [ -d $rootfs/$LIB ] || return
+
+    # sliceimage comes with graphical.target as default
+    chroot $rootfs ln -sf $LIB/multi-user.target $ETC/default.target
+    # sysinit.target seems to stick on boot, so disable it. However, we need
+    # systemd-tmpfiles-setup.service that was started by the dependency of
+    # sysinit.target to boot up correctly, so start it instead.
+    chroot $rootfs cp $LIB/basic.target $ETC/basic.target
+    chroot $rootfs sed -i 's/sysinit.target/systemd-tmpfiles-setup.service/' $ETC/basic.target
+    # Stop starting sysinit.target. Symlinking one to /dev/null is a standard way
+    # to disable a target (or a service and others).
+    chroot $rootfs ln -s /dev/null $ETC/sysinit.target
+    # It also a cause of stuck on boot
+    chroot $rootfs ln -s /dev/null $ETC/udev-settle.service
+    # It prevents systemd-tmpfiles-setup.service from starting
+    chroot $rootfs ln -s /dev/null $ETC/fedora-readonly.service
+    # Libvirt lxc provides only tty1
+    chroot $rootfs rm -f $ETC/getty.target.wants/getty\@tty{2,3,4,5,6}.service
+    # It launches sulogin on console(tty1) but it interferes getty@tty1
+    chroot $rootfs ln -s /dev/null $ETC/console-shell.service
+    # Workarounds for libvirt 0.9.4. Without this, getty@tty1 doen't launch
+    # because a trigger event on tty1 doesn't happen.
+    chroot $rootfs cp $LIB/getty\@.service $ETC/getty\@.service
+    chroot $rootfs sed -i 's/^BindTo/\#&/' $ETC/getty\@.service
+    chroot $rootfs ln -sf $ETC/getty\@.service $ETC/getty.target.wants/getty\@tty1.service
+
+}
+
+function unfold_system_slices () {
+    for clonedstamp in $sliceimage_stubs/*/*.cloned; do
+       unfold_system_slice_from_cloned $clonedstamp
+    done
+}
+
+function unfold_system_slice_from_cloned () {
+    clonedstamp=$1; shift
+    # e.g. NAME=planetflow
+    NAME=$(basename $clonedstamp .cloned)
+    DIR=$(dirname $clonedstamp)
+    # e.g. SLICEFAMILY=planetlab-f8-i386
+    SLICEFAMILY=$(cat $clonedstamp)
+    # deduce the actual name used in .vref by replacing the first part of slice-family 
+    # (pldistro) with the slice name
+    # e.g. VREFNAME=planetflow-f8-i386
+    VREFNAME=$(echo $SLICEFAMILY | sed -e "s,^[^-]*-,$NAME-,")
+
+    VREFPATH="$lxc_dir/$VREFNAME"
+
+    # do not redo existing vref's unless force is mentioned
+    [ -z "$FORCE" -a -d "$VREFPATH" ] && continue
+    [ -z "$FORCE" ] && message=Building
+    [ -n "$FORCE" ] && message=Force-building
+
+    # Copy base reference image
+    echo -n $"$message slice image for $NAME in $VREFNAME: "
+
+    # build the systemslice from the one it was originally cloned from
+    FAMILYREF="$lxc_dir/$SLICEFAMILY"
+    if [ ! -d "$FAMILYREF" ] ; then
+       echo system slice from $clonedstamp - could not find reference $FAMILYREF - skipped
+       return
+    fi
+    
+    # safe side
+    mkdir -p "$lxc_dir"
+    # cleanup reference image if already exists
+    [ -d "$VREFPATH" ] && btrfs subvolume delete "$VREFPATH"
+    # extra safe
+    [ -d "$VREFPATH" ] && rm -rf "$VREFPATH"
+
+    # clone subvolume
+    btrfs subvolume snapshot $FAMILYREF $VREFPATH
+    
+    # merge the stub with the reference to get the system slice
+    (cd "$DIR/$NAME"/ && find . | cpio -m -d -u -p "$VREFPATH"/) || \
+       { echo "Could not apply stub $DIR/$NAME - skipping $clonedstamp" ; btrfs subvolume delete "$VREFPATH" ; return ; }
+
+    # Clean RPM state
+    rm -f "$VREFPATH/var/lib/rpm/__db"*
+
+    echo Done
+}
+
 case "$1" in
     start|restart|reload)      start ; exit 0 ;;
     status)                    status ; exit 0 ;;