Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport | Add netplan config parding sh utility for ubuntu static ip #1027

Merged
merged 5 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 79 additions & 5 deletions virt-v2v/cold/scripts/rhel/run/network_config_util.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@ 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
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."
Expand All @@ -24,9 +28,12 @@ if [ -f "$UDEV_RULES_FILE" ]; then
exit 0
fi

# Helper functions
# ----------------

# Clean strigs in case they have quates
remove_quotes() {
echo "$1" | tr -d '"'
echo "$1" | tr -d '"' | tr -d "'" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'
}

# Validate MAC address and IPv4 address and extract them
Expand All @@ -39,6 +46,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
Expand All @@ -48,29 +58,33 @@ udev_from_ifcfg() {
fi

# Read the mapping file line by line
while IFS= read -r line; do
cat "$V2V_MAP_FILE" | while read line;
do
# Extract S_HW and S_IP
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: 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

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
Expand All @@ -82,31 +96,90 @@ udev_from_nm() {
fi

# Read the mapping file line by line
while IFS= read -r line; do
cat "$V2V_MAP_FILE" | while read line;
do
# Extract S_HW and S_IP
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: 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

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"
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: invalide 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
# ----------------------------------------

# Checks for duplicate hardware addresses
check_dupe_hws() {
input=$(cat)
Expand All @@ -128,6 +201,7 @@ main() {
{
udev_from_ifcfg
udev_from_nm
udev_from_netplan
} | check_dupe_hws > "$UDEV_RULES_FILE" 2>/dev/null
}

Expand Down
59 changes: 53 additions & 6 deletions virt-v2v/cold/scripts/rhel/run/network_config_util_test
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand All @@ -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 <<EOL > "$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"
Expand Down
Loading