mirror of
https://github.com/xcat2/xcat-core.git
synced 2025-05-29 09:13:08 +00:00
In some cases, FRU pages are not available, or don't contain relevant readable or relevant information. In those cases, we could still fall back to DMI to get the MTM information, and log a warning that MTMS-based discovery may not work as expected.
289 lines
13 KiB
Bash
Executable File
289 lines
13 KiB
Bash
Executable File
#!/bin/bash
|
|
log_label="xcat.genesis.dodiscovery"
|
|
|
|
minixcatd.awk &
|
|
PUBKEY=`openssl rsa -in /etc/xcat/privkey.pem -pubout 2> /dev/null|grep -v "PUBLIC KEY"`
|
|
PUBKEY=`echo $PUBKEY|sed -e 's/ //g'`
|
|
export PUBKEY
|
|
|
|
logger -s -t $log_label -p local4.info "Beginning node discovery process..."
|
|
for nic in `ip link|grep mtu|grep -v LOOPBACK|grep -v usb|grep -v ,LOWER_UP|awk -F: '{print $2}'`; do
|
|
ip link set $nic up
|
|
done
|
|
waitforlink=100
|
|
while [ ! -z "$NICSTOBRINGUP" -a $waitforlink -gt 0 ]; do
|
|
NICSTOBRINGUP=`ip link|grep mtu|grep -v LOOPBACK|grep -v usb|grep -v ,LOWER_UP|awk -F: '{print $2}'`
|
|
waitforlink=$((waitforlink - 1))
|
|
sleep 0.1
|
|
if [ $waitforlink = 1 ]; then
|
|
logger -s -t $log_label -p local4.warning "No link detected on $NICSTOBRINGUP after 10 seconds"
|
|
fi
|
|
done
|
|
NICSGETTINGADDR=`ip link|grep mtu|grep -v LOOPBACK|grep -v usb|grep ,LOWER_UP|awk -F: '{print $2}'`
|
|
timewaiting=0
|
|
logger -s -t $log_label -p local4.info "Waiting for nics to get addresses"
|
|
while [ ! -z "$NICSGETTINGADDR" -a $timewaiting != 700 ]; do
|
|
NEWNICSGETTINGADDR=""
|
|
for nic in $NICSGETTINGADDR; do
|
|
if ! ip addr show dev $nic |grep -v inet6|grep inet >/dev/null; then
|
|
NEWNICSGETTINGADDR="$NEWNICSGETTINGADDR $nic"
|
|
else
|
|
echo -n "$nic|"
|
|
ip addr show dev $nic |grep -v inet6|grep inet|sed -e s/\\/.*//|awk '{print $2}'
|
|
fi
|
|
done
|
|
sleep 0.1
|
|
timewaiting=$((timewaiting+1))
|
|
if [ $timewaiting = 699 ]; then
|
|
logger -s -t $log_label -p local4.warning "No DHCP answer for $nic, ignoring interface..."
|
|
fi
|
|
NICSGETTINGADDR=$NEWNICSGETTINGADDR
|
|
done
|
|
if [ $timewaiting != 700 -a $timewaiting -gt 450 ]; then
|
|
logger -s -t $log_label -p local4.warning "Obtained an IP address $NICSGETTINGADDR but it took $timewaiting cycles, you may want to check the spanning tree configuration in the switch."
|
|
fi
|
|
logger -s -t $log_label -p local4.info "Network configuration complete, commencing transmit of discovery packets"
|
|
XCATPORT=3001
|
|
export XCATPORT
|
|
for parm in `cat /proc/cmdline`; do
|
|
key=`echo $parm|awk -F= '{print $1}'`
|
|
if [ "$key" = "xcatd" ]; then
|
|
XCATMASTER=`echo $parm|awk -F= '{print $2}'|awk -F: '{print $1}'`
|
|
XCATPORT=`echo $parm|awk -F= '{print $2}'|awk -F: '{print $2}'`
|
|
fi
|
|
done
|
|
|
|
|
|
#time to make our packet...
|
|
while [ ! -r /restart ]; do
|
|
MTM=unknown
|
|
SERIAL=unknown
|
|
ARCH=unknown
|
|
ARCH=`uname -m` #32-bit only is old news
|
|
PLATFORM=unknown
|
|
if [ -r /sys/devices/virtual/dmi/id/product_name ]; then #x86
|
|
PRODNAME=`cat /sys/devices/virtual/dmi/id/product_name`
|
|
IAMAVM=0
|
|
if [ "$PRODNAME" = "KVM" ]; then
|
|
IAMAVM=1
|
|
MTM=KVM
|
|
elif [ "$PRODNAME" = "VMware Virtual Platform" ]; then
|
|
IAMAVM=1
|
|
MTM=VMware
|
|
else
|
|
MTM=`cat /sys/devices/virtual/dmi/id/product_name|awk -F'[' '{print $2}'|awk -F']' '{print $1}'`
|
|
if [ -z "$MTM" ]; then
|
|
FRU=`ipmitool fru print 0`
|
|
if [ $? -eq 0 ]; then
|
|
MTM=`echo "$FRU" | awk -F': ' '/Product Manufacturer/ {m=$2} /Product Name/ {n=$2} END {print m":"n}'`
|
|
else
|
|
logger -s -t $log_label -p local4.warning "Couldn't find MTM information in FRU, falling back to DMI (MTMS-based discovery may fail)"
|
|
m=`cat /sys/devices/virtual/dmi/id/sys_vendor`
|
|
n=`cat /sys/devices/virtual/dmi/id/product_name`
|
|
MTM="$m:$n"
|
|
fi
|
|
fi
|
|
SERIAL=`cat /sys/devices/virtual/dmi/id/product_serial`
|
|
fi
|
|
CPUCOUNT=`cat /proc/cpuinfo |grep "model name"|wc -l`
|
|
grep "model name" /proc/cpuinfo | while read line; do #to avoid pulling in tail, we do a goofy thing
|
|
echo $line > /tmp/cpumod
|
|
done
|
|
CPUTYPE=`cat /tmp/cpumod|awk -F':' '{print $2}'|sed -e 's/^ //'`
|
|
UUID=`sed -e 's/\(..\)\(..\)\(..\)\(..\)-\(..\)\(..\)-\(..\)\(..\)/\4\3\2\1-\6\5-\8\7/' /sys/devices/virtual/dmi/id/product_uuid`
|
|
|
|
elif [ -r /proc/device-tree/model ]; then #POWER
|
|
#MTM=`cat /proc/device-tree/model |awk -F, '{print $2}'`
|
|
MTM=`cat /proc/device-tree/model -vT | sed -e 's/^.*,//' | sed -e 's/^[\t ]*//'| sed -e 's/[\t ]*\^@//'`
|
|
CPUCOUNT=`cat /proc/cpuinfo |grep -e "^cpu\s*:"|wc -l`
|
|
PLATFORM=`cat /proc/cpuinfo | grep -e "^platform\s*:" | awk '{print \$3}'`
|
|
grep -e "^cpu\s*:" /proc/cpuinfo | while read line; do #to avoid pulling in tail, we do a goofy thing
|
|
echo $line > /tmp/cpumod
|
|
done
|
|
CPUTYPE=`cat /tmp/cpumod|awk -F':' '{print $2}'|sed -e 's/^ //'`
|
|
SERIAL=`cat /proc/device-tree/system-id -vT | sed -e 's/^.*,//' | sed -e 's/^[\t ]*//'| sed -e 's/[\t ]*\^@//'`
|
|
# For POWER servers, the /proc/sys/kernel/random/uuid is changing for each query, so use mtms + mac of first up nic as the UUID
|
|
#UUID=`sed -e 's/\(..\)\(..\)\(..\)\(..\)-\(..\)\(..\)-\(..\)\(..\)/\4\3\2\1-\6\5-\8\7/' /proc/sys/kernel/random/uuid`
|
|
UUID=unknown
|
|
|
|
fi
|
|
#CPUCOUNT=`cat /proc/cpuinfo |grep "model name"|wc -l`
|
|
|
|
# The MEMORY will look like this: 32868920
|
|
MEMORY=`cat /proc/meminfo |grep MemTotal|awk '{printf "%.0fMB\n", $2/1024}'`
|
|
# The MEMORY will look like this: 32GiB
|
|
#MEMORY=`lshw -C memory -short |grep "System Memory"|awk -F' ' '{print $3}'`
|
|
|
|
# The DISKSIZE will look like this: /dev/sda:250GB,/dev/sdb:250GB
|
|
#DISKSIZE=`lshw -C disk -short |grep disk |awk -F' ' '{print $2":"$4}'|sed 'N;s/\n/,/'`
|
|
# The DISKSIZE will look like this: sdb:250GB,sda:250GB
|
|
DISKSIZE=`cat /proc/partitions |grep -e "sd.\>" |awk -F' ' '{printf "%s:%.0fGB\n", $4, $3*0.000001024}' |sed 'N;s/\n/,/'`
|
|
|
|
#UUID=`sed -e 's/\(..\)\(..\)\(..\)\(..\)-\(..\)\(..\)-\(..\)\(..\)/\4\3\2\1-\6\5-\8\7/' /sys/devices/virtual/dmi/id/product_uuid`
|
|
#grep "model name" /proc/cpuinfo | while read line; do #to avoid pulling in tail, we do a goofy thing
|
|
# echo $line > /tmp/cpumod
|
|
#done
|
|
#CPUTYPE=`cat /tmp/cpumod|awk -F':' '{print $2}'|sed -e 's/^ //'`
|
|
|
|
logger -s -t $log_label -p local4.info "Beginning echo infomation to discovery packet file..."
|
|
echo '<xcatrequest>' > /tmp/discopacket
|
|
echo "<command>findme</command>" >> /tmp/discopacket
|
|
echo "<sequential>1</sequential>" >> /tmp/discopacket
|
|
echo "<arch>$ARCH</arch>" >> /tmp/discopacket
|
|
if [ "$IAMAVM" = 1 ]; then
|
|
echo "<nodetype>virtual</nodetype>" >> /tmp/discopacket
|
|
fi
|
|
echo "<cpucount>$CPUCOUNT</cpucount>" >> /tmp/discopacket
|
|
echo "<cputype>$CPUTYPE</cputype>" >> /tmp/discopacket
|
|
echo "<memory>$MEMORY</memory>" >> /tmp/discopacket
|
|
echo "<disksize>$DISKSIZE</disksize>" >> /tmp/discopacket
|
|
if [ "$UUID" != "unknown" ]; then
|
|
echo "<uuid>$UUID</uuid>" >> /tmp/discopacket
|
|
fi
|
|
|
|
if [ "$MTM" != "unknown" ]; then
|
|
echo "<mtm>$MTM</mtm>" >> /tmp/discopacket
|
|
fi
|
|
if [ "$SERIAL" != "unknown" ]; then
|
|
echo "<serial>$SERIAL</serial>" >> /tmp/discopacket
|
|
fi
|
|
if [ "$PLATFORM" != "unknown" ]; then
|
|
echo "<platform>$PLATFORM</platform>" >> /tmp/discopacket
|
|
fi
|
|
|
|
IsStatic=`ipmitool lan print 1 | grep 'IP Address Source' | grep 'Static'`
|
|
if [ "$IsStatic" ]; then
|
|
BMCIPADDR=`ipmitool lan print 1 | grep 'IP Address' | grep -v 'IP Address Source' | cut -d ":" -f2 | sed 's/ //'`
|
|
if [ "$BMCIPADDR" ]; then
|
|
echo "<bmc>$BMCIPADDR</bmc>" >> /tmp/discopacket
|
|
fi
|
|
fi
|
|
|
|
# Check whether the hardware support in-band BMC configuration with the IPMI device
|
|
if [ -r /dev/ipmi0 -o -r /dev/ipmi/0 -o -r /dev/ipmidev/0 ]; then
|
|
echo "<bmcinband>1</bmcinband>" >> /tmp/discopacket
|
|
fi
|
|
|
|
#so we have some cases where DMI table explictly records every function number, and some where only first function is enumerated
|
|
#so for each onboard device, we record it. If it is also the first function, we'll seek out other function numbers and append
|
|
#if that other function number does not show up in its own dmi type 41 record
|
|
if [ -f "/usr/sbin/dmidecode" ]; then
|
|
for onboard in `dmidecode -t 41|egrep '(Type:|Bus Address)'|grep -A1 Ethernet|grep -v Ethernet|sed -e 's/.*Address: //'`; do
|
|
obdevs=("${obdevs[@]}" $onboard)
|
|
if [ ${onboard#*.}=0 ]; then
|
|
truncslot=${onboard%.*}
|
|
for obslot in `grep $truncslot /sys/class/net/*/device/uevent|sed -e s/.*=//`; do
|
|
if ! dmidecode -t 41|grep $obslot > /dev/null; then
|
|
obdevs=("${obdevs[@]}" $obslot)
|
|
fi
|
|
done
|
|
fi
|
|
done
|
|
fi
|
|
MAC_OF_FIRST_UP_NIC=unknown
|
|
#TODO: downed nics, also examine /sys/bus/pci/*/ for more network class devices that might not have driver suppert
|
|
for dev in `ip link|grep -B1 ether|grep UP|awk '{print $2}'|sed -e s/://|grep -v usb0`; do
|
|
FIRMDESC=""
|
|
ONBOARDINDEX=""
|
|
DRIVER=`grep DRIVER /sys/class/net/$dev/device/uevent|awk -F= '{print $2}'`
|
|
PCI_SLOT=`grep PCI_SLOT_NAME /sys/class/net/$dev/device/uevent|awk -F= '{print $2}'`
|
|
ADDRESS=`ip address show dev $dev|grep "inet "|grep global|awk '{print $2}'`
|
|
MAC=`ip link show dev $dev|grep ether|awk '{print $2}'| tr /a-f/ /A-F/`
|
|
if [ "$MAC_OF_FIRST_UP_NIC" == "unknown" ]; then
|
|
MAC_OF_FIRST_UP_NIC=`echo $MAC | sed -e s/://g`
|
|
fi
|
|
if [[ ! -z "$PCI_SLOT" && -f "/usr/sbin/dmidecode" ]]; then
|
|
SLOTNAME=`dmidecode -t 9|egrep '(Designation|Address)'|grep -B1 $PCI_SLOT|grep Designation|sed -e 's/.*Designation:[ ]*//'`
|
|
if [ -z "$SLOTNAME" ]; then #check for on board device
|
|
index=1
|
|
for s in ${obdevs[@]}; do
|
|
if [ "$s" = "$PCI_SLOT" ]; then
|
|
ONBOARDINDEX=$index
|
|
break
|
|
fi
|
|
index=$((index+1))
|
|
done
|
|
if [ ! -z "$ONBOARDINDEX" ]; then
|
|
FIRMDESC=`dmidecode -t 41|egrep '(Designation|Address)' |grep -B 1 $PCI_SLOT|grep Designation|sed -e 's/.*: //'`
|
|
if [ -z "$FIRMDESC" ]; then
|
|
SHORTPCISLOT=${PCI_SLOT%.*}
|
|
FIRMDESC=`dmidecode -t 41|egrep '(Designation|Address)' |grep -B 1 $SHORTPCISLOT|grep Designation|sed -e 's/.*: //'`
|
|
fi
|
|
SLOTNAME="Onboard Ethernet $ONBOARDINDEX"
|
|
fi
|
|
fi
|
|
fi
|
|
echo "<mac>$DRIVER|$dev|$MAC|$ADDRESS</mac>" >> /tmp/discopacket
|
|
echo "<nic>" >> /tmp/discopacket
|
|
echo " <devname>$dev</devname>" >> /tmp/discopacket
|
|
echo " <driver>$DRIVER</driver>" >> /tmp/discopacket
|
|
if [ ! -z "$ADDRESS" ]; then
|
|
echo " <ip4address>$ADDRESS</ip4address>" >> /tmp/discopacket
|
|
fi
|
|
echo " <hwaddr>$MAC</hwaddr>" >> /tmp/discopacket
|
|
if [ ! -z "$PCI_SLOT" ]; then
|
|
echo " <pcidev>$PCI_SLOT</pcidev>" >> /tmp/discopacket
|
|
fi
|
|
if [ ! -z "$SLOTNAME" ]; then
|
|
echo " <location>$SLOTNAME</location>" >> /tmp/discopacket
|
|
fi
|
|
if [ ! -z "$ONBOARDINDEX" ]; then
|
|
echo " <onboardeth>$ONBOARDINDEX</onboardeth>" >> /tmp/discopacket
|
|
fi
|
|
if [ ! -z "$FIRMDESC" ]; then
|
|
echo " <firmdesc>$FIRMDESC</firmdesc>" >> /tmp/discopacket
|
|
fi
|
|
myswitch=`lldptool -n -i $dev -t -V sysName|grep -v 'System Name TLV'|sed -e 's/^ *//'`
|
|
if [ ! -z "$myswitch" -a "$myswitch" != "Agent instance for device not found" ]; then
|
|
echo " <switchname>$myswitch</switchname>" >> /tmp/discopacket
|
|
fi
|
|
for switchaddr in `lldptool -i $dev -n -t -V mngAddr|grep IP|sed -e 's/.*:.//'`; do
|
|
if [ "$switchaddr" = "Agent instance for device not found" ]; then break; fi
|
|
echo " <switchaddr>$switchaddr</switchaddr>" >> /tmp/discopacket
|
|
done
|
|
myswitchdesc=`lldptool -n -i $dev -t -V sysDesc|grep -v 'System Description TLV'|sed -e 's/^ *//'`
|
|
if [ ! -z "$myswitchdesc" -a "$myswitchdesc" != "Agent instance for device not found" ]; then
|
|
echo " <switchdesc>$myswitchdesc</switchdesc>" >> /tmp/discopacket
|
|
fi
|
|
myport=`lldptool -n -i $dev -t -V portDesc|grep -v 'Port Description TLV'|sed -e 's/^ *//'`
|
|
if [ ! -z "$myport" -a "$myswitchdesc" != "Agent instance for device not found" ]; then
|
|
echo " <switchport>$myport</switchport>" >> /tmp/discopacket
|
|
fi
|
|
|
|
echo "</nic>" >> /tmp/discopacket
|
|
done
|
|
if [ "$UUID" == "unknown" ]; then
|
|
UUID=`echo $MTM-$SERIAL-$MAC_OF_FIRST_UP_NIC | tr /A-Z/ /a-z/`
|
|
echo "<uuid>$UUID</uuid>" >> /tmp/discopacket
|
|
fi
|
|
echo "<xcatpubkey>$PUBKEY</xcatpubkey>" >> /tmp/discopacket #this is not secure to use by itself, switch sourced pubkey for security
|
|
echo "<sha512sig>" >> /tmp/discopacket
|
|
echo "</sha512sig>" >> /tmp/discopacket
|
|
echo "</xcatrequest>" >> /tmp/discopacket
|
|
openssl dgst -sha512 -out /tmp/discopacket.sha512 -sign /etc/xcat/privkey.pem /tmp/discopacket
|
|
openssl enc -e -a -in /tmp/discopacket.sha512 > /tmp/discopacket.b64sig
|
|
cat /tmp/discopacket |while read line; do
|
|
if [ "$line" = "</sha512sig>" ]; then
|
|
cat /tmp/discopacket.b64sig >> /tmp/discopacket.new
|
|
fi
|
|
echo $line >> /tmp/discopacket.new
|
|
done
|
|
mv /tmp/discopacket.new /tmp/discopacket
|
|
logger -s -t $log_label -p local4.info "Discovery packet file is ready."
|
|
rm -f /tmp/discopacket.gz
|
|
gzip -9 /tmp/discopacket
|
|
if [ ! -z "$XCATMASTER" ]; then
|
|
logger -s -t $log_label -p local4.info "Sending the discovery packet to xCAT ($XCATMASTER:$XCATPORT)..."
|
|
(cat /tmp/discopacket.gz | udpcat.awk $XCATMASTER $XCATPORT ) &
|
|
fi
|
|
for dhcps in `grep dhcp-server /var/lib/dhclient/dhclient.leases|awk '{print $4}'|sed -s 's/;//'`; do
|
|
logger -s -t $log_label -p local4.info "Sending the discovery packet to xCAT ($dhcps:$XCATPORT)..."
|
|
(cat /tmp/discopacket.gz | udpcat.awk $dhcps $XCATPORT ) &
|
|
done
|
|
#cat /tmp/discopacket
|
|
logger -s -t $log_label -p local4.info "Sleeping 5 seconds..."
|
|
sleep 5
|
|
done
|
|
logger -s -t $log_label -p local4.info "Restart network interfaces..."
|
|
/bin/restart
|