nic_add_replace_v2
nic_add_replace_v2
/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.
declare -r log_file="/var/log/nic_add_or_replace.log"
exec &> >(tee -a "$log_file")
IFCFG_DIR=/etc/sysconfig/network-scripts
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
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
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
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"
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
# 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."