Skip to content

Commit

Permalink
MTV-1711 | Keep static IP on Debian based interfaces
Browse files Browse the repository at this point in the history
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 <mnecas@redhat.com>
  • Loading branch information
mnecas committed Dec 3, 2024
1 parent 38f14ec commit a1888c3
Show file tree
Hide file tree
Showing 12 changed files with 121 additions and 0 deletions.
13 changes: 13 additions & 0 deletions virt-v2v/pkg/customize/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -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"],
Expand Down
Original file line number Diff line number Diff line change
@@ -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"
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SUBSYSTEM=="net",ACTION=="add",ATTR{address}=="aa:bb:cc:dd:ee:ff",NAME="ens192"
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
54 changes: 54 additions & 0 deletions virt-v2v/pkg/customize/scripts/rhel/run/network_config_util.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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:-/}"
Expand Down Expand Up @@ -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
# ----------------------------------------

Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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."
5 changes: 5 additions & 0 deletions virt-v2v/pkg/utils/embed-tool.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"io/fs"
"os"
"path/filepath"
"regexp"
)

// EmbedTool for manipulating the embedded Filesystem
Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit a1888c3

Please sign in to comment.