refine strategy to spot ip address, keep on calling guest_ipv4
[build.git] / lbuild-initvm.sh
index da0ef1c..58030cc 100755 (executable)
@@ -30,7 +30,7 @@ function lxcroot () {
 
 # XXX fixme : when creating a 32bits VM we need to call linux32 as appropriate...s
 
 
 # XXX fixme : when creating a 32bits VM we need to call linux32 as appropriate...s
 
-DEFAULT_FCDISTRO=f29
+DEFAULT_FCDISTRO=f39
 DEFAULT_PLDISTRO=lxc
 DEFAULT_PERSONALITY=linux64
 DEFAULT_MEMORY=3072
 DEFAULT_PLDISTRO=lxc
 DEFAULT_PERSONALITY=linux64
 DEFAULT_MEMORY=3072
@@ -51,28 +51,27 @@ DEBIAN_PREINSTALLED="openssh-server openssh-client"
 ########## networking utilities
 function gethostbyname () {
     local hostname=$1
 ########## networking utilities
 function gethostbyname () {
     local hostname=$1
-    python -c "import socket; print socket.gethostbyname('"$hostname"')" 2> /dev/null
+    python3 -c "import socket; print(socket.gethostbyname('"$hostname"'))" 2> /dev/null
 }
 
 # e.g. 21 -> 255.255.248.0
 function masklen_to_netmask () {
     local masklen=$1; shift
 }
 
 # e.g. 21 -> 255.255.248.0
 function masklen_to_netmask () {
     local masklen=$1; shift
-    python <<EOF
+    python3 <<EOF
 import sys
 import sys
-masklen=$masklen
-if not (masklen>=1 and masklen<=32):
-  print "Wrong masklen",masklen
+masklen = $masklen
+if not (1 <= masklen <= 32):
+  print("Wrong masklen", masklen)
   exit(1)
   exit(1)
-result=[]
+result = []
 for i in range(4):
 for i in range(4):
-    if masklen>=8:
+    if masklen >= 8:
        result.append(8)
        result.append(8)
-       masklen-=8
+       masklen -= 8
     else:
        result.append(masklen)
     else:
        result.append(masklen)
-       masklen=0
-print ".".join([ str(256-2**(8-i)) for i in result ])
-
+       masklen = 0
+print(".".join([ str(256-2**(8-i)) for i in result ]))
 EOF
 }
 
 EOF
 }
 
@@ -83,10 +82,33 @@ function package_method () {
     case $fcdistro in
         f[0-9]*|centos[0-9]*|sl[0-9]*)
             echo dnf ;;
     case $fcdistro in
         f[0-9]*|centos[0-9]*|sl[0-9]*)
             echo dnf ;;
-        wheezy|jessie|precise|trusty|utopic|vivid|wily|xenial)
+        wheezy|jessie|trusty|xenial|bionic|focal|jammy)
             echo debootstrap ;;
         *)
             echo debootstrap ;;
         *)
-            echo Unknown distro $fcdistro ;;
+            echo "Unknown package_method for distro $fcdistro" ;;
+    esac
+}
+
+### return
+# ifcfg          for fedora up to 36
+# networkmanager for fedora starting with f37 (probably works with older as well...)
+# interfaces     for older debian/uuntu
+# systemd        for more recent debian/ubuntu
+function network_config_method () {
+    local fcdistro=$1; shift
+    case $fcdistro in
+        # have not used centos or scientific linux for a very long time
+        #f[0-9]*|centos[0-9]*|sl[0-9]*)
+        f2*|f3[0-6])
+            echo ifcfg ;;
+        f3[7-9]|f[4-9]*)
+            echo networkmanager ;;
+        wheezy|jessie|trusty|xenial|bionic)
+            echo interfaces ;;
+        focal|jammy)
+            echo systemd ;;
+        *)
+            echo "Unknown network_config_method for distro $fcdistro" ;;
     esac
 }
 
     esac
 }
 
@@ -141,7 +163,7 @@ function fedora_install() {
             fedora_download $cache || { echo "Failed to download 'fedora base'"; return 1; }
         else
             echo "Updating cache $cache/rootfs ..."
             fedora_download $cache || { echo "Failed to download 'fedora base'"; return 1; }
         else
             echo "Updating cache $cache/rootfs ..."
-            if ! dnf --installroot $cache/rootfs --releasever ${fedora_release} -y --nogpgcheck update ; then
+            if ! dnf --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"
                 echo "Failed to update 'fedora base', continuing with last known good cache"
             else
                 echo "Update finished"
@@ -181,38 +203,42 @@ function fedora_download() {
     cp /etc/yum.conf $INSTALL_ROOT/etc/
     cp /etc/yum.repos.d/fedora{,-updates}.repo $INSTALL_ROOT/etc/yum.repos.d/
 
     cp /etc/yum.conf $INSTALL_ROOT/etc/
     cp /etc/yum.repos.d/fedora{,-updates}.repo $INSTALL_ROOT/etc/yum.repos.d/
 
-    # append fedora repo files with desired ${fedora_release} and $basearch
-    for f in $INSTALL_ROOT/etc/yum.repos.d/* ; do
-      sed -i "s/\$basearch/$arch/g; s/\$releasever/${fedora_release}/g;" $f
-    done
-
-    MIRROR_URL=$FEDORA_MIRROR/fedora/releases/${fedora_release}/Everything/$arch/os
-    # since fedora18 the rpms are scattered by first name
-    # first try the second version of fedora-release first
-    RELEASE_URLS=""
-    local subindex
-    for subindex in 3 2 1; do
-        RELEASE_URLS="$RELEASE_URLS $MIRROR_URL/Packages/f/fedora-release-${fedora_release}-${subindex}.noarch.rpm"
-    done
+    # append fedora repo files with hardwired releasever and basearch
+    if [ -z "$USE_UPSTREAM_REPOS" ]; then
+        for f in $INSTALL_ROOT/etc/yum.repos.d/* ; do
+            sed -i "s/\$basearch/$arch/g; s/\$releasever/${fedora_release}/g;" $f
+        done
+    fi
 
 
-    RELEASE_TARGET=$INSTALL_ROOT/fedora-release-${fedora_release}.noarch.rpm
-    local found=""
-    local attempt
-    for attempt in $RELEASE_URLS; do
-        if curl --silent --fail $attempt -o $RELEASE_TARGET; then
-            echo "Successfully Retrieved $attempt"
-            found=true
-            break
-        else
-            echo "Failed (not to worry about) with attempt $attempt"
-        fi
-    done
-    [ -n "$found" ] || { echo "Could not retrieve fedora-release rpm - exiting" ; exit 1; }
+# looks like all this business about fetching fedora-release is not needed
+# it does
+#    MIRROR_URL=$FEDORA_MIRROR/fedora/releases/${fedora_release}/Everything/$arch/os
+#    # since fedora18 the rpms are scattered by first name
+#    # first try the second version of fedora-release first
+#    RELEASE_URLS=""
+#    local subindex
+#    for subindex in 3 2 1; do
+#        RELEASE_URLS="$RELEASE_URLS $MIRROR_URL/Packages/f/fedora-release-${fedora_release}-${subindex}.noarch.rpm"
+#    done
+#
+#    RELEASE_TARGET=$INSTALL_ROOT/fedora-release-${fedora_release}.noarch.rpm
+#    local found=""
+#    local attempt
+#    for attempt in $RELEASE_URLS; do
+#        if curl --silent --fail $attempt -o $RELEASE_TARGET; then
+#            echo "Successfully Retrieved $attempt"
+#            found=true
+#            break
+#        else
+#            echo "Failed (not to worry about) with 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
     # 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-${fedora_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
@@ -223,7 +249,7 @@ 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)
 
-    DNF="dnf --installroot=$INSTALL_ROOT --releasever=${fedora_release} --nogpgcheck -y"
+    DNF="dnf --installroot=$INSTALL_ROOT --nogpgcheck -y --releasever=${fedora_release}"
     echo "$DNF install $FEDORA_PREINSTALLED"
     $DNF install $FEDORA_PREINSTALLED || { echo "Failed to download rootfs, aborting." ; return 1; }
 
     echo "$DNF install $FEDORA_PREINSTALLED"
     $DNF install $FEDORA_PREINSTALLED || { echo "Failed to download rootfs, aborting." ; return 1; }
 
@@ -277,25 +303,39 @@ EOF
 
     fedora_configure_systemd $lxc
 
 
     fedora_configure_systemd $lxc
 
-    local guest_ifcfg=${lxc_root}/etc/sysconfig/network-scripts/ifcfg-$VIF_GUEST
-    mkdir -p $(dirname ${guest_ifcfg})
-    # starting with f29, we go for NetworkManager as older network-scripts
-    # is about to be deprecated
-    local nm_controlled=false
-    [[ $fcdistro == f29 ]] && nm_controlled=true
-    [[ $fcdistro == f3[0-9] ]] && nm_controlled=true
-
-    if [ -n "$NAT_MODE" ]; then
-        write_guest_ifcfg_natip $nm_controlled
-    else
-        write_guest_ifcfg_publicip $nm_controlled
-    fi > $guest_ifcfg
+    fedora_configure_network $lxc
 
     [ -z "$IMAGE" ] && fedora_configure_yum $lxc $fcdistro $pldistro
 
     return 0
 }
 
 
     [ -z "$IMAGE" ] && fedora_configure_yum $lxc $fcdistro $pldistro
 
     return 0
 }
 
+function fedora_configure_network() {
+    local lxc="$1"
+    case $(network_config_method $fcdistro) in
+        ifcfg)
+            # probably no longer useful
+            local guest_ifcfg=${lxc_root}/etc/sysconfig/network-scripts/ifcfg-$VIF_GUEST
+            mkdir -p $(dirname ${guest_ifcfg})
+            if [ -n "$NAT_MODE" ]; then
+                write_guest_ifcfg_natip
+            else
+                write_guest_ifcfg_publicip
+            fi > $guest_ifcfg
+            ;;
+        networkmanager)
+            local guest_keyfile=${lxc_root}/etc/NetworkManager/system-connections/'Wired connection 1.nmconnection'
+            mkdir -p $(dirname "${guest_keyfile}")
+            if [ -n "$NAT_MODE" ]; then
+                write_guest_networkmanager_natip
+            else
+                write_guest_networkmanager_publicip
+            fi > "$guest_keyfile"
+            chmod 600 "$guest_keyfile"
+            ;;
+    esac
+}
+
 # this code of course is for guests that do run on systemd
 function fedora_configure_systemd() {
     set -e
 # this code of course is for guests that do run on systemd
 function fedora_configure_systemd() {
     set -e
@@ -314,8 +354,7 @@ function fedora_configure_systemd() {
 #    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 || :
 #    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
-    chroot ${lxc_root} $personality chkconfig network on
+    chroot ${lxc_root} $personality systemctl enable NetworkManager
 }
 
 # overwrite container yum config
 }
 
 # overwrite container yum config
@@ -332,23 +371,23 @@ function fedora_configure_yum () {
     # rpm --rebuilddb
     chroot ${lxc_root} $personality rpm --rebuilddb
 
     # rpm --rebuilddb
     chroot ${lxc_root} $personality rpm --rebuilddb
 
-    echo "Initializing yum.repos.d in $lxc"
-    rm -f $lxc_root/etc/yum.repos.d/*
-
-    # use mirroring/ stuff instead of a hard-wired config
-    local repofile=$lxc_root/etc/yum.repos.d/building.repo
-    yumconf_mirrors $repofile ${DIRNAME} $fcdistro \
-        "" $FEDORA_MIRROR
-    # the keys stuff requires adjustment though
-    sed -i $repofile -e s,'gpgkey=.*',"gpgkey=${FEDORA_MIRROR_KEYS}/RPM-GPG-KEY-fedora-${fedora_release}-primary,"
+    if [ -z "$USE_UPSTREAM_REPOS" ]; then
+        echo "Initializing yum.repos.d in $lxc"
+        rm -f $lxc_root/etc/yum.repos.d/*
 
 
+        # use mirroring/ stuff instead of a hard-wired config
+        local repofile=$lxc_root/etc/yum.repos.d/building.repo
+        yumconf_mirrors $repofile ${DIRNAME} $fcdistro "" $FEDORA_MIRROR
+        # the keys stuff requires adjustment though
+        sed -i $repofile -e s,'gpgkey=.*',"gpgkey=${FEDORA_MIRROR_KEYS}/RPM-GPG-KEY-fedora-${fedora_release}-primary,"
+    fi
     # 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
     # 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
+    if [ -n "$MYPLC_REPO_URL" ] ; then
         if [ ! -d $lxc_root/etc/yum.repos.d ] ; then
             echo "WARNING : cannot create myplc repo"
         else
         if [ ! -d $lxc_root/etc/yum.repos.d ] ; then
             echo "WARNING : cannot create myplc repo"
         else
@@ -361,7 +400,7 @@ function fedora_configure_yum () {
             cat > $lxc_root/etc/yum.repos.d/myplc.repo <<EOF
 [myplc]
 name= MyPLC
             cat > $lxc_root/etc/yum.repos.d/myplc.repo <<EOF
 [myplc]
 name= MyPLC
-baseurl=$REPO_URL
+baseurl=$MYPLC_REPO_URL
 enabled=1
 gpgcheck=0
 EOF
 enabled=1
 gpgcheck=0
 EOF
@@ -378,7 +417,7 @@ function debian_mirror () {
     case $fcdistro in
         wheezy|jessie)
             echo http://ftp2.fr.debian.org/debian/ ;;
     case $fcdistro in
         wheezy|jessie)
             echo http://ftp2.fr.debian.org/debian/ ;;
-        precise|trusty|utopic|vivid|wily|xenial)
+        trusty|xenial|bionic|focal|jammy)
             echo http://www-ftp.lip6.fr/pub/linux/distributions/Ubuntu/archive/ ;;
         *) echo unknown distro $fcdistro; exit 1;;
     esac
             echo http://www-ftp.lip6.fr/pub/linux/distributions/Ubuntu/archive/ ;;
         *) echo unknown distro $fcdistro; exit 1;;
     esac
@@ -407,8 +446,23 @@ EOF
 }
 
 function debian_configure () {
 }
 
 function debian_configure () {
-    local guest_interfaces=${lxc_root}/etc/network/interfaces
-    ( [ -n "$NAT_MODE" ] && write_guest_interfaces_natip || write_guest_interfaces_publicip ) > $guest_interfaces
+    local lxc=$1; shift
+    local fcdistro=$1; shift
+    case $(network_config_method $fcdistro) in
+        interfaces)
+            local guest_interfaces=${lxc_root}/etc/network/interfaces
+            ( [ -n "$NAT_MODE" ] \
+                && write_guest_interfaces_natip \
+                || write_guest_interfaces_publicip ) > $guest_interfaces
+            ;;
+        systemd)
+            local systemd_config="${lxc_root}/etc/systemd/network/wired.network"
+            ( [ -n "$NAT_MODE" ] \
+                && write_guest_systemd_natip \
+                || write_guest_systemd_publicip ) > $systemd_config
+            chroot "${lxc_root}" systemctl enable systemd-networkd
+            ;;
+    esac
 }
 
 function write_guest_interfaces_natip () {
 }
 
 function write_guest_interfaces_natip () {
@@ -427,6 +481,56 @@ netmask $NETMASK
 gateway $GATEWAY
 EOF
 }
 gateway $GATEWAY
 EOF
 }
+
+# systemd-networkd
+#   https://wiki.archlinux.org/title/systemd-networkd
+#   https://www.linuxtricks.fr/wiki/systemd-le-reseau-avec-systemd-networkd
+function write_guest_systemd_natip () {
+    cat << EOF
+[Match]
+Name=eth0
+
+[Network]
+DHCP=ipv4
+EOF
+}
+
+function write_guest_systemd_publicip () {
+    cat << EOF
+[Match]
+Name=eth0
+
+[Network]
+Address=${GUEST_IP}/${MASKLEN}
+Gateway=$GATEWAY
+EOF
+}
+
+function uuid() {
+    python -c "import uuid; print(uuid.uuid1())"
+}
+# xxx this seems to be no longer needed ?
+function write_guest_networkmanager_natip() {
+    cat << EOF
+EOF
+}
+function write_guest_networkmanager_publicip() {
+    cat << EOF
+[connection]
+id=Wired connection 1
+uuid=$(uuid)
+type=ethernet
+autoconnect-priority=-999
+# setting this seems to be counter-productive
+# interface-name=${VIF_GUEST}
+
+[ipv4]
+address1=${GUEST_IP}/${MASKLEN},${GATEWAY}
+#dhcp-hostname=${GUEST_HOSTNAME}
+method=manual
+EOF
+}
+
 ##############################
 function setup_lxc() {
 
 ##############################
 function setup_lxc() {
 
@@ -460,7 +564,7 @@ function setup_lxc() {
             if [ -z "$IMAGE" ]; then
                 debian_install $lxc || { echo "failed to install debian/ubuntu root image"; exit 1 ; }
             fi
             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 $lxc $fcdistro || { echo "failed to configure debian/ubuntu for a container"; exit 1 ; }
             ;;
         *)
             echo "$COMMAND:: unknown package_method - exiting"
             ;;
         *)
             echo "$COMMAND:: unknown package_method - exiting"
@@ -474,7 +578,14 @@ function setup_lxc() {
     ### 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
     ### 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
+    ### since fedora36, our hosts use systemd-resolved, but the guests can't use that
+    # so the administrator has the option to create /etc/resolv.conf.containers
+    # and if that file exists it will be copied in the containers instead of /etc/resolv.conf
+    if [ -f /etc/resolv.conf.containers ]; then
+        cp /etc/resolv.conf.containers $lxc_root/etc/resolv.conf
+    else
+        cp /etc/resolv.conf $lxc_root/etc/resolv.conf
+    fi
     ### and /etc/hosts for at least localhost
     [ -f $lxc_root/etc/hosts ] || echo "127.0.0.1 localhost localhost.localdomain" > $lxc_root/etc/hosts
 
     ### and /etc/hosts for at least localhost
     [ -f $lxc_root/etc/hosts ] || echo "127.0.0.1 localhost localhost.localdomain" > $lxc_root/etc/hosts
 
@@ -578,7 +689,6 @@ EOF
 
 # this one is dhcp-based
 function write_guest_ifcfg_natip () {
 
 # this one is dhcp-based
 function write_guest_ifcfg_natip () {
-    local nm_controlled=$1; shift
     cat <<EOF
 DEVICE=$VIF_GUEST
 BOOTPROTO=dhcp
     cat <<EOF
 DEVICE=$VIF_GUEST
 BOOTPROTO=dhcp
@@ -586,12 +696,10 @@ ONBOOT=yes
 TYPE=Ethernet
 MTU=1500
 EOF
 TYPE=Ethernet
 MTU=1500
 EOF
-    [ "$nm_controlled" == true ] || echo NM_CONTROLLED=no
 }
 
 # use fixed GUEST_IP as specified by GUEST_HOSTNAME
 function write_guest_ifcfg_publicip () {
 }
 
 # use fixed GUEST_IP as specified by GUEST_HOSTNAME
 function write_guest_ifcfg_publicip () {
-    local nm_controlled=$1; shift
     cat <<EOF
 DEVICE=$VIF_GUEST
 BOOTPROTO=static
     cat <<EOF
 DEVICE=$VIF_GUEST
 BOOTPROTO=static
@@ -603,7 +711,6 @@ GATEWAY=$GATEWAY
 TYPE=Ethernet
 MTU=1500
 EOF
 TYPE=Ethernet
 MTU=1500
 EOF
-    [ "$nm_controlled" == true ] || echo NM_CONTROLLED=no
 }
 
 function devel_or_test_tools () {
 }
 
 function devel_or_test_tools () {
@@ -624,9 +731,9 @@ function devel_or_test_tools () {
     local pkgsfile=$(pl_locateDistroFile $DIRNAME $pldistro $PREINSTALLED)
 
     ### install individual packages, then groups
     local pkgsfile=$(pl_locateDistroFile $DIRNAME $pldistro $PREINSTALLED)
 
     ### install individual packages, then groups
-    # get target arch - use uname -i here (we want either x86_64 or i386)
+    # get target arch - (we want either x86_64 or i386)
 
 
-    local lxc_arch=$(chroot ${lxc_root} $personality uname -i)
+    local lxc_arch=$(chroot ${lxc_root} $personality arch)
     # on debian systems we get arch through the 'arch' command
     [ "$lxc_arch" = "unknown" ] && lxc_arch=$(chroot ${lxc_root} $personality arch)
 
     # on debian systems we get arch through the 'arch' command
     [ "$lxc_arch" = "unknown" ] && lxc_arch=$(chroot ${lxc_root} $personality arch)
 
@@ -750,7 +857,7 @@ function post_install_myplc  () {
     [ -f /etc/sysconfig/network ] || /bin/echo NETWORKING=yes > /etc/sysconfig/network
 
     # turn off regular crond, as plc invokes plc_crond
     [ -f /etc/sysconfig/network ] || /bin/echo NETWORKING=yes > /etc/sysconfig/network
 
     # turn off regular crond, as plc invokes plc_crond
-    /sbin/chkconfig crond off
+    /sbin/chkconfig crond off >& /dev/null
 
     # customize root's prompt
     /bin/cat << PROFILE > /root/.profile
 
     # customize root's prompt
     /bin/cat << PROFILE > /root/.profile
@@ -765,13 +872,38 @@ EOF
 # 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
 # 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() {
-    local lxc=$1; shift
+function guest_ipv4_old() {
+    lxc=$1; shift
+
+    mac=$(virsh -c lxc:/// domiflist $lxc | grep -E 'network|bridge' | awk '{print $5;}')
+    [ -z "$mac" ] && { echo 1>&2 guest_ipv4_old cannot find mac; return 1; }
+    ip=$(arp -en | grep "$mac" | awk '{print $1;}')
+    # if not known: run a ping and try again
+    if [ -z $ip ]; then
+           ping -c1 -w1 -W1 $lxc >& /dev/null
+           ping -c1 -w1 -W1 $lxc.pl.sophia.inria.fr >& /dev/null
+           ip=$(arp -en | grep "$mac" | awk '{print $1;}')
+    fi
+    [ -z "$ip" ] && { echo 1>&2 guest_ipv4_old cannot find ip; return 1; }
+    echo $ip
+}
 
 
-    local 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 guest_ipv4() {
+    lxc=$1; shift
+
+    # this gives us the libvirt_lxc pid for the container
+    local lxc_pid=$(virsh -c lxc:/// dominfo $lxc | grep '^Id:' | awk '{print $2;}' | sed -e "s|-||g")
+    [[ -z "$lxc_pid" ]] && { echo 1>&2 guest_ipv4 cannot find lxc pid; return 1; }
+    # but we need the systemd (pid=1) instance for the container
+    local systemd_pid=$(pgrep -P $lxc_pid systemd)
+    [[ -z "$systemd_pid" ]] && { echo 1>&2 guest_ipv4 cannot systemd pid; return 1; }
+    # from there we can inspect the network interfaces
+    local domip=$(nsenter -t $systemd_pid -n ip -br addr show eth0 \
+                 | awk '{print $3}' \
+                 | cut -d/ -f1 \
+                 )
+    [ -z "$domip" ] && { echo 1>&2 guest_ipv4 cannot find ip; return 1; }
+    echo $domip
 }
 
 function wait_for_ssh () {
 }
 
 function wait_for_ssh () {
@@ -781,7 +913,8 @@ function wait_for_ssh () {
     local lxc=$1; shift
 
     # if run in public_ip mode, we know the IP of the guest and it is specified here
     local lxc=$1; shift
 
     # if run in public_ip mode, we know the IP of the guest and it is specified here
-    [ -n "$1" ] && { guest_ip=$1; shift; }
+    local specified_ip
+    [ -n "$1" ] && { specified_ip=$1; shift; }
 
     #wait max 2 min for sshd to start
     local success=""
 
     #wait max 2 min for sshd to start
     local success=""
@@ -790,13 +923,22 @@ function wait_for_ssh () {
 
     local counter=1
     while [ "$current_time" -lt "$stop_time" ] ; do
 
     local counter=1
     while [ "$current_time" -lt "$stop_time" ] ; do
-         echo "$counter-th attempt to reach sshd in container $lxc ..."
-         [ -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))
-         sleep 10
-         current_time=$(date +%s)
+        if [ -n "$specified_ip" ]; then
+            guest_ip="${specified_ip}"
+        else
+            guest_ip=$(guest_ipv4 $lxc) || :
+        fi
+        echo "$counter-th attempt to reach sshd in container $lxc on address $guest_ip ..."
+        [ -n "$guest_ip" ] && ssh -o "StrictHostKeyChecking no" $guest_ip arch && {
+            success=true; echo "SSHD in container $lxc is UP on IP $guest_ip"; break ; } || :
+        # some of our boxes have gone through a long upgrade historically, and
+        # so they don't end up with the same gid mapping for the ssh_keys
+        # group as the ones in the guest that result from a fresh install
+        # 2024 : lxc-enter-namespace is broken anyways
+        # virsh -c lxc:/// lxc-enter-namespace $lxc /bin/bash -c "chown root:ssh_keys /etc/ssh/*_key" || :
+        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
@@ -846,13 +988,14 @@ function main () {
     fi
 
     START_VM=true
     fi
 
     START_VM=true
-    while getopts "n:f:d:p:r:P:i:m:sv" opt ; do
+    while getopts "n:f:d:p:r:uP:i:m:sv" opt ; do
         case $opt in
             n) GUEST_HOSTNAME=$OPTARG;;
             f) fcdistro=$OPTARG;;
             d) pldistro=$OPTARG;;
             p) personality=$OPTARG;;
         case $opt in
             n) GUEST_HOSTNAME=$OPTARG;;
             f) fcdistro=$OPTARG;;
             d) pldistro=$OPTARG;;
             p) personality=$OPTARG;;
-            r) REPO_URL=$OPTARG;;
+            r) MYPLC_REPO_URL=$OPTARG;;
+            u) USE_UPSTREAM_REPOS=true;;
             P) PREINSTALLED=$OPTARG;;
             i) IMAGE=$OPTARG;;
             m) MEMORY=$OPTARG;;
             P) PREINSTALLED=$OPTARG;;
             i) IMAGE=$OPTARG;;
             m) MEMORY=$OPTARG;;
@@ -870,6 +1013,8 @@ function main () {
     local lxc_root=$(lxcroot $lxc)
 
     # rainchecks
     local lxc_root=$(lxcroot $lxc)
 
     # rainchecks
+    # when using with the -i option, checking that $lxc_root is void
+    # is a little too much stress..
     almost_empty $lxc_root || \
         { echo "container $lxc already exists in $lxc_root - exiting" ; exit 1 ; }
     virsh -c lxc:/// domuuid $lxc >& /dev/null && \
     almost_empty $lxc_root || \
         { echo "container $lxc already exists in $lxc_root - exiting" ; exit 1 ; }
     virsh -c lxc:/// domuuid $lxc >& /dev/null && \
@@ -878,9 +1023,13 @@ function main () {
 
     # if IMAGE, copy the provided rootfs to lxc_root
     if [ -n "$IMAGE" ] ; then
 
     # 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/
+        if [ ! -d "$IMAGE" ]; then
+            echo "$IMAGE rootfs folder does not exist - exiting"
+            exit 1
+        else
+            echo "Copying $IMAGE into $lxc_root with rsync --archive --delete"
+            rsync --archive --delete $IMAGE/ $lxc_root/
+        fi
     fi
 
     # check we've exhausted the arguments
     fi
 
     # check we've exhausted the arguments
@@ -914,9 +1063,9 @@ function main () {
         # 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
         # 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=""
-        elif [ -z "$REPO_URL" ] ; then
+        if [ "$MYPLC_REPO_URL" == "none" ] ; then
+            MYPLC_REPO_URL=""
+        elif [ -z "$MYPLC_REPO_URL" ] ; then
             echo "WARNING -- setting up a yum repo is recommended"
         fi
     fi
             echo "WARNING -- setting up a yum repo is recommended"
         fi
     fi
@@ -943,8 +1092,8 @@ function main () {
 
         GUEST_IP=$(gethostbyname $GUEST_HOSTNAME)
         # use same NETMASK as bridge interface br0
 
         GUEST_IP=$(gethostbyname $GUEST_HOSTNAME)
         # 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)
+        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
         GATEWAY=$(ip route show | grep default | awk '{print $3}' | head -1)
         VIF_HOST="vif$(echo $GUEST_HOSTNAME | cut -d. -f1)"
     fi