no more unversioned obsolete
[sliceimage.git] / bin / 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) rpms 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     echo "lxc-sliceimage: --- STARTING $(date) ---"
32
33     check_node
34     
35     mkdir -p $lxc_dir
36
37     slicefamilies=$(cd $sliceimage_dir ; ls )
38
39     for slicefamily in $slicefamilies; do
40         echo ==================== $slicefamily
41         # initialize if needed
42         [ -d $lxc_dir/$slicefamily ] || { 
43             echo "creating btrfs subvolume" ; 
44             btrfs subvolume create $lxc_dir/$slicefamily ;
45         }
46         # xxx what is that ?
47         #btrfs subvolume create $lxc_dir/lxc-squeeze-x86_64
48         # copy the slice image into the btrfs ?
49 #       echo "============================== mirroring start $(date)"
50         echo "$sliceimage_dir/$slicefamily/ onto btrfs subvolume $lxc_dir/$slicefamily/"
51         # mention --delete for rpm updates
52         # we want to keep only our own additions, that will be re-created in the remaining 
53         # of this script anyway
54         rsync -a --delete $sliceimage_dir/$slicefamily/ $lxc_dir/$slicefamily/ 
55 #       echo "============================== mirroring done $(date)"
56         # adapting slice images to the node virtualization mode can unfortunately
57         # not be done at build-time since we do not know that yet
58         patch_lvref $lxc_dir/$slicefamily
59     done
60
61     # create ref images from stubs
62     unfold_system_slices
63
64     echo "lxc-sliceimage: --- DONE $(date) ---"
65 }
66
67 function status () {
68     echo -n "Checking node .. "
69     check_node
70     echo OK
71     echo "From installed sliceimage variants"
72     ls $sliceimage_dir
73     echo "Exported to lxc"
74     ls $lxc_dir
75 }
76
77 # prefer to use e.g.
78 # sed -i $rootfs/etc/sudoers
79 # rather than
80 # chroot $rootfs sed -i /etc/sudoers
81 # because the latter has sed issue weird messages like
82 # sed: warning: failed to get security context of ...
83 function patch_lvref () {
84     rootfs=$1; shift
85
86     echo "patch_lvref : handling $rootfs"
87     
88     # Allow a user who logins via ssh to sudo
89     sed -i 's/^Defaults\ *requiretty/\#&/' $rootfs/etc/sudoers
90     # Allow to login at virsh console. loginuid.so doen't work in the absence of auditd
91     # which cannot run inside a container.
92     sed -i 's/^.*loginuid.so.*$/\#&/' $rootfs/etc/pam.d/login
93     # Enable eth0 on bootup
94     cat <<EOF > $rootfs/etc/sysconfig/network-scripts/ifcfg-eth0
95 DEVICE=eth0
96 BOOTPROTO=dhcp
97 ONBOOT=yes
98 EOF
99     # Tweak sshd configuration - not all slice images have sshd preinstalled
100     if [ -f $rootfs/etc/ssh/sshd_config ] ; then
101         sed -e 's/^UsePAM\ *yes/\#&/' \
102             -e 's/^GSSAPIAuthentication.*$/GSSAPIAuthentication no/' \
103             -e 's/^PasswordAuthentication.*$/PasswordAuthentication no/' \
104             -i $rootfs/etc/ssh/sshd_config
105     fi
106     # Allow root to login at virsh console
107     echo "pts/0" >> $rootfs/etc/securetty
108     # our image does not have NetworkManager, only network, and it is off by default
109     chroot $rootfs chkconfig network on
110
111     # this will run only if the rootfs seems to be systemd-based
112     patch_lvref_systemd $rootfs
113 }
114
115 # beware that patch_lvref_systemd will return early on non systemd-powered images
116 # inspired from https://gist.github.com/1142202
117 ETC=/etc/systemd/system
118 LIB=/lib/systemd/system
119
120 function patch_lvref_systemd () {
121     rootfs=$1; shift
122
123     absetc=$rootfs/$ETC
124     abslib=$rootfs/$LIB
125
126     # this applies to systemd only
127     [ -d $abslib ] || return
128
129     # stay away from trouble, avoid chroot'ing for straightforward stuff
130     echo "patch_lvref_systemd: handling $rootfs"
131     # sliceimage comes with graphical.target as default
132     ln -sf $LIB/multi-user.target $absetc/default.target
133     # sysinit.target seems to stick on boot, so disable it. However, we need
134     # systemd-tmpfiles-setup.service that was started by the dependency of
135     # sysinit.target to boot up correctly, so start it instead.
136     cp $abslib/basic.target $absetc/basic.target
137     sed -e 's/sysinit.target/systemd-tmpfiles-setup.service/' -i $absetc/basic.target
138     # Stop starting sysinit.target. Symlinking one to /dev/null is a standard way
139     # to disable a target (or a service and others).
140     ln -sf /dev/null $absetc/sysinit.target
141     # is also a cause of stuck on boot
142     ln -sf /dev/null $absetc/udev-settle.service
143     # It prevents systemd-tmpfiles-setup.service from starting
144     ln -sf /dev/null $absetc/fedora-readonly.service
145     # Libvirt lxc provides only tty1
146     rm -f $absetc/getty.target.wants/getty\@tty{2,3,4,5,6}.service
147     # It launches sulogin on console(tty1) but it interferes getty@tty1
148     ln -sf /dev/null $absetc/console-shell.service
149     # Workarounds for libvirt 0.9.4. Without this, getty@tty1 doen't launch
150     # because a trigger event on tty1 doesn't happen.
151     cp $abslib/getty\@.service $absetc/getty\@.service
152     sed -e 's/^BindTo/\#&/' -i $absetc/getty\@.service
153     ln -sf $ETC/getty\@.service $absetc/getty.target.wants/getty\@tty1.service
154
155 }
156
157 function unfold_system_slices () {
158     for clonedstamp in $sliceimage_stubs/*/*.cloned; do
159         unfold_system_slice_from_cloned $clonedstamp
160     done
161 }
162
163 # untested - how does this behave when updating the slice reference image ?
164 # OTOH system slices probably already run at update-time 
165 # so it's kind of too late anyways
166 function unfold_system_slice_from_cloned () {
167     clonedstamp=$1; shift
168     # e.g. NAME=planetflow
169     NAME=$(basename $clonedstamp .cloned)
170     DIR=$(dirname $clonedstamp)
171     # e.g. SLICEFAMILY=planetlab-f8-i386
172     SLICEFAMILY=$(cat $clonedstamp)
173     # deduce the actual name used in .vref by replacing the first part of slice-family 
174     # (pldistro) with the slice name
175     # e.g. VREFNAME=planetflow-f8-i386
176     VREFNAME=$(echo $SLICEFAMILY | sed -e "s,^[^-]*-,$NAME-,")
177
178     VREFPATH="$lxc_dir/$VREFNAME"
179
180     # do not redo existing vref's unless force is mentioned
181     [ -z "$FORCE" -a -d "$VREFPATH" ] && {
182         echo "unfold_system_slice_from_cloned : $VREFPATH looks fine" ;
183         return ;
184     }
185     [ -z "$FORCE" ] && message=Building
186     [ -n "$FORCE" ] && message=Force-building
187
188     # Copy base reference image
189     echo -n $"$message slice image for $NAME in $VREFNAME: "
190
191     # build the systemslice from the one it was originally cloned from
192     FAMILYREF="$lxc_dir/$SLICEFAMILY"
193     if [ ! -d "$FAMILYREF" ] ; then
194         echo system slice from $clonedstamp - could not find reference $FAMILYREF - skipped
195         return
196     fi
197     
198     # safe side
199     mkdir -p "$lxc_dir"
200     # cleanup reference image if already exists
201     [ -d "$VREFPATH" ] && btrfs subvolume delete "$VREFPATH"
202     # extra safe
203     [ -d "$VREFPATH" ] && rm -rf "$VREFPATH"
204
205     # clone subvolume
206     btrfs subvolume snapshot $FAMILYREF $VREFPATH
207     
208     # merge the stub with the reference to get the system slice
209     (cd "$DIR/$NAME"/ && find . | cpio -m -d -u -p "$VREFPATH"/) || \
210         { echo "Could not apply stub $DIR/$NAME - skipping $clonedstamp" ; btrfs subvolume delete "$VREFPATH" ; return ; }
211
212     # Clean RPM state
213     rm -f "$VREFPATH/var/lib/rpm/__db"*
214
215     echo Done
216 }
217
218 # run with the --tty option to see results, otherwise get that logged
219 case "$1" in
220     --tty) shift;;
221     *) exec >> /var/log/lxc-sliceimage 2>&1 ;;
222 esac
223
224 case "$1" in
225     start|restart|reload)       start ; exit 0 ;;
226     status)                     status ; exit 0 ;;
227     stop)                       exit 0 ;;
228     *)  echo $"Usage: $0 [--tty] {start|stop|status}"
229         exit 1
230         ;;
231 esac