mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-10-31 11:22:27 +00:00 
			
		
		
		
	Merge pull request #1220 from zet809/switch_probe
add command switchprobe to retrieve information from switches and/or …
This commit is contained in:
		| @@ -236,6 +236,109 @@ sub scan_qbridge_vlans { | ||||
| #TODO: try to scan | ||||
|     } | ||||
| } | ||||
|  | ||||
| #-------------------------------------------------------------------------------- | ||||
|  | ||||
| =head3   dump_mac_info | ||||
|     Descriptions: | ||||
|         Retrieve information (switchport and the mac addresses got for that port) for the specified switch or all switches if no specified. | ||||
|     Arguments: | ||||
|         $req: the xcat request hash  | ||||
|         $callback: the function to output information | ||||
|     Returns: | ||||
|         The hash variable store retrieved inforamtions | ||||
|     Usage example: | ||||
|         my $macmap = xCAT::MacMap->new(); | ||||
|         my $switch_data = $macmap->dump_mac_info($req, $callback); | ||||
|         foreach my $switch (keys %$switch_data) {...} | ||||
| =cut | ||||
|  | ||||
| #-------------------------------------------------------------------------------- | ||||
|  | ||||
| sub dump_mac_info { | ||||
|     my $self = shift; | ||||
|     my $req = shift; | ||||
|     my $callback = shift; | ||||
|     my $noderange = undef; | ||||
|     if (defined($req->{node})) { | ||||
|         $noderange = $req->{node}; | ||||
|     } | ||||
|     my %ret = (); | ||||
|     $self->{collect_mac_info} = 1; | ||||
|     if (defined($req->{opt}->{verbose})) { | ||||
|         $self->{show_verbose_info} = 1; | ||||
|         $self->{callback} = $callback; | ||||
|     } | ||||
|     my $community = "public"; | ||||
|     my $dump_all_switches = 0; | ||||
|     my %switches_to_dump = (); | ||||
|     if (!defined($noderange)) { | ||||
|         $dump_all_switches = 1; | ||||
|     } | ||||
|     else { | ||||
|         foreach (@$noderange) { | ||||
|             $switches_to_dump{$_} = 1; | ||||
|         } | ||||
|     } | ||||
|     my $switchestab = xCAT::Table->new('switches', -create=>0); | ||||
|     my @switchesents = $switchestab->getAllNodeAttribs([qw(switch snmpversion username password privacy auth)]); | ||||
|     $self->fill_switchparms(community=>$community,switchesents=>\@switchesents); | ||||
|     my $switchtab = xCAT::Table->new('switch', -create=>0); | ||||
|     my @entries = (); | ||||
|     if ($switchtab) { | ||||
|         @entries = $switchtab->getAllNodeAttribs(['node','switch','port']); | ||||
|     } | ||||
|     #Build hash of switch port names per switch | ||||
|     $self->{switches} = {}; | ||||
|     foreach my $entry (@entries) { | ||||
|         if (defined($entry->{switch}) and $entry->{switch} ne "" and defined($entry->{port}) and $entry->{port} ne "") { | ||||
|     	    if ( !$self->{switches}->{$entry->{switch}}->{$entry->{port}}) { | ||||
|                 $self->{switches}->{$entry->{switch}}->{$entry->{port}} = $entry->{node}; | ||||
|             } | ||||
|             else { | ||||
|                 $self->{switches}->{$entry->{switch}}->{$entry->{port}} .= ",$entry->{node}"; | ||||
|             } | ||||
|         }  | ||||
|         else { | ||||
|             xCAT::MsgUtils->message("S","xCAT Table error:".$entry->{node}."Has missing or invalid switch.switch and/or switch.port fields"); | ||||
|         } | ||||
|     } | ||||
|     foreach my $switch (keys $self->{switchparmhash}) { | ||||
|         if ($dump_all_switches or defined($switches_to_dump{$switch})) { | ||||
|             if ($self->{show_verbose_info}) { | ||||
|                 xCAT::MsgUtils->message("I",{data=>["<INFO>$switch: Start to get information"]}, $self->{callback}); | ||||
|             } | ||||
|             $self->refresh_switch(undef,$community,$switch); | ||||
|             if ($self->{show_verbose_info}) { | ||||
|                 xCAT::MsgUtils->message("I",{data=>["<INFO>$switch: Finish to get information"]}, $self->{callback}); | ||||
|             } | ||||
|             if (!defined($self->{macinfo}->{$switch})) {  | ||||
|                 $ret{$switch}->{ErrorStr} = "No information get"; | ||||
|                 foreach my $defportname (keys %{$self->{switches}->{$switch}}) { | ||||
|                     $ret{$switch}->{$defportname}->{Node} = $self->{switches}->{$switch}->{$defportname}; | ||||
|                 } | ||||
|             }    | ||||
|             elsif (defined($self->{macinfo}->{$switch}->{ErrorStr})) { | ||||
|                     $ret{$switch}->{ErrorStr} = $self->{macinfo}->{$switch}->{ErrorStr}; | ||||
|                     # To show the error message that the username/password related error is for SNMP only | ||||
|                     if ($ret{$switch}->{ErrorStr} =~ /username|password/i) { | ||||
|                         $ret{$switch}->{ErrorStr} .= " through SNMP"; | ||||
|                     } | ||||
|             } else { | ||||
|                 foreach my $snmpportname (keys %{$self->{macinfo}->{$switch}}) { | ||||
|                     foreach my $defportname (keys %{$self->{switches}->{$switch}}) { | ||||
|                         if (namesmatch($defportname, $snmpportname)) { | ||||
|                             $ret{$switch}->{$snmpportname}->{Node} = $self->{switches}->{$switch}->{$defportname}; | ||||
|                         } | ||||
|                     } | ||||
|                     @{$ret{$switch}->{$snmpportname}->{MACaddress}} = @{$self->{macinfo}->{$switch}->{$snmpportname}}; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     return \%ret; | ||||
| } | ||||
|  | ||||
| sub find_mac { | ||||
| # This function is given a mac address, checks for given mac address | ||||
| # and returns undef if unable to find the node, and the nodename otherwise | ||||
| @@ -410,6 +513,15 @@ sub walkoid { | ||||
|   my $oid = shift; | ||||
|   my %namedargs = @_; | ||||
|   my $retmap = undef;  | ||||
|   my $switch = undef; | ||||
|   my $callback = undef; | ||||
|   if (defined($namedargs{verbose})) { | ||||
|       $switch = $namedargs{switch}; | ||||
|       $callback = $namedargs{callback}; | ||||
|   } | ||||
|   if ($switch) { | ||||
|       xCAT::MsgUtils->message("I",{data=>["<INFO>$switch: SNMP Session query OID:\"$oid\""]}, $callback); | ||||
|   } | ||||
|   my $varbind = new SNMP::Varbind([$oid,'']); | ||||
|   $session->getnext($varbind); | ||||
|   if ($session->{ErrorStr}) { | ||||
| @@ -420,19 +532,28 @@ sub walkoid { | ||||
|             xCAT::MsgUtils->message("S","Error communicating with ".$session->{DestHost}.": ".$session->{ErrorStr}); | ||||
|         } | ||||
|     } | ||||
|     if ($switch) { | ||||
|         xCAT::MsgUtils->message("I",{data=>["<ERROR>$switch: SNMP Session query OID:\"$oid\" Failed"]}, $callback); | ||||
|     } | ||||
|     return undef; | ||||
|   } | ||||
|   my $count=0; | ||||
|   my $data_string; | ||||
|   while ($varbind->[0] =~ /^$oid\.?(.*)/) { | ||||
|     $count++; | ||||
|     if ($1) {  | ||||
|       $retmap->{$1.".".$varbind->[1]}=$varbind->[2]; #If $1 is set, means key should  | ||||
|       $data_string .= "\t\t '".$1.".".$varbind->[1]."' => '$varbind->[2]'\n"; | ||||
|     } else { | ||||
|       $retmap->{$varbind->[1]}=$varbind->[2]; #If $1 is set, means key should  | ||||
|       $data_string .= "\t\t '$varbind->[1]' => '$varbind->[2]'\n"; | ||||
|     } | ||||
|  | ||||
|     $session->getnext($varbind); | ||||
|   } | ||||
|   if ($switch) { | ||||
|       chomp ($data_string); | ||||
|       xCAT::MsgUtils->message("I",{data=>["<INFO>$switch: SNMP Session get data for OID:\"$oid\":\n$data_string"]}, $callback); | ||||
|   } | ||||
|   return $retmap; | ||||
| } | ||||
|  | ||||
| @@ -460,6 +581,10 @@ sub getsnmpsession { | ||||
|                       Community => $community, | ||||
|                       UseNumeric => 1 | ||||
|                  ); | ||||
|       if ($self->{show_verbose_info}) { | ||||
|           xCAT::MsgUtils->message("I",{data=>["<INFO>$switch: Generate SNMP session with parameter: \n\t\t'Version' => '$snmpver'\n\t\t'Community' => '$community'"]}, $self->{callback}); | ||||
|       } | ||||
|  | ||||
|   } else { #we have snmp3 | ||||
|        my %args= ( | ||||
|                       DestHost => $switch, | ||||
| @@ -476,6 +601,15 @@ sub getsnmpsession { | ||||
|           $args{PrivProto} = uc($swent->{privacy}); | ||||
|           $args{PrivPass} = $community; | ||||
|       } | ||||
|       if ($self->{show_verbose_info}) { | ||||
|           my $parameter_string = ''; | ||||
|           foreach (keys %args) { | ||||
|               $parameter_string .= "\t\t'$_' => '$args{$_}'\n"; | ||||
|           } | ||||
|           chomp($parameter_string); | ||||
|           xCAT::MsgUtils->message("I",{data=>["<INFO>$switch: Generate SNMP session with parameter: \n$parameter_string"]}, $self->{callback}); | ||||
|       } | ||||
|  | ||||
|       $session = new SNMP::Session(%args); | ||||
|   } | ||||
|   return $session; | ||||
| @@ -486,11 +620,19 @@ sub refresh_switch { | ||||
|   my $output = shift; | ||||
|   my $community = shift; | ||||
|   my $switch = shift; | ||||
|  | ||||
|   #if ($error) { die $error; } | ||||
|   my $session = $self->getsnmpsession('community'=>$community,'switch'=>$switch); | ||||
|   unless ($session) { xCAT::MsgUtils->message("S","Failed to communicate with $switch"); return; } | ||||
|   my $namemap = walkoid($session,'.1.3.6.1.2.1.31.1.1.1.1'); | ||||
|   unless ($session) {  | ||||
|       xCAT::MsgUtils->message("S","Failed to communicate with $switch");  | ||||
|       if ($self->{collect_mac_info}) { | ||||
|           $self->{macinfo}->{$switch}->{ErrorStr} = "Failed to communicate with $switch through SNMP"; | ||||
|       } | ||||
|       return;  | ||||
|   } | ||||
|   elsif ($session->{ErrorStr} and $self->{collect_mac_info}) { | ||||
|       $self->{macinfo}->{$switch}->{ErrorStr} = $session->{ErrorStr}; | ||||
|   } | ||||
|   my $namemap = walkoid($session,'.1.3.6.1.2.1.31.1.1.1.1', verbose=>$self->{show_verbose_info}, switch=>$switch, callback=>$self->{callback}); | ||||
|     #namemap is the mapping of ifIndex->(human readable name) | ||||
|   if ($namemap) { | ||||
|      my $ifnamesupport=0; #Assume broken ifnamesupport until proven good... (Nortel switch) | ||||
| @@ -505,15 +647,17 @@ sub refresh_switch { | ||||
|      } | ||||
|   } | ||||
|   unless ($namemap) { #Failback to ifDescr.  ifDescr is close, but not perfect on some switches | ||||
|      $namemap = walkoid($session,'.1.3.6.1.2.1.2.2.1.2'); | ||||
|       $namemap = walkoid($session,'.1.3.6.1.2.1.2.2.1.2', verbose=>$self->{show_verbose_info}, switch=>$switch, callback=>$self->{callback}); | ||||
|   } | ||||
|   unless ($namemap) { | ||||
|     if ($session->{ErrorStr} and $self->{collect_mac_info}) { | ||||
|         $self->{macinfo}->{$switch}->{ErrorStr} = $session->{ErrorStr}; | ||||
|     } | ||||
|     return; | ||||
|   } | ||||
|   #Above is valid without community string indexing, on cisco, we need it on the next one and onward | ||||
|   my $iftovlanmap = walkoid($session,'.1.3.6.1.4.1.9.9.68.1.2.2.1.2',silentfail=>1); #use cisco vlan membership mib to ascertain vlan | ||||
|   my $trunktovlanmap = walkoid($session,'.1.3.6.1.4.1.9.9.46.1.6.1.1.5',silentfail=>1); #for trunk ports, we are interested in the native vlan | ||||
|                                                                                         #so we need cisco vtp mib too | ||||
|   my $iftovlanmap = walkoid($session,'.1.3.6.1.4.1.9.9.68.1.2.2.1.2',silentfail=>1,verbose=>$self->{show_verbose_info}, switch=>$switch, callback=>$self->{callback}); #use cisco vlan membership mib to ascertain vlan | ||||
|   my $trunktovlanmap = walkoid($session,'.1.3.6.1.4.1.9.9.46.1.6.1.1.5', silentfail=>1, verbose=>$self->{show_verbose_info}, switch=>$switch, callback=>$self->{callback}); #for trunk ports, we are interested in the native vlan, so we need cisco vtp mib too | ||||
|   my %vlans_to_check; | ||||
|   if (defined($iftovlanmap) or defined($trunktovlanmap)) { #We have a cisco, the intelligent thing is to do SNMP gets on the ports  | ||||
|       $self->{switchinfo}->{$switch}->{vlanidtoindex}="NA";#mark this switch to ignore for qbridge scans | ||||
| @@ -551,22 +695,44 @@ sub refresh_switch { | ||||
|         $session = $self->getsnmpsession('switch'=>$switch,'community'=>$community,'vlanid'=>$vlan); | ||||
|     } | ||||
|     unless ($session) { return; }  | ||||
|     my $bridgetoifmap = walkoid($session,'.1.3.6.1.2.1.17.1.4.1.2',ciscowarn=>$iscisco); # Good for all switches | ||||
|     my $bridgetoifmap = walkoid($session,'.1.3.6.1.2.1.17.1.4.1.2', ciscowarn=>$iscisco, verbose=>$self->{show_verbose_info}, switch=>$switch, callback=>$self->{callback}); # Good for all switches | ||||
|     if (not ref $bridgetoifmap or !keys %{$bridgetoifmap}) {  | ||||
|             xCAT::MsgUtils->message("S","Error communicating with ".$session->{DestHost}.": failed to get a valid response to BRIDGE-MIB request"); | ||||
| 	    return; | ||||
|         xCAT::MsgUtils->message("S","Error communicating with ".$session->{DestHost}.": failed to get a valid response to BRIDGE-MIB request"); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     # my $mactoindexmap = walkoid($session,'.1.3.6.1.2.1.17.4.3.1.2');  | ||||
|     my $mactoindexmap = walkoid($session,'.1.3.6.1.2.1.17.7.1.2.2.1.2',silentfail=>1); | ||||
|     my $mactoindexmap = walkoid($session,'.1.3.6.1.2.1.17.7.1.2.2.1.2',silentfail=>1, verbose=>$self->{show_verbose_info}, switch=>$switch, callback=>$self->{callback}); | ||||
|     unless (defined($mactoindexmap)) { #if no qbridge defined, try bridge mib, probably cisco | ||||
|       #$mactoindexmap = walkoid($session,'.1.3.6.1.2.1.17.7.1.2.2.1.2'); | ||||
|       $mactoindexmap = walkoid($session,'.1.3.6.1.2.1.17.4.3.1.2',ciscowarn=>$iscisco);  | ||||
|       $mactoindexmap = walkoid($session,'.1.3.6.1.2.1.17.4.3.1.2',ciscowarn=>$iscisco, verbose=>$self->{show_verbose_info}, switch=>$switch, callback=>$self->{callback});  | ||||
|     } #Ok, time to process the data | ||||
|     if (not ref $mactoindexmap or !keys %{$mactoindexmap}) {  | ||||
|             xCAT::MsgUtils->message("S","Error communicating with ".$session->{DestHost}.": Unable to get MAC entries via either BRIDGE or Q-BRIDE MIB"); | ||||
| 	   return; | ||||
|     } | ||||
|     if (defined($self->{collect_mac_info})) { | ||||
|         my %index_to_mac = (); | ||||
|         foreach (keys %$mactoindexmap) { | ||||
|             my $index = $mactoindexmap->{$_}; | ||||
|             my @tmp = split /\./, $_; | ||||
|             my @mac = @tmp[-6 .. -1]; | ||||
|             my $macstring=sprintf("%02x:%02x:%02x:%02x:%02x:%02x",@mac); | ||||
|             push @{$index_to_mac{$index}}, $macstring; | ||||
|         } | ||||
|         foreach my $boid (keys %$bridgetoifmap) { | ||||
|             my $port_index = $boid; | ||||
|             my $port_name = $namemap->{$bridgetoifmap->{$port_index}}; | ||||
|             if (defined($index_to_mac{$port_index})) { | ||||
|                 push @{$self->{macinfo}->{$switch}->{$port_name}}, @{$index_to_mac{$port_index}}; | ||||
|             } | ||||
|             else { | ||||
|                 $self->{macinfo}->{$switch}->{$port_name}->[0] = ''; | ||||
|             } | ||||
|         } | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     foreach my $oid (keys %$namemap) { | ||||
|     #$oid =~ m/1.3.6.1.2.1.31.1.1.1.1.(.*)/; | ||||
|       my $ifindex = $oid; | ||||
|   | ||||
| @@ -304,6 +304,8 @@ my %usage = ( | ||||
|     "switchdiscover" => | ||||
| "Usage: switchdiscover [-h|--help|-v|--version] | ||||
|        switchdiscover [<noderange>|--range ipranges] [-s scan_methods] [-r|-x|-z] [-w] [-V|--verbose]", | ||||
|     "switchprobe" =>  | ||||
| "Usage: switchprobe [<noderange>] [-V|--verbose | -c|--check]", | ||||
|     "makentp" => | ||||
| "Usage: makentp [-h|--help|-v|--version] | ||||
|        makentp [-a|--all] [-V|--verbose]", | ||||
|   | ||||
| @@ -23,6 +23,7 @@ sub handled_commands { | ||||
|     return { | ||||
| 	findme => 'switch', | ||||
| 	findmac => 'switch', | ||||
|         switchprobe => 'switch', | ||||
| 	rspconfig => 'nodehm:mgt', | ||||
|     }; | ||||
| } | ||||
| @@ -36,13 +37,13 @@ sub preprocess_request { | ||||
|  | ||||
|   my $noderange = $request->{node};  | ||||
|   my $command = $request->{command}->[0]; | ||||
|   my $extrargs = $request->{arg}; | ||||
|   my @exargs=($request->{arg}); | ||||
|   if (ref($extrargs)) { | ||||
|     @exargs=@$extrargs; | ||||
|   } | ||||
|  | ||||
|   if ($command eq "rspconfig") { | ||||
|       my $extrargs = $request->{arg}; | ||||
|       my @exargs=($request->{arg}); | ||||
|       if (ref($extrargs)) { | ||||
|           @exargs=@$extrargs; | ||||
|       } | ||||
|       my $usage_string=xCAT::Usage->parseCommand($command, @exargs); | ||||
|       if ($usage_string) { | ||||
| 	  $callback->({data=>$usage_string}); | ||||
| @@ -100,6 +101,90 @@ sub preprocess_request { | ||||
|       } | ||||
|       return \@requests;   | ||||
|   } | ||||
|   elsif ($command eq 'switchprobe') { | ||||
|       @ARGV = (); | ||||
|       if (ref($request->{arg})) { | ||||
|           @ARGV = @{$request->{arg}}; | ||||
|       } | ||||
|       use Getopt::Long; | ||||
|       $Getopt::Long::ignorecase = 0; | ||||
|       Getopt::Long::Configure( "bundling" ); | ||||
|       my $verbose = undef; | ||||
|       my $check = undef; | ||||
|       my $help = undef; | ||||
|       unless (GetOptions('h|help' => \$help, 'V|verbose' => \$verbose, 'c|check'  => \$check)) { | ||||
|           $callback->({error=>["Parse args failed"], errorcode=>1}); | ||||
|           return; | ||||
|       } | ||||
|       if (@ARGV) { | ||||
|           $callback->({error=>["Option @ARGV not supported.\n".xCAT::Usage->getUsage($command)], errorcode=>1}); | ||||
|           return; | ||||
|       } | ||||
|       if (defined($help)) { | ||||
|           $callback->({data=>xCAT::Usage->getUsage($command)}); | ||||
|           return;  | ||||
|       } | ||||
|       if (defined($verbose)) { | ||||
|           $request->{opt}->{verbose} = $verbose; | ||||
|       } | ||||
|       if (defined($check)) { | ||||
|           $request->{opt}->{check} = $check; | ||||
|       } | ||||
|       if (defined($noderange)) { | ||||
|           my $nthash = undef; | ||||
|           my $swhash = undef; | ||||
|           my $nodetypetab=xCAT::Table->new('nodetype',-create=>0); | ||||
|           if ($nodetypetab) { | ||||
|               $nthash = $nodetypetab->getNodesAttribs($noderange, ['nodetype']); | ||||
|               if (!defined($nthash)) { | ||||
|                   $callback->({error=>["Get attributes from table 'nodetype' failed"],errorcode=>1}); | ||||
|                   return; | ||||
|               } | ||||
|           }  | ||||
|           else { | ||||
|               $callback->({error=>["Open table 'nodetype' failed"],errorcode=>1}); | ||||
|               return; | ||||
|           } | ||||
|           my $switchestab  = xCAT::Table->new('switches', -create=>0); | ||||
|           if ($switchestab) { | ||||
|               $swhash = $switchestab->getNodesAttribs($noderange, ['switch']); | ||||
|               if (!defined($swhash)) { | ||||
|                    $callback->({error=>["Get attributes from table 'switches' failed"],errorcode=>1}); | ||||
|                    return; | ||||
|               } | ||||
|           } | ||||
|           else { | ||||
|               $callback->({error=>["Open table 'switches' failed"],errorcode=>1}); | ||||
|               return; | ||||
|  | ||||
|           } | ||||
|           my @switchnode = (); | ||||
|           my @errswnode = (); | ||||
|           my @errornode = (); | ||||
|           foreach my $node (@$noderange) { | ||||
|               if (!defined($nthash->{$node}) or $nthash->{$node}->[0]->{nodetype} ne 'switch') { | ||||
|                   push @errornode, $node; | ||||
|               } | ||||
|               elsif (!defined($swhash->{$node})) { | ||||
|                   push @errswnode, $node; | ||||
|               } | ||||
|               else { | ||||
|                   push @switchnode, $node; | ||||
|               } | ||||
|           } | ||||
|           if (@errornode) { | ||||
|               $callback->({error=>["The nodetype is not 'switch' for nodes: ". join(",",@errornode)],errorcode=>1}); | ||||
|           } | ||||
|           if (@errswnode) { | ||||
|               $callback->({error=>["No switch configuration info find for ". join(",",@errswnode)],errorcode=>1}); | ||||
|           } | ||||
|           if (@switchnode) { | ||||
|               @{$request->{node}} = @switchnode; | ||||
|               return [$request]; | ||||
|           } | ||||
|           return; | ||||
|       } | ||||
|   } | ||||
|   return [$request]; | ||||
| } | ||||
|  | ||||
| @@ -119,6 +204,69 @@ sub process_request { | ||||
| 	return; | ||||
|     }  elsif ($req->{command}->[0] eq 'rspconfig') { | ||||
| 	return process_switch_config($req, $cb, $doreq); | ||||
|     } elsif ($req->{command}->[0] eq 'switchprobe') { | ||||
|         my $macinfo = $macmap->dump_mac_info($req, $cb); | ||||
|         if ($macinfo and ref($macinfo) eq 'HASH') { | ||||
|             my $switch_name_length = 0; | ||||
|             my $port_name_length = 0; | ||||
|             foreach my $switch (keys %$macinfo) { | ||||
|                 if (length($switch) > $switch_name_length) { | ||||
|                     $switch_name_length = length($switch); | ||||
|                 } | ||||
|                 if (defined($macinfo->{$switch}->{ErrorStr})) { | ||||
|                     next; | ||||
|                 } | ||||
|                 foreach my $portname (keys %{$macinfo->{$switch}}) { | ||||
|                     if (length($portname) > $port_name_length) { | ||||
|                         $port_name_length = length($portname); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             my $format = "%-".$switch_name_length."s  %-".$port_name_length."s  %-18s  %s"; | ||||
|             my %failed_switches = (); | ||||
|             my $header = sprintf($format, "Switch", "Port", "MAC address", "Node"); | ||||
|             if (!defined($req->{opt}->{check}) and $port_name_length) { | ||||
|                 $cb->({data=>$header}); | ||||
|                 $cb->({data=>"------------------------------------------------------------------"}) | ||||
|             }; | ||||
|             foreach my $switch (keys %$macinfo) { | ||||
|                 if (defined($macinfo->{$switch}->{ErrorStr})) { | ||||
|                     if (defined($req->{opt}->{check})) { | ||||
|                         $cb->({node=>[{name=>$switch, error=>[$macinfo->{$switch}->{ErrorStr}], errorcode=>1}]}); | ||||
|                     } | ||||
|                     else { | ||||
|                         $failed_switches{$switch} = "$macinfo->{$switch}->{ErrorStr}"; | ||||
|                     } | ||||
|                     next; | ||||
|                 } | ||||
|                 elsif (defined($req->{opt}->{check})) { | ||||
|                     $cb->({node=>[{name=>$switch, data=>["PASS"]}]}); | ||||
|                     next; | ||||
|                 } | ||||
|                 foreach my $port (sort keys %{$macinfo->{$switch}}) { | ||||
|                     my $node = ''; | ||||
|                     if (defined($macinfo->{$switch}->{$port}->{Node})) { | ||||
|                         $node = $macinfo->{$switch}->{$port}->{Node}; | ||||
|                     } | ||||
|                     my @macarrary = (); | ||||
|                     if (defined($macinfo->{$switch}->{$port}->{MACaddress})) { | ||||
|                         @macarray = @{$macinfo->{$switch}->{$port}->{MACaddress}}; | ||||
|                         foreach (@macarray) { | ||||
|                             my $data = sprintf($format, $switch, $port, ($_ ne '') ? $_ : '       N/A', $node); | ||||
|                             $cb->({data=>$data}); | ||||
|                             #$cb->({node=>[{name=>$switch,data=>$data}]}); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             if (!defined($req->{opt}->{check}) and $port_name_length) { | ||||
|                 $cb->({data=>"------------------------------------------------------------------"}) | ||||
|             } | ||||
|             foreach (keys %failed_switches) { | ||||
|                 $cb->({node=>[{name=>$_, error=>[$failed_switches{$_}], errorcode=>1}]}); | ||||
|             } | ||||
|         } | ||||
|         return; | ||||
|     } elsif ($req->{command}->[0] eq 'findme') { | ||||
| 	my $ip = $req->{'_xcat_clientip'}; | ||||
| 	if (defined $req->{nodetype} and $req->{nodetype}->[0] eq 'virtual') { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user