pcucontrol@master
[build.git] / lbuild-initvm.sh
index 9eda8d9..aa71460 100755 (executable)
@@ -1,87 +1,54 @@
 #!/bin/bash
 # -*-shell-*-
 
 #!/bin/bash
 # -*-shell-*-
 
+# close stdin, as with ubuntu and debian VMs this script tends to hang and wait for input ..
+0<&-
+
 #shopt -s huponexit
 
 COMMAND=$(basename $0)
 DIRNAME=$(dirname $0)
 BUILD_DIR=$(pwd)
 
 #shopt -s huponexit
 
 COMMAND=$(basename $0)
 DIRNAME=$(dirname $0)
 BUILD_DIR=$(pwd)
 
-# pkgs parsing utilities
-PATH=$(dirname $0):$PATH export PATH
+# pkgs parsing utilities + lbuild-bridge.sh
+export PATH=$(dirname $0):$PATH
 
 # old guests have e.g. mount in /bin but this is no longer part of 
 # the standard PATH in recent hosts after usrmove, so let's keep it simple
 
 # old guests have e.g. mount in /bin but this is no longer part of 
 # the standard PATH in recent hosts after usrmove, so let's keep it simple
-export PATH=PATH=$PATH:/bin:/sbin 
+export PATH=$PATH:/bin:/sbin
 
 . build.common
 
 
 . build.common
 
-DEFAULT_FCDISTRO=f20
+# xxx fixme : we pass $lxc around in functions,
+# but in fact then we use lxc_root which is a global..
+# it works, but this really is poor practice
+# we should have an lxc_root function instead
+function lxcroot () {
+    lxc=$1; shift
+    echo /vservers/$lxc
+}
+
+# XXX fixme : when creating a 32bits VM we need to call linux32 as appropriate...s
+
+DEFAULT_FCDISTRO=f27
 DEFAULT_PLDISTRO=lxc
 DEFAULT_PERSONALITY=linux64
 DEFAULT_PLDISTRO=lxc
 DEFAULT_PERSONALITY=linux64
-
-COMMAND_LBUILD="lbuild-initvm.sh"
-COMMAND_LTEST="ltest-initvm.sh"
+DEFAULT_MEMORY=3072
 
 ##########
 
 ##########
-# when creating build boxes we use private NAT'ed addresses for the VMs
-# as per virbr0 that is taken care of by libvirt at startup
-PRIVATE_BRIDGE="virbr0"
-PRIVATE_PREFIX="192.168.122."
-PRIVATE_GATEWAY="192.168.122.1"
-# beware that changing this would break the logic of random_private_byte...
-PRIVATE_MASKLEN=24
-
-# we just try randomly in that range until a free IP address shows up
-PRIVATE_ATTEMPTS=20
-
 # constant
 PUBLIC_BRIDGE=br0
 
 # the network interface name as seen from the container
 VIF_GUEST=eth0
 
 # constant
 PUBLIC_BRIDGE=br0
 
 # the network interface name as seen from the container
 VIF_GUEST=eth0
 
-##############################
-## stolen from tests/system/template-qemu/qemu-bridge-init
-# use /proc/net/dev instead of a hard-wired list
-function gather_interfaces () {
-    python <<EOF
-for line in file("/proc/net/dev"):
-    if ':' not in line: continue
-    ifname=line.replace(" ","").split(":")[0]
-    if ifname.find("lo")==0: continue
-    if ifname.find("br")==0: continue
-    if ifname.find("virbr")==0: continue
-    if ifname.find("tap")==0: continue
-    print ifname
-EOF
-}
-
-function discover_interface () {
-    for ifname in $(gather_interfaces); do
-       ip link show $ifname | grep -qi 'state UP' && { echo $ifname; return; }
-    done
-    # still not found ? that's bad
-    echo unknown
-}
-########## check for a free IP
-function ip_is_busy () {
-    target=$1; shift
-    ping -c 1 -W 1 $target >& /dev/null
-}
-
-function random_private_byte () {
-    for attempt in $(seq $PRIVATE_ATTEMPTS); do
-       byte=$(($RANDOM % 256))
-       if [ "$byte" == 0 -o "$byte" == 1 ] ; then continue; fi
-       ip=${PRIVATE_PREFIX}${byte}
-       ip_is_busy $ip || { echo $byte; return; }
-    done
-    echo "Cannot seem to find a free IP address in range ${PRIVATE_PREFIX}.xx/24 after $PRIVATE_ATTEMPTS attempts - exiting"
-    exit 1
-}
+##########
+FEDORA_MIRROR_BASE="http://mirror.onelab.eu/fedora/"
+FEDORA_MIRROR_KEYS="http://mirror.onelab.eu/keys/"
+FEDORA_PREINSTALLED="yum initscripts passwd rsyslog vim-minimal dhclient chkconfig rootfiles policycoreutils openssh-server openssh-clients"
+DEBIAN_PREINSTALLED="openssh-server openssh-client"
 
 
-########## networking -- ctd
+########## networking utilities
 function gethostbyname () {
     hostname=$1
     python -c "import socket; print socket.gethostbyname('"$hostname"')" 2> /dev/null
 function gethostbyname () {
     hostname=$1
     python -c "import socket; print socket.gethostbyname('"$hostname"')" 2> /dev/null
@@ -109,100 +76,17 @@ print ".".join([ str(256-2**(8-i)) for i in result ])
 EOF
 }
 
 EOF
 }
 
-#################### bridge initialization
-function create_bridge_if_needed() {
-   
-    # turn on verbosity
-    set -x
-
-    # already created ? - we're done
-    ip addr show $PUBLIC_BRIDGE >& /dev/null && {
-       echo "Bridge already set up - skipping create_bridge_if_needed"
-       return 0
-    }
-
-    # find out the physical interface to bridge onto
-    if_lan=$(discover_interface)
-
-    ip addr show $if_lan &>/dev/null || {
-        echo "Cannot use interface $if_lan - exiting"
-        exit 1
-    }
-
-    #################### bride initialization
-    check_yum_installed bridge-utils
-
-    echo "========== $COMMAND: entering create_bridge - beg"
-    hostname
-    uname -a
-    ip addr show
-    ip route
-    echo "========== $COMMAND: entering create_bridge - end"
-
-    # disable netfilter calls for bridge interface (they cause panick on 2.6.35 anyway)
-    #
-    # another option would be to accept the all forward packages for
-    # bridged interface like: -A FORWARD -m physdev --physdev-is-bridged -j ACCEPT
-    sysctl net.bridge.bridge-nf-call-iptables=0
-    sysctl net.bridge.bridge-nf-call-ip6tables=0
-    sysctl net.bridge.bridge-nf-call-arptables=0
-
-    
-    #Getting host IP/masklen
-    address=$(ip addr show $if_lan | grep -v inet6 | grep inet | head --lines=1 | awk '{print $2;}')
-    [ -z "$address" ] && { echo "ERROR: Could not determine IP address for $if_lan" ; exit 1 ; }
-
-    broadcast=$(ip addr show $if_lan | grep -v inet6 | grep inet | head --lines=1 | awk '{print $4;}')
-    [ -z "$broadcast" ] && echo "WARNING: Could not determine broadcast address for $if_lan"
-
-    gateway=$(ip route show | grep default | awk '{print $3;}')
-    [ -z "$gateway" ] && echo "WARNING: Could not determine gateway IP"
-
-
-    # creating the bridge
-    echo "Creating bridge PUBLIC_BRIDGE=$PUBLIC_BRIDGE"
-    brctl addbr $PUBLIC_BRIDGE
-    brctl addif $PUBLIC_BRIDGE $if_lan
-    echo "Activating promiscuous mode if_lan=$if_lan"
-    ip link set $if_lan up promisc on
-    sleep 2
-    # rely on dhcp to re assign IP.. 
-    echo "Starting dhclient on $PUBLIC_BRIDGE"
-    dhclient $PUBLIC_BRIDGE
-    sleep 1
-
-    #Reconfigure the routing table
-    echo "Configuring gateway=$gateway"
-    ip route add default via $gateway dev $PUBLIC_BRIDGE
-    ip route del default via $gateway dev $if_lan
-    # at this point we have an extra route like e.g.
-    ## ip route show
-    #default via 138.96.112.250 dev br0
-    #138.96.112.0/21 dev em1  proto kernel  scope link  src 138.96.112.57
-    #138.96.112.0/21 dev br0  proto kernel  scope link  src 138.96.112.57
-    #192.168.122.0/24 dev virbr0  proto kernel  scope link  src 192.168.122.1
-    route_dest=$(ip route show | grep -v default | grep "dev $PUBLIC_BRIDGE" | awk '{print $1;}')
-    ip route del $route_dest dev $if_lan
-
-    echo "========== $COMMAND: exiting create_bridge - beg"
-    ip addr show
-    ip route show
-    echo "========== $COMMAND: exiting create_bridge - end"
-
-    # for safety
-    sleep 3
-    return 0
-
-}
-
 ##############################
 # return yum or debootstrap
 function package_method () {
     fcdistro=$1; shift
     case $fcdistro in
 ##############################
 # return yum or debootstrap
 function package_method () {
     fcdistro=$1; shift
     case $fcdistro in
-       f[0-9]*|centos[0-9]*|sl[0-9]*) echo yum ;;
-       squeeze|wheezy|oneiric|precise|quantal|raring|saucy) echo debootstrap ;;
-       *) echo Unknown distro $fcdistro ;;
+       f[0-9]*|centos[0-9]*|sl[0-9]*)
+           echo yum ;;
+       wheezy|jessie|precise|trusty|utopic|vivid|wily|xenial)
+           echo debootstrap ;;
+       *)
+           echo Unknown distro $fcdistro ;;
     esac 
 }
 
     esac 
 }
 
@@ -229,51 +113,47 @@ function almost_empty () {
     count=$(cd $dir; ls | wc -l); [ $count -le 1 ]; 
 }
 
     count=$(cd $dir; ls | wc -l); [ $count -le 1 ]; 
 }
 
-##############################
-function check_yum_installed () {
-    package=$1; shift
-    rpm -q $package >& /dev/null || yum -y install $package
-}
-
-function check_yumgroup_installed () {
-    group="$1"; shift
-    yum grouplist "$group" | grep -q Installed || { yum -y groupinstall "$group" ; }
-}
-
 ##############################
 function fedora_install() {
     set -x
     set -e
 
 ##############################
 function fedora_install() {
     set -x
     set -e
 
-    mkdir -p /var/lock/subsys/
+    lxc=$1; shift
+    lxc_root=$(lxcroot $lxc)
+
+    cache=/var/cache/lxc/fedora/$arch/${fedora_release}
+    mkdir -p $cache
+    
     (
     (
-        flock -n -x 200 || { echo "Cache repository is busy." ; return 1 ; }
+        flock --exclusive --timeout 60 200 || { echo "Cache repository is busy." ; return 1 ; }
 
         if [ ! -e "$cache/rootfs" ]; then
             echo "Getting cache download in $cache/rootfs ... "
 
         if [ ! -e "$cache/rootfs" ]; then
             echo "Getting cache download in $cache/rootfs ... "
-            fedora_download || { echo "Failed to download 'fedora base'"; return 1; }
+            fedora_download $cache || { echo "Failed to download 'fedora base'"; return 1; }
         else
             echo "Updating cache $cache/rootfs ..."
         else
             echo "Updating cache $cache/rootfs ..."
-           if ! yum --installroot $cache/rootfs -y --nogpgcheck update ; then
+           if ! yum --installroot $cache/rootfs --releasever ${fedora_release} -y --nogpgcheck update ; then
                 echo "Failed to update 'fedora base', continuing with last known good cache"
             else
                 echo "Update finished"
             fi
         fi
 
                 echo "Failed to update 'fedora base', continuing with last known good cache"
             else
                 echo "Update finished"
             fi
         fi
 
-        echo "Copy $cache/rootfs to $rootfs_path ... "
-       mkdir -p $rootfs_path
-       rsync -a $cache/rootfs/ $rootfs_path/
+        echo "Filling $lxc_root from $cache/rootfs ... "
+       rsync -a $cache/rootfs/ $lxc_root/
        
         return 0
 
        
         return 0
 
-        ) 200>/var/lock/subsys/lxc
+        ) 200> $cache/lock
 
     return $?
 }
 
 function fedora_download() {
     set -x
 
     return $?
 }
 
 function fedora_download() {
     set -x
+
+    cache=$1; shift
+
     # check the mini fedora was not already downloaded
     INSTALL_ROOT=$cache/partial
     echo $INSTALL_ROOT
     # check the mini fedora was not already downloaded
     INSTALL_ROOT=$cache/partial
     echo $INSTALL_ROOT
@@ -292,18 +172,21 @@ function fedora_download() {
     cp /etc/yum.conf $INSTALL_ROOT/etc/
     cp /etc/yum.repos.d/fedora* $INSTALL_ROOT/etc/yum.repos.d/
 
     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
+    # append fedora repo files with desired ${fedora_release} and $basearch
     for f in $INSTALL_ROOT/etc/yum.repos.d/* ; do
     for f in $INSTALL_ROOT/etc/yum.repos.d/* ; do
-      sed -i "s/\$basearch/$arch/g; s/\$releasever/$release/g;" $f
+      sed -i "s/\$basearch/$arch/g; s/\$releasever/${fedora_release}/g;" $f
     done 
 
     done 
 
-    MIRROR_URL=http://mirror.onelab.eu/fedora/releases/$release/Everything/$arch/os
-    RELEASE_URL1="$MIRROR_URL/Packages/fedora-release-$release-1.noarch.rpm"
+    MIRROR_URL=$FEDORA_MIRROR_BASE/releases/${fedora_release}/Everything/$arch/os
+    RELEASE_URL1="$MIRROR_URL/Packages/fedora-release-${fedora_release}-1.noarch.rpm"
     # with fedora18 the rpms are scattered by first name
     # 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
+    # first try the second version of fedora-release first
+    RELEASE_URL2="$MIRROR_URL/Packages/f/fedora-release-${fedora_release}-2.noarch.rpm"
+    RELEASE_URL3="$MIRROR_URL/Packages/f/fedora-release-${fedora_release}-1.noarch.rpm"
+   
+    RELEASE_TARGET=$INSTALL_ROOT/fedora-release-${fedora_release}.noarch.rpm
     found=""
     found=""
-    for attempt in $RELEASE_URL1 $RELEASE_URL2; do
+    for attempt in $RELEASE_URL1 $RELEASE_URL2 $RELEASE_URL3; do
        if curl -f $attempt -o $RELEASE_TARGET ; then
            echo "Retrieved $attempt"
            found=true
        if curl -f $attempt -o $RELEASE_TARGET ; then
            echo "Retrieved $attempt"
            found=true
@@ -317,7 +200,7 @@ function fedora_download() {
     mkdir -p $INSTALL_ROOT/var/lib/rpm
     rpm --root $INSTALL_ROOT  --initdb
     # when installing f12 this apparently is already present, so ignore result
     mkdir -p $INSTALL_ROOT/var/lib/rpm
     rpm --root $INSTALL_ROOT  --initdb
     # when installing f12 this apparently is already present, so ignore result
-    rpm --root $INSTALL_ROOT -ivh $INSTALL_ROOT/fedora-release-$release.noarch.rpm || :
+    rpm --root $INSTALL_ROOT -ivh $INSTALL_ROOT/fedora-release-${fedora_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
     # 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
@@ -328,10 +211,9 @@ function fedora_download() {
     # 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)
 
     # 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 || { echo "Failed to download rootfs, aborting." ; return 1; }
+    YUM="yum --installroot=$INSTALL_ROOT --releasever=${fedora_release} --nogpgcheck -y"
+    echo "$YUM install $FEDORA_PREINSTALLED"
+    $YUM install $FEDORA_PREINSTALLED || { echo "Failed to download rootfs, aborting." ; return 1; }
 
     mv "$INSTALL_ROOT" "$cache/rootfs"
     echo "Download complete."
 
     mv "$INSTALL_ROOT" "$cache/rootfs"
     echo "Download complete."
@@ -345,30 +227,36 @@ function fedora_configure() {
     set -x
     set -e
 
     set -x
     set -e
 
+    lxc=$1; shift
+    lxc_root=$(lxcroot $lxc)
+
     # disable selinux in fedora
     # disable selinux in fedora
-    mkdir -p $rootfs_path/selinux
-    echo 0 > $rootfs_path/selinux/enforce
+    mkdir -p $lxc_root/selinux
+    echo 0 > $lxc_root/selinux/enforce
 
     # set the hostname
     case "$fcdistro" in 
        f18|f2?)
 
     # set the hostname
     case "$fcdistro" in 
        f18|f2?)
-           cat <<EOF > ${rootfs_path}/etc/hostname
+            cat <<EOF > ${lxc_root}/etc/sysconfig/network
+NETWORKING=yes
+EOF
+           cat <<EOF > ${lxc_root}/etc/hostname
 $GUEST_HOSTNAME
 EOF
            echo ;;
        *)
 $GUEST_HOSTNAME
 EOF
            echo ;;
        *)
-            cat <<EOF > ${rootfs_path}/etc/sysconfig/network
+            cat <<EOF > ${lxc_root}/etc/sysconfig/network
 NETWORKING=yes
 HOSTNAME=$GUEST_HOSTNAME
 EOF
             # set minimal hosts
 NETWORKING=yes
 HOSTNAME=$GUEST_HOSTNAME
 EOF
             # set minimal hosts
-           cat <<EOF > $rootfs_path/etc/hosts
+           cat <<EOF > $lxc_root/etc/hosts
 127.0.0.1 localhost $GUEST_HOSTNAME
 EOF
            echo ;;
     esac
 
 127.0.0.1 localhost $GUEST_HOSTNAME
 EOF
            echo ;;
     esac
 
-    dev_path="${rootfs_path}/dev"
+    dev_path="${lxc_root}/dev"
     rm -rf $dev_path
     mkdir -p $dev_path
     mknod -m 666 ${dev_path}/null c 1 3
     rm -rf $dev_path
     mkdir -p $dev_path
     mknod -m 666 ${dev_path}/null c 1 3
@@ -388,19 +276,16 @@ EOF
     mknod -m 600 ${dev_path}/initctl p
     mknod -m 666 ${dev_path}/ptmx c 5 2
 
     mknod -m 600 ${dev_path}/initctl p
     mknod -m 666 ${dev_path}/ptmx c 5 2
 
-    #echo "setting root passwd to $root_password"
-    #echo "root:$root_password" | chroot $rootfs_path chpasswd
-
     if [ "$(echo $fcdistro | cut -d"f" -f2)" -le "14" ]; then
     if [ "$(echo $fcdistro | cut -d"f" -f2)" -le "14" ]; then
-       fedora_configure_init
+       fedora_configure_init $lxc
     else
     else
-       fedora_configure_systemd
+       fedora_configure_systemd $lxc
     fi
 
     fi
 
-    guest_ifcfg=${rootfs_path}/etc/sysconfig/network-scripts/ifcfg-$VIF_GUEST
-    ( [ -n "$BUILD_MODE" ] && write_guest_ifcfg_build || write_guest_ifcfg_test ) > $guest_ifcfg
+    guest_ifcfg=${lxc_root}/etc/sysconfig/network-scripts/ifcfg-$VIF_GUEST
+    ( [ -n "$NAT_MODE" ] && write_guest_ifcfg_natip || write_guest_ifcfg_publicip ) > $guest_ifcfg
 
 
-    fedora_configure_yum $lxc $fcdistro $pldistro
+    [ -z "$IMAGE" ] && fedora_configure_yum $lxc $fcdistro $pldistro
 
     return 0
 }
 
     return 0
 }
@@ -408,36 +293,38 @@ EOF
 function fedora_configure_init() {
     set -e
     set -x
 function fedora_configure_init() {
     set -e
     set -x
-    sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc/rc.sysinit
-    sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc/rc.d/rc.sysinit
+    lxc=$1; shift
+    lxc_root=$(lxcroot $lxc)
+
+    sed -i 's|.sbin.start_udev||' ${lxc_root}/etc/rc.sysinit
+    sed -i 's|.sbin.start_udev||' ${lxc_root}/etc/rc.d/rc.sysinit
     # don't mount devpts, for pete's sake
     # 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} chkconfig udev-post off
-    chroot ${rootfs_path} chkconfig network on
+    sed -i 's/^.*dev.pts.*$/#\0/' ${lxc_root}/etc/rc.sysinit
+    sed -i 's/^.*dev.pts.*$/#\0/' ${lxc_root}/etc/rc.d/rc.sysinit
+    chroot ${lxc_root} $personality chkconfig udev-post off
+    chroot ${lxc_root} $personality chkconfig network on
 }
 
 # this code of course is for guests that do run on systemd
 function fedora_configure_systemd() {
     set -e
     set -x
 }
 
 # this code of course is for guests that do run on systemd
 function fedora_configure_systemd() {
     set -e
     set -x
+    lxc=$1; shift
+    lxc_root=$(lxcroot $lxc)
+
     # so ignore if we can't find /etc/systemd at all 
     # so ignore if we can't find /etc/systemd at all 
-    [ -d ${rootfs_path}/etc/systemd ] || return 0
+    [ -d ${lxc_root}/etc/systemd ] || return 0
     # otherwise let's proceed
     # otherwise let's proceed
-    ln -sf /lib/systemd/system/multi-user.target ${rootfs_path}/etc/systemd/system/default.target
-    touch ${rootfs_path}/etc/fstab
-    ln -sf /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
+    ln -sf /lib/systemd/system/multi-user.target ${lxc_root}/etc/systemd/system/default.target
+    touch ${lxc_root}/etc/fstab
+    ln -sf /dev/null ${lxc_root}/etc/systemd/system/udev.service
+# Thierry - Feb 2013 relying on getty is looking for trouble
 # so, turning getty off for now instead
 # 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 -sf /dev/null ${rootfs_path}/etc/systemd/system/"getty@.service"
-    rm -f ${rootfs_path}/etc/systemd/system/getty.target.wants/*service || :
+#    sed -i 's/After=dev-%i.device/After=/' ${lxc_root}/lib/systemd/system/getty\@.service
+    ln -sf /dev/null ${lxc_root}/etc/systemd/system/"getty@.service"
+    rm -f ${lxc_root}/etc/systemd/system/getty.target.wants/*service || :
 # can't seem to handle this one with systemctl
 # can't seem to handle this one with systemctl
-    chroot ${rootfs_path} chkconfig network on
+    chroot ${lxc_root} $personality chkconfig network on
 }
 
 # overwrite container yum config
 }
 
 # overwrite container yum config
@@ -450,43 +337,48 @@ function fedora_configure_yum () {
     fcdistro=$1; shift
     pldistro=$1; shift
 
     fcdistro=$1; shift
     pldistro=$1; shift
 
+    lxc_root=$(lxcroot $lxc)
     # rpm --rebuilddb
     # rpm --rebuilddb
-    chroot $rootfs_path rpm --rebuilddb
+    chroot ${lxc_root} $personality rpm --rebuilddb
 
     echo "Initializing yum.repos.d in $lxc"
 
     echo "Initializing yum.repos.d in $lxc"
-    rm -f $rootfs_path/etc/yum.repos.d/*
+    rm -f $lxc_root/etc/yum.repos.d/*
 
 
-    cat > $rootfs_path/etc/yum.repos.d/building.repo <<EOF
+    cat > $lxc_root/etc/yum.repos.d/building.repo <<EOF
 [fedora]
 [fedora]
-name=Fedora $release - $arch
-baseurl=http://mirror.onelab.eu/fedora/releases/$release/Everything/$arch/os/
+name=Fedora \$releasever - \$basearch
+baseurl=$FEDORA_MIRROR_BASE/releases/\$releasever/Everything/\$basearch/os/
 enabled=1
 metadata_expire=7d
 gpgcheck=1
 enabled=1
 metadata_expire=7d
 gpgcheck=1
-gpgkey=http://mirror.onelab.eu/keys/RPM-GPG-KEY-fedora-$release-primary
+gpgkey=$FEDORA_MIRROR_KEYS/RPM-GPG-KEY-fedora-${fedora_release}-primary
 
 [updates]
 
 [updates]
-name=Fedora $release - $arch - Updates
-baseurl=http://mirror.onelab.eu/fedora/updates/$release/$arch/
+name=Fedora \$releasever - \$basearch - Updates
+baseurl=$FEDORA_MIRROR_BASE/updates/\$releasever/\$basearch/
 enabled=1
 metadata_expire=7d
 gpgcheck=1
 enabled=1
 metadata_expire=7d
 gpgcheck=1
-gpgkey=http://mirror.onelab.eu/keys/RPM-GPG-KEY-fedora-$release-primary
+gpgkey=$FEDORA_MIRROR_KEYS/RPM-GPG-KEY-fedora-${fedora_release}-primary
 EOF
 EOF
-    
-    # for using vtest-init-lxc.sh as a general-purpose lxc creation wrapper
+
+    # import fedora key so that gpgckeck does not whine or require stdin
+    # required since fedora24
+    rpm --root $lxc_root --import $FEDORA_MIRROR_KEYS/RPM-GPG-KEY-fedora-${fedora_release}-primary
+
+    # for using this script as a general-purpose lxc creation wrapper
     # just mention 'none' as the repo url
     if [ -n "$REPO_URL" ] ; then
     # just mention 'none' as the repo url
     if [ -n "$REPO_URL" ] ; then
-       if [ ! -d $rootfs_path/etc/yum.repos.d ] ; then
+       if [ ! -d $lxc_root/etc/yum.repos.d ] ; then
            echo "WARNING : cannot create myplc repo"
        else
             # exclude kernel from fedora repos 
            yumexclude=$(pl_plcyumexclude $fcdistro $pldistro $DIRNAME)
            echo "WARNING : cannot create myplc repo"
        else
             # exclude kernel from fedora repos 
            yumexclude=$(pl_plcyumexclude $fcdistro $pldistro $DIRNAME)
-           for repo in $rootfs_path/etc/yum.repos.d/* ; do
+           for repo in $lxc_root/etc/yum.repos.d/* ; do
                [ -f $repo ] && yumconf_exclude $repo "exclude=$yumexclude" 
            done
            # the build repo is not signed at this stage
                [ -f $repo ] && yumconf_exclude $repo "exclude=$yumexclude" 
            done
            # the build repo is not signed at this stage
-           cat > $rootfs_path/etc/yum.repos.d/myplc.repo <<EOF
+           cat > $lxc_root/etc/yum.repos.d/myplc.repo <<EOF
 [myplc]
 name= MyPLC
 baseurl=$REPO_URL
 [myplc]
 name= MyPLC
 baseurl=$REPO_URL
@@ -498,14 +390,17 @@ EOF
 }    
 
 ##############################
 }    
 
 ##############################
+# apparently ubuntu exposes a mirrors list by country at
+# http://mirrors.ubuntu.com/mirrors.txt
 # need to specify the right mirror for debian variants like ubuntu and the like
 function debian_mirror () {
     fcdistro=$1; shift
     case $fcdistro in
 # need to specify the right mirror for debian variants like ubuntu and the like
 function debian_mirror () {
     fcdistro=$1; shift
     case $fcdistro in
-       squeeze|wheezy
+       wheezy|jessie
            echo http://ftp2.fr.debian.org/debian/ ;;
            echo http://ftp2.fr.debian.org/debian/ ;;
-       oneiric|precise|quantal|raring|saucy) 
-           echo http://mir1.ovh.net/ubuntu/ubuntu/ ;;
+       precise|trusty|utopic|vivid|wily|xenial) 
+#          echo http://mir1.ovh.net/ubuntu/ubuntu/ ;;
+           echo http://www-ftp.lip6.fr/pub/linux/distributions/Ubuntu/archive/ ;;
        *) echo unknown distro $fcdistro; exit 1;;
     esac
 }
        *) echo unknown distro $fcdistro; exit 1;;
     esac
 }
@@ -513,31 +408,44 @@ function debian_mirror () {
 function debian_install () {
     set -e
     set -x
 function debian_install () {
     set -e
     set -x
-    mkdir -p $rootfs_path
+    lxc=$1; shift
+    lxc_root=$(lxcroot $lxc)
+    mkdir -p $lxc_root
     arch=$(canonical_arch $personality $fcdistro)
     mirror=$(debian_mirror $fcdistro)
     arch=$(canonical_arch $personality $fcdistro)
     mirror=$(debian_mirror $fcdistro)
-    debootstrap --arch $arch $fcdistro $rootfs_path $mirror
+    debootstrap --no-check-gpg --arch $arch $fcdistro $lxc_root $mirror
+    # just like with fedora we ensure a few packages get installed as well
+    # not started yet
+    #virsh -c lxc:/// lxc-enter-namespace $lxc /usr/bin/$personality /bin/bash -c "apt-get update"
+    #virsh -c lxc:/// lxc-enter-namespace $lxc /usr/bin/$personality /bin/bash -c "apt-get -y install $DEBIAN_PREINSTALLED"
+    chroot ${lxc_root} $personality apt-get update
+    chroot ${lxc_root} $personality apt-get -y install $DEBIAN_PREINSTALLED
+    # configure hostname
+    cat <<EOF > ${lxc_root}/etc/hostname
+$GUEST_HOSTNAME
+EOF
+    
 }
 
 function debian_configure () {
 }
 
 function debian_configure () {
-    guest_interfaces=${rootfs_path}/etc/network/interfaces
-    ( [ -n "$BUILD_MODE" ] && write_guest_interfaces_build || write_guest_interfaces_test ) > $guest_interfaces
+    guest_interfaces=${lxc_root}/etc/network/interfaces
+    ( [ -n "$NAT_MODE" ] && write_guest_interfaces_natip || write_guest_interfaces_publicip ) > $guest_interfaces
 }
 
 }
 
-function write_guest_interfaces_build () {
+function write_guest_interfaces_natip () {
     cat <<EOF
 auto $VIF_GUEST
 iface $VIF_GUEST inet dhcp
 EOF
 }
 
     cat <<EOF
 auto $VIF_GUEST
 iface $VIF_GUEST inet dhcp
 EOF
 }
 
-function write_guest_interfaces_test () {
+function write_guest_interfaces_publicip () {
     cat <<EOF
 auto $VIF_GUEST
     cat <<EOF
 auto $VIF_GUEST
-iface $VIF_GUEST
-    address $IP
-    netmask $NETMASK
-    gateway $GATEWAY
+iface $VIF_GUEST inet static
+address $GUEST_IP
+netmask $NETMASK
+gateway $GATEWAY
 EOF
 }
 ##############################
 EOF
 }
 ##############################
@@ -552,16 +460,27 @@ function setup_lxc() {
     pldistro=$1; shift
     personality=$1; shift
 
     pldistro=$1; shift
     personality=$1; shift
 
+    lxc_root=$(lxcroot $lxc)
+
     # create lxc container 
     
     pkg_method=$(package_method $fcdistro)
     case $pkg_method in
        yum)
     # create lxc container 
     
     pkg_method=$(package_method $fcdistro)
     case $pkg_method in
        yum)
-           fedora_install || { echo "failed to install fedora root image"; exit 1 ; }
-           fedora_configure || { echo "failed to configure fedora for a container"; exit 1 ; }
+            if [ -z "$IMAGE" ]; then
+                fedora_install $lxc ||  { echo "failed to install fedora root image"; exit 1 ; }
+               # this appears to be safer; observed in Jan. 2016 on a f23 host and a f14 cached image
+               # we were getting this message when attempting the first chroot yum install
+               # rpmdb: Program version 4.8 doesn't match environment version 5.3
+               chroot $(lxcroot $lxc) $personality rm -rf /var/lib/rpm/__db.00{0,1,2,3,4,5,6,7,8,9}
+               chroot $(lxcroot $lxc) $personality rpm --rebuilddb
+            fi
+           fedora_configure $lxc || { echo "failed to configure fedora for a container"; exit 1 ; }
            ;;
        debootstrap)
            ;;
        debootstrap)
-           debian_install || { echo "failed to install debian/ubuntu root image"; exit 1 ; }
+            if [ -z "$IMAGE" ]; then
+               debian_install $lxc || { echo "failed to install debian/ubuntu root image"; exit 1 ; }
+            fi
            debian_configure || { echo "failed to configure debian/ubuntu for a container"; exit 1 ; }
            ;;
        *)
            debian_configure || { echo "failed to configure debian/ubuntu for a container"; exit 1 ; }
            ;;
        *)
@@ -571,19 +490,24 @@ function setup_lxc() {
     esac
 
     # Enable cgroup -- xxx -- is this really useful ?
     esac
 
     # Enable cgroup -- xxx -- is this really useful ?
-    mkdir $rootfs_path/cgroup
+    [ -d $lxc_root/cgroup ] || mkdir $lxc_root/cgroup
     
     
-    # set up resolv.conf
-    cp /etc/resolv.conf $rootfs_path/etc/resolv.conf
-    # and /etc/hosts for at least localhost
-    [ -f $rootfs_path/etc/hosts ] || echo "127.0.0.1 localhost localhost.localdomain" > $rootfs_path/etc/hosts
+    ### set up resolv.conf from host
+    # ubuntu precise and on, /etc/resolv.conf is a symlink to ../run/resolvconf/resolv.conf
+    [ -h $lxc_root/etc/resolv.conf ] && rm -f $lxc_root/etc/resolv.conf
+    cp /etc/resolv.conf $lxc_root/etc/resolv.conf
+    ### and /etc/hosts for at least localhost
+    [ -f $lxc_root/etc/hosts ] || echo "127.0.0.1 localhost localhost.localdomain" > $lxc_root/etc/hosts
     
     # grant ssh access from host to guest
     
     # grant ssh access from host to guest
-    mkdir $rootfs_path/root/.ssh
-    cat /root/.ssh/id_rsa.pub >> $rootfs_path/root/.ssh/authorized_keys
-    
-    config_xml=$config_path/"lxc.xml"
-    ( [ -n "$BUILD_MODE" ] && write_lxc_xml_build $lxc || write_lxc_xml_test $lxc ) > $config_xml
+    mkdir -p $lxc_root/root/.ssh
+    cat /root/.ssh/id_rsa.pub >> $lxc_root/root/.ssh/authorized_keys
+    chmod 700 $lxc_root/root/.ssh
+    chmod 600 $lxc_root/root/.ssh/authorized_keys
+
+    # don't keep the input xml, this can be retrieved at all times with virsh dumpxml
+    config_xml=/tmp/$lxc.xml
+    ( [ -n "$NAT_MODE" ] && write_lxc_xml_natip $lxc || write_lxc_xml_publicip $lxc ) > $config_xml
     
     # define lxc container for libvirt
     virsh -c lxc:/// define $config_xml
     
     # define lxc container for libvirt
     virsh -c lxc:/// define $config_xml
@@ -591,12 +515,22 @@ function setup_lxc() {
     return 0
 }
 
     return 0
 }
 
-function write_lxc_xml_test () {
+# this part does not belong in a domain any more
+# but goes in a network object of its own existence
+#      <network>
+#        <name>host-bridge</name>
+#        <forward mode="bridge"/>
+#        <bridge name="br0"/>
+#      </network>
+#
+
+function write_lxc_xml_publicip () {
     lxc=$1; shift
     lxc=$1; shift
+    lxc_root=$(lxcroot $lxc)
     cat <<EOF
 <domain type='lxc'>
   <name>$lxc</name>
     cat <<EOF
 <domain type='lxc'>
   <name>$lxc</name>
-  <memory>524288</memory>
+  <memory>$MEMORY</memory>
   <os>
     <type arch='$arch2'>exe</type>
     <init>/sbin/init</init>
   <os>
     <type arch='$arch2'>exe</type>
     <init>/sbin/init</init>
@@ -612,7 +546,7 @@ function write_lxc_xml_test () {
   <devices>
     <emulator>/usr/libexec/libvirt_lxc</emulator>
     <filesystem type='mount'>
   <devices>
     <emulator>/usr/libexec/libvirt_lxc</emulator>
     <filesystem type='mount'>
-      <source dir='$rootfs_path'/>
+      <source dir='$lxc_root'/>
       <target dir='/'/>
     </filesystem>
     <interface type="bridge">
       <target dir='/'/>
     </filesystem>
     <interface type="bridge">
@@ -621,27 +555,27 @@ function write_lxc_xml_test () {
     </interface>
     <console type='pty' />
   </devices>
     </interface>
     <console type='pty' />
   </devices>
-  <network>
-    <name>host-bridge</name>
-    <forward mode="bridge"/>
-    <bridge name="$PUBLIC_BRIDGE"/>
-  </network>
 </domain>
 EOF
 }
 
 </domain>
 EOF
 }
 
-function write_lxc_xml_build () { 
+# grant build guests the ability to do mknods
+function write_lxc_xml_natip () { 
     lxc=$1; shift
     lxc=$1; shift
+    lxc_root=$(lxcroot $lxc)
     cat <<EOF
 <domain type='lxc'>
   <name>$lxc</name>
     cat <<EOF
 <domain type='lxc'>
   <name>$lxc</name>
-  <memory>524288</memory>
+  <memory>$MEMORY</memory>
   <os>
     <type arch='$arch2'>exe</type>
     <init>/sbin/init</init>
   </os>
   <features>
     <acpi/>
   <os>
     <type arch='$arch2'>exe</type>
     <init>/sbin/init</init>
   </os>
   <features>
     <acpi/>
+    <capabilities policy='default'>
+      <mknod state='on'/>
+    </capabilities>
   </features>
   <vcpu>1</vcpu>
   <clock offset='utc'/>
   </features>
   <vcpu>1</vcpu>
   <clock offset='utc'/>
@@ -651,7 +585,7 @@ function write_lxc_xml_build () {
   <devices>
     <emulator>/usr/libexec/libvirt_lxc</emulator>
     <filesystem type='mount'>
   <devices>
     <emulator>/usr/libexec/libvirt_lxc</emulator>
     <filesystem type='mount'>
-      <source dir='$rootfs_path'/>
+      <source dir='$lxc_root'/>
       <target dir='/'/>
     </filesystem>
     <interface type="network">
       <target dir='/'/>
     </filesystem>
     <interface type="network">
@@ -664,7 +598,7 @@ EOF
 }
 
 # this one is dhcp-based
 }
 
 # this one is dhcp-based
-function write_guest_ifcfg_build () {
+function write_guest_ifcfg_natip () {
     cat <<EOF
 DEVICE=$VIF_GUEST
 BOOTPROTO=dhcp
     cat <<EOF
 DEVICE=$VIF_GUEST
 BOOTPROTO=dhcp
@@ -675,14 +609,14 @@ MTU=1500
 EOF
 }
 
 EOF
 }
 
-# use fixed IP as specified by GUEST_HOSTNAME
-function write_guest_ifcfg_test () {
+# use fixed GUEST_IP as specified by GUEST_HOSTNAME
+function write_guest_ifcfg_publicip () {
     cat <<EOF
 DEVICE=$VIF_GUEST
 BOOTPROTO=static
 ONBOOT=yes
 HOSTNAME=$GUEST_HOSTNAME
     cat <<EOF
 DEVICE=$VIF_GUEST
 BOOTPROTO=static
 ONBOOT=yes
 HOSTNAME=$GUEST_HOSTNAME
-IPADDR=$IP
+IPADDR=$GUEST_IP
 NETMASK=$NETMASK
 GATEWAY=$GATEWAY
 NM_CONTROLLED=no
 NETMASK=$NETMASK
 GATEWAY=$GATEWAY
 NM_CONTROLLED=no
@@ -691,7 +625,7 @@ MTU=1500
 EOF
 }
 
 EOF
 }
 
-function devel_or_vtest_tools () {
+function devel_or_test_tools () {
 
     set -x 
     set -e 
 
     set -x 
     set -e 
@@ -702,6 +636,8 @@ function devel_or_vtest_tools () {
     pldistro=$1; shift
     personality=$1; shift
 
     pldistro=$1; shift
     personality=$1; shift
 
+    lxc_root=$(lxcroot $lxc)
+
     pkg_method=$(package_method $fcdistro)
 
     pkgsfile=$(pl_locateDistroFile $DIRNAME $pldistro $PREINSTALLED)
     pkg_method=$(package_method $fcdistro)
 
     pkgsfile=$(pl_locateDistroFile $DIRNAME $pldistro $PREINSTALLED)
@@ -709,28 +645,51 @@ function devel_or_vtest_tools () {
     ### install individual packages, then groups
     # get target arch - use uname -i here (we want either x86_64 or i386)
    
     ### 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 ${lxc_root} $personality uname -i)
     # on debian systems we get arch through the 'arch' command
     # 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 ${lxc_root} $personality arch)
 
     packages=$(pl_getPackages -a $lxc_arch $fcdistro $pldistro $pkgsfile)
     groups=$(pl_getGroups -a $lxc_arch $fcdistro $pldistro $pkgsfile)
 
     case "$pkg_method" in
        yum)
 
     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
+           # --allowerasing required starting with fedora24
+           #
+           has_dnf=""
+           chroot ${lxc_root} $personality dnf --version && has_dnf=true
+           if [ -n "$has_dnf" ]; then
+               echo "container has dnf - invoking with --allowerasing"
+               pkg_installer="dnf -y install --allowerasing"
+               grp_installer="dnf -y groupinstall --allowerasing"
+           else
+               echo "container has only yum"
+               pkg_installer="yum -y install"
+               grp_installer="yum -y groupinstall"
+           fi
+           [ -n "$packages" ] && chroot ${lxc_root} $personality $pkg_installer $packages
            for group_plus in $groups; do
                group=$(echo $group_plus | sed -e "s,+++, ,g")
            for group_plus in $groups; do
                group=$(echo $group_plus | sed -e "s,+++, ,g")
-               chroot $rootfs_path yum -y groupinstall "$group"
+               chroot ${lxc_root} $personality $grp_installer "$group"
            done
            # store current rpm list in /init-lxc.rpms in case we need to check the contents
            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 ${lxc_root} $personality rpm -aq > $lxc_root/init-lxc.rpms
            ;;
        debootstrap)
            ;;
        debootstrap)
-           chroot $rootfs_path apt-get update
+           # for ubuntu
+           if grep -iq ubuntu /vservers/$lxc/etc/lsb-release 2> /dev/null; then
+               # on ubuntu, at this point we end up with a single feed in /etc/apt/sources.list
+               # we need at least to add the 'universe' feed for python-rpm
+               ( cd /vservers/$lxc/etc/apt ; head -1 sources.list | sed -e s,main,universe, > sources.list.d/universe.list )
+               # also adding a link to updates sounds about right
+               ( cd /vservers/$lxc/etc/apt ; head -1 sources.list | sed -e 's, main,-updates main,' > sources.list.d/updates.list )
+               # tell apt about the changes
+               chroot /vservers/$lxc apt-get update
+           fi
            for package in $packages ; do
            for package in $packages ; do
-               # close stdin in an attempt to avoid this hanging
-               chroot $rootfs_path apt-get install -y $package < /dev/null
+               # container not started yet
+               #virsh -c lxc:/// lxc-enter-namespace $lxc /usr/bin/$personality /bin/bash -c "apt-get install -y $package" || :
+               chroot ${lxc_root} $personality apt-get install -y $package || :
            done
            ### xxx todo install groups with apt..
            ;;
            done
            ### xxx todo install groups with apt..
            ;;
@@ -745,21 +704,33 @@ function devel_or_vtest_tools () {
 function post_install () {
     lxc=$1; shift 
     personality=$1; shift
 function post_install () {
     lxc=$1; shift 
     personality=$1; shift
-    if [ -n "$BUILD_MODE" ] ; then
-       post_install_build $lxc $personality
-       lxc_start $lxc
-       # manually run dhclient in guest - somehow this network won't start on its own
-       virsh -c lxc:/// lxc-enter-namespace $lxc /usr/sbin/dhclient $VIF_GUEST
-    else
-       post_install_myplc $lxc $personality
-       lxc_start $lxc
-       wait_for_ssh $lxc
-    fi
+    lxc_root=$(lxcroot $lxc)
     # setup localtime from the host
     # setup localtime from the host
-    cp /etc/localtime $rootfs_path/etc/localtime
+    cp /etc/localtime $lxc_root/etc/localtime
+    sshd_disable_password_auth $lxc
+    # post install hook
+    [ -n "$NAT_MODE" ] && post_install_natip $lxc $personality || post_install_myplc $lxc $personality
+    # start the VM unless specified otherwise
+    if [ -n "$START_VM" ] ; then
+       echo Starting guest $lxc
+       virsh -c lxc:/// start $lxc
+       if [ -n "$NAT_MODE" ] ; then
+           wait_for_ssh $lxc
+       else
+           wait_for_ssh $lxc $GUEST_IP
+       fi
+    fi
+}
+
+# just in case, let's stay on the safe side
+function sshd_disable_password_auth () {
+    lxc=$1; shift 
+    lxc_root=$(lxcroot $lxc)
+    sed --in-place=.password -e 's,^#\?PasswordAuthentication.*,PasswordAuthentication no,' \
+       $lxc_root/etc/ssh/sshd_config
 }
 
 }
 
-function post_install_build () {
+function post_install_natip () {
 
     set -x 
     set -e 
 
     set -x 
     set -e 
@@ -767,54 +738,17 @@ function post_install_build () {
 
     lxc=$1; shift
     personality=$1; shift
 
     lxc=$1; shift
     personality=$1; shift
+    lxc_root=$(lxcroot $lxc)
 
 ### From myplc-devel-native.spec
 # be careful to backslash $ in this, otherwise it's the root context that's going to do the evaluation
 
 ### 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
-    # set up /dev/loop* in lxc
-    for i in \$(seq 0 255) ; do
-       /bin/mknod -m 640 /dev/loop\$i b 7 \$i
-    done
-    
-    # create symlink for /dev/fd
-    [ ! -e "/dev/fd" ] && /bin/ln -s /proc/self/fd /dev/fd
-
-    # modify /etc/rpm/macros to not use /sbin/new-kernel-pkg
-    /bin/sed -i 's,/sbin/new-kernel-pkg:,,' /etc/rpm/macros
-    if [ -h "/sbin/new-kernel-pkg" ] ; then
-       filename=\$(/bin/readlink -f /sbin/new-kernel-pkg)
-       if [ "\$filename" == "/sbin/true" ] ; then
-               /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
+    cat << EOF | chroot ${lxc_root} $personality bash -x
     
     # customize root's prompt
     /bin/cat << PROFILE > /root/.profile
 export PS1="[$lxc] \\w # "
 PROFILE
 
     
     # customize root's prompt
     /bin/cat << PROFILE > /root/.profile
 export PS1="[$lxc] \\w # "
 PROFILE
 
-    uid=2000
-    gid=2000
-    
-    # add a "build" user to the system
-    builduser=\$(grep "^build:" /etc/passwd | wc -l)
-    if [ \$builduser -eq 0 ] ; then
-       groupadd -o -g \$gid build;
-       useradd -o -c 'Automated Build' -u \$uid -g \$gid -n -M -s /bin/bash build;
-    fi
-
-# Allow build user to build certain RPMs as root
-    if [ -f /etc/sudoers ] ; then
-       buildsudo=\$(grep "^build.*ALL=(ALL).*NOPASSWD:.*ALL"  /etc/sudoers | wc -l)
-       if [ \$buildsudo -eq 0 ] ; then
-           echo "build   ALL=(ALL)       NOPASSWD: ALL" >> /etc/sudoers
-       fi
-        sed -i 's,^Defaults.*requiretty,#Defaults requiretty,' /etc/sudoers
-    fi
-#
 EOF
        
 }
 EOF
        
 }
@@ -826,22 +760,17 @@ function post_install_myplc  () {
 
     lxc=$1; shift
     personality=$1; shift
 
     lxc=$1; shift
     personality=$1; shift
+    lxc_root=$(lxcroot $lxc)
 
 # be careful to backslash $ in this, otherwise it's the root context that's going to do the evaluation
 
 # 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 ${lxc_root} $personality bash -x
 
     # create /etc/sysconfig/network if missing
     [ -f /etc/sysconfig/network ] || /bin/echo NETWORKING=yes > /etc/sysconfig/network
 
 
     # create /etc/sysconfig/network if missing
     [ -f /etc/sysconfig/network ] || /bin/echo NETWORKING=yes > /etc/sysconfig/network
 
-    # create symlink for /dev/fd
-    [ ! -e "/dev/fd" ] && /bin/ln -s /proc/self/fd /dev/fd
-
     # turn off regular crond, as plc invokes plc_crond
     /sbin/chkconfig crond off
 
     # turn off regular crond, as plc invokes plc_crond
     /sbin/chkconfig crond off
 
-    # take care of loginuid in /etc/pam.d 
-    /bin/sed -i "s,#*\(.*loginuid.*\),#\1," /etc/pam.d/*
-
     # customize root's prompt
     /bin/cat << PROFILE > /root/.profile
 export PS1="[$lxc] \\w # "
     # customize root's prompt
     /bin/cat << PROFILE > /root/.profile
 export PS1="[$lxc] \\w # "
@@ -850,44 +779,47 @@ PROFILE
 EOF
 }
 
 EOF
 }
 
-function lxc_start() {
-
-    set -x
-    set -e
-    #trap failure ERR INT
-
+########################################
+# workaround for broken lxc-enter-namespace
+# 1st version was relying on virsh net-dhcp-leases
+# however this was too fragile, would not work for fedora14 containers
+# WARNING: this code is duplicated in lbuild-nightly.sh
+function guest_ipv4() {
     lxc=$1; shift
     lxc=$1; shift
-  
-    virsh -c lxc:/// start $lxc
-  
-    return 0
+
+    mac=$(virsh -c lxc:/// domiflist $lxc | egrep 'network|bridge' | awk '{print $5;}')
+    # sanity check
+    [ -z "$mac" ] && return 0
+    arp -en | grep "$mac" | awk '{print $1;}'
 }
 
 function wait_for_ssh () {
     set -x
     set -e
 }
 
 function wait_for_ssh () {
     set -x
     set -e
-    #trap failure ERR INT
 
     lxc=$1; shift
 
     lxc=$1; shift
-  
-    echo $IP is up, waiting for ssh...
 
 
-    #wait max 5 min for sshd to start 
-    ssh_up=""
-    stop_time=$(($(date +%s) + 300))
+    # if run in public_ip mode, we know the IP of the guest and it is specified here
+    [ -n "$1" ] && { guest_ip=$1; shift; }
+
+    #wait max 2 min for sshd to start 
+    success=""
     current_time=$(date +%s)
     current_time=$(date +%s)
+    stop_time=$(($current_time + 120))
     
     counter=1
     while [ "$current_time" -lt "$stop_time" ] ; do
          echo "$counter-th attempt to reach sshd in container $lxc ..."
     
     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))
+        [ -z "$guest_ip" ] && guest_ip=$(guest_ipv4 $lxc)
+        [ -n "$guest_ip" ] && ssh -o "StrictHostKeyChecking no" $guest_ip 'uname -i' && { 
+                success=true; echo "SSHD in container $lxc is UP on IP $guest_ip"; break ; } || :
          counter=$(($counter+1))
          counter=$(($counter+1))
+         sleep 10
+        current_time=$(date +%s)
     done
 
     # Thierry: this is fatal, let's just exit with a failure here
     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 ; } 
+    [ -z $success ] && { echo "SSHD in container $lxc could not be reached (guest_ip=$guest_ip)" ; exit 1 ; } 
     return 0
 }
 
     return 0
 }
 
@@ -899,18 +831,24 @@ function failure () {
 
 function usage () {
     set +x 
 
 function usage () {
     set +x 
-    echo "Usage: $COMMAND_LBUILD [options] lxc-name"
-    echo "Usage: $COMMAND_LTEST [options] lxc-name"
+    echo "Usage: $COMMAND [options] lxc-name             (aka build mode)"
+    echo "Usage: $COMMAND -n hostname [options] lxc-name (aka test mode)"
     echo "Description:"
     echo "Description:"
-    echo "   This command creates a fresh lxc instance, for building, or running a test myplc"
+    echo "    This command creates a fresh lxc instance, for building, or running a test myplc"
+    echo "In its first form, spawned VM gets a private IP bridged with virbr0 over dhcp/nat"
+    echo "With the second form, spawned VM gets a public IP bridged on public bridge br0"
+    echo ""
     echo "Supported options"
     echo "Supported options"
+    echo " -n hostname - the hostname to use in container"
     echo " -f fcdistro - for creating the root filesystem - defaults to $DEFAULT_FCDISTRO"
     echo " -f fcdistro - for creating the root filesystem - defaults to $DEFAULT_FCDISTRO"
-    echo " -d pldistro - defaults to $DEFAULT_PLDISTRO"
+    echo " -d pldistro - defaults to $DEFAULT_PLDISTRO - current support for fedoras debians ubuntus"
     echo " -p personality - defaults to $DEFAULT_PERSONALITY"
     echo " -p personality - defaults to $DEFAULT_PERSONALITY"
-    echo " -n hostname - the hostname to use in container - required with $COMMAND_LTEST"
-    echo " -r repo-url - used to populate yum.repos.d - required with $COMMAND_LTEST"
-    echo " -P pkgs_file - defines the set of extra pacakges"
-    echo "    by default we use vtest.pkgs or devel.pkgs according to $COMMAND"
+    echo " -r repo-url - used to populate yum.repos.d - required in test mode"
+    echo " -P pkgs_file - defines a set of extra packages to install in guest"
+    echo "    by default we use devel.pkgs (build mode) or runtime.pkgs (test mode)"
+    echo " -i image - the location of the rootfs"
+    echo " -m memory - the amount of allocated memory in MB - defaults to $DEFAULT_MEMORY MB"
+    echo " -s do not start VM"
     echo " -v be verbose"
     exit 1
 }
     echo " -v be verbose"
     exit 1
 }
@@ -926,31 +864,18 @@ function main () {
           exit 1
     fi
 
           exit 1
     fi
 
-    case "$COMMAND" in
-       $COMMAND_LBUILD)
-           BUILD_MODE=true ;;
-       $COMMAND_LTEST)
-           TEST_MODE=true;;
-       *)
-           usage ;;
-    esac
-
-    echo 'build mode=' $BUILD_MODE 'test mode=' $TEST_MODE
-
-    # the set of preinstalled packages - depends on vbuild or vtest
-    if [ -n "$BUILD_MODE" ] ; then
-       PREINSTALLED=devel.pkgs
-    else
-       PREINSTALLED=vtest.pkgs
-    fi
-    while getopts "f:d:p:n:r:P:v" opt ; do
+    START_VM=true
+    while getopts "n:f:d:p:r:P:i:m:sv" opt ; do
        case $opt in
        case $opt in
+           n) GUEST_HOSTNAME=$OPTARG;;
            f) fcdistro=$OPTARG;;
            d) pldistro=$OPTARG;;
            p) personality=$OPTARG;;
            f) fcdistro=$OPTARG;;
            d) pldistro=$OPTARG;;
            p) personality=$OPTARG;;
-           n) GUEST_HOSTNAME=$OPTARG;;
            r) REPO_URL=$OPTARG;;
            P) PREINSTALLED=$OPTARG;;
            r) REPO_URL=$OPTARG;;
            P) PREINSTALLED=$OPTARG;;
+            i) IMAGE=$OPTARG;;
+            m) MEMORY=$OPTARG;;
+           s) START_VM= ;;
            v) VERBOSE=true; set -x;;
            *) usage ;;
        esac
            v) VERBOSE=true; set -x;;
            *) usage ;;
        esac
@@ -961,18 +886,52 @@ function main () {
     # parse fixed arguments
     [[ -z "$@" ]] && usage
     lxc=$1 ; shift
     # parse fixed arguments
     [[ -z "$@" ]] && usage
     lxc=$1 ; shift
+    lxc_root=$(lxcroot $lxc)
+
+    # rainchecks
+    almost_empty $lxc_root || \
+       { echo "container $lxc already exists in $lxc_root - exiting" ; exit 1 ; }
+    virsh -c lxc:/// domuuid $lxc >& /dev/null && \
+       { echo "container $lxc already exists in libvirt - exiting" ; exit 1 ; }
+    mkdir -p $lxc_root
+
+    # if IMAGE, copy the provided rootfs to lxc_root
+    if [ -n "$IMAGE" ] ; then
+        [ ! -d "$IMAGE" ] && \
+        { echo "$IMAGE rootfs folder does not exist - exiting" ; exit 1 ; }
+        rsync -a $IMAGE/ $lxc_root/
+    fi
 
     # check we've exhausted the arguments
     [[ -n "$@" ]] && usage
 
 
     # check we've exhausted the arguments
     [[ -n "$@" ]] && usage
 
+    # NAT_MODE is true unless we specified a hostname
+    [ -n "$GUEST_HOSTNAME" ] || NAT_MODE=true
+
+    # set default values
     [ -z "$fcdistro" ] && fcdistro=$DEFAULT_FCDISTRO
     [ -z "$pldistro" ] && pldistro=$DEFAULT_PLDISTRO
     [ -z "$personality" ] && personality=$DEFAULT_PERSONALITY
     [ -z "$fcdistro" ] && fcdistro=$DEFAULT_FCDISTRO
     [ -z "$pldistro" ] && pldistro=$DEFAULT_PLDISTRO
     [ -z "$personality" ] && personality=$DEFAULT_PERSONALITY
+    [ -z "$MEMORY" ] && MEMORY=$DEFAULT_MEMORY
+    
+    # set memory in KB
+    MEMORY=$(($MEMORY * 1024))
     
     
-    if [ -n "$BUILD_MODE" ] ; then
-        [ -z "$GUEST_HOSTNAME" ] && GUEST_HOSTNAME=$lxc
+    # the set of preinstalled packages - depends on mode
+    if [ -z "$PREINSTALLED" ] ; then
+       if [ -n "$NAT_MODE" ] ; then
+           PREINSTALLED=devel.pkgs
+       else
+           PREINSTALLED=runtime.pkgs
+       fi
+    fi
+
+    if [ -n "$NAT_MODE" ] ; then
+       # we can now set GUEST_HOSTNAME safely
+        [ -z "$GUEST_HOSTNAME" ] && GUEST_HOSTNAME=$(echo $lxc | sed -e 's,\.,-,g')
     else
     else
-       [[ -z "$GUEST_HOSTNAME" ]] && usage
+       # as this command can be used in other contexts, not specifying
+       # a repo is considered a warning
        # use -r none to get rid of this warning
        if [ "$REPO_URL" == "none" ] ; then
            REPO_URL=""
        # use -r none to get rid of this warning
        if [ "$REPO_URL" == "none" ] ; then
            REPO_URL=""
@@ -982,7 +941,7 @@ function main () {
     fi
 
     ##########
     fi
 
     ##########
-    release=$(echo $fcdistro | cut -df -f2)
+    fedora_release=$(echo $fcdistro | cut -df -f2)
 
     if [ "$personality" == "linux32" ]; then
         arch=i386
 
     if [ "$personality" == "linux32" ]; then
         arch=i386
@@ -994,51 +953,33 @@ function main () {
         echo "Unknown personality: $personality"
     fi
 
         echo "Unknown personality: $personality"
     fi
 
-    if [ -n "$BUILD_MODE" ] ; then
+    # compute networking details for the test mode
+    # (build mode relies entirely on dhcp on the private subnet)
+    if [ -z "$NAT_MODE" ] ; then
 
 
-       # Bridge IP affectation
-       byte=$(random_private_byte)
-       IP=${PRIVATE_PREFIX}$byte
-       NETMASK=$(masklen_to_netmask $PRIVATE_MASKLEN)
-       GATEWAY=$PRIVATE_GATEWAY
-       VIF_HOST="i$byte"
-    else
-        [[ -z "GUEST_HOSTNAME" ]] && usage
-       
-       create_bridge_if_needed
+       #create_bridge_if_needed $PUBLIC_BRIDGE
+       lbuild-bridge.sh $PUBLIC_BRIDGE
 
 
-       IP=$(gethostbyname $GUEST_HOSTNAME)
+       GUEST_IP=$(gethostbyname $GUEST_HOSTNAME)
        # use same NETMASK as bridge interface br0
        # use same NETMASK as bridge interface br0
-       MASKLEN=$(ip addr show $PUBLIC_BRIDGE | grep -v inet6 | grep inet | awk '{print $2;}' | cut -d/ -f2)
-        NETMASK=$(masklen_to_netmask $MASKLEN)
-        GATEWAY=$(ip route show | grep default | awk '{print $3}')
-        VIF_HOST="i$(echo $GUEST_HOSTNAME | cut -d. -f1)"
+       masklen=$(ip addr show $PUBLIC_BRIDGE | grep -v inet6 | grep inet | awk '{print $2;}' | cut -d/ -f2)
+        NETMASK=$(masklen_to_netmask $masklen)
+        GATEWAY=$(ip route show | grep default | awk '{print $3}' | head -1)
+        VIF_HOST="vif$(echo $GUEST_HOSTNAME | cut -d. -f1)"
     fi
 
     fi
 
-    echo "the IP address of container $lxc is $IP, host virtual interface is $VIF_HOST"
-
-    path=/vservers
-    [ ! -d $path ] && mkdir $path
-    rootfs_path=$path/$lxc/rootfs
-    config_path=$path/$lxc
-    cache_base=/var/cache/lxc/fedora/$arch
-    cache=$cache_base/$release
-    root_password=root
-    
-    # check whether the rootfs directory is created to know if the container exists
-    # bacause /var/lib/lxc/$lxc is already created while putting $lxc.timestamp
-    [ -d $rootfs_path ] && \
-       { echo "container $lxc already exists in filesystem - exiting" ; exit 1 ; }
-    virsh -c lxc:/// domuuid $lxc >& /dev/null && \
-       { echo "container $lxc already exists in libvirt - exiting" ; exit 1 ; }
-
     setup_lxc $lxc $fcdistro $pldistro $personality 
 
     setup_lxc $lxc $fcdistro $pldistro $personality 
 
-    devel_or_vtest_tools $lxc $fcdistro $pldistro $personality
+    # historically this command is for setting up a build or a test VM
+    # kind of patchy right now though
+    devel_or_test_tools $lxc $fcdistro $pldistro $personality
 
 
+    # container gets started here
     post_install $lxc $personality
     
     echo $COMMAND Done
     post_install $lxc $personality
     
     echo $COMMAND Done
+
+    exit 0
 }
 
 main "$@"
 }
 
 main "$@"