0% found this document useful (0 votes)
50 views5 pages

Nic Add Replace v2

Uploaded by

Steven Tay
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
50 views5 pages

Nic Add Replace v2

Uploaded by

Steven Tay
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 5

#!

/bin/bash
#
# Disclaimer: Usage of this tool must be under guidance of Nutanix Support or an
authorised partner
# Summary: This is an enhancement of nic_replace with expansion to NIC_addition. It
is a v2 of the script.
# Version of the script: Version 2
# Compatible software version(s): AOS 5.15.4 + AHV 20190916.x and higher
# Brief syntax usage: ./nic_add_replace_v2
# Caveats - This script is not needed to be sourced from KB10029 from AOS 6.1 + AHV
20201105.30142 or higher because it is included in the release. Refer to AHV Admin
Guide on Nutanix Support Portal for usage.
#
# nic_replace: Update MAC address after NIC replacement,
# more background info can be found at the link below.
#
# https://portal.nutanix.com/kb/3261
#
# Copyright (c) 2019 Nutanix Inc. All rights reserved.

# Append the script's output to a file.

declare -r log_file="/var/log/nic_add_or_replace.log"
exec &> >(tee -a "$log_file")

# Prepend UTC ISO 8601 timestamps to the echo'ed messages.


log() {
echo "$(date --utc '+%F %TZ') $@"
}

log "$(basename -- $0) started."

IFCFG_DIR=/etc/sysconfig/network-scripts

# Devices whose ifcfg file is not mapped to eth interfaces.


declare -a spare_devices

# Devices whose ifcfg file is mapped to an interface.


declare -a valid_eth

# SW/USB devices Mac Address.


declare -a sw_interface

function main() {
# USB_interface is populating array sw_interface with MAC address
# of all the USB interfaces.
usb_interfaces
# Loop through network config scripts for "eth" devices
# in the incremental order.
for ifcfg in `ls -vd ${IFCFG_DIR}/ifcfg-eth* 2> /dev/null`; do
[ -f $ifcfg ] || continue

# Deduce device name by stripping everything up to final '-'.


dev=${ifcfg##*-}
log "Found ifcfg script for $dev, $ifcfg"
# MAC address stored in the ifcfg file.
sw_mac=$(awk -F= '/^HWADDR=/{print $2}' $ifcfg)
if [ -z "$sw_mac" ]; then
# If the IFCFG file doesn't have HWADDR then it is considered as unused file.
log " - Device $dev does not have a MAC address."
spare_devices=("${spare_devices[@]}" $ifcfg)
continue
fi
# Check whether a device with the corresponding name exists.
# Also, map interface to any USB interface before it is consumed for update.
if [ -e "/sys/class/net/$dev" ]; then
log " - Device $dev exists."
valid_eth=("${valid_eth[@]}" $dev)
elif [[ ${sw_interface[@]} =~ $sw_mac ]]; then
log " - Device $dev is a SW interface"
valid_eth=("${valid_eth[@]}" $dev)
else
log " - Device $dev not found."
# Push $dev onto the end of the spare_devices array.
spare_devices=("${spare_devices[@]}" $ifcfg)
fi
done

log "Unused names are: ${spare_devices[@]}"


rename_interface && final_changes
return 0
}

function usb_interfaces() {
#Collect interface mac address for all USB interfaces.
for usb_int in /sys/class/net/* ; do
[ -e $usb_int/device/uevent ] || continue
if [[ $usb_int == /sys/class/net/en* ]]; then
log " - Interfaces $usb_int needs to be re-named"
else
if awk -F= '/^DRIVER=/{print $2}' $usb_int/device/uevent \
|egrep -qx 'rndis_host|cdc_ether|cdc_eem' 2> /dev/null; then
sw_interface=("${sw_interface[@]}" ${usb_int##*net/})
log " - Interface ${usb_int##*net/} is a SW interface"
fi
fi
done
}

function rename_interface() {
# no_changes variable is used to determine if final_changes run.
# By default we don't execute final_changes.
local no_changes=1
# Look for "en" devices. These will only exist if an unrecognized NIC is present.
# List the enp devices in natural numeric order.
for dev in `ls -vd /sys/class/net/en* 2> /dev/null`; do
[ -e $dev ] || continue
if awk -F= '/^DRIVER=/{print $2}' $dev/device/uevent \
|egrep -qx 'rndis_host|cdc_ether|cdc_eem' 2> /dev/null; then
# Skip if the device is usb ethernet
# BMC >= 7.09 uses RNDIS device for Redfish
# CDC is used by OEM Devices.
log " - Device $dev is a SW interface using USB Ethernet"
continue
fi

dev=$(basename $dev)
log "Found device $dev that needs renaming."
# Query MAC address for device $dev.
mac=$(ethtool -P $dev | sed s/"Permanent[[:blank:]]address:[[:space:]]*"//)
log " - MAC for $dev is $mac"

if [ -n "$mac" ]; then
# Select a spare device to adopt.
ifcfg=${spare_devices[0]}

if [ -z "$ifcfg" ]; then
log " - WARNING: No spare device names found."
log " - This means all ifcfg scripts refer to devices that are present."
log " - Perhaps $dev was an additional NIC rather than a replacement?"
read -p "Do you wish to add new NIC Device? Yes/[No] " yn
case $yn in
[Yy]* )
add_ifcfg
ifcfg=${spare_devices[0]};;
[Nn]* )
log "Aborting"
continue ;;
* )
log "Please answer yes or no."
log "Aborting"
break;;
esac
fi

# Pop it from the spare_devices array.


spare_devices=(${spare_devices[@]:1})
log " - Selected $ifcfg"

# Read MAC address specified in ifcfg script.


prev_mac=$(awk -F= '/^HWADDR/{print $2}' $ifcfg)
log " - Previous MAC in $ifcfg was $prev_mac"

# Collect the SHA of the file before the update.


old_sha1sum=$(sha1sum $ifcfg|awk '{print $1}')

# Compare the MAC addresses.


if [ "$mac" == "$prev_mac" ]; then
log " - HWADDR was already correct"
verify_other_parameters $ifcfg $old_sha1sum
continue
fi

if [ -z "$prev_mac" ]; then
# The ifcfg script did not specify a MAC address.
log " - adding 'HWADDR=$mac' in $ifcfg"
echo "HWADDR=$mac" >> $ifcfg
else
# The ifcfg script specified an out-of-date MAC address.
log " - setting 'HWADDR=$mac' in $ifcfg"
sed -i s/"HWADDR=[0-9a-fA-F:]*"/"HWADDR=$mac"/ $ifcfg
fi

verify_other_parameters $ifcfg $old_sha1sum


# Re-run udev to rename the interface(s).
log "Renaming interface $dev ..."
udevadm test /sys/class/net/$dev
log
# Change no_changes to execute final_changes
no_changes=0
fi
done
return "$no_changes"
}

function add_ifcfg() {
# Decide the name of the ifcfg file.
# Verify there is no ifcfg-eth# missing from the highest existing,
# if it does we use it first else we increment the largest file by 1.
readarray -t sorted_valid_eth < <(for a in "${valid_eth[@]}"; do echo "$a"; \
done | sort)
new_dev_eth_index=${sorted_valid_eth[-1]//[^0-9]/}
#Lookup for unused index up to the highest existing.
for value in $(seq 0 $((${new_dev_eth_index} + 1))); do
if [ ! -f ${IFCFG_DIR}/ifcfg-eth${value} ]; then
file_creation ${IFCFG_DIR}/ifcfg-eth${value} && break
fi
done
}

function file_creation() {
#IFCFG files creations.
#$1 is the ifcfg file.
log "Creating ${1}"
touch ${1}
chmod 644 ${1}
spare_devices=("${spare_devices[@]}" ${1})
valid_eth=("${valid_eth[@]}" ${1##*-})
return 0
}

function verify_other_parameters() {
#Verify parameters other than the MAC Address
#in the ifcfg file.
#$1 is the ifcfg file.
#$2 is the sha1sum of the file.

local ifconf="${1}"

ethdev=${ifconf##*-}
ensure_parameters $ifconf "DEVICE" $ethdev
ensure_parameters $ifconf "TYPE" "Ethernet"
ensure_parameters $ifconf "NM_CONTROLLED" "no"
ensure_parameters $ifconf "NOZEROCONF" "yes"
ensure_parameters $ifconf "ONBOOT" "yes"
ensure_parameters $ifconf "BOOTPROTO" "none"
ensure_parameters $ifconf "MTU" "1500"

#Compare the SHA of the file.


if [ "$2" != "$(sha1sum $ifconf|awk '{print $1}')" ]; then
# If the file was updated then add a comment with time.
log " - adding NIC_ADD_REPLACE comment in $ifconf"
sed -i "1s|^|# This file is edited by $0 script on $(date -u).\n|" $ifconf
fi
}
function ensure_parameters() {
#Verify if the parameter exists or insert it.
#Value of the parameter is not changed if the parameter exists.
#$1 is the ifcfg file.
#$2 is the parameter within the ifcfg file.
#$3 is the status of the parameter.

if grep -q ^$2= $1 2> /dev/null; then


log " - '$2' exists in $1"
else
log " - adding $2 in $1"
echo "$2=$3" >> $1
fi
}

function final_changes() {
if [ "${#spare_devices[@]}" -gt 0 ]; then
log "WARNING: Leaving behind unused ifcfg file(s) ${spare_devices[@]}"
log " - This probably means the host has had NIC(s) removed."
fi

log "Applying the changes..."

# If any NICs are DHCP-enabled then dhclient will prevent network.service


# from restarting. Kill it now, and it will be restarted automatically by
# network.service.
killall dhclient 2>/dev/null

systemctl restart network.service

# Regenerate the initramfs in case the new NIC requires a different driver
for k in /lib/modules/*; do
k=${k##*/}
log "Regenerating initrd for ${k} ..."
dracut -f /boot/initramfs-${k}.img ${k}
done
}

main
log "Done."

You might also like