From c237860efa43aec81fff6bb4c9239f3990c7ebbf Mon Sep 17 00:00:00 2001 From: yaacov Date: Tue, 10 Sep 2024 20:30:12 +0300 Subject: [PATCH 1/5] Add netplan config parding sh utility for ubuntu static ip Signed-off-by: yaacov --- .../scripts/rhel/run/network_config_util.sh | 82 +++++++++++++++++-- .../scripts/rhel/run/network_config_util_test | 59 +++++++++++-- 2 files changed, 130 insertions(+), 11 deletions(-) diff --git a/virt-v2v/scripts/rhel/run/network_config_util.sh b/virt-v2v/scripts/rhel/run/network_config_util.sh index 191c49cae..4b56e2fca 100644 --- a/virt-v2v/scripts/rhel/run/network_config_util.sh +++ b/virt-v2v/scripts/rhel/run/network_config_util.sh @@ -5,6 +5,7 @@ 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}" UDEV_RULES_FILE="${UDEV_RULES_FILE:-/etc/udev/rules.d/70-persistent-net.rules}" +NETPLAN_DIR="${NETPLAN_DIR:-/}" # Dump debug strings into a new file descriptor and redirect it to stdout. exec 3>&1 @@ -12,6 +13,9 @@ log() { echo $@ >&3 } +# Sanity checks +# ------------- + # Check if mapping file does not exist if [ ! -f "$V2V_MAP_FILE" ]; then log "File $V2V_MAP_FILE does not exist. Exiting." @@ -24,9 +28,19 @@ if [ -f "$UDEV_RULES_FILE" ]; then exit 0 fi +# Helper functions +# ---------------- + +# Get the v2v map file as list +v2v_list_as_envs() { + while IFS= read -r line; do + echo "$line" + done < "$V2V_MAP_FILE" +} + # Clean strigs in case they have quates remove_quotes() { - echo "$1" | tr -d '"' + echo "$1" | tr -d '"' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' } # Validate MAC address and IPv4 address and extract them @@ -39,6 +53,9 @@ extract_mac_ip() { fi } +# Network infrastructure reading functions +# ---------------------------------------- + # Create udev rules based on the macToip mapping + ifcfg network scripts udev_from_ifcfg() { # Check if the network scripts directory exists @@ -48,7 +65,8 @@ udev_from_ifcfg() { fi # Read the mapping file line by line - while IFS= read -r line; do + v2v_list_as_envs | while read line; + do # Extract S_HW and S_IP extract_mac_ip "$line" @@ -70,7 +88,7 @@ udev_from_ifcfg() { fi echo "SUBSYSTEM==\"net\",ACTION==\"add\",ATTR{address}==\"$(remove_quotes "$S_HW")\",NAME=\"$(remove_quotes "$DEVICE")\"" - done < "$V2V_MAP_FILE" + done } # Create udev rules based on the macToip mapping + network manager connections @@ -82,7 +100,8 @@ udev_from_nm() { fi # Read the mapping file line by line - while IFS= read -r line; do + v2v_list_as_envs | while read line; + do # Extract S_HW and S_IP extract_mac_ip "$line" @@ -104,9 +123,61 @@ udev_from_nm() { fi echo "SUBSYSTEM==\"net\",ACTION==\"add\",ATTR{address}==\"$(remove_quotes "$S_HW")\",NAME=\"$(remove_quotes "$DEVICE")\"" - done < "$V2V_MAP_FILE" + done +} + +# Create udev rules based on the macToIP mapping + output from parse_netplan_file +udev_from_netplan() { + # Check if netplan command exist + if ! command -v netplan >/dev/null 2>&1; then + log "Warning: netplan is not installed." + return 0 + fi + + # netplan with root dir + netplan_get() { + netplan get --root-dir "$NETPLAN_DIR" "$@" 2>/dev/null + } + + # Loop over all interface names and treturn 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 + netplan_get ethernets | grep -Eo "^[^[:space:]]+[^:]" | while read IFNAME; do + if netplan_get ethernets."$IFNAME".addresses | grep -q "$target_ip"; then + echo "$IFNAME" + fi + done + } + + # Read the mapping file line by line + v2v_list_as_envs | 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 + 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 + 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 +# ---------------------------------------- + # Checks for duplicate hardware addresses check_dupe_hws() { input=$(cat) @@ -128,6 +199,7 @@ main() { { udev_from_ifcfg udev_from_nm + udev_from_netplan } | check_dupe_hws > "$UDEV_RULES_FILE" 2>/dev/null } diff --git a/virt-v2v/scripts/rhel/run/network_config_util_test b/virt-v2v/scripts/rhel/run/network_config_util_test index 7d8f6bfc1..c76c61a9d 100644 --- a/virt-v2v/scripts/rhel/run/network_config_util_test +++ b/virt-v2v/scripts/rhel/run/network_config_util_test @@ -10,13 +10,14 @@ export V2V_MAP_FILE="$TEST_DIR/macToIP" export NETWORK_SCRIPTS_DIR="$TEST_DIR/network-scripts" export NETWORK_CONNECTIONS_DIR="$TEST_DIR/system-connections" export UDEV_RULES_FILE="$TEST_DIR/70-persistent-net.rules" +export NETPLAN_DIR="$TEST_DIR" # Test systems using network-scripts # ---------------------------------- # Clean up from previous runs rm -f "$UDEV_RULES_FILE" -rm -rf "$NETWORK_SCRIPTS_DIR" "$NETWORK_CONNECTIONS_DIR" +rm -rf "$NETWORK_SCRIPTS_DIR" "$NETWORK_CONNECTIONS_DIR" "$NETPLAN_DIR" mkdir -p "$NETWORK_SCRIPTS_DIR" # Create mock data @@ -52,16 +53,13 @@ fi # Clean up from previous runs rm -f "$UDEV_RULES_FILE" -rm -rf "$NETWORK_SCRIPTS_DIR" "$NETWORK_CONNECTIONS_DIR" +rm -rf "$NETWORK_SCRIPTS_DIR" "$NETWORK_CONNECTIONS_DIR" "$NETPLAN_DIR" mkdir -p "$NETWORK_CONNECTIONS_DIR" # Create mock data printf "aa:bb:cc:dd:ee:ff:ip:192.168.1.10,things,more\naa:bb:cc:dd:ee:fe:ip:192.168.1.11,hello,world\naa:bb:cc:dd:ee:fd:ip:2001:0db8:85a3:0000:0000:8a2e:0370:7334\n" > "$V2V_MAP_FILE" printf "[connection]\ninterface-name=eth3\naddress1=192.168.1.11/24\n" > "$NETWORK_CONNECTIONS_DIR/eth1 but with spaces.nmconnection" -# Source the script under test -. ${SCRIPT_DIR}/network_config_util.sh - # Run the script main @@ -76,13 +74,62 @@ if [ ! -f "$UDEV_RULES_FILE" ]; then exit 1 fi -# Test 3: Verify the content of the udev rules file +# Test 1: Verify the content of the udev rules file EXPECTED_RULE="SUBSYSTEM==\"net\",ACTION==\"add\",ATTR{address}==\"aa:bb:cc:dd:ee:fe\",NAME=\"eth3\"" if ! echo "$EXPECTED_RULE" | cmp -s - "$UDEV_RULES_FILE"; then echo "Test 2 Failed: The content of $UDEV_RULES_FILE does not match the expected rule." exit 1 fi +# Test systems using netplan YAML +# ------------------------------- + +NETPLAN_FILE="$NETPLAN_DIR/etc/netplan/50-netplan.yaml" + +# Clean up from previous runs +rm -f "$UDEV_RULES_FILE" +rm -rf "$NETWORK_SCRIPTS_DIR" "$NETWORK_CONNECTIONS_DIR" "$NETPLAN_DIR" +mkdir -p "$NETPLAN_DIR/etc/netplan" + +# Create mock data for netplan YAML test +cat < "$NETPLAN_FILE" +network: + version: 2 + ethernets: + eth0: + dhcp4: true + eth1: + dhcp4: false + addresses: + - 192.168.1.11/24 + enp3s0: + addresses: [192.168.1.12/24] +EOL + +# Create mock mapping file +printf "aa:bb:cc:dd:ee:ff:ip:192.168.1.10,things,more\naa:bb:cc:dd:ee:fe:ip:192.168.1.11,hello,world\naa:bb:cc:dd:ee:fd:ip:192.168.1.12,ipv6,support\n" > "$V2V_MAP_FILE" + +# Run the script +main + +printf "\nTest netplan output:\n" +echo "FILE_START" +cat $UDEV_RULES_FILE +echo "FILE_END" + +# Test 1: Verify the udev rules file was created +if [ ! -f "$UDEV_RULES_FILE" ]; then + echo "Test 1 Failed: UDEV_RULES_FILE not created." + exit 1 +fi + +# Test 2: Verify the content of the udev rules file +EXPECTED_RULE="SUBSYSTEM==\"net\",ACTION==\"add\",ATTR{address}==\"aa:bb:cc:dd:ee:fe\",NAME=\"eth1\"\nSUBSYSTEM==\"net\",ACTION==\"add\",ATTR{address}==\"aa:bb:cc:dd:ee:fd\",NAME=\"enp3s0\"" +if ! echo "$EXPECTED_RULE" | cmp -s - "$UDEV_RULES_FILE"; then + echo "Test 2 Failed: The content of $UDEV_RULES_FILE does not match the expected rule." + exit 1 +fi + # ----------------------- printf "\nAll tests passed successfully.\n" From f7a8cabe6ef754dde157e1a8adf86f06671a4aff Mon Sep 17 00:00:00 2001 From: yaacov Date: Wed, 11 Sep 2024 12:46:14 +0300 Subject: [PATCH 2/5] Address single quat Signed-off-by: yaacov --- virt-v2v/scripts/rhel/run/network_config_util.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/virt-v2v/scripts/rhel/run/network_config_util.sh b/virt-v2v/scripts/rhel/run/network_config_util.sh index 4b56e2fca..ca30a2f0a 100644 --- a/virt-v2v/scripts/rhel/run/network_config_util.sh +++ b/virt-v2v/scripts/rhel/run/network_config_util.sh @@ -40,7 +40,7 @@ v2v_list_as_envs() { # Clean strigs in case they have quates remove_quotes() { - echo "$1" | tr -d '"' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' + echo "$1" | tr -d '"' | tr -d "'" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' } # Validate MAC address and IPv4 address and extract them From 88465dd264b469102f4d1fcd43f76eb50b74e693 Mon Sep 17 00:00:00 2001 From: yaacov Date: Wed, 11 Sep 2024 12:52:22 +0300 Subject: [PATCH 3/5] replace file reading funtion with cat Signed-off-by: yaacov --- virt-v2v/scripts/rhel/run/network_config_util.sh | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/virt-v2v/scripts/rhel/run/network_config_util.sh b/virt-v2v/scripts/rhel/run/network_config_util.sh index ca30a2f0a..bde08ae38 100644 --- a/virt-v2v/scripts/rhel/run/network_config_util.sh +++ b/virt-v2v/scripts/rhel/run/network_config_util.sh @@ -31,13 +31,6 @@ fi # Helper functions # ---------------- -# Get the v2v map file as list -v2v_list_as_envs() { - while IFS= read -r line; do - echo "$line" - done < "$V2V_MAP_FILE" -} - # Clean strigs in case they have quates remove_quotes() { echo "$1" | tr -d '"' | tr -d "'" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' @@ -65,7 +58,7 @@ udev_from_ifcfg() { fi # Read the mapping file line by line - v2v_list_as_envs | while read line; + cat "$V2V_MAP_FILE" | while read line; do # Extract S_HW and S_IP extract_mac_ip "$line" @@ -100,7 +93,7 @@ udev_from_nm() { fi # Read the mapping file line by line - v2v_list_as_envs | while read line; + cat "$V2V_MAP_FILE" | while read line; do # Extract S_HW and S_IP extract_mac_ip "$line" @@ -152,7 +145,7 @@ udev_from_netplan() { } # Read the mapping file line by line - v2v_list_as_envs | while read 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" From 7bb3e01b6ee549ec787a2ae8f4b6e34bdfb29254 Mon Sep 17 00:00:00 2001 From: yaacov Date: Wed, 11 Sep 2024 12:56:16 +0300 Subject: [PATCH 4/5] Add loging when can't find a name for ip in netplan configuration Signed-off-by: yaacov --- virt-v2v/scripts/rhel/run/network_config_util.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/virt-v2v/scripts/rhel/run/network_config_util.sh b/virt-v2v/scripts/rhel/run/network_config_util.sh index bde08ae38..d55facc02 100644 --- a/virt-v2v/scripts/rhel/run/network_config_util.sh +++ b/virt-v2v/scripts/rhel/run/network_config_util.sh @@ -160,6 +160,7 @@ udev_from_netplan() { # If no interface is found, skip this entry if [ -z "$interface_name" ]; then + log "Info: no interface name found to $S_IP." continue fi From 8564390793f0165f215627252642a48294204ced Mon Sep 17 00:00:00 2001 From: yaacov Date: Wed, 11 Sep 2024 13:01:00 +0300 Subject: [PATCH 5/5] return after first netplan device found, add logs Signed-off-by: yaacov --- virt-v2v/scripts/rhel/run/network_config_util.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/virt-v2v/scripts/rhel/run/network_config_util.sh b/virt-v2v/scripts/rhel/run/network_config_util.sh index d55facc02..37e86415b 100644 --- a/virt-v2v/scripts/rhel/run/network_config_util.sh +++ b/virt-v2v/scripts/rhel/run/network_config_util.sh @@ -65,18 +65,21 @@ udev_from_ifcfg() { # If S_HW and S_IP were not extracted, skip the line if [ -z "$S_HW" ] || [ -z "$S_IP" ]; then + log "Warning: invalide mac to ip line: $line." continue fi # Find the matching network script file IFCFG=$(grep -l "IPADDR=$S_IP" "$NETWORK_SCRIPTS_DIR"/*) if [ -z "$IFCFG" ]; then + log "Info: no ifcg config file name foud for $S_IP." continue fi # Source the matching file, if found DEVICE=$(grep '^DEVICE=' "$IFCFG" | cut -d'=' -f2) if [ -z "$DEVICE" ]; then + log "Info: no interface name found to $S_IP." continue fi @@ -100,18 +103,21 @@ udev_from_nm() { # If S_HW and S_IP were not extracted, skip the line if [ -z "$S_HW" ] || [ -z "$S_IP" ]; then + log "Warning: invalide mac to ip line: $line." continue fi # Find the matching NetworkManager connection file NM_FILE=$(grep -El "address[0-9]*=$S_IP" "$NETWORK_CONNECTIONS_DIR"/*) if [ -z "$NM_FILE" ]; then + log "Info: no nm config file name foud for $S_IP." continue fi # Extract the DEVICE (interface name) from the matching file DEVICE=$(grep '^interface-name=' "$NM_FILE" | cut -d'=' -f2) if [ -z "$DEVICE" ]; then + log "Info: no interface name found to $S_IP." continue fi @@ -140,6 +146,7 @@ udev_from_netplan() { netplan_get ethernets | grep -Eo "^[^[:space:]]+[^:]" | while read IFNAME; do if netplan_get ethernets."$IFNAME".addresses | grep -q "$target_ip"; then echo "$IFNAME" + return fi done } @@ -152,6 +159,7 @@ udev_from_netplan() { # If S_HW and S_IP were not extracted, skip the line if [ -z "$S_HW" ] || [ -z "$S_IP" ]; then + log "Warning: invalide mac to ip line: $line." continue fi