2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2025-05-29 09:13:08 +00:00

add cumulus discover script

This commit is contained in:
immarvin 2017-05-24 04:40:43 -04:00
parent 18c1a5d06d
commit 65d882b990
9 changed files with 410 additions and 59 deletions

View File

@ -51,7 +51,9 @@ $::STATUS_BOOTED = "booted";
$::STATUS_POWERING_ON = "powering-on";
$::STATUS_POWERING_OFF = "powering-off";
$::STATUS_DISCOVERING = "discovering";
$::STATUS_DISCOVERED = "discovered";
$::STATUS_CONFIGURING = "configuring";
$::STATUS_CONFIGURED = "configured";
$::STATUS_STANDING_BY = "standingby";
$::STATUS_SHELL = "shell";
$::STATUS_DEFINED = "defined";
@ -69,7 +71,9 @@ $::STATUS_BMCREADY = "bmcready";
$::STATUS_POWERING_ON => 1,
$::STATUS_POWERING_OFF => 1,
$::STATUS_DISCOVERING => 1,
$::STATUS_DISCOVERED => 1,
$::STATUS_CONFIGURING => 1,
$::STATUS_CONFIGURED => 1,
$::STATUS_STANDING_BY => 1,
$::STATUS_SHELL => 1,
$::STATUS_DEFINED => 1,

View File

@ -0,0 +1,45 @@
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
#This module includes some glocal table to look up the switch type via mac and vendor
package xCAT::data::switchinfo;
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw();
@EXPORT_OK = qw(global_mac_identity global_switch_type);
use strict;
#the hash to look up switch type with MAC
our %global_mac_identity = (
"a8:97:dc" => "BNT G8052 switch",
"6c:ae:8b" => "BNT G8264-T switch",
"fc:cf:62" => "BNT G8124 switch",
"7c:fe:90" => "Mellanox IB switch",
"cc:37:ab" => "Edgecore Networks Switch",
"8c:ea:1b" => "Edgecore Networks Switch"
);
#the hash to lookup switch type with vendor
our %global_switch_type = (
Juniper => "Juniper",
juniper => "Juniper",
Cisco => "Cisco",
cisco => "Cisco",
BNT => "BNT",
Blade => "BNT",
G8052 => "BNT",
RackSwitch => "BNT",
Mellanox => "Mellanox",
mellanox => "Mellanox",
MLNX => "Mellanox",
MELLAN => "Mellanox",
Cumulus => "onie",
cumulus => "onie",
Edgecore => "onie"
);
1;

View File

@ -4,10 +4,8 @@ package xCAT_plugin::nodediscover;
use xCAT::Table;
use IO::Socket;
use strict;
use XML::Simple;
$XML::Simple::PREFERRED_PARSER = 'XML::Parser';
use Data::Dumper;
use POSIX "WNOHANG";
use Storable qw(freeze thaw);
use IO::Select;
@ -15,7 +13,7 @@ use IO::Handle;
use xCAT::Utils;
use Sys::Syslog;
use Text::Balanced qw(extract_bracketed);
use xCAT::data::switchinfo;
use xCAT::DiscoveryUtils;
@ -175,6 +173,7 @@ sub process_request {
}
}
# save inventory info into the hwinv table
if (defined($request->{cpucount}) or defined($request->{cputype}) or defined($request->{memory}) or defined($request->{disksize})) {
my $basicdata;
@ -232,15 +231,32 @@ sub process_request {
if ($rent and $rent->{'netboot'}) {
$currboot = $rent->{'netboot'};
}
if ($request->{arch}->[0] =~ /x86/ and $currboot !~ /pxe/ and $currboot !~ /xnba/) {
$nrtab->setNodeAttribs($node, { netboot => 'xnba' });
} elsif ($request->{arch}->[0] =~ /ppc/ and $request->{platform}->[0] =~ /PowerNV/) {
$nrtab->setNodeAttribs($node, { netboot => 'petitboot' });
} elsif ($request->{arch}->[0] =~ /ppc/ and $currboot !~ /yaboot/) {
$nrtab->setNodeAttribs($node, { netboot => 'yaboot' });
} elsif($request->{arch}->[0] =~ /armv7l/ and $currboot !~ /onie/) {
#for onie switch, the netboot should be "onie"
$nrtab->setNodeAttribs($node, { netboot => 'onie' });
}
}
if(defined $request->{nodetype} and $request->{nodetype}->[0] = 'switch' and $request->{_xcat_clientmac}->[0]){
#for onie switch, lookup and set the switchtype via mac of mgt interface
my $switchestab = xCAT::Table->new('switches');
if ($switchestab) {
my $switchtype=$xCAT::data::switchinfo::global_mac_identity{substr(lc($request->{_xcat_clientmac}->[0]),0,8)};
if(defined $switchtype){
$switchestab->setNodeAttribs($node,{ switchtype => $switchtype });
}
$switchestab->close();
}
}
my $macstring = "";
if (defined($request->{mac})) {
my $mactab = xCAT::Table->new("mac", -create => 1);
@ -252,9 +268,11 @@ sub process_request {
my $forcenic = 0; #-1 is force skip, 0 is use default behavior, 1 is force to be declared even if hosttag is skipped to do so
foreach (@{ $request->{mac} }) {
@ifinfo = split /\|/;
if ($ifinfo[1] eq 'usb0') { #skip usb nic
next;
}
$bydriverindex{ $ifinfo[0] } += 1;
if (scalar @discoverynics) {
$forcenic = -1; #$forcenic defaults to explicitly skip nic
@ -295,7 +313,7 @@ sub process_request {
push @hostnames_to_update, $hosttag;
}
}
print Dumper($hosttag) . "\n";
#print Dumper($hosttag) . "\n";
if ($hosttag) {
$usednames{$hosttag} = 1;
unless ($usednames_for_net{$netn}) {

View File

@ -21,6 +21,7 @@ no strict;
use Data::Dumper;
use Socket;
use Expect;
use xCAT::data::switchinfo;
#global variables for this module
my $community;
@ -33,42 +34,6 @@ my %global_scan_type = (
snmp => "snmp_scan"
);
my %global_mac_identity = (
"a8:97:dc" => "BNT G8052 switch",
"6c:ae:8b" => "BNT G8264-T switch",
"fc:cf:62" => "BNT G8124 switch",
"7c:fe:90" => "Mellanox switch",
"e4:1d:2d" => "Mellanox switch",
"24:8a:07" => "Mellanox switch",
"00:25:8b" => "Mellanox switch",
"00:02:c9" => "Mellanox switch",
"f4:52:14" => "Mellanox switch",
"ec:0d:9a" => "Mellanox switch",
"cc:37:ab" => "Edgecore Networks Switch",
"a8:2b:b5" => "Edgecore Networks Switch",
"70:72:cf" => "Edgecore Networks Switch",
"8c:ea:1b" => "Edgecore Networks Switch"
);
my %global_switch_type = (
Juniper => "Juniper",
juniper => "Juniper",
Cisco => "Cisco",
cisco => "Cisco",
BNT => "BNT",
Blade => "BNT",
G8052 => "BNT",
RackSwitch => "BNT",
Mellanox => "Mellanox",
mellanox => "Mellanox",
MLNX => "Mellanox",
MELLAN => "Mellanox",
Cumulus => "onie",
cumulus => "onie",
Edgecore => "onie"
);
#-------------------------------------------------------------------------------
=head1 xCAT_plugin:switchdiscover
@ -748,16 +713,16 @@ sub nmap_scan {
}
my $vendor = $addr->{vendor};
if ($vendor) {
my $search_string = join '|', keys(%global_switch_type);
my $search_string = join '|', keys(%xCAT::data::switchinfo::global_switch_type);
if ($vendor =~ /($search_string)/) {
$found = 1;
}
}
if ( ($found == 0) && ($type eq "mac") ) {
my $search_string = join '|', keys(%global_mac_identity);
my $search_string = join '|', keys(%xCAT::data::switchinfo::global_mac_identity);
if ($mac =~ /($search_string)/i) {
my $key = $1;
$vendor = $global_mac_identity{lc $key};
$vendor = $xCAT::data::switchinfo::global_mac_identity{lc $key};
$found = 1;
}
@ -851,7 +816,7 @@ sub nmap_osguess {
last;
}
}
my $search_string = join '|', keys(%global_switch_type);
my $search_string = join '|', keys(%xCAT::data::switchinfo::global_switch_type);
if ($line =~ /Running/) {
if ($line =~ /($search_string)/){
$vendor = $1;
@ -1180,10 +1145,10 @@ sub get_switchtype {
my $vendor = shift;
my $key = "Not support";
my $search_string = join '|', keys(%global_switch_type);
my $search_string = join '|', keys(%xCAT::data::switchinfo::global_switch_type);
if ($vendor =~ /($search_string)/) {
$key = $1;
return $global_switch_type{$key};
return $xCAT::data::switchinfo::global_switch_type{$key};
} else {
return $key;
}

View File

@ -9,6 +9,11 @@ fi
xcat_intf="/etc/network/interfaces.d/xCAT.intf"
if [ -f $xcat_intf ] && grep -w '#This is sample interface file provided by xCAT' $xcat_intf ; then
echo "The switch data ports and default brige have been configured. Do nothing..."
exit 0
fi
echo "#This is sample interface file provided by xCAT" > $xcat_intf
echo "# bridge-vlan-aware: set to yes to indicate that the bridge is VLAN-aware. " >> $xcat_intf
echo "# bridge-access: declares the access port. " >> $xcat_intf

View File

@ -1,4 +1,7 @@
#!/bin/bash
#this script will be invoked by ZTP(zero touch provision) process in the onie switch
#this script finish the discovery and configuration after the switch is pluged in the cluster and powered on
function error() {
echo -e "\e[0;33mERROR: The Zero Touch Provisioning script failed while running the command $BASH_COMMAND at line $BASH_LINENO.\e[0m" >&2
exit 1
@ -7,28 +10,144 @@ function error() {
# Log all output from this script
exec >/var/log/autoprovision 2>&1
trap error ERR
#trap error ERR
#Add Debian Repositories
echo "deb http://http.us.debian.org/debian jessie main" >> /etc/apt/sources.list
echo "deb http://security.debian.org/ jessie/updates main" >> /etc/apt/sources.list
#since in most cases, the switch has no internet access, skip this step
#echo "deb http://http.us.debian.org/debian jessie main" >> /etc/apt/sources.list
#echo "deb http://security.debian.org/ jessie/updates main" >> /etc/apt/sources.list
#get ip address for server node
server_ip=`grep cumulus-provision-url /var/lib/dhcp/dhclient.eth0.leases | tail -1 | awk -F/ '{print $3}'`
#download /install/postscripts from MN
max_retries=5
retry=0
rc=1 # this is a fail return
downloaded=0
while [ 0 -eq 0 ]; do
if [ -e "/xcatpost" ]; then
rm -rf "/xcatpost"
fi
export LANG=C; wget -l inf -nH -N -r --waitretry=10 --random-wait -e robots=off -T 60 -nH --cut-dirs=2 --reject "index.html*" --no-parent http://$server_ip/install/postscripts/ -P /xcatpost 2> /tmp/wget.log
rc=$?
if [ $rc -eq 0 ]; then
# return from wget was 0 but some OS do not return errors, so we
# have additional checks for
# failed: Connection httpd not running
# 404: Not Found - if directory does not exist
grep -i -E "... failed: Connection refused.$" /tmp/wget.log
rc1=$?
grep -i -E "ERROR 404: Not Found.$" /tmp/wget.log
rc2=$?
# check to see no errors at all, grep returns 1
if [ $rc1 -eq 1 ] && [ $rc2 -eq 1 ]; then
logger -s -t "xcat.cumulusztp" -p local4.info "download_postscripts return successfully "
downloaded=1
break
fi
fi
retry=$(($retry+1))
logger -s -t "xcat.cumulusztp" -p local4.info "download_postscripts retry $retry"
if [ $retry -eq $max_retries ]; then
break
fi
SLI=$(awk 'BEGIN{srand(); printf("%d\n",rand()*20)}')
sleep $SLI
done
if [ "$downloaded" = "0" ];then
logger -s -t "xcat.cumulusztp" -p local4.err "download_postscripts failed"
ztp -R
exit 1
fi
chmod -R +x `find /xcatpost/ -maxdepth 1 -print | grep -E -v '^(/xcatpost/|/xcatpost/_xcat|/xcatpost/_ssh|/xcatpost/ca|/xcatpost/hostkeys)$'`
cd /xcatpost
rc=0
./documulusdiscovery
rc=$?
if [ "$rc" != "0" ];then
ztp -R
exit 1
fi
logger -s -t "xcat.cumulusztp" -p local4.info "switch discovered!"
#restart mgt interface to apply the specified IP address
ifdown eth0;ifup eth0
retry=0
while true; do
#check whether the network access between MN/CN and the node is ready
ping $server_ip -c 1 >/dev/null && break
retry=$[ $retry + 1 ]
if [ $retry -eq 90 ];then
#timeout, complain and exit
logger -s -t "xcat.cumulusztp" -p local4.err " the network between the node and $server_ip is not ready, please check[retry=$retry]..." "/var/log/xcat/xcat.log"
ztp -R
exit 1
fi
#sleep sometime before the next scan
sleep 2
done
#push root ssh keys, config passwordless
echo "CumulusLinux!" | sudo -S mkdir -p /root/.ssh
echo "CumulusLinux!" | sudo -S /usr/bin/wget -O /root/.ssh/authorized_keys http://$server_ip/install/postscripts/_ssh/authorized_keys
mkdir -p /root/.ssh
mv _ssh/authorized_keys /root/.ssh/authorized_keys
#enable and config snmpd
echo "CumulusLinux!" | sudo -S /usr/bin/wget -O /home/cumulus/enablesnmp http://$server_ip/install/postscripts/enablesnmp
sudo chmod +x /home/cumulus/enablesnmp
sudo /home/cumulus/enablesnmp
./enablesnmp
rc=$?
if [ "$rc" != "0" ];then
logger -s -t "xcat.cumulusztp" -p local4.err "enablesnmp: failed to enable SNMP"
echo "enablesnmp: failed to enable SNMP"
else
logger -s -t "xcat.cumulusztp" -p local4.info "SNMP enabled!"
fi
#config base interface
echo "CumulusLinux!" | sudo -S /usr/bin/wget -O /home/cumulus/configinterface http://$server_ip/install/postscripts/configinterface
sudo chmod +x /home/cumulus/configinterface
sudo /home/cumulus/configinterface
./configinterface
rc=$?
if [ "$rc" != "0" ];then
echo "configinterface: failed to config switch data ports"
else
logger -s -t "xcat.cumulusztp" -p local4.info "data ports enabled!"
fi
#obtain myposctscript from MN
./getmypostscript.cumulus $server_ip:3001
rc=$?
if [ "$rc" != "0" ]; then
logger -s -t "xcat.cumulusztp" -p local4.info "failed to get mypostscript"
echo "failed to get mypostscript"
ztp -R
exit 1
fi
#config static ip address for mgt interface
echo './confignics -s' >> ./mypostscript
chmod +x ./mypostscript
./mypostscript
rc=$?
if [ "$rc" != "0" ]; then
logger -s -t "xcat.cumulusztp" -p local4.info "failed to set static ip address for mgt interface"
echo "failed to set static ip address for mgt interface"
ztp -R
exit 1
fi
#report status
echo "installstatus configured" | socat STDIN TCP:$server_ip:3002,sourceport=301,reuseaddr,retry=5
# CUMULUS-AUTOPROVISIONING
exit 0

View File

@ -0,0 +1,132 @@
#!/bin/bash
#this script grabs the switch information, then composes a "findme" request and sends it to MN
#so that the switch can be discovered
# TODO: Figure out the master based on the DHCP packet
XCATMASTER=$(cat /var/lib/dhcp/dhclient.eth0.leases |grep cumulus-provision-url|tail -1|awk -F/ '{print $3}')
XCATPORT=3001
log_label="xcat.documulusdiscovery"
#helper script for socat, write the received message to /tmp/helper.socat.sh
cat > /tmp/helper.socat.sh << 'EOF'
read strin
echo $strin > /tmp/result.socat.out
EOF
[ -f "/tmp/helper.socat.sh" ] && chmod 777 /tmp/helper.socat.sh
#listen to the 3001 port for any response from xcatd on MN
#the message in the response will be written to /tmp/result.socat.out
socat TCP4-LISTEN:3001,reuseaddr EXEC:"/tmp/helper.socat.sh" &
#generate key pairs for the SSL connection between switch and xcatd on MN
mkdir -p /etc/xcat
mkdir -p /etc/pki/tls
if [ ! -f /etc/xcat/privkey.pem ]; then
echo "[ req ]
distinguished_name = nodedn
[ nodedn ]" > /etc/pki/tls/openssl.cnf
logger -s -t $log_label -p local4.info "Generating private key..."
openssl genrsa -out /etc/xcat/privkey.pem 1024 >& /dev/null
logger -s -t $log_label -p local4.info "Done"
fi
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 switch discovery process..."
#grab the switch information
dmidweinfo=$(/usr/sbin/dmidecode 2>/dev/null)
PRODUCTNAME=$(echo "$dmidweinfo"|grep "Product Name"|cut -d: -f2|sed -e 's/^\s*//' -e 's/\s*$//')
MTM=$PRODUCTNAME
ARCH=$(uname -m)
SERIAL=$(echo "$dmidweinfo"|grep "Serial Number"|cut -d: -f2|sed -e 's/^\s*//' -e 's/\s*$//')
#compose the findme request
echo '<xcatrequest>' > /tmp/discopacket
echo "<command>findme</command>" >> /tmp/discopacket
echo "<sequential>1</sequential>" >> /tmp/discopacket
echo "<nodetype>switch</nodetype>" >> /tmp/discopacket
echo "<arch>$ARCH</arch>" >> /tmp/discopacket
#echo "<switchtype>$MTM</switchtype>" >> /tmp/discopacket
echo "<vendor>$MTM</vendor>" >> /tmp/discopacket
echo "<serial>$SERIAL</serial>" >> /tmp/discopacket
MAC_OF_FIRST_UP_NIC=$(ip addr show eth0|grep "link/ether"|awk -F' ' '{print $2}')
MAC=$MAC_OF_FIRST_UP_NIC
ADDRESS=$(ip address show dev eth0|grep "inet "|grep global|awk '{print $2}')
DRIVER=$(grep DRIVER /sys/class/net/eth0/device/uevent|awk -F= '{print $2}')
echo "<mac>$DRIVER|eth0|$MAC|$ADDRESS</mac>" >> /tmp/discopacket
UUID=`echo $MTM-$SERIAL-$MAC_OF_FIRST_UP_NIC| tr /A-Z/ /a-z/`
echo "<uuid>$UUID</uuid>" >> /tmp/discopacket
echo "<xcatpubkey>$PUBKEY</xcatpubkey>" >> /tmp/discopacket
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" ] || [ -z "$XCATPORT" ]; then
logger -s -t $log_label -p local4.err "Failed to get xcatd connection information, exit..."
rm -rf /tmp/result.socat.out
rm -rf /tmp/helper.socat.sh
exit 1
fi
#send the find me request ot xcatd on MN
MAX_RETRY=10
RETRY=0
DISCOVERED=0
while [ $RETRY -lt $MAX_RETRY ]; do
logger -s -t $log_label -p local4.info "Sending the discovery packet to xCAT ($XCATMASTER:$XCATPORT) [ RETRY= $RETRY ] ..."
(cat /tmp/discopacket.gz | socat STDIN UDP:$XCATMASTER:$XCATPORT,sourceport=301 ) &
WAITRETRY=0
while [ $WAITRETRY -lt 100 ]; do
if [ -f "/tmp/result.socat.out" ] && grep "restart" /tmp/result.socat.out; then
DISCOVERED=1
break;
fi
sleep 1
((WAITRETRY=WAITRETRY+1))
done
if [ "$DISCOVERED" = "1" ]; then
break
fi
sleep 2
((RETRY=RETRY+1))
done
rm -rf /tmp/result.socat.out
rm -rf /tmp/helper.socat.sh
if [ "$DISCOVERED" = "0" ] ; then
logger -s -t $log_label -p local4.info "Failed to discover me, exit..."
exit 1
elif [ "$DISCOVERED" = "1" ]; then
echo "installstatus discovered" | socat STDIN TCP:$XCATMASTER:3002,sourceport=301,reuseaddr,retry=5
fi
exit 0

View File

@ -6,7 +6,12 @@ if ! cat /etc/os-release |grep -i '^NAME=[ "]*Cumulus Linux[ "]*$' >/dev/null 2
echo "This script is only supported on Cumulus OS in ONIE switch"
exit 2
fi
snmp_conf="/etc/snmp/snmpd.conf"
if [ -f "$snmp_conf" ] && grep -w '#xCAT customized snmpd configuration' $snmp_conf;then
echo "The snmp has already been configured. Do nothing..."
exit 0
fi
[ -f "$snmp_conf" ] || exit -1

View File

@ -0,0 +1,58 @@
#!/bin/bash
#this script send getpostscript request to xcatd on MN and generate /xcatpost/mypostscript
#which includes the glocal environment variables to run postscripts
if [ -z "$XCATDEST" ]; then
XCATDEST=$1
fi
#compose getpostscript request
echo "<xcatrequest>
<command>getpostscript</command>
</xcatrequest>" > /tmp/req.xml
if [ -f /tmp/resp.xml ]; then
#remove any existing response file
rm /tmp/resp.xml;
fi
#communicate with xcatd on MN with getpostscript request
#the response will be saved in /tmp/resp.xml
while [ ! -f /tmp/resp.xml ] || grep error /tmp/resp.xml; do
if [ -f /tmp/resp.xml ]; then
timer=60
while [ $timer -gt 0 ]; do
echo -en "Retrying in $timer seconds \r" >&2
sleep 1
timer=$(($timer-1));
done
fi
#echo " " >&2
if [ -f /etc/xcat/cert.pem -a -f /etc/xcat/certkey.pem ]; then #use client cert if available
cat /tmp/req.xml | /usr/bin/openssl s_client -key /etc/xcat/certkey.pem -cert /etc/xcat/cert.pem -connect $XCATDEST -quiet 2> /dev/null > /tmp/resp.xml
else
cat /tmp/req.xml | /usr/bin/openssl s_client -connect $XCATDEST -quiet 2>/dev/null > /tmp/resp.xml
fi
done
if [ -f /tmp/resp.xml ] && grep '<data>' /tmp/resp.xml >/dev/null 2>&1 ;then
echo "Success to obtain mypostscript!"
else
echo "Failed to obtain mypostscript!"
exit 1
fi
#parse the script from the xml-formated resposne
cat /tmp/resp.xml | egrep '<data>' | sed -e 's/<[^>]*>//g'|egrep -v '^ *$'|sed -e 's/^ *//' | sed -e 's/&lt;/</g' -e 's/&gt;/>/g' -e 's/&amp;/\&/g' -e 's/&quot;/"/g' -e "s/&apos;/'/g" > /xcatpost/mypostscript
#the script specified in the "postscripts" and "postbootscripts" are currently not supported
#will be supported if there is requrement on this
sed -i -e "/# postscripts-start-here/,$ d" /xcatpost/mypostscript
rm -f /tmp/req.xml
rm -f /tmp/resp.xml
exit 0