From 97595fb00be0f37f458a3734f17326af911596cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= Date: Thu, 20 Jul 2023 22:33:45 +0200 Subject: [PATCH 01/12] tools: add nm-in-vm script Script to download, configure and install a virtual machine to build and test NetworkManager. This is useful because there are some things that doesn't work properly on containers so a VM is needed to test. It works almost the same way than nm-in-container. Configurations specific to NetworkManager such as installing the required packages are not implemented yet. --- tools/nm-in-vm | 280 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 280 insertions(+) create mode 100755 tools/nm-in-vm diff --git a/tools/nm-in-vm b/tools/nm-in-vm new file mode 100755 index 0000000000..293daad841 --- /dev/null +++ b/tools/nm-in-vm @@ -0,0 +1,280 @@ +#!/bin/bash + +set -e + +############################################################################### +# Script to create a virtual machine for testing NetworkManager. +# +# Commands: +# - build: build a new VM, named "$VM" ("nm"). +# - run: start the VM. +# - exec: run bash inside the VM, connecting via ssh (this is the default). +# - stop: stop the VM. +# - reexec: stop and exec. +# - clean: stop the VM and delete the image. +# +# Commands exec and reexec accepts extra arguments, which are the command to +# execute in the VM instead of opening an ssh session. +# +# NetworkManager directories: +# +# The NetworkManager root directory is mounted in the VM as a filesystem share. +# You can run `make install` and run tests. +# +# Create a symlink ./.git/NetworkManager-ci, to share the CI directory too. +# +# Required packages: +# +# Your host needs libvirt, libvirt-nss and guestfs-tools. To access the VM with +# `ssh root@$VM`, configure /etc/nsswitch.conf as explained in +# https://libvirt.org/nss.html (otherwise, `nm-in-vm exec` won't work, either). +# +# Prepare for testing: +# +# There is a script nm-env-prepare.sh to generate a net1 interface for testing. +# Currently NM-ci requires a working eth1, so use this before running a CI test: +# `nm-env-prepare.sh --prefix eth -i 1 && sleep 1 && nmcli device connect eth1` +# +# Additional VMs: +# +# By default, the VM named 'nm' is created, but additional ones can be created: +# $ VM=nm2 nm-in-vm build +# $ VM=nm2 nm-in-vm exec +# $ VM=nm2 nm-in-vm stop +# +# Choosing a different OS: +# +# By default Fedora is used, but you can choose a different OS. Most from the +# list `virt-builder --list` will work. +# $ OS_VERSION=debian-12 nm-in-vm build +# $ nm-in-vm exec +# $ nm-in-vm stop +############################################################################### + +# Check for libvirt +if ! (command -v virsh && command -v virt-builder && command -v virt-install) &>/dev/null; then + echo "libvirt and guestfs-tools are required" >&2 + exit 1 +fi + +# set defaults if user didn't define these values +VM=${VM:="nm"} +OS_VERSION=${OS_VERSION:=} +RAM=${RAM:=2048} +IMAGE_SIZE=${IMAGE_SIZE:=10G} +ROOT_PASSWORD=${ROOT_PASSWORD:=nm} +LIBVIRT_POOL=${LIBVIRT_POOL:=default} # only useful if BASEDIR_VM_IMAGE is empty +BASEDIR_VM_IMAGE=${BASEDIR_VM_IMAGE:=} +BASEDIR_NM=${BASEDIR_NM:=} +BASEDIR_NM_CI=${BASEDIR_NM_CI:=} +HOST_BRIDGE=${HOST_BRIDGE:=virbr0} +SSH_LOG_LEVEL=${SSH_LOG_LEVEL:=ERROR} + +if [[ -z $OS_VERSION ]]; then + # if running Fedora, select same version, else select latest Fedora + if grep -q "^ID=fedora$" /etc/os-release 2>/dev/null ; then + OS_VERSION="$(sed -n 's/^VERSION_ID=\([0-9]\+\)$/fedora-\1/p' /etc/os-release)" + else + OS_VERSION=$(virt-builder --list | grep '^fedora' | sort | tail -n 1 | cut -d" " -f 1) + fi +fi + +if [[ -z $BASEDIR_NM ]]; then + BASEDIR_NM="$(readlink -f "$(dirname -- "$BASH_SOURCE")/..")" +fi + +if [[ -z $BASEDIR_NM_CI && -d "$BASEDIR_NM/.git/NetworkManager-ci" ]]; then + BASEDIR_NM_CI="$(readlink -f "$BASEDIR_NM/.git/NetworkManager-ci")" +fi + +if [[ -z $BASEDIR_VM_IMAGE ]]; then + libvirt_pool_path_xml=$(virsh pool-dumpxml $LIBVIRT_POOL | grep -F '') + if [[ $libvirt_pool_path_xml =~ \(.*)\ ]]; then + BASEDIR_VM_IMAGE=${BASH_REMATCH[1]} + else + BASEDIR_VM_IMAGE=$BASEDIR_NM + fi +fi + +# compute some values that depends on user selectable variables +basedir_vm_image=$(readlink -f "$BASEDIR_VM_IMAGE") +vm_image_file="$VM.qcow2" +os_variant=${OS_VERSION//-/} # virt-install --os-variant value, deduced from OS_VERSION +os_variant=${os_variant/centosstream/centos-stream} + +############################################################################## + +do_build() { + local t + t=$'\t' + + if vm_is_installed; then + echo "The virtual machine '$VM' is already installed, skiping build" >&2 + return 0 + fi + + if vm_image_exists; then + echo "The image '$basedir_vm_image/$vm_image_file' already exists, skiping build" >&2 + return 0 + fi + + if [[ -n $BASEDIR_NM_CI ]]; then + nm_ci_mkdir=("--mkdir" "$BASEDIR_NM_CI") + nm_ci_fstab=("--append-line" "/etc/fstab:/NM_CI${t}$BASEDIR_NM_CI${t}9p${t}trans=virtio,rw,_netdev${t}0${t}0") + nm_ci_fs=("--filesystem" "$BASEDIR_NM_CI,/NM_CI") + fi + + echo "Creating VM" + echo " - VM NAME: $VM" + echo " - OS VERSION: $OS_VERSION" + echo " - SIZE: $IMAGE_SIZE" + echo " - RAM: $RAM" + echo " - ROOT PASSWORD: $ROOT_PASSWORD" + echo " - IMAGE PATH: $basedir_vm_image/$vm_image_file" + echo " - NM DIR: $BASEDIR_NM" + echo " - NM CI DIR: $([[ -n $BASEDIR_NM_CI ]] && echo "$BASEDIR_NM_CI" || echo '')" + echo " - HOST BRIDGE: $HOST_BRIDGE" + + virt-builder "$OS_VERSION" \ + --output "$basedir_vm_image/$vm_image_file" \ + --size "$IMAGE_SIZE" \ + --format qcow2 \ + --arch x86_64 \ + --hostname "$VM" \ + --root-password password:nm \ + --ssh-inject root \ + --mkdir "$BASEDIR_NM" \ + --append-line "/etc/fstab:/NM${t}$BASEDIR_NM${t}9p${t}trans=virtio,rw,_netdev${t}0${t}0" \ + "${nm_ci_mkdir[@]}" \ + "${nm_ci_fstab[@]}" \ + --update + + virt-install \ + --name "$VM" \ + --ram "$RAM" \ + --disk "path=$basedir_vm_image/$vm_image_file,format=qcow2" \ + --os-variant "$os_variant" \ + --filesystem "$BASEDIR_NM,/NM" \ + "${nm_ci_fs[@]}" \ + --network "bridge=$HOST_BRIDGE" \ + --import \ + --autoconsole none \ + --noreboot +} + +do_clean() { + vm_is_running && virsh shutdown "$VM" &>/dev/null + vm_is_installed && virsh undefine "$VM" &>/dev/null + rm -f "$basedir_vm_image/$vm_image_file" +} + +do_run() { + vm_is_installed || do_build + vm_is_running && return 0 + virsh start "$VM" >&2 +} + +do_exec() { + do_run + + local failed=0 + while ! ping -c 1 "$VM" &>/dev/null; do + failed=$((failed + 1)) + (( failed < 15 )) || die "Timeout trying to ping the VM" + sleep 1 + done + + ssh \ + -o StrictHostKeyChecking=no \ + -o UserKnownHostsFile=/dev/null \ + -o LogLevel="$SSH_LOG_LEVEL" \ + "root@$VM" "$@" +} + +do_reexec() { + vm_is_running && do_stop + + local waited=0 + while vm_is_running; do + waited=$((waited + 1)) + (( waited < 30 )) || die "Timeout waiting for VM shutdown" + sleep 1 + done + + do_exec "$@" +} + +do_stop() { + vm_is_running && virsh shutdown "$VM" >&2 +} + +############################################################################### + +vm_image_exists() { + [[ -f "$basedir_vm_image/$vm_image_file" ]] || return 1 +} + +vm_is_installed() { + virsh list --all --name | grep --fixed-strings --line-regexp "$VM" &>/dev/null || return 1 +} + +vm_is_running() { + virsh list --name | grep --fixed-strings --line-regexp "$VM" &>/dev/null || return 1 +} + +usage() { + echo "nm-in-vm [-h|--help] build|run|exec|stop|reexec|clean" +} + +help() { + usage + echo + awk '/^####*$/ { if (on) exit; on=-1; } !/^####*$/ { if (on) print(substr($0,3)) }' "$BASH_SOURCE" + echo +} + +die() { + echo "$1" >&2 + exit 1 +} + +############################################################################### + +cmd= + +while (( $# > 0 )); do + case "$1" in + build|run|exec|reexec|stop|clean) + cmd="$1" + shift + ;; + -h|--help) + help + exit 0 + ;; + --) + shift + break + ;; + *) + [[ $cmd != "" ]] && break + echo "Invalid argument '$1'" >&2 + echo $(usage) >&2 + exit 1 + ;; + esac +done + +if [[ $cmd == "" ]]; then + cmd=exec +fi + +if [[ $UID == 0 ]]; then + die "cannot run as root" +fi + +if [[ $cmd != exec && $cmd != reexec && $# != 0 ]]; then + die "Extra arguments are only allowed with exec|reexec command" +fi + +do_$cmd "$@" From 3100e4b6e2e4ab06e1c91d8e165b8aec822a7dcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= Date: Fri, 21 Jul 2023 13:29:29 +0200 Subject: [PATCH 02/12] tools: nm-in-container: move data to a common path for nm-in-vm nm-in-vm can use the same generated files than nm-in-container, so let's move them to a place common for both: tools/nm-guest-data. With this change, it is not worth it to have the nm-in-container directory, so move the script to tools and delete the subdirectory. --- .../{nm-in-container/data => nm-guest-data}/.gitignore | 0 tools/nm-guest-data/README.md | 10 ++++++++++ .../data-_nm-in-container-setup.sh | 0 .../data => nm-guest-data}/data-etc-rc.local | 0 .../data-etc-systemd-20-nm-in-container.override | 0 .../data => nm-guest-data}/data-nm-deploy.sh | 0 .../data => nm-guest-data}/data-nm-env-prepare.sh | 0 tools/{nm-in-container => }/nm-in-container | 4 ++-- tools/nm-in-container/README.md | 9 --------- 9 files changed, 12 insertions(+), 11 deletions(-) rename tools/{nm-in-container/data => nm-guest-data}/.gitignore (100%) create mode 100644 tools/nm-guest-data/README.md rename tools/{nm-in-container/data => nm-guest-data}/data-_nm-in-container-setup.sh (100%) rename tools/{nm-in-container/data => nm-guest-data}/data-etc-rc.local (100%) rename tools/{nm-in-container/data => nm-guest-data}/data-etc-systemd-20-nm-in-container.override (100%) rename tools/{nm-in-container/data => nm-guest-data}/data-nm-deploy.sh (100%) rename tools/{nm-in-container/data => nm-guest-data}/data-nm-env-prepare.sh (100%) rename tools/{nm-in-container => }/nm-in-container (99%) delete mode 100644 tools/nm-in-container/README.md diff --git a/tools/nm-in-container/data/.gitignore b/tools/nm-guest-data/.gitignore similarity index 100% rename from tools/nm-in-container/data/.gitignore rename to tools/nm-guest-data/.gitignore diff --git a/tools/nm-guest-data/README.md b/tools/nm-guest-data/README.md new file mode 100644 index 0000000000..2b6aac3a53 --- /dev/null +++ b/tools/nm-guest-data/README.md @@ -0,0 +1,10 @@ +Run NetworkManager in Container for Development +=============================================== + +Run `nm-in-container` script for running NetworkManager in a non-root, +privileged podman container. Run `nm-in-vm` to do it in a vitual machine. +This is useful for testing NetworkManager for development. + +Try `./nm-in-container --help` or `./nm-in-vm --help` to see options. Inside +the container, see the bash history for useful commands and read the hints in +"/etc/motd". diff --git a/tools/nm-in-container/data/data-_nm-in-container-setup.sh b/tools/nm-guest-data/data-_nm-in-container-setup.sh similarity index 100% rename from tools/nm-in-container/data/data-_nm-in-container-setup.sh rename to tools/nm-guest-data/data-_nm-in-container-setup.sh diff --git a/tools/nm-in-container/data/data-etc-rc.local b/tools/nm-guest-data/data-etc-rc.local similarity index 100% rename from tools/nm-in-container/data/data-etc-rc.local rename to tools/nm-guest-data/data-etc-rc.local diff --git a/tools/nm-in-container/data/data-etc-systemd-20-nm-in-container.override b/tools/nm-guest-data/data-etc-systemd-20-nm-in-container.override similarity index 100% rename from tools/nm-in-container/data/data-etc-systemd-20-nm-in-container.override rename to tools/nm-guest-data/data-etc-systemd-20-nm-in-container.override diff --git a/tools/nm-in-container/data/data-nm-deploy.sh b/tools/nm-guest-data/data-nm-deploy.sh similarity index 100% rename from tools/nm-in-container/data/data-nm-deploy.sh rename to tools/nm-guest-data/data-nm-deploy.sh diff --git a/tools/nm-in-container/data/data-nm-env-prepare.sh b/tools/nm-guest-data/data-nm-env-prepare.sh similarity index 100% rename from tools/nm-in-container/data/data-nm-env-prepare.sh rename to tools/nm-guest-data/data-nm-env-prepare.sh diff --git a/tools/nm-in-container/nm-in-container b/tools/nm-in-container similarity index 99% rename from tools/nm-in-container/nm-in-container rename to tools/nm-in-container index 83d8f7bde3..39f7ab1b54 100755 --- a/tools/nm-in-container/nm-in-container +++ b/tools/nm-in-container @@ -43,8 +43,8 @@ if [ -z "$BASE_IMAGE" ]; then BASE_IMAGE=fedora:latest fi -BASEDIR_NM="$(readlink -f "$(dirname "$(readlink -f "$0")")/../..")" -BASEDIR_DATA="$BASEDIR_NM/tools/nm-in-container/data" +BASEDIR_NM="$(readlink -f "$(dirname "$(readlink -f "$0")")/..")" +BASEDIR_DATA="$BASEDIR_NM/tools/nm-guest-data" BASEDIR_NM_CI= if [ -d "$BASEDIR_NM/.git/NetworkManager-ci" ] ; then diff --git a/tools/nm-in-container/README.md b/tools/nm-in-container/README.md deleted file mode 100644 index 64f699eb46..0000000000 --- a/tools/nm-in-container/README.md +++ /dev/null @@ -1,9 +0,0 @@ -Run NetworkManager in Container for Development -=============================================== - -Run `nm-in-container` script for running NetworkManager in a non-root, -privileged podman container. This is useful for testing NetworkManager for -development. - -Try `./nm-in-container --help` to see options. Inside the container, see the -bash history for useful commands and read the hints in "/etc/motd". From d00a5d2a8b3c3a97fb723f4a3a9d104079401063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= Date: Fri, 21 Jul 2023 15:36:22 +0200 Subject: [PATCH 03/12] tools: nm-in-container: don't generate files from the script The script was generating the data-* files that later copies to the container. In order to the files being reusable for nm-in-vm, put them as separate files inside the data directory. However, some of the files need the full path to NetworkManager project, which varies for each user. Instead, make a sed replacement on them and generate the actual files that will be copied. Replacement: {{BASEDIR_NM}} -> $BASEDIR_NM Also, rename the files to more descriptive names, using some prefixes that give a hint of where those files will be put, and the .in extension to indicate that they will be processed. --- ...up.sh => bin-_nm-in-container-setup.sh.in} | 0 ...{data-nm-deploy.sh => bin-nm-deploy.sh.in} | 0 ...nv-prepare.sh => bin-nm-env-prepare.sh.in} | 0 tools/nm-guest-data/etc-bashrc.my.in | 48 ++++ tools/nm-guest-data/etc-motd-container.in | 75 ++++++ tools/nm-guest-data/etc-motd-vm.in | 63 +++++ .../{data-etc-rc.local => etc-rc.local.in} | 0 tools/nm-guest-data/home-bash_history.in | 31 +++ tools/nm-guest-data/home-behaverc.in | 2 + tools/nm-guest-data/home-gdb_history.in | 2 + tools/nm-guest-data/home-gdbinit.in | 2 + tools/nm-guest-data/nm-90-my.conf.in | 15 ++ tools/nm-guest-data/nm-95-user.conf.in | 0 ...ner.override => systemd-20-nm.override.in} | 0 tools/nm-in-container | 238 ++---------------- 15 files changed, 265 insertions(+), 211 deletions(-) rename tools/nm-guest-data/{data-_nm-in-container-setup.sh => bin-_nm-in-container-setup.sh.in} (100%) mode change 100755 => 100644 rename tools/nm-guest-data/{data-nm-deploy.sh => bin-nm-deploy.sh.in} (100%) mode change 100755 => 100644 rename tools/nm-guest-data/{data-nm-env-prepare.sh => bin-nm-env-prepare.sh.in} (100%) mode change 100755 => 100644 create mode 100644 tools/nm-guest-data/etc-bashrc.my.in create mode 100644 tools/nm-guest-data/etc-motd-container.in create mode 100644 tools/nm-guest-data/etc-motd-vm.in rename tools/nm-guest-data/{data-etc-rc.local => etc-rc.local.in} (100%) mode change 100755 => 100644 create mode 100644 tools/nm-guest-data/home-bash_history.in create mode 100644 tools/nm-guest-data/home-behaverc.in create mode 100644 tools/nm-guest-data/home-gdb_history.in create mode 100644 tools/nm-guest-data/home-gdbinit.in create mode 100644 tools/nm-guest-data/nm-90-my.conf.in create mode 100644 tools/nm-guest-data/nm-95-user.conf.in rename tools/nm-guest-data/{data-etc-systemd-20-nm-in-container.override => systemd-20-nm.override.in} (100%) diff --git a/tools/nm-guest-data/data-_nm-in-container-setup.sh b/tools/nm-guest-data/bin-_nm-in-container-setup.sh.in old mode 100755 new mode 100644 similarity index 100% rename from tools/nm-guest-data/data-_nm-in-container-setup.sh rename to tools/nm-guest-data/bin-_nm-in-container-setup.sh.in diff --git a/tools/nm-guest-data/data-nm-deploy.sh b/tools/nm-guest-data/bin-nm-deploy.sh.in old mode 100755 new mode 100644 similarity index 100% rename from tools/nm-guest-data/data-nm-deploy.sh rename to tools/nm-guest-data/bin-nm-deploy.sh.in diff --git a/tools/nm-guest-data/data-nm-env-prepare.sh b/tools/nm-guest-data/bin-nm-env-prepare.sh.in old mode 100755 new mode 100644 similarity index 100% rename from tools/nm-guest-data/data-nm-env-prepare.sh rename to tools/nm-guest-data/bin-nm-env-prepare.sh.in diff --git a/tools/nm-guest-data/etc-bashrc.my.in b/tools/nm-guest-data/etc-bashrc.my.in new file mode 100644 index 0000000000..db8598a05c --- /dev/null +++ b/tools/nm-guest-data/etc-bashrc.my.in @@ -0,0 +1,48 @@ +alias m="make -j 8" +alias n="ninja -C build" + +alias l='ls -l --color=auto' + +ulimit -c unlimited + +export G_DEBUG=fatal-warnings + +unset DEBUGINFOD_URLS + +export NMCI_DEBUG=1 + +Clean() { + systemctl stop NetworkManager + rm -i -rf /run/NetworkManager + nm-env-prepare.sh +} + +Cat-Timestamp() { + while IFS=$'\n' read line; do + printf "[%s]: %s\n" "1689938340.403232924" "$line" + done +} + +Journald-clear() { + rm -rf /var/log/journal/????????????????????????????????/* + systemctl restart systemd-journald +} + +nm_run_gdb() { + systemctl stop NetworkManager.service + gdb --args "${1:-/opt/test/sbin/NetworkManager}" --debug +} + +nm_run_normal() { + systemctl stop NetworkManager.service + "${1:-/opt/test/sbin/NetworkManager}" --debug 2>&1 | tee /tmp/nm-log.txt +} + +. /usr/share/git-core/contrib/completion/git-prompt.sh +PS1="\[\033[01;36m\]\u@\h\[\033[00m\]:\t:\[\033[01;34m\]\w\$(__git_ps1 \" \[\033[01;36m\](%s)\[\033[00m\]\")\[\033[00m\]$ " +export GIT_PS1_SHOWDIRTYSTATE=1 + +if test "$SHOW_MOTD" != 0; then + cat /etc/motd + export SHOW_MOTD=0 +fi diff --git a/tools/nm-guest-data/etc-motd-container.in b/tools/nm-guest-data/etc-motd-container.in new file mode 100644 index 0000000000..131f815c37 --- /dev/null +++ b/tools/nm-guest-data/etc-motd-container.in @@ -0,0 +1,75 @@ +*** nm-in-container: + +find NetworkManager bind mounted at {{BASEDIR_NM}} +run `nm-env-prepare.sh setup --idx 1` to setup test interfaces + +Coredumps: coredumps are not namespaced, so by default they will +be sent to coredumpctl of the outer host, which has no idea where +to get the debugging symbols from. A possible workaround is setting + + $ echo '/tmp/core.%e.%p' | sudo tee /proc/sys/kernel/core_pattern + +so that core dumps get written to file. Afterwards, restore with + + $ echo '|/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %h' | sudo tee /proc/sys/kernel/core_pattern + +from /usr/lib/sysctl.d/50-coredump.conf. + +For example, configure NetworkManager with + $ ./configure \ + --enable-address-sanitizer=no \ + --enable-compile-warnings=yes \ + --enable-concheck \ + --enable-config-plugin-ibft=yes \ + --enable-gtk-doc \ + --enable-ifcfg-rh=yes \ + --enable-ifcfg-suse \ + --enable-ifnet \ + --enable-ifupdown=yes \ + --enable-introspection \ + --enable-json-validation=yes \ + --enable-maintainer-mode \ + --enable-more-logging \ + --enable-more-warnings=error \ + --enable-ovs=yes \ + --enable-polkit=yes \ + --enable-teamdctl=yes \ + --enable-undefined-sanitizer=no \ + --enable-vala=yes \ + --enable-wimax \ + --localstatedir=/var \ + --prefix=/opt/test \ + --sysconfdir=/etc \ + --with-config-dhcp-default=internal \ + --with-config-dns-rc-manager-default=auto \ + --with-consolekit=yes \ + --with-consolekit=yes \ + --with-crypto=nss \ + --with-dhclient=yes \ + --with-dhcpcanon=yes \ + --with-dhcpcd=yes \ + --with-iwd=yes \ + --with-libnm-glib=yes \ + --with-modem-manager-1 \ + --with-netconfig=/bin/nowhere/netconfig \ + --with-nm-cloud-setup=yes \ + --with-nmcli=yes \ + --with-nmtui=yes \ + --with-ofono=yes \ + --with-resolvconf=/bin/nowhere/resolvconf \ + --with-session-tracking=systemd \ + --with-suspend-resume=systemd \ + --with-systemd-logind=yes \ + --with-valgrind=yes \ + --enable-tests="${NM_BUILD_TESTS:-yes}" \ + --with-more-asserts="${NM_BUILD_MORE_ASSERTS:-1000}" \ + "${NM_CONFIGURE_OTPS[@]}" +Test with: + $ systemctl stop NetworkManager; /opt/test/sbin/NetworkManager --debug 2>&1 | tee -a /tmp/nm-log.txt + +Or better, configure with `contrib/fedora/rpm/configure-for-system.sh`, +subsequent `make && make install` will overwrite your system's NetworkManager, +and you can test it with `systemctl daemon-reload ; systemctl restart NetworkManager`. + +Run NM-ci tests after creating eth1 with +`nm-env-prepare.sh --prefix eth -i 1 && sleep 1 && nmcli device connect eth1`. diff --git a/tools/nm-guest-data/etc-motd-vm.in b/tools/nm-guest-data/etc-motd-vm.in new file mode 100644 index 0000000000..17332d5ea0 --- /dev/null +++ b/tools/nm-guest-data/etc-motd-vm.in @@ -0,0 +1,63 @@ +*** nm-in-vm: + +find NetworkManager bind mounted at {{BASEDIR_NM}} +run `nm-env-prepare.sh setup --idx 1` to setup test interfaces + +For example, configure NetworkManager with + $ ./configure \ + --enable-address-sanitizer=no \ + --enable-compile-warnings=yes \ + --enable-concheck \ + --enable-config-plugin-ibft=yes \ + --enable-gtk-doc \ + --enable-ifcfg-rh=yes \ + --enable-ifcfg-suse \ + --enable-ifnet \ + --enable-ifupdown=yes \ + --enable-introspection \ + --enable-json-validation=yes \ + --enable-maintainer-mode \ + --enable-more-logging \ + --enable-more-warnings=error \ + --enable-ovs=yes \ + --enable-polkit=yes \ + --enable-teamdctl=yes \ + --enable-undefined-sanitizer=no \ + --enable-vala=yes \ + --enable-wimax \ + --localstatedir=/var \ + --prefix=/opt/test \ + --sysconfdir=/etc \ + --with-config-dhcp-default=internal \ + --with-config-dns-rc-manager-default=auto \ + --with-consolekit=yes \ + --with-consolekit=yes \ + --with-crypto=nss \ + --with-dhclient=yes \ + --with-dhcpcanon=yes \ + --with-dhcpcd=yes \ + --with-iwd=yes \ + --with-libnm-glib=yes \ + --with-modem-manager-1 \ + --with-netconfig=/bin/nowhere/netconfig \ + --with-nm-cloud-setup=yes \ + --with-nmcli=yes \ + --with-nmtui=yes \ + --with-ofono=yes \ + --with-resolvconf=/bin/nowhere/resolvconf \ + --with-session-tracking=systemd \ + --with-suspend-resume=systemd \ + --with-systemd-logind=yes \ + --with-valgrind=yes \ + --enable-tests="${NM_BUILD_TESTS:-yes}" \ + --with-more-asserts="${NM_BUILD_MORE_ASSERTS:-1000}" \ + "${NM_CONFIGURE_OTPS[@]}" +Test with: + $ systemctl stop NetworkManager; /opt/test/sbin/NetworkManager --debug 2>&1 | tee -a /tmp/nm-log.txt + +Or better, configure with `contrib/fedora/rpm/configure-for-system.sh`, +subsequent `make && make install` will overwrite your system's NetworkManager, +and you can test it with `systemctl daemon-reload ; systemctl restart NetworkManager`. + +Run NM-ci tests after creating eth1 with +`nm-env-prepare.sh --prefix eth -i 1 && sleep 1 && nmcli device connect eth1`. diff --git a/tools/nm-guest-data/data-etc-rc.local b/tools/nm-guest-data/etc-rc.local.in old mode 100755 new mode 100644 similarity index 100% rename from tools/nm-guest-data/data-etc-rc.local rename to tools/nm-guest-data/etc-rc.local.in diff --git a/tools/nm-guest-data/home-bash_history.in b/tools/nm-guest-data/home-bash_history.in new file mode 100644 index 0000000000..d97c561e18 --- /dev/null +++ b/tools/nm-guest-data/home-bash_history.in @@ -0,0 +1,31 @@ +NM-log +NM-log /tmp/nm-log.txt +behave -f html --stop -t ipv4_method_static_with_IP ./features/scenarios/ipv4.feature +behave -f html --stop ./features/scenarios/vrf.feature +cd {{BASEDIR_NM}} +cd /NetworkManager-ci +cd /NetworkManager +for i in {1..9}; do nm-env-prepare.sh --prefix eth -i $i; done +Journald-clear +journalctl | NM-log +journalctl --since '3 min ago' | NM-log +m +make +make install +n +nm-deploy.sh +nm-env-prepare.sh +nm-env-prepare.sh --prefix eth -i 1 +nm-env-prepare.sh --prefix eth -i 1 && sleep 1 && nmcli device connect eth1 +nm_run_gdb +nm_run_normal +gdb /usr/sbin/NetworkManager /tmp/core.NetworkManager. +nmcli connection add type pppoe con-name ppp-net1 ifname ppp-net1 pppoe.parent net1 service isp username test password networkmanager autoconnect no +nmcli device connect eth1 +systemctl stop NetworkManager; /opt/test/sbin/NetworkManager --debug 2>&1 | tee -a ./nm-log.txt +systemctl stop NetworkManager; gdb -ex run --args /opt/test/sbin/NetworkManager --debug +systemctl stop NetworkManager +systemctl daemon-reload ; systemctl restart NetworkManager +(cd /NetworkManager && n && n install && systemctl daemon-reload && systemctl restart NetworkManager.service) +(cd /NetworkManager && m && m install && systemctl daemon-reload && systemctl restart NetworkManager.service) +systemctl status NetworkManager diff --git a/tools/nm-guest-data/home-behaverc.in b/tools/nm-guest-data/home-behaverc.in new file mode 100644 index 0000000000..ebb49fa7e4 --- /dev/null +++ b/tools/nm-guest-data/home-behaverc.in @@ -0,0 +1,2 @@ +[behave.formatters] +html = behave_html_formatter:HTMLFormatter diff --git a/tools/nm-guest-data/home-gdb_history.in b/tools/nm-guest-data/home-gdb_history.in new file mode 100644 index 0000000000..39fb9abf43 --- /dev/null +++ b/tools/nm-guest-data/home-gdb_history.in @@ -0,0 +1,2 @@ +run +run --debug 2>&1 | tee /tmp/nm-log.txt diff --git a/tools/nm-guest-data/home-gdbinit.in b/tools/nm-guest-data/home-gdbinit.in new file mode 100644 index 0000000000..f55a669a09 --- /dev/null +++ b/tools/nm-guest-data/home-gdbinit.in @@ -0,0 +1,2 @@ +set history save +set history filename ~/.gdb_history diff --git a/tools/nm-guest-data/nm-90-my.conf.in b/tools/nm-guest-data/nm-90-my.conf.in new file mode 100644 index 0000000000..fdc05b64d2 --- /dev/null +++ b/tools/nm-guest-data/nm-90-my.conf.in @@ -0,0 +1,15 @@ +[main] +no-auto-default=* +debug=RLIMIT_CORE,fatal-warnings + +[logging] +level=TRACE +domains=ALL,VPN_PLUGIN:TRACE + +[device-managed-0] +match-device=interface-name:d_*,interface-name:tap* +managed=0 + +[device-managed-1] +match-device=interface-name:net*,interface-name:eth* +managed=1 diff --git a/tools/nm-guest-data/nm-95-user.conf.in b/tools/nm-guest-data/nm-95-user.conf.in new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tools/nm-guest-data/data-etc-systemd-20-nm-in-container.override b/tools/nm-guest-data/systemd-20-nm.override.in similarity index 100% rename from tools/nm-guest-data/data-etc-systemd-20-nm-in-container.override rename to tools/nm-guest-data/systemd-20-nm.override.in diff --git a/tools/nm-in-container b/tools/nm-in-container index 39f7ab1b54..2b48ac3803 100755 --- a/tools/nm-in-container +++ b/tools/nm-in-container @@ -100,6 +100,13 @@ tmp_file() { test -z "$2" || chmod "$2" "$1" } +gen_file() { + local PERMS + [[ $1 =~ bin-* ]] && PERMS=755 || PERMS=644 + sed "s|{{BASEDIR_NM}}|$BASEDIR_NM|g" "$BASEDIR_DATA/$1.in" \ + | tmp_file "$BASEDIR_DATA/data-$1" $PERMS +} + bind_files() { VARIABLE_NAME="$1" @@ -123,208 +130,17 @@ create_dockerfile() { local CONTAINERFILE="$1" local BASE_IMAGE="$2" + local GEN_FILES="bin-nm-env-prepare.sh bin-nm-deploy.sh bin-_nm-in-container-setup.sh + etc-rc.local etc-motd-container etc-bashrc.my nm-90-my.conf nm-95-user.conf + home-bash_history home-gdbinit home-gdb_history home-behaverc systemd-20-nm.override" - cp "$BASEDIR_NM/contrib/scripts/NM-log" "$BASEDIR_DATA/data-NM-log" + cp "$BASEDIR_NM/contrib/scripts/NM-log" "$BASEDIR_DATA/data-bin-NM-log" CLEANUP_FILES+=( "$BASEDIR_DATA/data-NM-log" ) - cat <&1 | tee -a /tmp/nm-log.txt - -Or better, configure with \`contrib/fedora/rpm/configure-for-system.sh\`, -subsequent \`make && make install\` will overwrite your system's NetworkManager, -and you can test it with \`systemctl daemon-reload ; systemctl restart NetworkManager\`. - -Run NM-ci tests after creating eth1 with -\`nm-env-prepare.sh --prefix eth -i 1 && sleep 1 && nmcli device connect eth1\`. -EOF - - cat <&1 | tee /tmp/nm-log.txt -} - -. /usr/share/git-core/contrib/completion/git-prompt.sh -PS1="\[\\033[01;36m\]\u@\h\[\\033[00m\]:\\t:\[\\033[01;34m\]\w\\\$(__git_ps1 \\" \[\\033[01;36m\](%s)\[\\033[00m\]\\")\[\\033[00m\]\$ " -export GIT_PS1_SHOWDIRTYSTATE=1 - -if test "\$SHOW_MOTD" != 0; then - cat /etc/motd - export SHOW_MOTD=0 -fi -EOF - - cat <&1 | tee -a ./nm-log.txt -systemctl stop NetworkManager; gdb -ex run --args /opt/test/sbin/NetworkManager --debug -systemctl stop NetworkManager -systemctl daemon-reload ; systemctl restart NetworkManager -(cd /NetworkManager && n && n install && systemctl daemon-reload && systemctl restart NetworkManager.service) -(cd /NetworkManager && m && m install && systemctl daemon-reload && systemctl restart NetworkManager.service) -systemctl status NetworkManager -EOF - - cat <&1 | tee /tmp/nm-log.txt -EOF - - cat < Date: Thu, 3 Aug 2023 11:49:29 +0200 Subject: [PATCH 04/12] tools: nm-in-vm: add NM custom files, packages and configs Same packages and customizations than in nm-in-container. Packages for Debian/Ubuntu pending of being added because they have different names. --- tools/nm-in-container | 3 +- tools/nm-in-vm | 96 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 89 insertions(+), 10 deletions(-) diff --git a/tools/nm-in-container b/tools/nm-in-container index 2b48ac3803..0a58d821a2 100755 --- a/tools/nm-in-container +++ b/tools/nm-in-container @@ -169,6 +169,7 @@ RUN dnf install -y \\ audit-libs-devel \\ bash-completion \\ bind-utils \\ + black \\ bluez-libs-devel \\ ccache \\ clang \\ @@ -294,7 +295,7 @@ RUN dnf install -y \\ wireguard-tools \\ wireshark-cli -RUN dnf debuginfo-install --skip-broken \$(ldd /usr/sbin/NetworkManager | sed -n 's/.* => \\(.*\\) (0x[0-9A-Fa-f]*)$/\1/p' | xargs -n1 readlink -f) -y +RUN dnf debuginfo-install --skip-broken NetworkManager \$(ldd /usr/sbin/NetworkManager | sed -n 's/.* => \\(.*\\) (0x[0-9A-Fa-f]*)$/\1/p' | xargs -n1 readlink -f) -y RUN dnf clean all diff --git a/tools/nm-in-vm b/tools/nm-in-vm index 293daad841..c9f2988e95 100755 --- a/tools/nm-in-vm +++ b/tools/nm-in-vm @@ -101,12 +101,30 @@ basedir_vm_image=$(readlink -f "$BASEDIR_VM_IMAGE") vm_image_file="$VM.qcow2" os_variant=${OS_VERSION//-/} # virt-install --os-variant value, deduced from OS_VERSION os_variant=${os_variant/centosstream/centos-stream} +datadir="$BASEDIR_NM/tools/nm-guest-data" ############################################################################## do_build() { - local t - t=$'\t' + local t=$'\t' + local nm_ci_build_args + local nm_ci_install_args + local extra_pkgs + local install_pkgs + local install_files + local gen_files=( + "bin-nm-env-prepare.sh:/usr/bin/nm-env-prepare.sh" + "bin-nm-deploy.sh:/usr/bin/nm-deploy.sh" + "etc-motd-vm:/etc/motd" + "etc-bashrc.my:/etc/bashrc.my" + "nm-90-my.conf:/etc/NetworkManager/conf.d/90-my.conf" + "nm-95-user.conf:/etc/NetworkManager/conf.d/95-user.conf" + "home-bash_history:/root/.bash_history" + "home-gdbinit:/root/.gdbinit" + "home-gdb_history:/root/.gdb_history" + "home-behaverc:/root/.behaverc" + "systemd-20-nm.override:/etc/systemd/system/NetworkManager.service.d/20-nm.override" + ) if vm_is_installed; then echo "The virtual machine '$VM' is already installed, skiping build" >&2 @@ -119,11 +137,50 @@ do_build() { fi if [[ -n $BASEDIR_NM_CI ]]; then - nm_ci_mkdir=("--mkdir" "$BASEDIR_NM_CI") - nm_ci_fstab=("--append-line" "/etc/fstab:/NM_CI${t}$BASEDIR_NM_CI${t}9p${t}trans=virtio,rw,_netdev${t}0${t}0") - nm_ci_fs=("--filesystem" "$BASEDIR_NM_CI,/NM_CI") + nm_ci_build_args=( + --mkdir "$BASEDIR_NM_CI" + --link "$BASEDIR_NM_CI:/NetworkManager-ci" + --append-line "/etc/fstab:/NM_CI${t}$BASEDIR_NM_CI${t}9p${t}trans=virtio,rw,_netdev${t}0${t}0" + ) + nm_ci_install_args=( + --filesystem "$BASEDIR_NM_CI,/NM_CI" + ) fi + if [[ $OS_VERSION =~ fedora* || $OS_VERSION =~ centos* ]]; then + extra_pkgs=(bash-completion bind-utils ccache clang-tools-extra cryptsetup cscope \'dbus\*\' + dhcp-client dhcp-relay dhcp-server dnsmasq dracut-network ethtool firewalld gcc gdb + glibc-langpack-pl hostapd intltool iproute ipsec-tools iputils iscsi-initiator-utils + iw ldns libreswan libselinux-utils libyaml-devel logrotate lvm2 mdadm mlocate net-tools + NetworkManager NetworkManager-openvpn NetworkManager-ovs NetworkManager-ppp + NetworkManager-pptp NetworkManager-strongswan NetworkManager-team NetworkManager-vpnc + NetworkManager-wifi nfs-utils nispor nmap-ncat nmstate nss-tools openvpn + \'openvswitch2\*\' perl-IO-Pty-Easy perl-IO-Tty procps psmisc python3-behave + python3-black python3-devel python3-netaddr python3-pip python3-pyte python3-pyyaml + qemu-kvm radvd rp-pppoe scsi-target-utils strace systemd tcpdump tcpreplay tuned + /usr/bin/debuginfo-install /usr/bin/pytest /usr/bin/python vim wireguard-tools + wireshark-cli) + + install_pkgs=( + --run "$BASEDIR_NM/contrib/fedora/REQUIRED_PACKAGES" + --run-command "dnf install -y --skip-broken ${extra_pkgs[*]}" + --run-command "dnf debuginfo-install -y --skip-broken NetworkManager \ + \$(ldd /usr/sbin/NetworkManager \ + | sed -n 's/.* => \(.*\) (0x[0-9A-Fa-f]*)\$/\1/p' \ + | xargs -n1 readlink -f)" + ) + elif [[ $OS_VERSION =~ debian* || $OS_VERSION =~ ubuntu* ]]; then + install_pkgs=( + --run "$BASEDIR_NM/contrib/debian/REQUIRED_PACKAGES" + ) + fi + + install_files=(--upload "$BASEDIR_NM/contrib/scripts/NM-log:/usr/bin/NM-log") + for f in "${gen_files[@]}"; do + gen_file "${f%:*}" + install_files+=(--upload "$datadir/data-$f") + done + echo "Creating VM" echo " - VM NAME: $VM" echo " - OS VERSION: $OS_VERSION" @@ -143,11 +200,23 @@ do_build() { --hostname "$VM" \ --root-password password:nm \ --ssh-inject root \ + --append-line "/etc/ssh/sshd_config:PermitRootLogin yes" \ --mkdir "$BASEDIR_NM" \ + --link "$BASEDIR_NM:/NetworkManager" \ --append-line "/etc/fstab:/NM${t}$BASEDIR_NM${t}9p${t}trans=virtio,rw,_netdev${t}0${t}0" \ - "${nm_ci_mkdir[@]}" \ - "${nm_ci_fstab[@]}" \ - --update + "${nm_ci_build_args[@]}" \ + --update \ + "${install_pkgs[@]}" \ + --run-command "pip3 install --user behave_html_formatter" \ + --mkdir "/etc/systemd/system/NetworkManager.service.d" \ + "${install_files[@]}" \ + --write "/var/lib/NetworkManager/secret_key:nm-in-container-secret-key" \ + --chmod "700:/var/lib/NetworkManager" \ + --chmod "600:/var/lib/NetworkManager/secret_key" \ + --edit "/etc/systemd/journald.conf:s/.*RateLimitBurst=.*/RateLimitBurst=0/" \ + --delete "/etc/NetworkManager/system-connections/*" \ + --append-line "/etc/bashrc:. /etc/bashrc.my" \ + --run-command "updatedb" virt-install \ --name "$VM" \ @@ -155,7 +224,7 @@ do_build() { --disk "path=$basedir_vm_image/$vm_image_file,format=qcow2" \ --os-variant "$os_variant" \ --filesystem "$BASEDIR_NM,/NM" \ - "${nm_ci_fs[@]}" \ + "${nm_ci_install_args[@]}" \ --network "bridge=$HOST_BRIDGE" \ --import \ --autoconsole none \ @@ -222,6 +291,15 @@ vm_is_running() { virsh list --name | grep --fixed-strings --line-regexp "$VM" &>/dev/null || return 1 } +gen_file() { + sed "s|{{BASEDIR_NM}}|$BASEDIR_NM|g" "$datadir/$1.in" > "$datadir/data-$1" + if [[ $1 =~ bin-* ]]; then + chmod 755 "$datadir/data-$1" + else + chmod 644 "$datadir/data-$1" + fi +} + usage() { echo "nm-in-vm [-h|--help] build|run|exec|stop|reexec|clean" } From 2b44baf137b1987f56d3bd14544fb75440b6a219 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= Date: Thu, 3 Aug 2023 11:53:42 +0200 Subject: [PATCH 05/12] tools: nm-in-vm: fix connectivity with host The connectivity with the host depends on getting a DHCP lease from the host. With the latest commit's customizations, the virtual NIC is not managed by NM so it is not configured. Keep it unmanaged so debuging NetworkManager doesn't affect to this virtual NIC. Use dhclient to get a DHCP lease from the host. Assign a fixed interface name (host_net) to match it from NM and dhclient config files. --- tools/nm-guest-data/nm-90-my.conf.in | 4 ++++ tools/nm-guest-data/systemd-10-host-net.link.in | 6 ++++++ tools/nm-guest-data/systemd-dhcp-host.service.in | 14 ++++++++++++++ tools/nm-in-vm | 5 ++++- 4 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 tools/nm-guest-data/systemd-10-host-net.link.in create mode 100644 tools/nm-guest-data/systemd-dhcp-host.service.in diff --git a/tools/nm-guest-data/nm-90-my.conf.in b/tools/nm-guest-data/nm-90-my.conf.in index fdc05b64d2..72aeb110c2 100644 --- a/tools/nm-guest-data/nm-90-my.conf.in +++ b/tools/nm-guest-data/nm-90-my.conf.in @@ -13,3 +13,7 @@ managed=0 [device-managed-1] match-device=interface-name:net*,interface-name:eth* managed=1 + +[device-host-net] +match-device=interface-name:host_net +managed=0 diff --git a/tools/nm-guest-data/systemd-10-host-net.link.in b/tools/nm-guest-data/systemd-10-host-net.link.in new file mode 100644 index 0000000000..6425d92667 --- /dev/null +++ b/tools/nm-guest-data/systemd-10-host-net.link.in @@ -0,0 +1,6 @@ +[Match] +Driver=virtio_net + +[Link] +NamePolicy= +Name=host_net diff --git a/tools/nm-guest-data/systemd-dhcp-host.service.in b/tools/nm-guest-data/systemd-dhcp-host.service.in new file mode 100644 index 0000000000..2aae471f9d --- /dev/null +++ b/tools/nm-guest-data/systemd-dhcp-host.service.in @@ -0,0 +1,14 @@ +[Unit] +Description=dhclient service to get connectivity with the host +After=network.target + +[Service] +Type=simple +Restart=on-failure +User=root +RestartSec=5 +ExecStart=dhclient -d -H "%H" host_net +ExecStop=dhclient -r host_net + +[Install] +WantedBy=multi-user.target diff --git a/tools/nm-in-vm b/tools/nm-in-vm index c9f2988e95..f616de5e69 100755 --- a/tools/nm-in-vm +++ b/tools/nm-in-vm @@ -123,6 +123,8 @@ do_build() { "home-gdbinit:/root/.gdbinit" "home-gdb_history:/root/.gdb_history" "home-behaverc:/root/.behaverc" + "systemd-10-host-net.link:/etc/systemd/network/10-host-net.link" + "systemd-dhcp-host.service:/etc/systemd/system/dhcp-host.service" "systemd-20-nm.override:/etc/systemd/system/NetworkManager.service.d/20-nm.override" ) @@ -216,7 +218,8 @@ do_build() { --edit "/etc/systemd/journald.conf:s/.*RateLimitBurst=.*/RateLimitBurst=0/" \ --delete "/etc/NetworkManager/system-connections/*" \ --append-line "/etc/bashrc:. /etc/bashrc.my" \ - --run-command "updatedb" + --run-command "updatedb" \ + --firstboot-command "systemctl enable --now dhcp-host" virt-install \ --name "$VM" \ From 49175cb2cbd1130fbd876b72f3ce49d59f40f183 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= Date: Fri, 4 Aug 2023 10:14:45 +0200 Subject: [PATCH 06/12] tools: nm-in-vm: Debian/Ubuntu with extra pkgs and fixed installation --- .../systemd-dhcp-host.service.in | 2 +- tools/nm-in-vm | 42 +++++++++++++++++-- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/tools/nm-guest-data/systemd-dhcp-host.service.in b/tools/nm-guest-data/systemd-dhcp-host.service.in index 2aae471f9d..844e766ca5 100644 --- a/tools/nm-guest-data/systemd-dhcp-host.service.in +++ b/tools/nm-guest-data/systemd-dhcp-host.service.in @@ -7,7 +7,7 @@ Type=simple Restart=on-failure User=root RestartSec=5 -ExecStart=dhclient -d -H "%H" host_net +ExecStart=dhclient -d host_net ExecStop=dhclient -r host_net [Install] diff --git a/tools/nm-in-vm b/tools/nm-in-vm index f616de5e69..c8b9b38ff1 100755 --- a/tools/nm-in-vm +++ b/tools/nm-in-vm @@ -164,17 +164,51 @@ do_build() { wireshark-cli) install_pkgs=( + --update --run "$BASEDIR_NM/contrib/fedora/REQUIRED_PACKAGES" --run-command "dnf install -y --skip-broken ${extra_pkgs[*]}" + --run-command "pip3 install --user behave_html_formatter" --run-command "dnf debuginfo-install -y --skip-broken NetworkManager \ \$(ldd /usr/sbin/NetworkManager \ | sed -n 's/.* => \(.*\) (0x[0-9A-Fa-f]*)\$/\1/p' \ | xargs -n1 readlink -f)" ) elif [[ $OS_VERSION =~ debian* || $OS_VERSION =~ ubuntu* ]]; then - install_pkgs=( - --run "$BASEDIR_NM/contrib/debian/REQUIRED_PACKAGES" + extra_pkgs=(bash-completion bind9-utils ccache clang-tools cryptsetup cscope \'dbus\*\' + isc-dhcp-client isc-dhcp-relay isc-dhcp-server dnsmasq dracut-network ethtool firewalld + gcc gdb hostapd intltool iproute2 \'iputils-\*\' iw libldns3 libreswan + libyaml-dev logrotate lvm2 mdadm mlocate net-tools network-manager + network-manager-openvpn network-manager-pptp network-manager-strongswan + network-manager-vpnc nfs-common ncat libnss3-tools openvpn \'openvswitch2\*\' procps + psmisc python3-behave black python3-dev python3-netaddr python3-pip python3-pyte + python3-pretty-yaml qemu-kvm radvd pppoe strace systemd tcpdump tcpreplay tuned + debian-goodies python3-pytest python3 vim wireguard-tools tshark) + + if [[ $OS_VERSION =~ debian ]]; then + install_pkgs=( + --run-command "echo deb http://deb.debian.org/debian-debug/ \$(lsb_release -cs)-debug main >> /etc/apt/sources.list.d/debug.list" + --run-command "echo deb http://deb.debian.org/debian-debug/ \$(lsb_release -cs)-proposed-updates-debug main >> /etc/apt/sources.list.d/debug.list" + ) + elif [[ $OS_VERSION =~ ubuntu ]]; then + install_pkgs=( + --run-command "echo deb http://ddebs.ubuntu.com \$(lsb_release -cs) main restricted universe multiverse >> /etc/apt/sources.list.d/debug.list" + --run-command "echo deb http://ddebs.ubuntu.com \$(lsb_release -cs)-updates main restricted universe multiverse >> /etc/apt/sources.list.d/debug.list" + --run-command "echo deb http://ddebs.ubuntu.com \$(lsb_release -cs)-proposed main restricted universe multiverse >> /etc/apt/sources.list.d/debug.list" + ) + fi + + install_pkgs+=( + --update + --upload "$BASEDIR_NM/contrib/debian/REQUIRED_PACKAGES:/tmp/REQUIRED_PACKAGES" + --run-command "/bin/bash /tmp/REQUIRED_PACKAGES" # using only --run fails + --run-command "apt-get install -y \$(find-dbgsym-packages NetworkManager 2>/dev/null)" + --edit "/etc/locale.gen:s/^# pl_PL.UTF-8/pl_PL.UTF-8/" + --run-command "locale-gen" ) + + for p in "${extra_pkgs[@]}"; do + install_pkgs+=(--run-command "apt-get install -y $p || :") + done fi install_files=(--upload "$BASEDIR_NM/contrib/scripts/NM-log:/usr/bin/NM-log") @@ -203,13 +237,12 @@ do_build() { --root-password password:nm \ --ssh-inject root \ --append-line "/etc/ssh/sshd_config:PermitRootLogin yes" \ + --run-command "ssh-keygen -A" \ --mkdir "$BASEDIR_NM" \ --link "$BASEDIR_NM:/NetworkManager" \ --append-line "/etc/fstab:/NM${t}$BASEDIR_NM${t}9p${t}trans=virtio,rw,_netdev${t}0${t}0" \ "${nm_ci_build_args[@]}" \ - --update \ "${install_pkgs[@]}" \ - --run-command "pip3 install --user behave_html_formatter" \ --mkdir "/etc/systemd/system/NetworkManager.service.d" \ "${install_files[@]}" \ --write "/var/lib/NetworkManager/secret_key:nm-in-container-secret-key" \ @@ -219,6 +252,7 @@ do_build() { --delete "/etc/NetworkManager/system-connections/*" \ --append-line "/etc/bashrc:. /etc/bashrc.my" \ --run-command "updatedb" \ + --append-line "/etc/dhcp/dhclient.conf:send host-name = gethostname();" \ --firstboot-command "systemctl enable --now dhcp-host" virt-install \ From 28cb8024e3c86dd1147134170f9ba7f7e6d72587 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= Date: Fri, 4 Aug 2023 11:02:24 +0200 Subject: [PATCH 07/12] tools: nm-in-vm add convenience options --vm and os_version Using more than one VM can be a quite common use case. Insteado of having to do VM=vm_name ./nm-in-vm, allow the more common way of passing options ./nm-in-vm --vm vm_name. Also, in build command, accept one positional argument to set OS_VERSION. --- tools/nm-in-vm | 47 ++++++++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/tools/nm-in-vm b/tools/nm-in-vm index c8b9b38ff1..da6d9f3cdb 100755 --- a/tools/nm-in-vm +++ b/tools/nm-in-vm @@ -6,15 +6,19 @@ set -e # Script to create a virtual machine for testing NetworkManager. # # Commands: -# - build: build a new VM, named "$VM" ("nm"). +# - build: build a new VM, named "$VM" ("nm") +# Args: the name of the OS to build, from `virt-builder --list` (Fedora by default) # - run: start the VM. # - exec: run bash inside the VM, connecting via ssh (this is the default). +# Args: command to execute inside the VM (then, ssh session won't open). # - stop: stop the VM. # - reexec: stop and exec. # - clean: stop the VM and delete the image. # -# Commands exec and reexec accepts extra arguments, which are the command to -# execute in the VM instead of opening an ssh session. +# Options (they MUST go before the command): +# -v | --vm: name of the VM to run the command on (by default 'nm'). +# This allows to have more than one VM at the same time +# -h | --help: show this text # # NetworkManager directories: # @@ -38,15 +42,15 @@ set -e # Additional VMs: # # By default, the VM named 'nm' is created, but additional ones can be created: -# $ VM=nm2 nm-in-vm build -# $ VM=nm2 nm-in-vm exec -# $ VM=nm2 nm-in-vm stop +# $ nm-in-vm -v nm2 build +# $ nm-in-vm -v nm2 exec +# $ nm-in-vm -v nm2 stop # # Choosing a different OS: # # By default Fedora is used, but you can choose a different OS. Most from the # list `virt-builder --list` will work. -# $ OS_VERSION=debian-12 nm-in-vm build +# $ nm-in-vm build debian-12 # $ nm-in-vm exec # $ nm-in-vm stop ############################################################################### @@ -96,17 +100,11 @@ if [[ -z $BASEDIR_VM_IMAGE ]]; then fi fi -# compute some values that depends on user selectable variables -basedir_vm_image=$(readlink -f "$BASEDIR_VM_IMAGE") -vm_image_file="$VM.qcow2" -os_variant=${OS_VERSION//-/} # virt-install --os-variant value, deduced from OS_VERSION -os_variant=${os_variant/centosstream/centos-stream} -datadir="$BASEDIR_NM/tools/nm-guest-data" - ############################################################################## do_build() { local t=$'\t' + local os_variant local nm_ci_build_args local nm_ci_install_args local extra_pkgs @@ -128,6 +126,11 @@ do_build() { "systemd-20-nm.override:/etc/systemd/system/NetworkManager.service.d/20-nm.override" ) + (( $# > 1 )) && die "build only accepts one argument" + (( $# > 0 )) && OS_VERSION="$1" + os_variant=${OS_VERSION//-/} # virt-install --os-variant value, deduced from OS_VERSION + os_variant=${os_variant/centosstream/centos-stream} + if vm_is_installed; then echo "The virtual machine '$VM' is already installed, skiping build" >&2 return 0 @@ -338,7 +341,7 @@ gen_file() { } usage() { - echo "nm-in-vm [-h|--help] build|run|exec|stop|reexec|clean" + echo "nm-in-vm [options] build|run|exec|stop|reexec|clean [command_args]" } help() { @@ -367,6 +370,11 @@ while (( $# > 0 )); do help exit 0 ;; + -v|--vm) + (( $# > 1 )) || die "--vm requires one argument" + VM="$2" + shift 2 + ;; --) shift break @@ -380,6 +388,11 @@ while (( $# > 0 )); do esac done +# compute some values that depends on user selectable variables +basedir_vm_image=$(readlink -f "$BASEDIR_VM_IMAGE") +vm_image_file="$VM.qcow2" +datadir="$BASEDIR_NM/tools/nm-guest-data" + if [[ $cmd == "" ]]; then cmd=exec fi @@ -388,8 +401,8 @@ if [[ $UID == 0 ]]; then die "cannot run as root" fi -if [[ $cmd != exec && $cmd != reexec && $# != 0 ]]; then - die "Extra arguments are only allowed with exec|reexec command" +if [[ $cmd != exec && $cmd != reexec && $cmd != build && $# != 0 ]]; then + die "Extra arguments are only allowed with exec|reexec|build command" fi do_$cmd "$@" From f9cfe80b56c3033232611f350ec02653304bfbf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= Date: Fri, 4 Aug 2023 11:29:29 +0200 Subject: [PATCH 08/12] tools: nm-in-vm: change default image size Images of qcow2 format dynamically grow up to the maximum size that they have been configured at creation time. Because of this, higher size can be selected without wasting unnecesary space in the host. Rise image size to 20G. Also, allow to set an empty value to IMAGE_SIZE, and don't resize in that case. This is useful because virt-resize fails with some guest partition layouts (like with ubuntu-20.04). --- tools/nm-in-vm | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tools/nm-in-vm b/tools/nm-in-vm index da6d9f3cdb..62ed593afd 100755 --- a/tools/nm-in-vm +++ b/tools/nm-in-vm @@ -65,7 +65,7 @@ fi VM=${VM:="nm"} OS_VERSION=${OS_VERSION:=} RAM=${RAM:=2048} -IMAGE_SIZE=${IMAGE_SIZE:=10G} +IMAGE_SIZE=${IMAGE_SIZE=20G} ROOT_PASSWORD=${ROOT_PASSWORD:=nm} LIBVIRT_POOL=${LIBVIRT_POOL:=default} # only useful if BASEDIR_VM_IMAGE is empty BASEDIR_VM_IMAGE=${BASEDIR_VM_IMAGE:=} @@ -104,6 +104,8 @@ fi do_build() { local t=$'\t' + local ram + local size local os_variant local nm_ci_build_args local nm_ci_install_args @@ -141,6 +143,10 @@ do_build() { return 0 fi + if [[ -n $IMAGE_SIZE ]]; then + size=(--size "$IMAGE_SIZE") + fi + if [[ -n $BASEDIR_NM_CI ]]; then nm_ci_build_args=( --mkdir "$BASEDIR_NM_CI" @@ -223,7 +229,7 @@ do_build() { echo "Creating VM" echo " - VM NAME: $VM" echo " - OS VERSION: $OS_VERSION" - echo " - SIZE: $IMAGE_SIZE" + echo " - SIZE: $([[ -n $IMAGE_SIZE ]] && echo "$IMAGE_SIZE" || echo "don't resize")" echo " - RAM: $RAM" echo " - ROOT PASSWORD: $ROOT_PASSWORD" echo " - IMAGE PATH: $basedir_vm_image/$vm_image_file" @@ -233,7 +239,7 @@ do_build() { virt-builder "$OS_VERSION" \ --output "$basedir_vm_image/$vm_image_file" \ - --size "$IMAGE_SIZE" \ + "${size[@]}" \ --format qcow2 \ --arch x86_64 \ --hostname "$VM" \ From 25e6218e94c9c14d68400abf51ff17535edd4327 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= Date: Mon, 7 Aug 2023 15:19:14 +0200 Subject: [PATCH 09/12] tools: nm-in-vm: fix CentOS Stream guest Install missing repositories required to install all the packages. Unluckily, it doesn't support 9P filesystem shares, and virtiofs is not supported for non-root hosts. Emit a warning about that. --- tools/nm-in-vm | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/tools/nm-in-vm b/tools/nm-in-vm index 62ed593afd..2123a51c9e 100755 --- a/tools/nm-in-vm +++ b/tools/nm-in-vm @@ -158,7 +158,7 @@ do_build() { ) fi - if [[ $OS_VERSION =~ fedora* || $OS_VERSION =~ centos* ]]; then + if [[ $OS_VERSION =~ fedora* || $OS_VERSION =~ centosstream* ]]; then extra_pkgs=(bash-completion bind-utils ccache clang-tools-extra cryptsetup cscope \'dbus\*\' dhcp-client dhcp-relay dhcp-server dnsmasq dracut-network ethtool firewalld gcc gdb glibc-langpack-pl hostapd intltool iproute ipsec-tools iputils iscsi-initiator-utils @@ -172,7 +172,21 @@ do_build() { /usr/bin/debuginfo-install /usr/bin/pytest /usr/bin/python vim wireguard-tools wireshark-cli) - install_pkgs=( + if [[ $OS_VERSION == centosstream-8 ]]; then + install_pkgs=( + --run-command "dnf -y copr enable nmstate/nm-build-deps" + --run-command "dnf config-manager -y --set-enabled powertools" + --install epel-release,epel-next-release + ) + elif [[ $OS_VERSION == centosstream-9 ]]; then + install_pkgs=( + --run-command "dnf -y copr enable nmstate/nm-build-deps" + --run-command "dnf config-manager -y --set-enabled crb" + --install epel-release,epel-next-release + ) + fi + + install_pkgs+=( --update --run "$BASEDIR_NM/contrib/fedora/REQUIRED_PACKAGES" --run-command "dnf install -y --skip-broken ${extra_pkgs[*]}" @@ -236,6 +250,12 @@ do_build() { echo " - NM DIR: $BASEDIR_NM" echo " - NM CI DIR: $([[ -n $BASEDIR_NM_CI ]] && echo "$BASEDIR_NM_CI" || echo '')" echo " - HOST BRIDGE: $HOST_BRIDGE" + + if [[ $OS_VERSION =~ centosstream-* ]]; then + echo "WARNING: NetworkManager repositories can't be shared with the guest" \ + "(CentOS Stream doesn't support 9P filesystem). You'll need to manually" \ + "share by NFS or make a new clone of the repository inside the guest." >&2 + fi virt-builder "$OS_VERSION" \ --output "$basedir_vm_image/$vm_image_file" \ @@ -253,6 +273,7 @@ do_build() { "${nm_ci_build_args[@]}" \ "${install_pkgs[@]}" \ --mkdir "/etc/systemd/system/NetworkManager.service.d" \ + --mkdir "/etc/systemd/network" \ "${install_files[@]}" \ --write "/var/lib/NetworkManager/secret_key:nm-in-container-secret-key" \ --chmod "700:/var/lib/NetworkManager" \ From c8a329bc12da48ba7fae1512ebe78da77361743f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= Date: Thu, 31 Aug 2023 10:40:38 +0200 Subject: [PATCH 10/12] tools: nm-in-vm: don't allow invalid hostnames, fix regex The $VM name is used also as hostname in the guest so ssh connection can be made to root@$VM. However, valid hostnames can only contain letters, numbers and '-'. If other characters are used, they are removed from the hostname so you cannot connect to root@$VM. Fix it by not allowing invalid hostnames in $VM at VM creation. Also, fix some incorrect bash regexes. --- tools/nm-in-vm | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tools/nm-in-vm b/tools/nm-in-vm index 2123a51c9e..7b82981089 100755 --- a/tools/nm-in-vm +++ b/tools/nm-in-vm @@ -133,6 +133,11 @@ do_build() { os_variant=${OS_VERSION//-/} # virt-install --os-variant value, deduced from OS_VERSION os_variant=${os_variant/centosstream/centos-stream} + if [[ ! $VM =~ ^[a-zA-Z0-9\-]*$ ]]; then + echo "Invalid VM name '$VM', use only letters, numbers and '-' character" + return 1 + fi + if vm_is_installed; then echo "The virtual machine '$VM' is already installed, skiping build" >&2 return 0 @@ -158,7 +163,7 @@ do_build() { ) fi - if [[ $OS_VERSION =~ fedora* || $OS_VERSION =~ centosstream* ]]; then + if [[ $OS_VERSION =~ fedora || $OS_VERSION =~ centosstream ]]; then extra_pkgs=(bash-completion bind-utils ccache clang-tools-extra cryptsetup cscope \'dbus\*\' dhcp-client dhcp-relay dhcp-server dnsmasq dracut-network ethtool firewalld gcc gdb glibc-langpack-pl hostapd intltool iproute ipsec-tools iputils iscsi-initiator-utils @@ -196,7 +201,7 @@ do_build() { | sed -n 's/.* => \(.*\) (0x[0-9A-Fa-f]*)\$/\1/p' \ | xargs -n1 readlink -f)" ) - elif [[ $OS_VERSION =~ debian* || $OS_VERSION =~ ubuntu* ]]; then + elif [[ $OS_VERSION =~ debian || $OS_VERSION =~ ubuntu ]]; then extra_pkgs=(bash-completion bind9-utils ccache clang-tools cryptsetup cscope \'dbus\*\' isc-dhcp-client isc-dhcp-relay isc-dhcp-server dnsmasq dracut-network ethtool firewalld gcc gdb hostapd intltool iproute2 \'iputils-\*\' iw libldns3 libreswan @@ -251,7 +256,7 @@ do_build() { echo " - NM CI DIR: $([[ -n $BASEDIR_NM_CI ]] && echo "$BASEDIR_NM_CI" || echo '')" echo " - HOST BRIDGE: $HOST_BRIDGE" - if [[ $OS_VERSION =~ centosstream-* ]]; then + if [[ $OS_VERSION =~ centosstream ]]; then echo "WARNING: NetworkManager repositories can't be shared with the guest" \ "(CentOS Stream doesn't support 9P filesystem). You'll need to manually" \ "share by NFS or make a new clone of the repository inside the guest." >&2 @@ -360,7 +365,7 @@ vm_is_running() { gen_file() { sed "s|{{BASEDIR_NM}}|$BASEDIR_NM|g" "$datadir/$1.in" > "$datadir/data-$1" - if [[ $1 =~ bin-* ]]; then + if [[ $1 =~ ^bin- ]]; then chmod 755 "$datadir/data-$1" else chmod 644 "$datadir/data-$1" From 0ec71289ed3377ad2a844417dc34e9191a01d3b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= Date: Thu, 31 Aug 2023 11:21:12 +0200 Subject: [PATCH 11/12] tools: nm-in-vm: fix motd Message of the day was shown twice because the same bashrc.my file than for containers was used. That file contained some code to show motd in the container, where it is not shown by default. But in the VM, the motd is shown by default, so it was shown twice. Move the code to show motd to a file used only by nm-in-container and not by nm-in-vm. Also, modify the explanation about using prepare-for-system.sh because it's only valid for Fedora but nm-in-vm can be used with other SOs too. --- tools/nm-guest-data/etc-bashrc-motd.my.in | 4 ++++ tools/nm-guest-data/etc-bashrc.my.in | 5 ----- tools/nm-guest-data/etc-motd-vm.in | 2 +- tools/nm-in-container | 7 +++++-- 4 files changed, 10 insertions(+), 8 deletions(-) create mode 100644 tools/nm-guest-data/etc-bashrc-motd.my.in diff --git a/tools/nm-guest-data/etc-bashrc-motd.my.in b/tools/nm-guest-data/etc-bashrc-motd.my.in new file mode 100644 index 0000000000..510d30f8fa --- /dev/null +++ b/tools/nm-guest-data/etc-bashrc-motd.my.in @@ -0,0 +1,4 @@ +if test "$SHOW_MOTD" != 0; then + cat /etc/motd + export SHOW_MOTD=0 +fi diff --git a/tools/nm-guest-data/etc-bashrc.my.in b/tools/nm-guest-data/etc-bashrc.my.in index db8598a05c..531519bad7 100644 --- a/tools/nm-guest-data/etc-bashrc.my.in +++ b/tools/nm-guest-data/etc-bashrc.my.in @@ -41,8 +41,3 @@ nm_run_normal() { . /usr/share/git-core/contrib/completion/git-prompt.sh PS1="\[\033[01;36m\]\u@\h\[\033[00m\]:\t:\[\033[01;34m\]\w\$(__git_ps1 \" \[\033[01;36m\](%s)\[\033[00m\]\")\[\033[00m\]$ " export GIT_PS1_SHOWDIRTYSTATE=1 - -if test "$SHOW_MOTD" != 0; then - cat /etc/motd - export SHOW_MOTD=0 -fi diff --git a/tools/nm-guest-data/etc-motd-vm.in b/tools/nm-guest-data/etc-motd-vm.in index 17332d5ea0..10ae1f9fc8 100644 --- a/tools/nm-guest-data/etc-motd-vm.in +++ b/tools/nm-guest-data/etc-motd-vm.in @@ -55,7 +55,7 @@ For example, configure NetworkManager with Test with: $ systemctl stop NetworkManager; /opt/test/sbin/NetworkManager --debug 2>&1 | tee -a /tmp/nm-log.txt -Or better, configure with `contrib/fedora/rpm/configure-for-system.sh`, +Or better, if using Fedora, configure with `contrib/fedora/rpm/configure-for-system.sh`, subsequent `make && make install` will overwrite your system's NetworkManager, and you can test it with `systemctl daemon-reload ; systemctl restart NetworkManager`. diff --git a/tools/nm-in-container b/tools/nm-in-container index 0a58d821a2..f91a747f32 100755 --- a/tools/nm-in-container +++ b/tools/nm-in-container @@ -131,8 +131,9 @@ create_dockerfile() { local CONTAINERFILE="$1" local BASE_IMAGE="$2" local GEN_FILES="bin-nm-env-prepare.sh bin-nm-deploy.sh bin-_nm-in-container-setup.sh - etc-rc.local etc-motd-container etc-bashrc.my nm-90-my.conf nm-95-user.conf - home-bash_history home-gdbinit home-gdb_history home-behaverc systemd-20-nm.override" + etc-rc.local etc-motd-container etc-bashrc.my etc-bashrc-motd.my nm-90-my.conf + nm-95-user.conf home-bash_history home-gdbinit home-gdb_history home-behaverc + systemd-20-nm.override" cp "$BASEDIR_NM/contrib/scripts/NM-log" "$BASEDIR_DATA/data-bin-NM-log" CLEANUP_FILES+=( "$BASEDIR_DATA/data-NM-log" ) @@ -310,6 +311,7 @@ COPY data-bin-_nm-in-container-setup.sh "/usr/bin/_nm-in-container-setup.sh" COPY data-etc-rc.local "/etc/rc.d/rc.local" COPY data-etc-motd-container /etc/motd COPY data-etc-bashrc.my /etc/bashrc.my +COPY data-etc-bashrc-motd.my /etc/bashrc-motd.my COPY data-nm-90-my.conf /etc/NetworkManager/conf.d/90-my.conf COPY data-nm-95-user.conf /etc/NetworkManager/conf.d/95-user.conf COPY data-home-bash_history /root/.bash_history @@ -339,6 +341,7 @@ $RUN_LN_BASEDIR_NM_CI RUN rm -rf /etc/NetworkManager/system-connections/* RUN echo -e '\n. /etc/bashrc.my\n' >> /etc/bashrc +RUN echo -e '\n. /etc/bashrc-motd.my\n' >> /etc/bashrc RUN updatedb EOF From 52c347677f2ac67a37cea90b6bdb2b3d2a07005c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= Date: Wed, 6 Sep 2023 12:38:07 +0200 Subject: [PATCH 12/12] tools: nm-in-vm: fix error if pool folder doesn't exist yet If libvirt's default pool folder doesn't exist yet (i.e. the user has never installed a VM there), create it to avoid error and script exit. --- tools/nm-in-vm | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/nm-in-vm b/tools/nm-in-vm index 7b82981089..569c766c91 100755 --- a/tools/nm-in-vm +++ b/tools/nm-in-vm @@ -421,6 +421,7 @@ while (( $# > 0 )); do done # compute some values that depends on user selectable variables +mkdir -p "$BASEDIR_VM_IMAGE" basedir_vm_image=$(readlink -f "$BASEDIR_VM_IMAGE") vm_image_file="$VM.qcow2" datadir="$BASEDIR_NM/tools/nm-guest-data"