From a1888c35a026ec8dd89b7bff7937f256c6d4c377 Mon Sep 17 00:00:00 2001 From: Martin Necas Date: Mon, 2 Dec 2024 16:10:04 +0100 Subject: [PATCH] MTV-1711 | Keep static IP on Debian based interfaces Issue: All Debian-based operating systems can have the network configurations in the `/etc/network/interfaces`. Right now we are not fetching information from these config files when creating the udev rule to set the interface name. Fix: Add a new function to the `network_config_util.sh` script. I have decided to use the `ifquery` inside the guest. Alternatively, we would need to start parsing the config files. We can easily grep the IP address from the configfile and find the interface name but there could be multiple interface configurations inside one file. Docs: https://man.cx/interfaces(5) Signed-off-by: Martin Necas --- virt-v2v/pkg/customize/BUILD.bazel | 13 +++++ .../expected-udev.rule | 2 + .../root/etc/network/interfaces | 8 +++ .../root/etc/network/interfaces.d/if-ens192 | 5 ++ .../root/etc/network/interfaces.d/if-eth0 | 5 ++ .../root/tmp/macToIP | 3 ++ .../expected-udev.rule | 1 + .../root/etc/network/interfaces | 14 +++++ .../root/tmp/macToIP | 3 ++ .../scripts/rhel/run/network_config_util.sh | 54 +++++++++++++++++++ .../rhel/run/test-network_config_util.sh | 8 +++ virt-v2v/pkg/utils/embed-tool.go | 5 ++ 12 files changed, 121 insertions(+) create mode 100644 virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-multiple-test.d/expected-udev.rule create mode 100644 virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-multiple-test.d/root/etc/network/interfaces create mode 100644 virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-multiple-test.d/root/etc/network/interfaces.d/if-ens192 create mode 100644 virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-multiple-test.d/root/etc/network/interfaces.d/if-eth0 create mode 100644 virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-multiple-test.d/root/tmp/macToIP create mode 100644 virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-single-test.d/expected-udev.rule create mode 100644 virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-single-test.d/root/etc/network/interfaces create mode 100644 virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-single-test.d/root/tmp/macToIP diff --git a/virt-v2v/pkg/customize/BUILD.bazel b/virt-v2v/pkg/customize/BUILD.bazel index 99ab66a48..a894ca43f 100644 --- a/virt-v2v/pkg/customize/BUILD.bazel +++ b/virt-v2v/pkg/customize/BUILD.bazel @@ -39,6 +39,19 @@ go_library( "scripts/rhel/run/systemd-test.d/root/etc/netplan/50-netplan.yaml", "scripts/rhel/run/systemd-test.d/root/run/systemd/network/netplan-ens160.network", "scripts/rhel/run/systemd-test.d/root/tmp/macToIP", + "scripts/rhel/run/ifcfg-hwaddr-test.d/expected-udev.rule", + "scripts/rhel/run/ifcfg-hwaddr-test.d/root/etc/sysconfig/network-scripts/ifcfg-ens192", + "scripts/rhel/run/ifcfg-hwaddr-test.d/root/etc/sysconfig/network-scripts/ifcfg-ens224", + "scripts/rhel/run/ifcfg-hwaddr-test.d/root/tmp/macToIP", + "scripts/rhel/run/network-interfaces-multiple-test.d/expected-udev.rule", + "scripts/rhel/run/network-interfaces-multiple-test.d/root/etc/network/interfaces", + "scripts/rhel/run/network-interfaces-multiple-test.d/root/etc/network/interfaces.d/if-ens192", + "scripts/rhel/run/network-interfaces-multiple-test.d/root/etc/network/interfaces.d/if-eth0", + "scripts/rhel/run/network-interfaces-multiple-test.d/root/tmp/macToIP", + "scripts/rhel/run/network-interfaces-single-test.d/expected-udev.rule", + "scripts/rhel/run/network-interfaces-single-test.d/root/etc/network/interfaces", + "scripts/rhel/run/network-interfaces-single-test.d/root/tmp/macToIP", + "scripts/rhel/run/test-network_config_util.sh", ], importpath = "github.com/konveyor/forklift-controller/virt-v2v/pkg/customize", visibility = ["//visibility:public"], diff --git a/virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-multiple-test.d/expected-udev.rule b/virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-multiple-test.d/expected-udev.rule new file mode 100644 index 000000000..f025e47ba --- /dev/null +++ b/virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-multiple-test.d/expected-udev.rule @@ -0,0 +1,2 @@ +SUBSYSTEM=="net",ACTION=="add",ATTR{address}=="aa:bb:cc:dd:ee:ff",NAME="ens192" +SUBSYSTEM=="net",ACTION=="add",ATTR{address}=="aa:bb:cc:dd:ee:fe",NAME="eth0" diff --git a/virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-multiple-test.d/root/etc/network/interfaces b/virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-multiple-test.d/root/etc/network/interfaces new file mode 100644 index 000000000..97589ca62 --- /dev/null +++ b/virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-multiple-test.d/root/etc/network/interfaces @@ -0,0 +1,8 @@ +# This file describes the network interfaces available on your system +# and how to activate them. For more information, see interfaces(5). + +source /etc/network/interfaces.d/* + +# The loopback network interface +auto lo +iface lo inet loopback diff --git a/virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-multiple-test.d/root/etc/network/interfaces.d/if-ens192 b/virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-multiple-test.d/root/etc/network/interfaces.d/if-ens192 new file mode 100644 index 000000000..f94541991 --- /dev/null +++ b/virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-multiple-test.d/root/etc/network/interfaces.d/if-ens192 @@ -0,0 +1,5 @@ +# The primary network interface +auto ens192 +iface ens192 inet static + address 10.184.121.84/24 + gateway 10.184.121.1 diff --git a/virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-multiple-test.d/root/etc/network/interfaces.d/if-eth0 b/virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-multiple-test.d/root/etc/network/interfaces.d/if-eth0 new file mode 100644 index 000000000..b291ad114 --- /dev/null +++ b/virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-multiple-test.d/root/etc/network/interfaces.d/if-eth0 @@ -0,0 +1,5 @@ +# The primary network interface +auto eth0 +iface eth0 inet static + address 192.168.1.11/24 + gateway 192.168.1.1 diff --git a/virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-multiple-test.d/root/tmp/macToIP b/virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-multiple-test.d/root/tmp/macToIP new file mode 100644 index 000000000..83f0f79c7 --- /dev/null +++ b/virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-multiple-test.d/root/tmp/macToIP @@ -0,0 +1,3 @@ +aa:bb:cc:dd:ee:ff:ip:10.184.121.84,things,more +aa:bb:cc:dd:ee:fe:ip:192.168.1.11,hello,world +aa:bb:cc:dd:ee:fd:ip:192.168.1.12,ipv6,support diff --git a/virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-single-test.d/expected-udev.rule b/virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-single-test.d/expected-udev.rule new file mode 100644 index 000000000..edf56d478 --- /dev/null +++ b/virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-single-test.d/expected-udev.rule @@ -0,0 +1 @@ +SUBSYSTEM=="net",ACTION=="add",ATTR{address}=="aa:bb:cc:dd:ee:ff",NAME="ens192" diff --git a/virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-single-test.d/root/etc/network/interfaces b/virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-single-test.d/root/etc/network/interfaces new file mode 100644 index 000000000..e54d5e4bd --- /dev/null +++ b/virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-single-test.d/root/etc/network/interfaces @@ -0,0 +1,14 @@ +# This file describes the network interfaces available on your system +# and how to activate them. For more information, see interfaces(5). + +source /etc/network/interfaces.d/* + +# The loopback network interface +auto lo +iface lo inet loopback + +# The primary network interface +auto ens192 +iface ens192 inet static + address 10.184.121.84/24 + gateway 10.184.121.1 diff --git a/virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-single-test.d/root/tmp/macToIP b/virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-single-test.d/root/tmp/macToIP new file mode 100644 index 000000000..83f0f79c7 --- /dev/null +++ b/virt-v2v/pkg/customize/scripts/rhel/run/network-interfaces-single-test.d/root/tmp/macToIP @@ -0,0 +1,3 @@ +aa:bb:cc:dd:ee:ff:ip:10.184.121.84,things,more +aa:bb:cc:dd:ee:fe:ip:192.168.1.11,hello,world +aa:bb:cc:dd:ee:fd:ip:192.168.1.12,ipv6,support diff --git a/virt-v2v/pkg/customize/scripts/rhel/run/network_config_util.sh b/virt-v2v/pkg/customize/scripts/rhel/run/network_config_util.sh index f57bdc62d..a8d74ce58 100644 --- a/virt-v2v/pkg/customize/scripts/rhel/run/network_config_util.sh +++ b/virt-v2v/pkg/customize/scripts/rhel/run/network_config_util.sh @@ -4,6 +4,8 @@ V2V_MAP_FILE="${V2V_MAP_FILE:-/tmp/macToIP}" NETWORK_SCRIPTS_DIR="${NETWORK_SCRIPTS_DIR:-/etc/sysconfig/network-scripts}" NETWORK_CONNECTIONS_DIR="${NETWORK_CONNECTIONS_DIR:-/etc/NetworkManager/system-connections}" +NETWORK_INTERFACES_DIR="${NETWORK_INTERFACES_DIR:-/etc/network/interfaces}" +IFQUERY_CMD="${IFQUERY_CMD:-ifquery}" SYSTEMD_NETWORK_DIR="${SYSTEMD_NETWORK_DIR:-/run/systemd/network}" UDEV_RULES_FILE="${UDEV_RULES_FILE:-/etc/udev/rules.d/70-persistent-net.rules}" NETPLAN_DIR="${NETPLAN_DIR:-/}" @@ -225,6 +227,57 @@ udev_from_netplan() { done } +# Create udev rules based on the macToIP mapping + output from parse_ifquery_file +udev_from_ifquery() { + # Check if ifquery command exist + if ! ${IN_TESTING:-false} && ! command -v $IFQUERY_CMD>/dev/null 2>&1; then + log "Warning: ifquery is not installed." + return 0 + fi + + # ifquery with interface dir + ifquery_get() { + $IFQUERY_CMD -i "$NETWORK_INTERFACES_DIR" "$@" 2>&3 + } + + # Loop over all interface names and return the one with target_ip, or null + find_interface_by_ip() { + target_ip="$1" + # Loop through all interfaces and check for the given IP address + ifquery_get -l | while read IFNAME; do + if ifquery_get $IFNAME | grep -q "$target_ip"; then + echo "$IFNAME" + return + fi + done + } + + # Read the mapping file line by line + cat "$V2V_MAP_FILE" | while read line; + do + # Extract S_HW and S_IP from the current line in the mapping file + extract_mac_ip "$line" + + # If S_HW and S_IP were not extracted, skip the line + if [ -z "$S_HW" ] || [ -z "$S_IP" ]; then + log "Warning: invalid mac to ip line: $line." + continue + fi + + # Search the parsed netplan output for a matching IP address + interface_name=$(find_interface_by_ip "$S_IP") + + # If no interface is found, skip this entry + if [ -z "$interface_name" ]; then + log "Info: no interface name found to $S_IP." + continue + fi + + # Create the udev rule based on the extracted MAC address and interface name + echo "SUBSYSTEM==\"net\",ACTION==\"add\",ATTR{address}==\"$(remove_quotes "$S_HW")\",NAME=\"$(remove_quotes "$interface_name")\"" + done +} + # Write to udev config # ---------------------------------------- @@ -250,6 +303,7 @@ main() { udev_from_ifcfg udev_from_nm udev_from_netplan + udev_from_ifquery } | check_dupe_hws > "$UDEV_RULES_FILE" 2>/dev/null echo "New udev rule:" cat $UDEV_RULES_FILE diff --git a/virt-v2v/pkg/customize/scripts/rhel/run/test-network_config_util.sh b/virt-v2v/pkg/customize/scripts/rhel/run/test-network_config_util.sh index 263f0983e..4f554b113 100644 --- a/virt-v2v/pkg/customize/scripts/rhel/run/test-network_config_util.sh +++ b/virt-v2v/pkg/customize/scripts/rhel/run/test-network_config_util.sh @@ -20,6 +20,11 @@ test_dir() { export SYSTEMD_NETWORK_DIR="$TEST_DIR/run/systemd/network" export NETPLAN_DIR="$TEST_DIR/etc/netplan" + export IFQUERY_CMD=" + podman run + -v $TEST_DIR/etc/network:/etc/network + cmd.cat/ifquery ifquery + " export TEST_SRC_DIR=$1 #${SCRIPT_DIR}/ifcfg-test.d export EXPECTED_UDEV_RULE_FILE="$TEST_SRC_DIR/expected-udev.rule" @@ -92,5 +97,8 @@ expected_to_pass_dirs ${SCRIPT_DIR}/netplan*-test.d; # -------------------------- expected_to_fail_dirs ${SCRIPT_DIR}/systemd*-test.d; +# Test systems using network interfaces +# -------------------------- +expected_to_pass_dirs ${SCRIPT_DIR}/network-interfaces*-test.d; PASS "All tests behaved as expected." diff --git a/virt-v2v/pkg/utils/embed-tool.go b/virt-v2v/pkg/utils/embed-tool.go index 4c02cc1e4..fa77d0c01 100644 --- a/virt-v2v/pkg/utils/embed-tool.go +++ b/virt-v2v/pkg/utils/embed-tool.go @@ -6,6 +6,7 @@ import ( "io/fs" "os" "path/filepath" + "regexp" ) // EmbedTool for manipulating the embedded Filesystem @@ -77,10 +78,14 @@ func (t *EmbedTool) writeFileFromFS(src, dst string) error { // - []files: The file paths which are located inside the embedded Filesystem. // - error: An error if the file cannot be read, or nil if successful. func (t *EmbedTool) getAllFilenames() (files []string, err error) { + var nameExcludeChars = regexp.MustCompile(".*test.*") if err := fs.WalkDir(t.Filesystem, ".", func(path string, d fs.DirEntry, err error) error { if d.IsDir() { return nil } + if nameExcludeChars.MatchString(path) { + return nil + } files = append(files, path) return nil }); err != nil {