# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html package xCAT_plugin::lsslp; use lib "/opt/xcat/lib/perl"; use strict; use Getopt::Long; use Socket; use xCAT::Usage; use POSIX "WNOHANG"; use Storable qw(freeze thaw); use Time::HiRes qw(gettimeofday); use xCAT::SvrUtils qw/sendmsg/; use IO::Select; use XML::Simple; $XML::Simple::PREFERRED_PARSER = 'XML::Parser'; use xCAT::PPCdb; use xCAT::NodeRange; use xCAT::Utils; use xCAT::MacMap; use xCAT::IMMUtils; use xCAT_plugin::blade; use xCAT::SLP; require xCAT::data::ibmhwtypes; my $mpahash; my $defaultbladeuser; my $defaultbladepass; my $currentbladepass; my $currentbladeuser; my %nodebymp; my $macmap; my %chassisbyuuid; my %flexchassisuuid; my %flexchassismap; my %passwordmap; my %doneaddrs; my %btresult; my $option_s; ####################################### # Constants ####################################### use constant { HARDWARE_SERVICE => "service:management-hardware.IBM", SOFTWARE_SERVICE => "service:management-software.IBM", WILDCARD_SERVICE => "service:management-*", SERVICE_FSP => "cec-service-processor", SERVICE_BPA => "bulk-power-controller", SERVICE_CEC => "cec-service-processor", SERVICE_FRAME => "bulk-power-controller", SERVICE_HMC => "hardware-management-console", SERVICE_IVM => "integrated-virtualization-manager", SERVICE_MM => "management-module", SERVICE_CMM => "chassis-management-module", SERVICE_IMM2 => "integrated-management-module2", SERVICE_RSA => "remote-supervisor-adapter", SERVICE_RSA2 => "remote-supervisor-adapter-2", #SLP_CONF => "/usr/local/etc/slp.conf", #SLPTOOL => "/usr/local/bin/slptool", TYPE_MM => "mm", TYPE_CMM => "cmm", TYPE_IMM2 => "imm2", TYPE_RSA => "rsa", TYPE_BPA => "bpa", TYPE_HMC => "hmc", TYPE_IVM => "ivm", TYPE_FSP => "fsp", TYPE_CEC => "cec", TYPE_FRAME => "frame", IP_ADDRESSES => 4, TEXT => 0, FORMAT => 1, SUCCESS => 0, RC_ERROR => 1, }; ####################################### # Globals ####################################### my %service_slp = ( @{ [SERVICE_FSP] } => TYPE_FSP, @{ [SERVICE_BPA] } => TYPE_BPA, @{ [SERVICE_CEC] } => TYPE_CEC, @{ [SERVICE_FRAME] } => TYPE_FRAME, @{ [SERVICE_HMC] } => TYPE_HMC, @{ [SERVICE_IVM] } => TYPE_IVM, @{ [SERVICE_MM] } => TYPE_MM, @{ [SERVICE_CMM] } => TYPE_CMM, @{ [SERVICE_IMM2] } => TYPE_IMM2, @{ [SERVICE_RSA] } => TYPE_RSA, @{ [SERVICE_RSA2] } => TYPE_RSA ); ####################################### # SLP display header ####################################### my @header = ( [ "device", "%-8s" ], [ "type-model", "%-12s" ], [ "serial-number", "%-15s" ], [ "side", "%-6s" ], [ "ip-addresses", "placeholder" ], [ "hostname", "%s" ] ); my %headertoattr = ( "device" => "type", "type-model" => "mtm", "serial-number" => "serial", "side" => "side", "ip-addresses" => "ip", "hostname" => "hostname", ); ####################################### # Invalid IP address list ####################################### my @invalidiplist = ( "192.168.2.144", "192.168.2.145", "192.168.2.146", "192.168.2.147", "192.168.2.148", "192.168.2.149", "192.168.3.144", "192.168.3.145", "192.168.3.146", "192.168.3.147", "192.168.3.148", "192.168.3.149", "169.254.", "127.0.0.0", "127", 0, ); ####################################### # Power methods ####################################### my %globalopt; #these globals are only used in mn my %ip_addr = (); #my $macmap; my @filternodes; my $TRACE = 0; my $DEBUG_MATCH = 0; my %globalhwtype = ( fsp => $::NODETYPE_FSP, bpa => $::NODETYPE_BPA, lpar => $::NODETYPE_LPAR, hmc => $::NODETYPE_HMC, ivm => $::NODETYPE_IVM, frame => $::NODETYPE_FRAME, cec => $::NODETYPE_CEC, cmm => $::NODETYPE_CMM, imm2 => $::NODETYPE_IMM2, pbmc => "pbmc", ); my %globalnodetype = ( fsp => $::NODETYPE_PPC, bpa => $::NODETYPE_PPC, cec => $::NODETYPE_PPC, frame => $::NODETYPE_PPC, hmc => $::NODETYPE_PPC, ivm => $::NODETYPE_PPC, cmm => $::NODETYPE_MP, lpar => "$::NODETYPE_PPC,$::NODETYPE_OSI", pbmc => $::NODETYPE_MP, ); my %globalmgt = ( fsp => "fsp", bpa => "bpa", cec => "fsp", frame => "bpa", mm => "blade", ivm => "ivm", rsa => "blade", cmm => "blade", imm2 => "blade", hmc => "hmc", pbmc => "ipmi", ); my %globalid = ( fsp => "cid", cec => "cid", bpa => "fid", frame => "fid" ); ########################################################################## # Command handler method from tables ########################################################################## sub handled_commands { return ({ lsslp => "lsslp" }); } ########################################################################## # Invokes the callback with the specified message ########################################################################## sub send_msg { my $request = shift; my $ecode = shift; my $msg = shift; my %output; ################################################# # Called from child process - send to parent ################################################# if (exists($request->{pipe})) { my $out = $request->{pipe}; $output{errorcode} = $ecode; $output{data} = \@_; print $out freeze([ \%output ]); print $out "\nENDOFFREEZE6sK4ci\n"; } ################################################# # Called from parent - invoke callback directly ################################################# elsif (exists($request->{callback})) { my $callback = $request->{callback}; $output{errorcode} = $ecode; $output{data} = $msg; $callback->(\%output); } } ########################################################################## # Parse the command line options and operands ########################################################################## sub parse_args { my $request = shift; my $args = $request->{arg}; my $cmd = $request->{command}; my %opt; my %services = ( HMC => SOFTWARE_SERVICE . ":" . SERVICE_HMC . ":", IVM => SOFTWARE_SERVICE . ":" . SERVICE_IVM . ":", BPA => HARDWARE_SERVICE . ":" . SERVICE_BPA, FSP => HARDWARE_SERVICE . ":" . SERVICE_FSP, CEC => HARDWARE_SERVICE . ":" . SERVICE_CEC, FRAME => HARDWARE_SERVICE . ":" . SERVICE_FRAME, RSA => HARDWARE_SERVICE . ":" . SERVICE_RSA . ":", CMM => HARDWARE_SERVICE . ":" . SERVICE_CMM, IMM2 => HARDWARE_SERVICE . ":" . SERVICE_IMM2, MM => HARDWARE_SERVICE . ":" . SERVICE_MM . ":", PBMC => HARDWARE_SERVICE . ":" . SERVICE_FSP ); ############################################# # Responds with usage statement ############################################# local *usage = sub { my $usage_string = xCAT::Usage->getUsage($cmd); return ([ $_[0], $usage_string ]); }; ############################################# # No command-line arguments - use defaults ############################################# if (!defined($args)) { return (0); } ############################################# # Checks case in GetOptions, allows opts # to be grouped (e.g. -vx), and terminates # at the first unrecognized option. ############################################# @ARGV = @$args; $Getopt::Long::ignorecase = 0; Getopt::Long::Configure("bundling"); ############################################# # Process command-line flags ############################################# if (!GetOptions(\%opt, qw(h|help V|verbose v|version i=s x z w r s=s e=s t=s m c n C=s T=s I u range=s flexdiscover updatehosts vpdtable))) { return (usage()); } ############################################# # Check for node range ############################################# if (scalar(@ARGV) == 1) { my @nodes = xCAT::NodeRange::noderange(@ARGV); foreach (@nodes) { push @filternodes, $_; } unless (@filternodes) { return (usage("Invalid Argument: $ARGV[0]")); } } elsif (scalar(@ARGV) > 1) { return (usage("Invalid flag, please check and retry.")); } ############################################# # Option -V for verbose output ############################################# if (exists($opt{V})) { $globalopt{verbose} = 1; } ############################################# # Check for mutually-exclusive formatting ############################################# if ((exists($opt{r}) + exists($opt{x}) + exists($opt{z}) + exists($opt{vpdtable})) > 1) { return (usage()); } ############################################# # Command tries ############################################# if (exists($opt{t})) { $globalopt{maxtries} = $opt{t}; if ($globalopt{maxtries} !~ /^\d+$/) { return (usage("Invalid command tries (1-9)")); } } ############################################# # Check for unsupported service type ############################################# if (exists($opt{s})) { if (!exists($services{ $opt{s} })) { return (usage("Invalid service: $opt{s}")); } $option_s = $opt{s}; $globalopt{service} = $services{ $opt{s} }; } ############################################# # Check the validation of -T option ############################################# if (exists($opt{T})) { $globalopt{T} = $opt{T}; if ($globalopt{T} !~ /^\d+$/) { return (usage("Invalid timeout value, should be number")); } #if (!exists( $opt{C} )) { # return ( usage( "-T should be used with -C" )); #} } ############################################# # Check the validation of -C option ############################################# if (exists($opt{C})) { $globalopt{C} = $opt{C}; if ($globalopt{C} !~ /^\d+$/) { return (usage("Invalid expect entries, should be number")); } if (!exists($opt{i})) { return (usage("-C should be used with -i")); } } ############################################# # Check the validation of -i option ############################################# if (exists($opt{i})) { foreach (split /,/, $opt{i}) { my $ip = $_; ################################### # Length for IPv4 addresses ################################### my (@octets) = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/; if (scalar(@octets) != 4) { return (usage("Invalid IP address: $ip")); } foreach my $octet (@octets) { if (($octet < 0) or ($octet > 255)) { return (usage("Invalid IP address: $ip")); } } } $globalopt{i} = $opt{i}; } ############################################# # write to the database ############################################# if (exists($opt{w})) { $globalopt{w} = 1; } ############################################# # list the raw information ############################################# if (exists($opt{r})) { $globalopt{r} = 1; } ############################################# # list the xml formate data ############################################# if (exists($opt{x})) { $globalopt{x} = 1; } ############################################# # list the stanza formate data ############################################# if (exists($opt{z})) { $globalopt{z} = 1; } ############################################# # match vpd table ############################################# if (exists($opt{vpdtable})) { $globalopt{vpdtable} = 1; } ######################################################### # only list the nodes that discovered for the first time ######################################################### if (exists($opt{n})) { $globalopt{n} = 1; } ############################################## # unicast ############################################## if (exists($opt{u})) { $globalopt{u} = 1; unless (exists($opt{s}) and exists($opt{range})) { return (usage("-u should be used with -s and --range")); } $globalopt{range} = $opt{range}; } if (exists($opt{range})) { unless (exists($opt{u})) { return (usage("range is used in unicast mode")); } } ############################################## # warn for no discovered nodes in database ############################################## if (exists($opt{I})) { $globalopt{I} = 1; } ############################################## # do slp and setup for cmm ############################################## if (exists($opt{flexdiscover})) { $globalopt{flexdiscover} = 1; } return (0); } ########################################################################## # Verbose mode (-V) ########################################################################## sub trace { my $request = shift; my $msg = shift; my $sig = shift; if ($sig) { if ($TRACE) { my ($sec, $min, $hour, $mday, $mon, $yr, $wday, $yday, $dst) = localtime(time); my $msg = sprintf "%02d:%02d:%02d %5d %s", $hour, $min, $sec, $$, $msg; send_msg($request, 0, $msg); } } else { if ($globalopt{verbose}) { my ($sec, $min, $hour, $mday, $mon, $yr, $wday, $yday, $dst) = localtime(time); my $msg = sprintf "%02d:%02d:%02d %5d %s", $hour, $min, $sec, $$, $msg; send_msg($request, 0, $msg); } } } ########################################################################## # Forks a process to run the slp command (1 per adapter) ########################################################################## sub fork_cmd { my $request = shift; ####################################### # Pipe childs output back to parent ####################################### my $parent; my $child; pipe $parent, $child; my $pid = xCAT::Utils->xfork(); if (!defined($pid)) { ################################### # Fork error ################################### send_msg($request, 1, "Fork error: $!"); return undef; } elsif ($pid == 0) { ################################### # Child process ################################### close($parent); $request->{pipe} = $child; invoke_dodiscover($request); ######################################## # Pass result array back to parent ######################################## my @results = ("FORMATDATA6sK4ci"); my $out = $request->{pipe}; print $out freeze(\@results); print $out "\nENDOFFREEZE6sK4ci\n"; exit(0); } else { ################################### # Parent process ################################### close($child); return ($parent); } return (0); } ########################################################################## # Run the forked command and send reply to parent ########################################################################## sub invoke_dodiscover { my $request = shift; ######################################## # SLP command ######################################## my $services; my $maxt; if ($globalopt{service}) { $services = $globalopt{service}; } else { $services = [ WILDCARD_SERVICE, HARDWARE_SERVICE, SOFTWARE_SERVICE, SERVICE_IMM2 ]; } #efix for hmc bug if ($services =~ /hardware-management-console/) { $services = [SOFTWARE_SERVICE]; } if ($globalopt{maxtries}) { $maxt = $globalopt{maxtries}; } else { $maxt = 0; } my %arg; if ($globalopt{flexdiscover}) { #we do two SLP passes, one to hopefully catch the less numerous management modules reliably, a separate one to best-effort catch imms $arg{SrvTypes} = [qw/service:management-hardware.IBM:chassis-management-module service:management-hardware.IBM:management-module/]; my ($searchmacsref, $sendcount, $rsp) = xCAT::SLP::dodiscover(SrvTypes => $arg{SrvTypes}, Callback => \&bt_handle_new_slp_entity); $arg{SrvTypes} = [qw/service:management-hardware.IBM:integrated-management-module2/]; my ($newsearchmacsref, $newsendcount, $newrsp) = xCAT::SLP::dodiscover(SrvTypes => $arg{SrvTypes}, Callback => \&bt_handle_new_slp_entity); foreach (keys %$newsearchmacsref) { $searchmacsref->{$_} = $newsearchmacsref->{$_}; } $sendcount += $newsendcount; $rsp += $newrsp; return ($searchmacsref, $sendcount, $rsp); } $arg{SrvTypes} = $services; #$arg{Callback} = \&handle_new_slp_entity; $arg{Ip} = $globalopt{i} if ($globalopt{i}); $arg{Retry} = $maxt; $arg{Count} = $globalopt{C} if ($globalopt{C}); $arg{Time} = $globalopt{T} if ($globalopt{T}); $arg{nomsg} = 1 if ($globalopt{z} or $globalopt{x}); $arg{reqcallback} = $request->{callback} if ($request->{callback}); if ($globalopt{u}) { $arg{unicast} = 1; $arg{range} = $globalopt{range}; } my ($searchmacsref, $sendcount, $rsp) = xCAT::SLP::dodiscover(%arg); ######################################### ## Need to check if the result is enough ######################################### #if ( $request->{C} != 0) { # send_msg( $request, 0, "\n Begin to try again, this may takes long time \n" ); # my %val_tmp = %$values; # my %found_cec; # for my $v (keys %val_tmp) { # $v =~ /type=([^\)]+)\)\,\(serial-number=([^\)]+)\)\,\(machinetype-model=([^\)]+)\)\,/; # if ( $found_cec{$2.'*'.$3} ne 1 and $1 eq SERVICE_FSP) { # $found_cec{$2.'*'.$3} = 1; # } # } # # my $rlt; # my $val; # my $start_time = Time::HiRes::gettimeofday(); # my $elapse; # my $found = scalar(keys %found_cec); # while ( $found < $globalopt{C} ) { # $rlt = xCAT::SLP::dodiscover(SrvTypes=>$services,Callback=>sub { print Dumper(@_) }); # $val = @$rlt[1]; # for my $v (keys %$val) { # $v =~ /type=([^\)]+)\)\,\(serial-number=([^\)]+)\)\,\(machinetype-model=([^\)]+)\)\,/; # if ( $found_cec{$2.'*'.$3} ne 1 and $1 eq SERVICE_FSP) { # $found_cec{$2.'*'.$3} = 1; # $val_tmp{$v} = 1; # } # } # $found = scalar(keys %val_tmp); # $elapse = Time::HiRes::gettimeofday() - $start_time; # if ( $elapse > $globalopt{time_out} ) { # send_msg( $request, 0, "Time out, Force return.\n" ); # last; # } # } # send_msg( $request, 0, "Discovered $found nodes \n" ); # $values = \%val_tmp; #} return ($searchmacsref, $sendcount, $rsp); } ########################################################################## # Formats slp responses ########################################################################## sub format_output { my $request = shift; my $searchmacsref = shift; my %searchmacs = %$searchmacsref; my $length = length($header[IP_ADDRESSES][TEXT]); my $result; ########################################### # No responses ########################################### if (keys %searchmacs == 0) { send_msg($request, 0, "No responses"); return; } ########################################### # Check -C -T ########################################### if ($globalopt{C}) { if (scalar(keys %searchmacs) ne $globalopt{C}) { send_msg($request, 0, "Timeout...Fource to return"); } } ########################################### # Read table to get exists data ########################################### unless ($globalopt{service} =~ /hardware-management-console/) { my $errcode = read_from_table(); if ($errcode) { send_msg($request, 0, "Can't open $errcode table"); return; } } ########################################### # Parse responses and add to hash ########################################### my $outhash = parse_responses($request, \$length, $searchmacsref); #hmc bug efix #my $newouthash; #if ($globalopt{service} =~ /hardware-management-console/) { # for my $en ( keys %$outhash ) { # if (${$outhash->{$en}}{type} eq 'hmc') { # $newouthash->{$en} = $outhash->{$en}; # } # } # $outhash = $newouthash; #} ########################################### # filter the result in the same vlan ########################################### if (exists($globalopt{i})) { my $outhash1 = filtersamevlan($outhash); $outhash = $outhash1; } # filter the result and keep the specified nodes ########################################### if (scalar(@filternodes)) { my $outhash1 = filter($outhash); $outhash = $outhash1; } ########################################### # -w flag for write to xCat database ########################################### if ($globalopt{w}) { send_msg($request, 0, "Begin to write into Database, this may change node name"); xCATdB($outhash); } ########################################### # -r flag for raw response format ########################################### my %rawhash; if ($globalopt{r}) { foreach (keys %$outhash) { my $raw = ${ $outhash->{$_} }{url}; $rawhash{$raw} = 1; } foreach my $en (keys %rawhash) { if ($en =~ /(\(type.*\))/) { $result .= "$1\n"; } } send_msg($request, 0, $result); return; } ########################################### # -x flag for xml format ########################################### if ($globalopt{x}) { send_msg($request, 0, format_xml($outhash)); return; } ########################################### # -z flag for stanza format ########################################### if ($globalopt{z}) { send_msg($request, 0, format_stanza($outhash)); return; } ########################################### # -T flag for vpd table format ########################################### if ($globalopt{vpdtable}) { send_msg($request, 0, format_table($outhash)); return; } ########################################### # Get longest IP for formatting purposes ########################################### my $format = sprintf "%%-%ds", ($length + 2); $header[IP_ADDRESSES][FORMAT] = $format; ########################################### # Display header ########################################### foreach (@header) { $result .= sprintf @$_[1], @$_[0]; } $result .= "\n"; ########################################### # Display response attributes ########################################### foreach my $nameentry (sort keys %$outhash) { my $hostname = ${ $outhash->{$nameentry} }{hostname}; foreach (@header) { my $attr = $headertoattr{ @$_[0] }; $result .= sprintf @$_[1], ${ $outhash->{$nameentry} }{$attr}; } $result .= "\n"; } send_msg($request, 0, $result); } ########################################################################## # Read the table and cache the data that will be used frequently ########################################################################## sub read_from_table { my %vpdhash; my @nodelist; my %ppchash; my %iphash; if (!(%::OLD_DATA_CACHE)) { #find out all the existed nodes my $nodelisttab = xCAT::Table->new('nodelist'); if ($nodelisttab) { my @typeentries = $nodelisttab->getAllNodeAttribs(['node']); for my $typeentry (@typeentries) { push @nodelist, $typeentry->{node}; } } else { return "nodelist"; } #find out all the existed nodes my $hoststab = xCAT::Table->new('hosts'); if ($hoststab) { my @hostsentries = $hoststab->getAllNodeAttribs([ 'node', 'ip' ]); for my $hostsentry (@hostsentries) { $iphash{ $hostsentry->{node} } = $hostsentry->{ip}; } } else { return "hosts"; } #find out all the existed nodes' type my $typehashref = xCAT::DBobjUtils->getnodetype(\@nodelist); # find out all the existed nodes' mtms and side my $vpdtab = xCAT::Table->new('vpd'); if ($vpdtab) { my @vpdentries = $vpdtab->getAllNodeAttribs([ 'node', 'mtm', 'serial', 'side' ]); for my $entry (@vpdentries) { @{ $vpdhash{ $entry->{node} } }[0] = $entry->{mtm}; @{ $vpdhash{ $entry->{node} } }[1] = $entry->{serial}; @{ $vpdhash{ $entry->{node} } }[2] = $entry->{side}; } } else { return "vpd"; } # find out all the existed nodes' attributes my $ppctab = xCAT::Table->new('ppc'); if ($ppctab) { my @identries = $ppctab->getAllNodeAttribs([ 'node', 'id', 'parent' ]); for my $entry (@identries) { next if ($entry->{nodetype} =~ /lpar/); @{ $ppchash{ $entry->{node} } }[0] = $entry->{id}; #id @{ $ppchash{ $entry->{node} } }[1] = $entry->{parent}; #parent } } else { return "ppc"; } foreach my $node (@nodelist) { my $type = $$typehashref{$node}; my $mtm = @{ $vpdhash{$node} }[0]; my $sn = @{ $vpdhash{$node} }[1]; my $side = @{ $vpdhash{$node} }[2]; my $id = $ppchash{$node}[0]; my $parent = $ppchash{$node}[1]; my $pmtm = @{ $vpdhash{$parent} }[0]; my $psn = @{ $vpdhash{$parent} }[1]; my $ip = $iphash{$node}; if ($type =~ /frame/) { $::OLD_DATA_CACHE{ "frame*" . $mtm . "*" . $sn } = $node if (defined $mtm and defined $sn); } elsif ($type =~ /cec/) { $::OLD_DATA_CACHE{ "cec*" . $mtm . "*" . $sn } = $node if (defined $mtm and defined $sn); my $iid = int($id); $parent = 'Server-' . $pmtm . '-SN' . $psn; $::OLD_DATA_CACHE{ "cec*" . $parent . "*" . $iid } = $node if (defined $parent and defined $id); } elsif ($type =~ /^fsp|bpa$/) { $::OLD_DATA_CACHE{ $type . "*" . $mtm . "*" . $sn . "*" . $side } = $node if (defined $mtm and defined $sn); } elsif ($type =~ /hmc/) { $::OLD_DATA_CACHE{ "hmc*" . $ip } = $node if (defined $ip); } else { $::OLD_DATA_CACHE{ $type . "*" . $mtm . "*" . $sn } = $node if (defined $mtm and defined $sn); } } } return undef; } ########################################################################## # Makesure the ip in SLP URL is valid # return 1 if valid, 0 if invalid ########################################################################## sub check_ip { my $myip = shift; $myip =~ s/^(\d+)\..*/$1/; if ($myip >= 224 and $myip <= 239) { return 0; } foreach (@invalidiplist) { if ($myip =~ /^($_)/) { return 0; } } return 1; } ########################################################################## # Get hostname from SLP URL response ########################################################################## sub get_host_from_url { my $request = shift; my $attr = shift; my $vip; my $host; ####################################### # Extract IP from URL ####################################### my $nets = xCAT::NetworkUtils::my_nets(); my $inc = $globalopt{i}; my @ips = (exists $attr->{'ip-address'}) ? @{ $attr->{'ip-address'} } : @{ $attr->{'ipv4-address'} }; my @ips2 = split /,/, $inc; my @validip; if ($inc) { for my $net (keys %$nets) { my $fg = 1; for my $einc (@ips2) { if ($nets->{$net} eq $einc) { $fg = 0; } } delete $nets->{$net} if ($fg); } } ####################################### # Check if valid IP ####################################### for my $tip (@ips) { next if ($tip =~ /:/); #skip IPV6 addresses for my $net (keys %$nets) { my ($n, $m) = split /\//, $net; if ( #xCAT::NetworkUtils::isInSameSubnet($n, $tip, $m, 1) and xCAT::NetworkUtils::isPingable($tip) and (length(inet_aton($tip)) == 4)) { push @validip, $tip; } } } if (scalar(@validip) == 0) { trace($request, "Invalid IP address in URL"); return undef; } ####################################### # Get Factory Hostname ####################################### if (${ $attr->{'hostname'} }[0]) { $host = ${ $attr->{'hostname'} }[0]; } else { $host = "Server-" . ${ $attr->{'machinetype-model'} }[0] . "-SN" . ${ $attr->{'serial-number'} }[0]; foreach my $ip (@validip) { my $hname = gethostbyaddr(inet_aton($ip), AF_INET); if ($hname) { $host = $hname; $vip = $ip; last; } } foreach my $ip (@validip) { my $hoststab = xCAT::Table->new('hosts'); my @entries = $hoststab->getAllNodeAttribs([ 'node', 'ip' ]); foreach my $entry (@entries) { if ($entry->{ip} and $entry->{ip} eq $ip) { $host = $entry->{node}; $vip = $ip; } } } } if ($host =~ /([^\.]+)\./) { $host = $1; } return $host; } ########################################################################## # ######################################################################### sub parse_responses { my $request = shift; my $length = shift; my $searchmacsref = shift; my $matchflag; my %outhash; my $host; my @matchnode; my @cmmnodes; my %searchmacs = %$searchmacsref; #get networks information for defining HMC my %net; my %addr; my $nettab = xCAT::Table->new('networks'); my @nets = $nettab->getAllAttribs('netname', 'net', 'mask', 'mgtifname'); if (scalar(@nets) == 0) { send_msg($request, 0, "Can't get networks information from networks table"); } else { foreach my $enet (@nets) { next if ($enet->{'net'} =~ /:/); $net{ $enet->{'mgtifname'} }{subnet} = $enet->{'net'}; $net{ $enet->{'mgtifname'} }{netmask} = $enet->{'mask'}; } } my $netref = xCAT::NetworkUtils->get_nic_ip(); for my $entry (keys %$netref) { $addr{ $netref->{$entry} }{subnet} = $net{$entry}{subnet}; $addr{ $netref->{$entry} }{netmask} = $net{$entry}{netmask}; } trace($request, "Now lsslp begin to parse its response..."); foreach my $rsp (keys(%searchmacs)) { ########################################### # attribute not found ########################################### if (!exists(${ $searchmacs{$rsp} }{attributes})) { trace($request, "Attribute not found for $rsp"); next; } ########################################### # Valid service-type attribute ########################################### my $attributes = ${ $searchmacs{$rsp} }{attributes}; my $type = ${ $attributes->{'type'} }[0]; if (!exists($service_slp{$type})) { trace($request, "Discarding unsupported type $type"); next; } ########################################### # Define nodes ########################################### my %atthash; if (($type eq SERVICE_RSA) or ($type eq SERVICE_RSA2) or ($type eq SERVICE_MM) or ($type eq SERVICE_IMM2)) { $atthash{type} = $service_slp{$type}; $atthash{mtm} = ${ $attributes->{'enclosure-machinetype-model'} }[0]; $atthash{serial} = ${ $attributes->{'enclosure-serial-number'} }[0]; $atthash{slot} = int(${ $attributes->{'slot'} }[0]); if ($type eq SERVICE_IMM2) { $atthash{ip} = ${ $attributes->{'ipv4-address'} }[0]; } else { $atthash{ip} = ${ $attributes->{'ip-address'} }[0]; } $atthash{mac} = $rsp; $atthash{hostname} = get_host_from_url($request, $attributes); $atthash{otherinterfaces} = ${ $attributes->{'ip-address'} }[0]; $atthash{url} = ${ $searchmacs{$rsp} }{payload}; $outhash{ 'Server-' . $atthash{mtm} . '-SN' . $atthash{serial} } = \%atthash; $$length = length($atthash{ip}) if (length($atthash{ip}) > $$length); trace($request, "Discover node $atthash{hostname}: type is $atthash{type}, \ mtm is $atthash{mtm}, sn is $atthash{serial}, slot is $atthash{slot}, \ ip is $atthash{ip}, mac is $atthash{mac}, otherinterfaces is $atthash{otherinterfaces}"); } elsif ($type eq SERVICE_CMM) { $atthash{type} = $service_slp{$type}; $atthash{mtm} = ${ $attributes->{'enclosure-mtm'} }[0]; $atthash{serial} = ${ $attributes->{'enclosure-serial-number'} }[0]; $atthash{side} = int(${ $attributes->{'slot'} }[0]); $atthash{ip} = ${ $attributes->{'ipv4-address'} }[0]; $atthash{mac} = $rsp; $atthash{mname} = ${ $attributes->{'mm-name'} }[0]; $atthash{url} = ${ $searchmacs{$rsp} }{payload}; $atthash{hostname} = get_host_from_url($request, $attributes); $atthash{mpa} = $atthash{hostname}; $atthash{otherinterfaces} = ${ $attributes->{'ipv4-address'} }[0]; $outhash{ 'Server-' . $atthash{mtm} . '-SN' . $atthash{serial} } = \%atthash; $$length = length($atthash{ip}) if (length($atthash{ip}) > $$length); if (exists($::OLD_DATA_CACHE{ "mp*" . $atthash{mtm} . "*" . $atthash{serial} })) { $atthash{hostname} = $::OLD_DATA_CACHE{ "mp*" . $atthash{mtm} . "*" . $atthash{serial} }; push @matchnode, 'Server-' . $atthash{mtm} . '-SN' . $atthash{serial}; } push @cmmnodes, 'Server-' . $atthash{mtm} . '-SN' . $atthash{serial}; trace($request, "Discover node $atthash{hostname}: type is $atthash{type}, \ mtm is $atthash{mtm}, sn is $atthash{serial}, side is $atthash{side}, \ ip is $atthash{ip}, mac is $atthash{mac}, mname is $atthash{mname},\ mpa is $atthash{mpa}, otherinterfaces is $atthash{otherinterfaces}"); } elsif ($type eq SERVICE_HMC) { $atthash{type} = $service_slp{$type}; $atthash{mtm} = ${ $attributes->{'machinetype-model'} }[0]; $atthash{serial} = ${ $attributes->{'serial-number'} }[0]; $atthash{ip} = ${ $attributes->{'ip-address'} }[0]; $atthash{hostname} = get_host_from_url($request, $attributes); my @ips = @{ $attributes->{'ip-address'} }; foreach my $tmpip (@ips) { if (exists($::OLD_DATA_CACHE{ "hmc*" . $tmpip })) { $atthash{hostname} = $::OLD_DATA_CACHE{ "hmc*" . $tmpip }; push @matchnode, 'Server-' . $atthash{mtm} . '-SN' . $atthash{serial}; $atthash{ip} = $tmpip; } } $atthash{mac} = $rsp; $atthash{url} = ${ $searchmacs{$rsp} }{payload}; $atthash{otherinterfaces} = ${ $attributes->{'ip-address'} }[0]; $outhash{ 'Server-' . $atthash{mtm} . '-SN' . $atthash{serial} } = \%atthash; $$length = length($atthash{ip}) if (length($atthash{ip}) > $$length); trace($request, "Discover node $atthash{hostname}: type is $atthash{type},\ mtm is $atthash{mtm},sn is $atthash{serial}, ip is $atthash{ip},\ mac is $atthash{mac}, otherinterfaces is $atthash{otherinterfaces}"); } elsif ($type eq SERVICE_IVM) { $atthash{type} = $service_slp{$type}; $atthash{mtm} = ${ $attributes->{'machinetype-model'} }[0]; $atthash{serial} = ${ $attributes->{'serial-number'} }[0]; $atthash{id} = ${ $attributes->{'lparid'} }[0]; $atthash{ip} = ${ $attributes->{'ip-address'} }[0]; $atthash{hostname} = get_host_from_url($request, $attributes); $atthash{hostname} =~ s/^Server/ivm/; my @ips = @{ $attributes->{'ip-address'} }; foreach my $tmpip (@ips) { if (exists($::OLD_DATA_CACHE{ "ivm*" . $atthash{mtm} . "*" . $atthash{serial} })) { $atthash{hostname} = $::OLD_DATA_CACHE{ "ivm*" . $atthash{mtm} . "*" . $atthash{serial} }; push @matchnode, 'Server-' . $atthash{mtm} . '-SN' . $atthash{serial}; $atthash{ip} = $tmpip; } } $atthash{mac} = $rsp; $atthash{url} = ${ $searchmacs{$rsp} }{payload}; $atthash{otherinterfaces} = ${ $attributes->{'ip-address'} }[0]; $outhash{ 'Server-' . $atthash{mtm} . '-SN' . $atthash{serial} } = \%atthash; $$length = length($atthash{ip}) if (length($atthash{ip}) > $$length); trace($request, "Discover node $atthash{hostname}: type is $atthash{type},\ mtm is $atthash{mtm},sn is $atthash{serial}, ip is $atthash{ip},\ mac is $atthash{mac}, otherinterfaces is $atthash{otherinterfaces}"); } elsif (($type eq SERVICE_FSP) && ($option_s eq "PBMC")) { my %tmphash; $atthash{type} = "pbmc"; $atthash{mtm} = ${ $attributes->{'machinetype-model'} }[0]; $atthash{serial} = ${ $attributes->{'serial-number'} }[0]; $atthash{ip} = ${ $searchmacs{$rsp} }{peername}; $atthash{url} = ${ $searchmacs{$rsp} }{payload}; $atthash{hostname} = 'Server-' . $atthash{mtm} . '-SN' . $atthash{serial}; if (exists($::OLD_DATA_CACHE{ "mp*" . $atthash{mtm} . "*" . $atthash{serial} })) { $atthash{hostname} = $::OLD_DATA_CACHE{ "mp*" . $atthash{mtm} . "*" . $atthash{serial} }; push @matchnode, 'Server-' . $atthash{mtm} . '-SN' . $atthash{serial}; } $outhash{ 'Server-' . $atthash{mtm} . '-SN' . $atthash{serial} } = \%atthash; } elsif (($type eq SERVICE_FSP) && (${ $attributes->{'machinetype-model'} }[0] =~ /^7895|1457|7954/)) { # Skip this entry if "-s CEC" was specified - we do not list FSP entries for Flex when only CECs were requested next unless ($option_s ne "CEC"); #begin to define fsp and bpa my %tmphash; $tmphash{type} = ($type eq SERVICE_BPA) ? TYPE_BPA : TYPE_FSP; $tmphash{mtm} = ${ $attributes->{'machinetype-model'} }[0]; $tmphash{serial} = ${ $attributes->{'serial-number'} }[0]; $tmphash{ip} = ${ $searchmacs{$rsp} }{peername}; my $loc = ($tmphash{ip} =~ ${ $attributes->{'ip-address'} }[0]) ? 0 : 1; #every entry has two ip-addresses $tmphash{side} = (int(${ $attributes->{'slot'} }[0]) == 0) ? 'B-' . $loc : 'A-' . $loc; $tmphash{mac} = $rsp; $tmphash{parent} = 'Server-' . $tmphash{mtm} . '-SN' . $tmphash{serial}; $tmphash{hostname} = $tmphash{ip}; $tmphash{url} = ${ $searchmacs{$rsp} }{payload}; $tmphash{otherinterfaces} = ${ $searchmacs{$rsp} }{peername}; $tmphash{bpcmtm} = ${ $attributes->{'bpc-machinetype-model'} }[0]; $tmphash{bpcsn} = ${ $attributes->{'bpc-serial-number'} }[0]; $tmphash{fid} = int(${ $attributes->{'frame-number'} }[0]); $tmphash{cid} = int(${ $attributes->{'cage-number'} }[0]); $outhash{ $tmphash{ip} } = \%tmphash; $$length = length($tmphash{ip}) if (length($tmphash{ip}) > $$length); trace($request, "Discover node $tmphash{hostname}:type is $tmphash{type}, mtm is $tmphash{mtm}, \ sn is $tmphash{serial}, side is $tmphash{side},parent is $tmphash{parent},ip is $tmphash{ip}, \ cec id is $tmphash{cid} , frame id is $tmphash{fid},mac is $tmphash{mac}, \ otherinterfaces is $tmphash{otherinterfaces}"); ##################################################################### #define another side to fix the issue that the result is imcomplete ##################################################################### my %tmphash1; $tmphash1{ip} = (${ $searchmacs{$rsp} }{peername} =~ ${ $attributes->{'ip-address'} }[0]) ? ${ $attributes->{'ip-address'} }[1] : ${ $attributes->{'ip-address'} }[0]; unless ($outhash{ $tmphash1{ip} }) { my $validflag = 1; foreach (@invalidiplist) { if ($tmphash1{ip} =~ /^($_)/) { $validflag = 0; last; } } if ($validflag == 1) { $tmphash1{type} = ($type eq SERVICE_BPA) ? TYPE_BPA : TYPE_FSP; $tmphash1{mtm} = ${ $attributes->{'machinetype-model'} }[0]; $tmphash1{serial} = ${ $attributes->{'serial-number'} }[0]; my $loc = ($tmphash1{ip} =~ ${ $attributes->{'ip-address'} }[0]) ? 0 : 1; #every entry has two ip-addresses $tmphash1{side} = (int(${ $attributes->{'slot'} }[0]) == 0) ? 'B-' . $loc : 'A-' . $loc; $tmphash1{mac} = xCAT::SLP::get_mac_for_addr($tmphash1{ip}); $tmphash1{parent} = 'Server-' . $tmphash1{mtm} . '-SN' . $tmphash1{serial}; $tmphash1{hostname} = $tmphash1{ip}; $tmphash1{otherinterfaces} = ${ $searchmacs{$rsp} }{peername}; $tmphash1{bpcmtm} = ${ $attributes->{'bpc-machinetype-model'} }[0]; $tmphash1{bpcsn} = ${ $attributes->{'bpc-serial-number'} }[0]; $tmphash1{fid} = int(${ $attributes->{'frame-number'} }[0]); $tmphash1{cid} = int(${ $attributes->{'cage-number'} }[0]); $outhash{ $tmphash1{ip} } = \%tmphash1; $$length = length($tmphash1{ip}) if (length($tmphash1{ip}) > $$length); trace($request, "Discover another node $tmphash1{hostname}:type is $tmphash1{type}, mtm is $tmphash1{mtm}, \ sn is $tmphash1{serial}, side is $tmphash1{side},parent is $tmphash1{parent},ip is $tmphash1{ip}, \ cec id is $tmphash1{cid} , frame id is $tmphash1{fid},mac is $tmphash1{mac}, \ otherinterfaces is $tmphash1{otherinterfaces}"); } } } else { #begin to define fsp and bpa my %tmphash; $tmphash{type} = ($type eq SERVICE_BPA) ? TYPE_BPA : TYPE_FSP; $tmphash{mtm} = ${ $attributes->{'machinetype-model'} }[0]; $tmphash{serial} = ${ $attributes->{'serial-number'} }[0]; $tmphash{ip} = ${ $searchmacs{$rsp} }{peername}; my $loc = ($tmphash{ip} =~ ${ $attributes->{'ip-address'} }[0]) ? 0 : 1; #every entry has two ip-addresses $tmphash{side} = (int(${ $attributes->{'slot'} }[0]) == 0) ? 'B-' . $loc : 'A-' . $loc; $tmphash{mac} = $rsp; $tmphash{parent} = 'Server-' . $tmphash{mtm} . '-SN' . $tmphash{serial}; $tmphash{hostname} = $tmphash{ip}; $tmphash{otherinterfaces} = ${ $searchmacs{$rsp} }{peername}; $tmphash{bpcmtm} = ${ $attributes->{'bpc-machinetype-model'} }[0]; $tmphash{bpcsn} = ${ $attributes->{'bpc-serial-number'} }[0]; $tmphash{fid} = int(${ $attributes->{'frame-number'} }[0]); $tmphash{cid} = int(${ $attributes->{'cage-number'} }[0]); $outhash{ $tmphash{ip} } = \%tmphash; $$length = length($tmphash{ip}) if (length($tmphash{ip}) > $$length); trace($request, "Discover node $tmphash{hostname}:type is $tmphash{type}, mtm is $tmphash{mtm}, \ sn is $tmphash{serial}, side is $tmphash{side},parent is $tmphash{parent},ip is $tmphash{ip}, \ cec id is $tmphash{cid} , frame id is $tmphash{fid},mac is $tmphash{mac}, \ otherinterfaces is $tmphash{otherinterfaces}"); ##################################################################### #define another side to fix the issue that the result is imcomplete ##################################################################### my %tmphash1; $tmphash1{ip} = (${ $searchmacs{$rsp} }{peername} =~ ${ $attributes->{'ip-address'} }[0]) ? ${ $attributes->{'ip-address'} }[1] : ${ $attributes->{'ip-address'} }[0]; unless ($outhash{ $tmphash1{ip} }) { my $validflag = 1; foreach (@invalidiplist) { if ($tmphash1{ip} =~ /^($_)/) { $validflag = 0; last; } } if ($validflag == 1) { $tmphash1{type} = ($type eq SERVICE_BPA) ? TYPE_BPA : TYPE_FSP; $tmphash1{mtm} = ${ $attributes->{'machinetype-model'} }[0]; $tmphash1{serial} = ${ $attributes->{'serial-number'} }[0]; my $loc = ($tmphash1{ip} =~ ${ $attributes->{'ip-address'} }[0]) ? 0 : 1; #every entry has two ip-addresses $tmphash1{side} = (int(${ $attributes->{'slot'} }[0]) == 0) ? 'B-' . $loc : 'A-' . $loc; $tmphash1{mac} = xCAT::SLP::get_mac_for_addr($tmphash1{ip}); $tmphash1{parent} = 'Server-' . $tmphash1{mtm} . '-SN' . $tmphash1{serial}; $tmphash1{hostname} = $tmphash1{ip}; $tmphash1{otherinterfaces} = ${ $searchmacs{$rsp} }{peername}; $tmphash1{bpcmtm} = ${ $attributes->{'bpc-machinetype-model'} }[0]; $tmphash1{bpcsn} = ${ $attributes->{'bpc-serial-number'} }[0]; $tmphash1{fid} = int(${ $attributes->{'frame-number'} }[0]); $tmphash1{cid} = int(${ $attributes->{'cage-number'} }[0]); $outhash{ $tmphash1{ip} } = \%tmphash1; $$length = length($tmphash1{ip}) if (length($tmphash1{ip}) > $$length); trace($request, "Discover another node $tmphash1{hostname}:type is $tmphash1{type}, mtm is $tmphash1{mtm}, \ sn is $tmphash1{serial}, side is $tmphash1{side},parent is $tmphash1{parent},ip is $tmphash1{ip}, \ cec id is $tmphash1{cid} , frame id is $tmphash1{fid},mac is $tmphash1{mac}, \ otherinterfaces is $tmphash1{otherinterfaces}"); } } # this part of code is used to avoid two messages sent from different ports of fsp give different info. Although this hasn't showed. #else { # ${$outhash{$tmphash1{ip}}{fid} = int(${$attributes->{'frame-number'}}[0]) if(int(${$attributes->{'frame-number'}}[0]) != 0); # ${$outhash{$tmphash1{ip}}{cid} = int(${$attributes->{'cage-number'}}[0]) if(int(${$attributes->{'cage-number'}}[0]) != 0); # trace( $request, "change frame id to ${$outhash{$tmphash1{ip}}{fid}, change cec id to ${$outhash{$tmphash1{ip}}{cid} \n"); #} ###################################################################### #begin to define frame and cec $atthash{type} = $service_slp{$type}; $atthash{mtm} = ${ $attributes->{'machinetype-model'} }[0]; $atthash{serial} = ${ $attributes->{'serial-number'} }[0]; my $name = 'Server-' . $atthash{mtm} . '-SN' . $atthash{serial}; unless (exists $outhash{$name}) { $atthash{slot} = ''; $atthash{ip} = ''; $atthash{hostname} = 'Server-' . $atthash{mtm} . '-SN' . $atthash{serial}; $atthash{mac} = ""; $atthash{bpcmtm} = ${ $attributes->{'bpc-machinetype-model'} }[0]; $atthash{bpcsn} = ${ $attributes->{'bpc-serial-number'} }[0]; $atthash{fid} = int(${ $attributes->{'frame-number'} }[0]); $atthash{cid} = int(${ $attributes->{'cage-number'} }[0]); $atthash{parent} = 'Server-' . $atthash{bpcmtm} . '-SN' . $atthash{bpcsn} if ($type eq SERVICE_FSP); $atthash{children} = ${ $attributes->{'ip-address'} }[0] . "," . ${ $attributes->{'ip-address'} }[1]; $atthash{url} = ${ $searchmacs{$rsp} }{payload}; $outhash{ 'Server-' . $atthash{mtm} . '-SN' . $atthash{serial} } = \%atthash; trace($request, "Discover node $atthash{hostname}: type is $atthash{type}, mtm is $atthash{mtm},\ sn is $atthash{serial}, mac is $atthash{mac}, children is $atthash{children}, frame id is $atthash{fid}, \ cec id is $atthash{cid}, otherinterfaces is $atthash{otherinterfaces}, parent is $atthash{parent}"); } else { #update frameid and cageid to fix the firmware mistake ${ $outhash{$name} }{fid} = int(${ $attributes->{'frame-number'} }[0]) if (int(${ $attributes->{'frame-number'} }[0]) != 0); ${ $outhash{$name} }{cid} = int(${ $attributes->{'cage-number'} }[0]) if (int(${ $attributes->{'cage-number'} }[0]) != 0); ${ $outhash{$name} }{bpcmtm} = ${ $attributes->{'bpc-machinetype-model'} }[0] if (int(${ $attributes->{'bpc-machinetype-model'} }[0]) != 0); ${ $outhash{$name} }{bpcsn} = ${ $attributes->{'bpc-serial-number'} }[0] if (int(${ $attributes->{'bpc-serial-number'} }[0]) != 0); $atthash{parent} = 'Server-' . ${ $outhash{$name} }{bpcmtm} . '-SN' . ${ $outhash{$name} }{bpcsn} if ($type eq SERVICE_FSP); $outhash{$name}{children} .= "," . ${ $attributes->{'ip-address'} }[0] . "," . ${ $attributes->{'ip-address'} }[1]; # at most save 8 ips and have redendant trace($request, "adjust frame id to ${$outhash{$name}}{fid}, cec id to ${$outhash{$name}}{cid}, children to $outhash{$name}{children},\ bpcmtm to ${$outhash{$name}}{bpcmtm}, bpcsn to ${$outhash{$name}}{bpcsn}"); } } } ########################################################### # find frame's hostname first, then use find the cec's parent # until then can begin with finding cec's hostname # the order of finding PPC nodes' hostname can't be wrong # and can't be done together ########################################################### my $newhostname; trace($request, "\n\n\nBegin to find find frame's hostname"); foreach my $h (keys %outhash) { if (${ $outhash{$h} }{type} eq TYPE_FRAME) { $newhostname = $::OLD_DATA_CACHE{ "frame*" . ${ $outhash{$h} }{mtm} . "*" . ${ $outhash{$h} }{serial} }; if ($newhostname) { ${ $outhash{$h} }{hostname} = $newhostname; trace($request, "$h found hostname $newhostname"); push @matchnode, $h; } } } trace($request, "\n\n\nBegin to find cec's parent"); foreach my $h (keys %outhash) { next unless (${ $outhash{$h} }{type} eq TYPE_CEC); my $parent; #find parent in the discovered nodes foreach my $h1 (keys %outhash) { if (${ $outhash{$h1} }{type} eq "frame" and ${ $outhash{$h} }{bpcmtm} eq ${ $outhash{$h1} }{mtm} and ${ $outhash{$h} }{bpcsn} eq ${ $outhash{$h1} }{serial}) { $parent = ${ $outhash{$h1} }{hostname}; last; } } #find parent in database if (!defined($parent)) { my $existing_node = $::OLD_DATA_CACHE{ "frame*" . ${ $outhash{$h} }{bpcmtm} . '*' . ${ $outhash{$h} }{bpcsn} }; $parent = $existing_node if ($existing_node); } ${ $outhash{$h} }{parent} = $parent; trace($request, "$h found parent $parent") if ($parent); } trace($request, "\n\n\nBegin to find cec hostname"); foreach my $h (keys %outhash) { if (${ $outhash{$h} }{type} eq TYPE_CEC) { my $newhostname1 = $::OLD_DATA_CACHE{ "cec*" . ${ $outhash{$h} }{mtm} . '*' . ${ $outhash{$h} }{serial} }; if ($newhostname1) { trace($request, "$h found hostname $newhostname1 with mtms"); ${ $outhash{$h} }{hostname} = $newhostname1; push @matchnode, $h; } my $tp = 'Server-' . ${ $outhash{$h} }{bpcmtm} . '-SN' . ${ $outhash{$h} }{bpcsn}; trace($request, "$h begin to find hostname with parent $tp and id ${$outhash{$h}}{cid}"); my $newhostname2 = $::OLD_DATA_CACHE{ "cec*" . $tp . '*' . ${ $outhash{$h} }{cid} }; if ($newhostname2) { ${ $outhash{$h} }{hostname} = $newhostname2; trace($request, "$h found hostname $newhostname2 with parent and id"); push @matchnode, $h; } } } trace($request, "\n\n\nBegin to find fsp/bpa's hostname and parent"); foreach my $h (keys %outhash) { # Added a skip if processing Flex blades if (${ $outhash{$h} }{type} eq TYPE_FSP or ${ $outhash{$h} }{type} eq TYPE_BPA) { $newhostname = $::OLD_DATA_CACHE{ ${ $outhash{$h} }{type} . "*" . ${ $outhash{$h} }{mtm} . '*' . ${ $outhash{$h} }{serial} . '*' . ${ $outhash{$h} }{side} }; if ($newhostname) { ${ $outhash{$h} }{hostname} = $newhostname; trace($request, "$h found hostname $newhostname"); push @matchnode, $h; } my $ptmp = ${ $outhash{$h} }{parent}; ${ $outhash{$h} }{parent} = ${ $outhash{$ptmp} }{hostname} unless ((${ $outhash{$h} }{type} eq TYPE_FSP) && ${ $outhash{$h} }{mtm} =~ /^7895|1457|7954/); trace($request, "$h found parent ${$outhash{$ptmp}}{hostname}"); #check if fsp/bpa's ip is valid my $vip = check_ip(${ $outhash{$h} }{ip}); unless ($vip) { #which means the ip is a valid one delete $outhash{$h}; } } } trace($request, "\n\n\nBegin to adjust fsp/bpa's id"); foreach my $h (keys %outhash) { if (${ $outhash{$h} }{type} eq TYPE_CEC or ${ $outhash{$h} }{type} eq TYPE_FRAME) { my @children = split /,/, ${ $outhash{$h} }{children}; foreach my $child (@children) { ${ $outhash{$child} }{fid} = ${ $outhash{$h} }{fid}; ${ $outhash{$child} }{cid} = ${ $outhash{$h} }{cid}; trace($request, "child is $child, fid is ${$outhash{$child}}{fid}, cid is ${$outhash{$child}}{cid}"); } } } trace($request, "\n\n\nBegin to find cmm hostname in switch table"); $macmap = xCAT::MacMap->new(); $macmap->refresh_table(); foreach my $cmmnode (@cmmnodes) { my $macvalue = ${ $outhash{$cmmnode} }{mac}; my $hostn = $macmap->find_mac($macvalue, 1); if ($hostn) { ${ $outhash{$cmmnode} }{hostname} = $hostn; trace($request, "cmmnode $cmmnode find hostname $hostn"); } } ########################################################## # If there is -n flag, skip the matched nodes ########################################################## if (exists($globalopt{n})) { trace($request, "\n\n\nThere is -n flag, skip these nodes:\n"); for my $matchednode (@matchnode) { if ($outhash{$matchednode}) { trace($request, "skip the node $matchednode\n"); delete $outhash{$matchednode}; } } } if (exists($globalopt{I})) { my %existsnodes; my $nodelisttab = xCAT::Table->new('nodelist'); unless ($nodelisttab) { return ("Error opening 'nodelisttable'"); } my @nodes = $nodelisttab->getAllNodeAttribs([qw(node)]); my $notdisnode; for my $enode (@nodes) { for my $mnode (@matchnode) { if ($enode->{node} eq ${ $outhash{$mnode} }{hostname}) { $existsnodes{ $enode->{node} } = 1; last; } } } for my $enode (@nodes) { unless ($existsnodes{ $enode->{node} }) { $notdisnode .= $enode->{node} . ","; } } send_msg($request, 0, "These nodes defined in database but can't be discovered: $notdisnode \n"); } foreach my $no (keys %outhash) { delete $outhash{$no} unless (${ $outhash{$no} }{hostname}); } return \%outhash; } ########################################################################## # Write result to xCat database ########################################################################## sub xCATdB { my $outhash = shift; ######################################## # Begin to collect attributes for each node ######################################## my %nodelisthash; my %ppchash; my %vpdhash; my %nodehmhash; my %nodetypehash; my %ppcdirecthash; my %hostshash; my %machash; my %mphash; my %ipmihash; foreach my $nodeentry (keys %$outhash) { my $type = ${ $outhash->{$nodeentry} }{type}; my $model = ${ $outhash->{$nodeentry} }{mtm}; my $serial = ${ $outhash->{$nodeentry} }{serial}; my $side = ${ $outhash->{$nodeentry} }{side}; my $ip = ${ $outhash->{$nodeentry} }{ip}; my $frameid = ${ $outhash->{$nodeentry} }{fid}; my $cageid = ${ $outhash->{$nodeentry} }{cid}; my $parent = ${ $outhash->{$nodeentry} }{parent}; my $mac = ${ $outhash->{$nodeentry} }{mac}; my $otherif = ${ $outhash->{$nodeentry} }{otherinterfaces}; my $hostname = ${ $outhash->{$nodeentry} }{hostname}; my $id = ($type =~ /bpa|frame/) ? $frameid : $cageid; my $hidden = ($type =~ /bpa|fsp/) ? 1 : 0; my $groups = lc($type) . ",all"; my $tmp_pre = xCAT::data::ibmhwtypes::parse_group($model); if (defined($tmp_pre)) { $groups .= ",$tmp_pre"; } ######################################## # Write result to every tables, ######################################## if ($type =~ /^bpa|fsp|cec|frame$/) { #$nodelisthash{$hostname} = {groups=>"$type,all", hidden=>$hidden}; $nodelisthash{$hostname} = { groups => $groups, hidden => $hidden }; $ppchash{$hostname} = { id => $id, parent => $parent, hcp => $hostname, nodetype => $globalhwtype{$type} }; $vpdhash{$hostname} = { mtm => $model, serial => $serial, side => $side }; $nodehmhash{$hostname} = { mgt => $globalmgt{$type} }; $nodetypehash{$hostname} = { nodetype => $globalnodetype{$type} }; $hostshash{$hostname} = { otherinterfaces => $otherif } if ($type =~ /fsp|bpa/); $machash{$hostname} = { mac => $mac } if ($type =~ /^fsp|bpa$/); } elsif ($type =~ /^pbmc$/) { $nodelisthash{$hostname} = { groups => $groups, hidden => $hidden }; $mphash{$hostname} = { nodetype => $globalhwtype{$type} }; $vpdhash{$hostname} = { mtm => $model, serial => $serial }; $nodehmhash{$hostname} = { mgt => $globalmgt{$type} }; $nodetypehash{$hostname} = { nodetype => $globalnodetype{$type} }; $ipmihash{$hostname} = { bmc => $ip }; } elsif ($type =~ /^(rsa|mm)$/) { my @data = ($type, $model, $serial, $side, $ip, $frameid, $cageid, $parent, $mac); xCAT::PPCdb::add_systemX($type, $hostname, \@data); } elsif ($type =~ /^(hmc|ivm)$/) { $nodelisthash{$hostname} = { groups => $groups, hidden => $hidden }; $ppchash{$hostname} = { nodetype => $globalhwtype{$type} }; $vpdhash{$hostname} = { mtm => $model, serial => $serial }; $nodetypehash{$hostname} = { nodetype => $globalnodetype{$type} }; $nodehmhash{$hostname} = { mgt => $globalmgt{$type} }; $hostshash{$hostname} = { ip => $ip }; $machash{$hostname} = { mac => $mac }; } elsif ($type =~ /^cmm$/) { $nodelisthash{$hostname} = { groups => $groups, hidden => $hidden }; $vpdhash{$hostname} = { mtm => $model, serial => $serial, side => $side }; $nodetypehash{$hostname} = { nodetype => $globalnodetype{$type} }; $nodehmhash{$hostname} = { mgt => "blade" }; $mphash{$hostname} = { nodetype => $globalhwtype{$type}, mpa => $hostname }; $hostshash{$hostname} = { otherinterfaces => $otherif }; } } ######################################## # Update database ######################################## my %dbhash; $dbhash{nodelist} = \%nodelisthash, if (%nodelisthash); $dbhash{ppc} = \%ppchash, if (%ppchash); $dbhash{vpd} = \%vpdhash, if (%vpdhash); $dbhash{nodehm} = \%nodehmhash, if (%nodehmhash); $dbhash{nodetype} = \%nodetypehash, if (%nodetypehash); $dbhash{ppcdirect} = \%ppcdirecthash, if (%ppcdirecthash); $dbhash{hosts} = \%hostshash, if (%hostshash); $dbhash{mac} = \%machash, if (%machash); $dbhash{mp} = \%mphash, if (%mphash); $dbhash{ipmi} = \%ipmihash, if (%ipmihash); for my $tab (keys %dbhash) { my $db = xCAT::Table->new($tab); if (!$db) { return ("Error opening $db"); } $db->setNodesAttribs($dbhash{$tab}); $db->close(); } } ########################################################################## # Stanza formatting ########################################################################## sub format_stanza { my $outhash = shift; my $result; ##################################### # Write attributes ##################################### foreach my $name (keys %$outhash) { my $hostname = ${ $outhash->{$name} }{hostname}; my $ip = ${ $outhash->{$name} }{ip}; if ($hostname =~ /^([^\(]+)\(([^\)]+)\)$/) { $hostname = $1; $ip = $2; } my $type = ${ $outhash->{$name} }{type}; my $groups = "$type,all"; my $tmp_pre = xCAT::data::ibmhwtypes::parse_group(${ $outhash->{$name} }{mtm}); if (defined($tmp_pre)) { $groups .= ",$tmp_pre"; } ################################# # Node attributes ################################# $result .= "$hostname:\n\tobjtype=node\n"; if ($type =~ /^cmm$/) { $result .= "\tmpa=${$outhash->{$name}}{hostname}\n"; } elsif ($type =~ /^pbmc$/) { $result .= "\tbmc=${$outhash->{$name}}{ip}\n"; } else { $result .= "\thcp=${$outhash->{$name}}{hostname}\n"; } $result .= "\tnodetype=$globalnodetype{$type}\n"; $result .= "\tmtm=${$outhash->{$name}}{mtm}\n"; $result .= "\tserial=${$outhash->{$name}}{serial}\n"; if ($type =~ /^fsp|bpa|cmm$/) { $result .= "\tside=${$outhash->{$name}}{side}\n"; } #$result .= "\tgroups=$type,all\n"; $result .= "\tgroups=$groups\n"; $result .= "\tmgt=$globalmgt{$type}\n"; if ($type =~ /^fsp|bpa|frame|cec$/) { $result .= "\tid=${$outhash->{$name}}{$globalid{$type}}\n"; } if ($type =~ /^fsp|bpa|cec$/ and exists(${ $outhash->{$name} }{parent})) { $result .= "\tparent=${$outhash->{$name}}{parent}\n"; } unless ($type =~ /^frame|cec$/ or !exists(${ $outhash->{$name} }{mac})) { $result .= "\tmac=${$outhash->{$name}}{mac}\n"; } if ($type =~ /^fsp|bpa$/) { $result .= "\thidden=1\n"; } else { $result .= "\thidden=0\n"; } #unless ($type =~ /^cmm$/) { # $result .= "\tip=$ip\n"; #} if ($type =~ /^fsp|bpa|cmm$/) { $result .= "\totherinterfaces=${$outhash->{$name}}{otherinterfaces}\n"; } if ($type eq "ivm") { $result .= "\tip=${$outhash->{$name}}{ip}\n"; } $result .= "\thwtype=$globalhwtype{$type}\n"; } return ($result); } ########################################################################## # XML formatting ########################################################################## sub format_xml { my $outhash = shift; my $xml; my $result = format_stanza($outhash); my @nodeentry = split 'objtype=', $result; foreach my $entry (@nodeentry) { my $href = { Node => {} }; my @attr = split '\\n\\t', $entry; $href->{Node}->{node} = $attr[0]; for (my $i = 1 ; $i < scalar(@attr) ; $i++) { if ($attr[$i] =~ /(\w+)\=(.*)/) { $href->{Node}->{$1} = $2; } } $xml .= XMLout($href, NoAttr => 1, KeyAttr => [], RootName => undef); } return ($xml); } ########################################################################## # VPD table formatting ########################################################################## sub format_table { my $outhash = shift; my $result; ##################################### # Create XML formatted attributes ##################################### foreach my $name (keys %$outhash) { my $type = ${ $outhash->{$name} }{type}; next if ($type =~ /^(fsp|bpa)$/); $result .= "${$outhash->{$name}}{hostname}:\n"; $result .= "\tobjtype=node\n"; $result .= "\tmtm=${$outhash->{$name}}{mtm}\n"; $result .= "\tserial=${$outhash->{$name}}{serial}\n"; } return ($result); } ########################################################################## # Collect output from the child processes ########################################################################## sub child_response { my $callback = shift; my $fds = shift; my @ready_fds = $fds->can_read(1); foreach my $rfh (@ready_fds) { my $data = <$rfh>; ################################# # Read from child process ################################# if (defined($data)) { while ($data !~ /ENDOFFREEZE6sK4ci/) { $data .= <$rfh>; } my $responses = thaw($data); ############################# # Formatted SLP results ############################# if (@$responses[0] =~ /^FORMATDATA6sK4ci$/) { my $result = @$responses[1]; foreach (keys %$result) { #$slp_result{$_} = 1; } next; } ############################# # Message or verbose trace ############################# foreach (@$responses) { $callback->($_); } next; } ################################# # Done - close handle ################################# $fds->remove($rfh); close($rfh); } } ############################################################################# # Preprocess request from xCAT daemon and send request to service nodes ############################################################################# sub preprocess_request { my $req = shift; if ($req->{_xcatpreprocessed}->[0] == 1) { return [$req]; } my $callback = shift; my @requests; my $command = $req->{command}->[0]; my $extrargs = $req->{arg}; my @exargs = ($req->{arg}); if (ref($extrargs)) { @exargs = @$extrargs; } my $usage_string = xCAT::Usage->parseCommand($command, @exargs); if ($usage_string) { $callback->({ data => [$usage_string] }); $req = {}; return; } ########################################### # find all the service nodes for xCAT cluster # build an individual request for each service node ########################################### my %sv_hash = (); #my @all = xCAT::Utils::getAllSN(); #foreach (@all) { # $sv_hash{$_}=1; #} ########################################### # build each request for each service node ########################################### my @result = (); my $mncopy = {%$req}; push @result, $mncopy; #foreach my $sn (keys (%sv_hash)) { # my $reqcopy = {%$req}; # $reqcopy->{_xcatdest} = $sn; # $reqcopy->{_xcatpreprocessed}->[0] = 1; # push @result, $reqcopy; #} return \@result; } ########################################################################## # Process request from xCat daemon ########################################################################## sub process_request { my $req = shift; my $callback = shift; #unless ($macmap) { $macmap = xCAT::MacMap->new(); } ########################################### # Build hash to pass around ########################################### my %request; $request{arg} = $req->{arg}; $request{callback} = $callback; $request{command} = $req->{command}->[0]; #################################### # Process command-specific options #################################### my $result = parse_args(\%request); #################################### # Return error #################################### if (ref($result) eq 'ARRAY') { send_msg(\%request, 1, @$result); return (1); } ####################################### # Write header for trace ####################################### my $tm = localtime(time); my $msg = "\n-------- $tm\nTime PID"; trace(\%request, $msg); ########################################### # Record begin time ########################################### my $start = Time::HiRes::gettimeofday(); ############################################ ## Fork one process per adapter ############################################ #my $children = 0; #$SIG{CHLD} = sub { # my $rc_bak = $?; # while (waitpid(-1, WNOHANG) > 0) { $children--; } # $? = $rc_bak; #}; #my $fds = new IO::Select; # #foreach ( keys %ip_addr ) { # my $pipe = fork_cmd( $req, $_); # if ( $pipe ) { # $fds->add( $pipe ); # $children++; # } #} ############################################ ## Process slp responses from children ############################################ #while ( $children > 0 ) { # child_response( $callback, $fds ); #} #while (child_response($callback,$fds)) {} my ($searchmacsref, $sendcount, $rspc) = invoke_dodiscover(\%request); if ($globalopt{flexdiscover}) { bt_process($req, $callback, $searchmacsref); return (SUCCESS); } ########################################### # Record ending time ########################################### my $elapsed = Time::HiRes::gettimeofday() - $start; my $msg2 = sprintf("Total SLP Time: %.3f sec\n", $elapsed); trace(\%request, $msg2); ########################################### # Combined responses from all children ########################################### my $num = keys %$searchmacsref; my $min; if ($num < 500) { $min = "0-1"; } elsif (500 < $num and $num < 1000) { $min = "1-2"; } else { $min = "more than 2"; } #my $start1 = Time::HiRes::gettimeofday(); send_msg(\%request, 0, "$sendcount requests with $rspc responses. Now processing responses. This will take $min minutes...") unless ($globalopt{x} or $globalopt{z}); format_output(\%request, $searchmacsref); #my $elapsed1 = Time::HiRes::gettimeofday() - $start1; #send_msg( \%request, 0, "$num nodes takes $elapsed1"); return (SUCCESS); } ########################################################################## # Filter nodes the user specified ########################################################################## sub filter { my $oldhash = shift; my $newhash; # find HMC/CEC/Frame that the user want to find foreach my $n (@filternodes) { for my $foundnode (keys %$oldhash) { if (${ $oldhash->{$foundnode} }{hostname} =~ /^(\w+)\(.*\)/) { if ($1 eq $n) { $newhash->{$foundnode} = $oldhash->{$foundnode}; if (${ $oldhash->{$foundnode} }{type} eq TYPE_CEC or ${ $oldhash->{$foundnode} }{type} eq TYPE_FRAME) { my @ips = split /,/, ${ $oldhash->{$foundnode} }{children}; for (my $i = 0 ; $i < scalar(@ips) ; $i++) { $newhash->{ $ips[$i] } = $oldhash->{ $ips[$i] }; } } } } elsif (${ $oldhash->{$foundnode} }{hostname} eq $n) { $newhash->{$foundnode} = $oldhash->{$foundnode}; if (${ $oldhash->{$foundnode} }{type} eq TYPE_CEC or ${ $oldhash->{$foundnode} }{type} eq TYPE_FRAME) { my @ips = split /,/, ${ $oldhash->{$foundnode} }{children}; for (my $i = 0 ; $i < scalar(@ips) ; $i++) { $newhash->{ $ips[$i] } = $oldhash->{ $ips[$i] }; } } } } } return $newhash; } ########################################################################## # Filter nodes not in the user specified vlan ########################################################################## sub filtersamevlan { my $oldhash = shift; my $newhash; my $nets = xCAT::NetworkUtils::my_nets(); my $validnets; for my $net (keys %$nets) { for my $nic (split /,/, $globalopt{i}) { if ($nets->{$net} eq $nic) { $validnets->{$net} = $nic; } } } foreach my $name (keys %$oldhash) { if (${ $oldhash->{$name} }{type} =~ /^(fsp|bpa)$/) { my $ip = ${ $oldhash->{$name} }{ip}; for my $net (keys %$validnets) { my ($n, $m) = split /\//, $net; if (xCAT::NetworkUtils::isInSameSubnet($n, $ip, $m, 1)) { #and xCAT::NetworkUtils::isPingable( $ip)) { $newhash->{$name} = $oldhash->{$name}; } } } else { $newhash->{$name} = $oldhash->{$name}; } } return $newhash; } ########################################################################## # This is the function that merged in from slpdiscover ########################################################################## sub bt_process { my $request = shift; my $callback = shift; my $searef = shift; my $mpatab = xCAT::Table->new("mpa", -create => 0); my @mpaentries; $mpahash = {}; if (ref $request->{environment} and ref $request->{environment}->[0]->{XCAT_CURRENTPASS}) { $currentbladepass = $request->{environment}->[0]->{XCAT_CURRENTPASS}->[0]; } else { $currentbladepass = "PASSW0RD"; } if (ref $request->{environment} and ref $request->{environment}->[0]->{XCAT_CURRENTUSER}) { $currentbladeuser = $request->{environment}->[0]->{XCAT_CURRENTUSER}->[0]; } else { $currentbladeuser = "USERID"; } if ($mpatab) { @mpaentries = $mpatab->getAllNodeAttribs([qw/mpa username password/]); foreach (@mpaentries) { $mpahash->{ $_->{mpa} } = $_; } } my $passwdtab = xCAT::Table->new("passwd", -create => 0); $defaultbladeuser = "USERID"; $defaultbladepass = ""; if ($passwdtab) { my @ents = $passwdtab->getAttribs({ key => 'blade' }, 'username', 'password'); foreach (@ents) { if ($_->{username} eq "HMC") { next; } if ($_->{username}) { $defaultbladeuser = $_->{username}; } if ($_->{password}) { $defaultbladepass = $_->{password}; } } } my $mactab = xCAT::Table->new("mac"); my %machash; my %node2machash; my %macuphash; my @maclist = $mactab->getAllNodeAttribs([qw/node mac/]); foreach (@maclist) { $machash{ $_->{node} } = $_->{mac}; $node2machash{ $_->{mac} } = $_->{node}; } my $mptab = xCAT::Table->new('mp'); my $nodecandidates; if ($mptab) { my @mpents = $mptab->getAllNodeAttribs([ 'node', 'mpa', 'id' ]); foreach (@mpents) { $nodebymp{ $_->{mpa} }->{ $_->{id} } = $_->{node}; } } $macmap = xCAT::MacMap->new(); $macmap->refresh_table(); my @toconfig; foreach my $mac (keys(%btresult)) { my $node = $macmap->find_mac($mac, 1); unless ($node) { if (defined $node2machash{$mac}) { $node = $node2machash{$mac}; } else { next; } } my $data = $btresult{$mac}; $data->{nodename} = $node; $data->{macaddress} = $mac; $chassisbyuuid{ $data->{attributes}->{"enclosure-uuid"}->[0] } = $node; push @toconfig, $data; } foreach my $data (@toconfig) { my $mac = $data->{macaddress}; my $nodename = $data->{nodename}; my $addr = $data->{peername}; #todo, use sockaddr and remove the 427 port from it instead? if ($addr =~ /^fe80/) { #Link local address requires scope index $addr .= "%" . $data->{scopeid}; } $flexchassisuuid{$nodename} = $data->{attributes}->{"enclosure-uuid"}->[0]; if ($data->{SrvType} eq "service:management-hardware.IBM:chassis-management-module") { sendmsg(":Found " . $data->{SrvType} . " at address $addr", $callback, $nodename); setup_cmm_pass($nodename); if ($machash{$nodename} =~ /$mac/i) { #ignore prospects already known to mac table configure_hosted_elements($nodename, $callback); next; } unless (do_blade_setup($data, $callback, curraddr => $addr)) { next; } configure_hosted_elements($nodename, $callback); unless (do_blade_setup($data, $callback, curraddr => $addr, pass2 => 1)) { next; } sendmsg(":Configuration complete, configuration may take a few minutes to take effect", $callback, $nodename); $macuphash{$nodename} = { mac => $mac }; } } $mactab->setNodesAttribs(\%macuphash); } sub configure_hosted_elements { my $cmm = shift; my $callback = shift; my $uuid = $flexchassisuuid{$cmm}; my $node; my $immdata; my $slot; my $user = $passwordmap{$cmm}->{username}; my $pass = $passwordmap{$cmm}->{password}; foreach $immdata (values %{ $flexchassismap{$uuid} }) { $slot = $immdata->{attributes}->{slot}->[0]; if (defined $immdata->{attributes}->{'chassis-sub-slot'}) { $slot .= ":" . $immdata->{attributes}->{'chassis-sub-slot'}->[0]; } if ($node = $nodebymp{$cmm}->{$slot}) { my $addr = $immdata->{peername}; #todo, use sockaddr and remove the 427 port from it instead? if ($addr =~ /^fe80/) { #Link local address requires scope index $addr .= "%" . $immdata->{scopeid}; } if ($doneaddrs{$node}) { next; } $doneaddrs{$node} = 1; xCAT::IMMUtils::setupIMM($node, nodedata => $immdata, curraddr => $addr, cliusername => $user, clipassword => $pass, callback => $callback); } else { sendmsg(": Ignoring target in bay $slot, no node found with mp.mpa/mp.id matching", $callback, $cmm); } } while (wait() > 0) { } } sub setup_cmm_pass { my $nodename = shift; my $localuser = $defaultbladeuser; my $localpass = $defaultbladepass; if ($mpahash->{$nodename}) { if ($mpahash->{$nodename}->{username}) { $localuser = $mpahash->{$nodename}->{username}; } if ($mpahash->{$nodename}->{password}) { $localpass = $mpahash->{$nodename}->{password}; } } $passwordmap{$nodename}->{username} = $localuser; $passwordmap{$nodename}->{password} = $localpass; } sub do_blade_setup { my $data = shift; my $callback = shift; my %args = @_; my $addr = $args{curraddr}; my $nodename = $data->{nodename}; my $localuser = $passwordmap{$nodename}->{username}; my $localpass = $passwordmap{$nodename}->{password}; if (not $localpass or $localpass eq "PASSW0RD") { sendmsg([ 1, ":Password for blade must be specified in either mpa or passwd tables, and it must not be PASSW0RD" ], $callback, $nodename); return 0; } require xCAT_plugin::blade; my @cmds; my %exargs; if ($args{pass2}) { @cmds = qw/initnetwork=*/; %exargs = (nokeycheck => 1); #still not at the 'right' ip, so the known hosts shouldn't be bothered } else { @cmds = qw/snmpcfg=enable sshcfg=enable textid=*/; # initnetwork=*/; defer initnetwork until after chassis members have been configured %exargs = (curruser => $currentbladeuser, currpass => $currentbladepass); } my $result; $@ = ""; my $rc = eval { $result = xCAT_plugin::blade::clicmds( $nodename, $localuser, $localpass, $nodename, 0, curraddr => $addr, %exargs, cmds => \@cmds); 1; }; my $errmsg = $@; if ($errmsg) { if ($errmsg =~ /Incorrect Password/) { sendmsg([ 1, "Failed to set up Management module due to Incorrect Password (You may try the environment variables XCAT_CURRENTUSER and/or XCAT_CURRENTPASS to try a different value)" ], $callback, $nodename); } else { sendmsg([ 1, "Failed to set up Management module due to $errmsg" ], $callback, $nodename); } return 0; } if ($result) { if ($result->[0]) { if ($result->[2] =~ /Incorrect Password/) { sendmsg([ 1, "Failed to set up Management module due to Incorrect Password (You may try the environment variables XCAT_CURRENTUSER and/or XCAT_CURRENTPASS to try a different value)" ], $callback, $nodename); return 0; } my $errors = $result->[2]; if (ref $errors) { foreach my $error (@$errors) { sendmsg([ $result->[0], $error ], $callback, $nodename); } } else { sendmsg([ $result->[0], $result->[2] ], $callback, $nodename); } return 0; } } return $rc; } sub bt_handle_new_slp_entity { my $data = shift; delete $data->{sockaddr}; #won't need it my $mac = xCAT::SLP::get_mac_for_addr($data->{peername}); if ($data->{SrvType} eq "service:management-hardware.IBM:integrated-management-module2" and $data->{attributes}->{"enclosure-form-factor"}->[0] eq "BC2") { $data->{macaddress} = $mac; #this is a Flex ITE, don't go mac searching for it, but remember the chassis UUID for later if ($flexchassismap{ $data->{attributes}->{"chassis-uuid"}->[0] }->{$mac} and $data->{peername} !~ /fe80/) { return; } $flexchassismap{ $data->{attributes}->{"chassis-uuid"}->[0] }->{$mac} = $data; return; } unless ($mac) { return; } $btresult{$mac} = $data; } 1;