Setting tag planetlab-umts-tools-0.7-1
[build.git] / vbuild-init-lxc.sh
index def2330..561be5e 100755 (executable)
@@ -19,8 +19,7 @@ DEFAULT_IFNAME=eth0
 COMMAND_VBUILD="vbuild-init-lxc.sh"
 COMMAND_MYPLC="vtest-init-lxc.sh"
 
-lxc_version="0.8.0-rc2"
-
+libvirt_version="1.0.4"
 function bridge_init () {
 
     # turn on verbosity
@@ -66,7 +65,7 @@ function bridge_init () {
     address=$(/sbin/ip addr show $INTERFACE_LAN | grep -v inet6 | grep inet | head --lines=1 | awk '{print $2;}')
     [ -z "$address" ] && { echo "ERROR: Could not determine IP address for $INTERFACE_LAN" ; exit 1 ; }
 
-broadcast=$(/sbin/ip addr show $INTERFACE_LAN | grep -v inet6 | grep inet | head --lines=1 | awk '{print $4;}')
+    broadcast=$(/sbin/ip addr show $INTERFACE_LAN | grep -v inet6 | grep inet | head --lines=1 | awk '{print $4;}')
     [ -z "$broadcast" ] && echo "WARNING: Could not determine broadcast address for $INTERFACE_LAN"
 
     gateway=$(netstat -rn | grep '^0.0.0.0' | awk '{print $2;}')
@@ -139,37 +138,27 @@ function check_yumgroup_installed () {
 }
 
 function prepare_host() {
-        
-    #################### lxc-tools : rebuild as current fedora release has flaws
-    #install development tools
-    check_yumgroup_installed "Development Tools"
-    #install libcap-devel, libvirt
-    check_yum_installed libcap-devel
-    check_yum_installed libvirt
-
-    #retrieve and install lxc from sources 
-    raw_version=$(lxc-version ||: )
-    lxc_installed_version=$(echo $raw_version | sed -e 's,.*: ,,')
-    if [ "$lxc_installed_version" != "$lxc_version" ] ; then
-       echo "Expecting version" '['$lxc_version']'
-       echo "Found version" '['$lxc_installed_version']'
-        echo "Installing lxc ..."
-        cd /root
-       [ -d lxc ] || git clone git://lxc.git.sourceforge.net/gitroot/lxc/lxc 
-        cd lxc
-       git pull
-       git checkout $lxc_version
-        ./autogen.sh
-        ./configure --prefix=/usr --exec-prefix=/usr
-        make
-        make install
-        mkdir -p /usr/var/lib/
-        [ -d /usr/var/lib/lxc ] || ln -s /var/lib/lxc /usr/var/lib/lxc
-       cd $BUILD_DIR
-    fi
-#    #create a placeholder (just a hack to make lxc works)
-#    [ -d "/usr/local/var/lib" ] || mkdir -p /usr/local/var/lib
+   
+    host_fcdistro="$(cat /etc/fedora-release | cut -d' ' -f3)"    
+    ## check if libvirt_version is installed
+    virsh -v | grep -e $libvirt_version || { echo "$libvirt_version needs to be installed!!!" ; exit 1 ; }
+#    host_fcdistro="$(cat /etc/fedora-release | cut -d' ' -f3)"
+#    if [ ! -f /etc/yum.repos.d/libvirt.repo ] ; then
+#       touch /etc/yum.repos.d/libvirt.repo
+#       cat <<EOF > /etc/yum.repos.d/libvirt.repo
+#[libvirt]
+#name=libvirt-1.0.2-1
+#baseurl=http://build.onelab.eu/lxc/2013.02.25--lxc$host_fcdistro/RPMS/
+#enabled=1
+#gpgcheck=0
+#EOF
+#
+#       yum --assumeno update
+#       check_yumgroup_installed "Development Tools"
+#       check_yum_installed libcap-devel
+#       check_yum_installed libvirt
+#       systemctl start libvirtd
+#    fi
 
     #################### bride initialization
     check_yum_installed bridge-utils
@@ -207,15 +196,20 @@ MTU=1500
 EOF
 
 # set the hostname
+if [[ "$fcdistro" == "f18" ]] ; then
+    cat <<EOF > ${rootfs_path}/etc/hostname
+$HOSTNAME
+EOF
+else
     cat <<EOF > ${rootfs_path}/etc/sysconfig/network
 NETWORKING=yes
 HOSTNAME=$HOSTNAME
 EOF
-
     # set minimal hosts
-#    cat <<EOF > $rootfs_path/etc/hosts
-#127.0.0.1 localhost $HOSTNAME
-#EOF
+    cat <<EOF > $rootfs_path/etc/hosts
+127.0.0.1 localhost $HOSTNAME
+EOF
+fi
 
     dev_path="${rootfs_path}/dev"
     rm -rf $dev_path
@@ -248,20 +242,33 @@ function configure_fedora_init() {
 
     sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc/rc.sysinit
     sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc/rc.d/rc.sysinit
-    chroot ${rootfs_path} chkconfig udev-post off
-    chroot ${rootfs_path} chkconfig network on
+    # don't mount devpts, for pete's sake
+    sed -i 's/^.*dev.pts.*$/#\0/' ${rootfs_path}/etc/rc.sysinit
+    sed -i 's/^.*dev.pts.*$/#\0/' ${rootfs_path}/etc/rc.d/rc.sysinit
+    chroot ${rootfs_path} /sbin/chkconfig udev-post off
+    chroot ${rootfs_path} /sbin/chkconfig network on
 }
 
-
+# this code of course is for guests that do run on systemd
 function configure_fedora_systemd() {
-
+    # so ignore if we can't find /etc/systemd at all 
+    [ -d ${rootfs_path}/etc/systemd ] || return 0
+    # otherwise let's proceed
     unlink ${rootfs_path}/etc/systemd/system/default.target
+    ln -s /lib/systemd/system/multi-user.target ${rootfs_path}/etc/systemd/system/default.target
     touch ${rootfs_path}/etc/fstab
-    chroot ${rootfs_path} ln -s /dev/null //etc/systemd/system/udev.service
-    chroot ${rootfs_path} ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target
-    #dependency on a device unit fails it specially that we disabled udev
-    sed -i 's/After=dev-%i.device/After=/' ${rootfs_path}/lib/systemd/system/getty\@.service
-    chroot ${rootfs_path} chkconfig network on
+    ln -s /dev/null ${rootfs_path}/etc/systemd/system/udev.service
+# Thierry - Feb 2013
+# this was intended for f16 initially, in order to enable getty that otherwise would not start
+# having a getty running is helpful only if ssh won't start though, and we see a correlation between
+# VM's that refuse to lxc-stop and VM's that run crazy getty's
+# so, turning getty off for now instead
+#   #dependency on a device unit fails it specially that we disabled udev
+#    sed -i 's/After=dev-%i.device/After=/' ${rootfs_path}/lib/systemd/system/getty\@.service
+    ln -s /dev/null ${rootfs_path}/etc/systemd/system/"getty@.service"
+    rm -f ${rootfs_path}/etc/systemd/system/getty.target.wants/*service || :
+# can't seem to handle this one with systemctl
+    chroot ${rootfs_path} /sbin/chkconfig network on
 }
 
 function download_fedora() {
@@ -269,26 +276,64 @@ set -x
     # check the mini fedora was not already downloaded
     INSTALL_ROOT=$cache/partial
     echo $INSTALL_ROOT
+
+    # download a mini fedora into a cache
+    echo "Downloading fedora minimal ..."
+
     mkdir -p $INSTALL_ROOT
     if [ $? -ne 0 ]; then
         echo "Failed to create '$INSTALL_ROOT' directory"
         return 1
     fi
 
-    # download a mini fedora into a cache
-    echo "Downloading fedora minimal ..."
-    YUM="yum --installroot $INSTALL_ROOT -y --nogpgcheck --releasever=$release"
-    PKG_LIST="yum initscripts passwd rsyslog vim-minimal dhclient chkconfig rootfiles policycoreutils openssh-server openssh-clients"
-  
-    
+    mkdir -p $INSTALL_ROOT/etc/yum.repos.d   
+    mkdir -p $INSTALL_ROOT/dev
+    mknod -m 0444 $INSTALL_ROOT/dev/random c 1 8
+    mknod -m 0444 $INSTALL_ROOT/dev/urandom c 1 9
+
+    # copy yum config and repo files
+    cp /etc/yum.conf $INSTALL_ROOT/etc/
+    cp /etc/yum.repos.d/fedora* $INSTALL_ROOT/etc/yum.repos.d/
+
+    # append fedora repo files with desired $release and $basearch
+    for f in $INSTALL_ROOT/etc/yum.repos.d/*
+    do
+      sed -i "s/\$basearch/$arch/g; s/\$releasever/$release/g;" $f
+    done 
+
     MIRROR_URL=http://mirror.onelab.eu/fedora/releases/$release/Everything/$arch/os
-    RELEASE_URL="$MIRROR_URL/Packages/fedora-release-$release-1.noarch.rpm"
-    echo "Fetching from $RELEASE_URL"
-    curl -f "$RELEASE_URL" > $INSTALL_ROOT/fedora-release-$release.noarch.rpm
+    RELEASE_URL1="$MIRROR_URL/Packages/fedora-release-$release-1.noarch.rpm"
+    # with fedora18 the rpms are scattered by first name
+    RELEASE_URL2="$MIRROR_URL/Packages/f/fedora-release-$release-1.noarch.rpm"
+    RELEASE_TARGET=$INSTALL_ROOT/fedora-release-$release.noarch.rpm
+    found=""
+    for attempt in $RELEASE_URL1 $RELEASE_URL2; do
+       if curl -f $attempt -o $RELEASE_TARGET ; then
+           echo "Retrieved $attempt"
+           found=true
+           break
+       else
+           echo "Failed attempt $attempt"
+       fi
+    done
+    [ -n "$found" ] || { echo "Could not retrieve fedora-release rpm - exiting" ; exit 1; }
     
     mkdir -p $INSTALL_ROOT/var/lib/rpm
     rpm --root $INSTALL_ROOT  --initdb
-    rpm --root $INSTALL_ROOT -ivh $INSTALL_ROOT/fedora-release-$release.noarch.rpm
+    # when installing f12 this apparently is already present, so ignore result
+    rpm --root $INSTALL_ROOT -ivh $INSTALL_ROOT/fedora-release-$release.noarch.rpm || :
+    # however f12 root images won't get created on a f18 host
+    # (the issue here is the same as the one we ran into when dealing with a vs-box)
+    # in a nutshell, in f12 the glibc-common and filesystem rpms have an apparent conflict
+    # >>> file /usr/lib/locale from install of glibc-common-2.11.2-3.x86_64 conflicts 
+    #          with file from package filesystem-2.4.30-2.fc12.x86_64
+    # in fact this was - of course - allowed by f12's rpm but later on a fix was made 
+    #   http://rpm.org/gitweb?p=rpm.git;a=commitdiff;h=cf1095648194104a81a58abead05974a5bfa3b9a
+    # So ideally if we want to be able to build f12 images from f18 we need an rpm that has
+    # this patch undone, like we have in place on our f14 boxes (our f14 boxes need a f18-like rpm)
+
+    YUM="yum --installroot=$INSTALL_ROOT --nogpgcheck -y"
+    PKG_LIST="yum initscripts passwd rsyslog vim-minimal dhclient chkconfig rootfiles policycoreutils openssh-server openssh-clients"
     echo "$YUM install $PKG_LIST"
     $YUM install $PKG_LIST
 
@@ -435,16 +480,16 @@ function configure_yum_in_lxc () {
 
     cat > $rootfs_path/etc/yum.repos.d/building.repo <<EOF
 [fedora]
-name=Fedora $release - \$basearch
-baseurl=http://mirror.onelab.eu/fedora/releases/$release/Everything/\$basearch/os/
+name=Fedora $release - $arch
+baseurl=http://mirror.onelab.eu/fedora/releases/$release/Everything/$arch/os/
 enabled=1
 metadata_expire=7d
 gpgcheck=1
 gpgkey=http://mirror.onelab.eu/keys/RPM-GPG-KEY-fedora-$release-primary
 
 [updates]
-name=Fedora $release - \$basearch - Updates
-baseurl=http://mirror.onelab.eu/fedora/updates/$release/\$basearch/
+name=Fedora $release - $arch - Updates
+baseurl=http://mirror.onelab.eu/fedora/updates/$release/$arch/
 enabled=1
 metadata_expire=7d
 gpgcheck=1
@@ -537,8 +582,7 @@ function setup_lxc() {
         exit 1
     fi
 
-    type /bin/systemd >/dev/null 2>&1
-    if [ $? -ne 0 ]; then
+    if [ "$(echo $fcdistro | cut -d"f" -f2)" -le "14" ]; then
         configure_fedora_init
     else
         configure_fedora_systemd
@@ -556,31 +600,50 @@ function setup_lxc() {
     mkdir $rootfs_path/root/.ssh
     cat /root/.ssh/id_rsa.pub >> $rootfs_path/root/.ssh/authorized_keys
     
-    # start container
-    lxc-start -d -n $lxc
-
-    lxc-wait -n $lxc -s RUNNING
-
-    echo $IP is up, waiting for ssh...
-
-    # wait max 5 min for sshd to start 
-    ssh_up=""
-    stop_time=$(($(date +%s) + 300))
-    current_time=$(date +%s)
-
-    while [ "$current_time" -lt "$stop_time" ] ; do
-         echo "ssh attempt ..."
-         ssh -o "StrictHostKeyChecking no" $IP 'uname -i' && { ssh_up=true; echo "SSHD in container $lxc is UP"; break ; } || :
-         sleep 10
-         current_time=$(($current_time + 10))
-    done
-
-    [ -z $ssh_up ] && echo "SSHD in container $lxc is not running"
-     
+    # copy libvirt xml template
+    veth_pair="i$(echo $HOSTNAME | cut -d. -f1)" 
+    tmpl_name="$lxc.xml"
+    cat > $config_path/$tmpl_name<<EOF
+<domain type='lxc'>
+  <name>$lxc</name>
+  <memory>524288</memory>
+  <os>
+    <type arch='$arch2'>exe</type>
+    <init>/sbin/init</init>
+  </os>
+  <features>
+    <acpi/>
+  </features>
+  <vcpu>1</vcpu>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/libexec/libvirt_lxc</emulator>
+    <filesystem type='mount'>
+      <source dir='$rootfs_path'/>
+      <target dir='/'/>
+    </filesystem>
+    <interface type="bridge">
+      <source bridge="br0"/>
+      <target dev='$veth_pair'/>
+    </interface>
+    <console type='pty' />
+  </devices>
+  <network>
+    <name>host-bridge</name>
+    <forward mode="bridge"/>
+    <bridge name="br0"/>
+  </network>
+</domain>
+EOF
+   
+    # define lxc container for libvirt
+    virsh -c lxc:// define $config_path/$tmpl_name
 
     # rpm --rebuilddb
-    chroot $rootfs_path rpm --rebuilddb
-    #ssh -o "StrictHostKeyChecking no" $IP "rpm --rebuilddb"
+    chroot $rootfs_path /bin/rpm --rebuilddb
 
     configure_yum_in_lxc $lxc $fcdistro $pldistro
 
@@ -611,27 +674,27 @@ function devel_or_vtest_tools () {
     ### install individual packages, then groups
     # get target arch - use uname -i here (we want either x86_64 or i386)
    
-    lxc_arch=$(chroot $rootfs_path uname -i)
+    lxc_arch=$(chroot $rootfs_path /bin/uname -i)
     # on debian systems we get arch through the 'arch' command
-    [ "$lxc_arch" = "unknown" ] && lxc_arch=$(chroot $rootfs_path arch)
+    [ "$lxc_arch" = "unknown" ] && lxc_arch=$(chroot $rootfs_path /bin/arch)
 
     packages=$(pl_getPackages -a $lxc_arch $fcdistro $pldistro $pkgsfile)
     groups=$(pl_getGroups -a $lxc_arch $fcdistro $pldistro $pkgsfile)
 
     case "$pkg_method" in
        yum)
-           [ -n "$packages" ] && chroot $rootfs_path yum -y install $packages
+           [ -n "$packages" ] && chroot $rootfs_path /usr/bin/yum -y install $packages
            for group_plus in $groups; do
                group=$(echo $group_plus | sed -e "s,+++, ,g")
-               chroot $rootfs_path yum -y groupinstall "$group"
+               chroot $rootfs_path /usr/bin/yum -y groupinstall "$group"
            done
            # store current rpm list in /init-lxc.rpms in case we need to check the contents
-           chroot $rootfs_path rpm -aq > $rootfs_path/init-lxc.rpms
+           chroot $rootfs_path /bin/rpm -aq > $rootfs_path/init-lxc.rpms
            ;;
        debootstrap)
-           chroot $rootfs_path apt-get update
+           chroot $rootfs_path /usr/bin/apt-get update
            for package in $packages ; do 
-               chroot $rootfs_path  apt-get install -y $package 
+               chroot $rootfs_path  /usr/bin/apt-get install -y $package 
            done
            ### xxx todo install groups with apt..
            ;;
@@ -665,29 +728,29 @@ function post_install_vbuild () {
 
 ### From myplc-devel-native.spec
 # be careful to backslash $ in this, otherwise it's the root context that's going to do the evaluation
-    cat << EOF | chroot $rootfs_path bash -x
+    cat << EOF | chroot $rootfs_path /bin/bash -x
     # set up /dev/loop* in lxc
     for i in \$(seq 0 255) ; do
-       mknod -m 640 /dev/loop\$i b 7 \$i
+       /bin/mknod -m 640 /dev/loop\$i b 7 \$i
     done
     
     # create symlink for /dev/fd
-    [ ! -e "/dev/fd" ] && ln -s /proc/self/fd /dev/fd
+    [ ! -e "/dev/fd" ] && /bin/ln -s /proc/self/fd /dev/fd
 
     # modify /etc/rpm/macros to not use /sbin/new-kernel-pkg
-    sed -i 's,/sbin/new-kernel-pkg:,,' /etc/rpm/macros
+    /bin/sed -i 's,/sbin/new-kernel-pkg:,,' /etc/rpm/macros
     if [ -h "/sbin/new-kernel-pkg" ] ; then
-       filename=\$(readlink -f /sbin/new-kernel-pkg)
+       filename=\$(/bin/readlink -f /sbin/new-kernel-pkg)
        if [ "\$filename" == "/sbin/true" ] ; then
-               echo "WARNING: /sbin/new-kernel-pkg symlinked to /sbin/true"
-               echo "\tmost likely /etc/rpm/macros has /sbin/new-kernel-pkg declared in _netsharedpath."
-               echo "\tPlease remove /sbin/new-kernel-pkg from _netsharedpath and reintall mkinitrd."
+               /bin/echo "WARNING: /sbin/new-kernel-pkg symlinked to /sbin/true"
+               /bin/echo "\tmost likely /etc/rpm/macros has /sbin/new-kernel-pkg declared in _netsharedpath."
+               /bin/echo "\tPlease remove /sbin/new-kernel-pkg from _netsharedpath and reintall mkinitrd."
                exit 1
        fi
     fi
     
     # customize root's prompt
-    cat << PROFILE > /root/.profile
+    /bin/cat << PROFILE > /root/.profile
 export PS1="[$lxc] \\w # "
 PROFILE
 
@@ -723,28 +786,60 @@ function post_install_myplc  () {
     personality=$1; shift
 
 # be careful to backslash $ in this, otherwise it's the root context that's going to do the evaluation
-    cat << EOF | chroot $rootfs_path bash -x
+    cat << EOF | chroot $rootfs_path /bin/bash -x
 
     # create /etc/sysconfig/network if missing
-    [ -f /etc/sysconfig/network ] || echo NETWORKING=yes > /etc/sysconfig/network
+    [ -f /etc/sysconfig/network ] || /bin/echo NETWORKING=yes > /etc/sysconfig/network
 
     # create symlink for /dev/fd
-    [ ! -e "/dev/fd" ] && ln -s /proc/self/fd /dev/fd
+    [ ! -e "/dev/fd" ] && /bin/ln -s /proc/self/fd /dev/fd
 
     # turn off regular crond, as plc invokes plc_crond
-    chkconfig crond off
+    /sbin/chkconfig crond off
 
     # take care of loginuid in /etc/pam.d 
-    sed -i "s,#*\(.*loginuid.*\),#\1," /etc/pam.d/*
+    /bin/sed -i "s,#*\(.*loginuid.*\),#\1," /etc/pam.d/*
 
     # customize root's prompt
-    cat << PROFILE > /root/.profile
+    /bin/cat << PROFILE > /root/.profile
 export PS1="[$lxc] \\w # "
 PROFILE
 
 EOF
 }
 
+function start_lxc() {
+
+    set -x
+    set -e
+    #trap failure ERR INT
+
+    lxc=$1; shift
+  
+    virsh -c lxc:// start $lxc
+  
+    echo $IP is up, waiting for ssh...
+
+    #wait max 5 min for sshd to start 
+    ssh_up=""
+    stop_time=$(($(date +%s) + 300))
+    current_time=$(date +%s)
+    
+    counter=1
+    while [ "$current_time" -lt "$stop_time" ] ; do
+         echo "$counter-th attempt to reach sshd in container $lxc ..."
+         ssh -o "StrictHostKeyChecking no" $IP 'uname -i' && { ssh_up=true; echo "SSHD in container $lxc is UP"; break ; } || :
+         sleep 10
+         current_time=$(($current_time + 10))
+         counter=$(($counter+1))
+    done
+
+    # Thierry: this is fatal, let's just exit with a failure here
+    [ -z $ssh_up ] && { echo "SSHD in container $lxc is not running" ; exit 1 ; } 
+
+    return 0
+}
+
 function usage () {
     set +x 
     echo "Usage: $COMMAND_VBUILD [options] lxc-name"
@@ -840,7 +935,7 @@ function main () {
 
     if [ "$personality" == "linux32" ]; then
         arch=i386
-        arch2=x86
+        arch2=i686
     elif [ "$personality" == "linux64" ]; then
         arch=x86_64
         arch2=x86_64
@@ -870,7 +965,8 @@ function main () {
     else
         [[ -z "$REPO_URL" ]] && usage
         [[ -z "$IP" ]] && usage
-        NETMASK=$(ifconfig br0 | grep 'inet addr' | awk '{print $4}' | sed -e 's/.*://')
+       
+        NETMASK=$(ifconfig br0 | grep 'inet ' | awk '{print $4}' | sed -e 's/.*://')
         GATEWAY=$(route -n | grep 'UG' | awk '{print $2}')
         [[ -z "$HOSTNAME" ]] && usage
         lxc_network_type=veth
@@ -886,7 +982,8 @@ function main () {
           exit 1
     fi
 
-    path=/var/lib/lxc
+    path=/vservers
+    [ ! -d $path ] && mkdir $path
     rootfs_path=$path/$lxc/rootfs
     config_path=$path/$lxc
     cache_base=/var/cache/lxc/fedora/$arch
@@ -903,6 +1000,7 @@ function main () {
 
     post_install $lxc $personality
     
+    start_lxc $lxc
 
     echo $COMMAND Done
 }