-Some fixups and 'scaffolding' for qbridge mib queries and manipulation
git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@7739 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
		| @@ -1,6 +1,7 @@ | ||||
| #!/usr/bin/perl | ||||
| # IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html | ||||
| package xCAT::MacMap; | ||||
| use strict; | ||||
| use xCAT::Table; | ||||
| use xCAT::Utils; | ||||
| use xCAT::MsgUtils; | ||||
| @@ -8,6 +9,7 @@ use IO::Select; | ||||
| use IO::Handle; | ||||
| use Sys::Syslog; | ||||
| use Data::Dumper; | ||||
| use POSIX qw/WNOHANG/; | ||||
| use SNMP; | ||||
| my %cisco_vlans; #Special hash structure to reflect discovered VLANS on Cisco equip | ||||
| #use IF-MIB (1.3.6.1.2.1.2) for all switches | ||||
| @@ -111,8 +113,61 @@ sub rvlan { | ||||
|     #QBridge also has dot1qPvid, but wasn't writable in Brocade.. it is readable though, so can guide the read, mask out, mask in activity above | ||||
|     #argument specification: | ||||
|     #  nodes => [ list reference of nodes to query/set ] | ||||
|     #  operation => "pvid=<vid>" for now, addvlan= and delvlan= for tagged vlans, 'pvid' without = checks current value | ||||
|     my %args = %_; | ||||
|     #  operation => "pvid=<vid> or vlan=<vid>" for now, addvlan= and delvlan= for tagged vlans, 'pvid', vlan, or stat without = checks current value | ||||
|     my $self=shift; | ||||
|     my $community = "public"; | ||||
|     $self->{sitetab} = xCAT::Table->new('site'); | ||||
|     my $tmp = $self->{sitetab}->getAttribs({key=>'snmpc'},'value'); | ||||
|     if ($tmp and $tmp->{value}) { $community = $tmp->{value} } | ||||
|     my %args = @_; | ||||
|     my $op=$args{operation}; | ||||
|     my $nodes=$args{nodes}; | ||||
|     #first order of business is to identify the target switches | ||||
|     my $switchtab=xCAT::Table->new('switch',-create=>0); | ||||
|     unless ($switchtab) { return; } | ||||
|     my $switchents = $switchtab->getNodesAttribs($nodes,[qw/switch port/]); | ||||
|     my $node; | ||||
|     foreach $node (keys %$switchents) { | ||||
|         my $entry; | ||||
|         foreach $entry (@{$switchents->{$node}}) { | ||||
|             $self->{switches}->{$entry->{switch}}->{$entry->{port}} = $node; | ||||
|         } | ||||
|     }  | ||||
|     my $switches=[keys %{$self->{switches}}]; | ||||
|     my $switchestab=xCAT::Table->new('switches',-create=>0); | ||||
|     my @switchesents; | ||||
|     if ($switchestab) { | ||||
|         foreach (values %{$switchestab->getNodesAttribs($switches,[qw(switch snmpversion username password privacy auth)])}) { | ||||
|             push @switchesents,@$_; | ||||
|         } | ||||
|     } | ||||
|     $self->fill_switchparms(community=>$community,switchesents=>\@switchesents); | ||||
|     my $switch; | ||||
|     foreach $switch (keys %{$self->{switches}}) { #first we'll extract the lay of the land... | ||||
|           $self->refresh_switch(undef,$community,$switch); | ||||
|           unless ($self->{switchinfo}->{$switch}->{vlanidtoindex}) { #need vlan id to vlanindex map for qbridge unless cisco | ||||
|             $self->scan_qbridge_vlans(switch=>$switch,community=>$community); | ||||
|           } | ||||
|     } | ||||
|     #print Dumper($self->{switchinfo}); | ||||
|        #   $self->{switchinfo}->{$switch}->{bridgeidxtoifname}->{$boid}=$portname; | ||||
|        #   $self->{switchinfo}->{$switch}->{ifnametobridgeidx}->{$portname}=$boid; | ||||
|     $op =~ s/stat/pvid/; | ||||
|     $op =~ s/vlan/pvid/; | ||||
|     if ($op =~ /^addpvid/) { # add tagged vlan | ||||
|     } elsif ($op =~ /delpvid/) { #remove tagged vlan | ||||
|     } else { #native vlan query or set | ||||
|     } | ||||
| } | ||||
| sub scan_qbridge_vlans { | ||||
|     my $self = shift; | ||||
|     my %args = @_; | ||||
|     my $switch = $args{switch}; | ||||
|     my $session = $self->{switchsessions}->{$switch}; | ||||
|     $self->{switchinfo}->{vlanindextoid} = walkoid($session,'.1.3.6.1.2.1.17.7.1.4.2.1.3'); | ||||
|     foreach (keys %{$self->{switchinfo}->{vlanindextoid}}) { | ||||
| #TODO: try to scan | ||||
|     } | ||||
| } | ||||
| sub find_mac { | ||||
| # This function is given a mac address, checks for given mac address | ||||
| @@ -148,6 +203,33 @@ sub find_mac { | ||||
|   return undef; | ||||
| } | ||||
|  | ||||
| sub fill_switchparms { | ||||
|   my $self = shift; | ||||
|   my %args = @_; | ||||
|   my $community=$args{community}; | ||||
|   $self->{switchparmhash}={}; | ||||
|   my @switchentries = @{$args{switchesents}}; | ||||
|   foreach (@switchentries) { | ||||
|      my $curswitch=$_->{switch}; | ||||
|      $self->{switchparmhash}->{$curswitch}=$_; | ||||
|      if ($_->{snmpversion}) { | ||||
|           if ($_->{snmpversion} =~ /3/) { #clean up to accept things like v3 or ver3 or 3, whatever. | ||||
|               $self->{switchparmhash}->{$curswitch}->{snmpversion}=3; | ||||
|               unless ($_->{auth}) { | ||||
|                 $self->{switchparmhash}->{$curswitch}->{auth}='md5'; #Default to md5 auth if not specified but using v3 | ||||
|               } | ||||
|           } elsif ($_->{snmpversion} =~ /2/) { | ||||
|               $self->{switchparmhash}->{$curswitch}->{snmpversion}=2; | ||||
|           } else { | ||||
|               $self->{switchparmhash}->{$curswitch}->{snmpversion}=1; #Default to lowest common denominator, snmpv1 | ||||
|           } | ||||
|      } | ||||
|      unless (defined $_->{password}) { #if no password set, inherit the community | ||||
|          $self->{switchparmhash}->{$curswitch}->{password}=$community; | ||||
|      } | ||||
|   } | ||||
| } | ||||
|  | ||||
| sub refresh_table { | ||||
|   my $self = shift; | ||||
|   my $curswitch; | ||||
| @@ -155,13 +237,13 @@ sub refresh_table { | ||||
|   $self->{switchtab} = xCAT::Table->new('switch', -create => 1); | ||||
|   $self->{switchestab} = xCAT::Table->new('switches', -create => 1); | ||||
|   my @switchentries=$self->{switchestab}->getAllNodeAttribs([qw(switch snmpversion username password privacy auth)]); | ||||
|   $self->{switchparmhash}={}; | ||||
|   my $community = "public"; | ||||
|   $self->{sitetab} = xCAT::Table->new('site'); | ||||
|   my $tmp = $self->{sitetab}->getAttribs({key=>'snmpc'},'value'); | ||||
|   if ($tmp and $tmp->{value}) { $community = $tmp->{value} } | ||||
|   else { #Would warn here..  | ||||
|   } | ||||
|   $self->{switchparmhash}={}; | ||||
|   foreach (@switchentries) { | ||||
|       $curswitch=$_->{switch}; | ||||
|       $self->{switchparmhash}->{$curswitch}=$_; | ||||
| @@ -185,7 +267,7 @@ sub refresh_table { | ||||
|   my @entries = $self->{switchtab}->getAllNodeAttribs(['node','port','switch']); | ||||
|   #Build hash of switch port names per switch | ||||
|   $self->{switches} = {}; | ||||
|   foreach $entry (@entries) { | ||||
|   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}}) | ||||
|         { | ||||
| @@ -202,7 +284,7 @@ sub refresh_table { | ||||
|   my $children = 0; | ||||
|   my $inputs = new IO::Select; | ||||
|   $SIG{CHLD}= sub { while(waitpid(-1,WNOHANG) > 0) { $children-- } }; | ||||
|   foreach $entry (@entries) { | ||||
|   foreach my $entry (@entries) { | ||||
|     if ($checked_pairs{$entry->{switch}}) { | ||||
|       next; | ||||
|     } | ||||
| @@ -211,7 +293,7 @@ sub refresh_table { | ||||
|     $child->autoflush(1); | ||||
|     $parent->autoflush(1); | ||||
|     $children++; | ||||
|     $cpid = xCAT::Utils->xfork; | ||||
|     my $cpid = xCAT::Utils->xfork; | ||||
|     unless (defined $cpid) { die "Cannot fork" }; | ||||
|     if ($cpid == 0) { | ||||
|       close($child); | ||||
| @@ -256,7 +338,7 @@ sub walkoid { | ||||
|   $session->getnext($varbind); | ||||
|   if ($session->{ErrorStr}) { | ||||
|     unless ($namedargs{silentfail}) { | ||||
|         if ($namedargs{warncisco}) { | ||||
|         if ($namedargs{ciscowarn}) { | ||||
|             xCAT::MsgUtils->message("S","Error communicating with ".$session->{DestHost}." (First attempt at indexing by VLAN failed, ensure that the switch has the vlan configured such that it appears in 'show vlan'): ".$session->{ErrorStr}); | ||||
|         } else { | ||||
|             xCAT::MsgUtils->message("S","Error communicating with ".$session->{DestHost}.": ".$session->{ErrorStr}); | ||||
| @@ -330,7 +412,7 @@ sub refresh_switch { | ||||
|   my $switch = shift; | ||||
|  | ||||
|   #if ($error) { die $error; } | ||||
|   $session = $self->getsnmpsession('community'=>$community,'switch'=>$switch); | ||||
|   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'); | ||||
|     #namemap is the mapping of ifIndex->(human readable name) | ||||
| @@ -358,6 +440,7 @@ sub refresh_switch { | ||||
|                                                                                         #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 | ||||
| # that we can verify are populated per switch table | ||||
|     my $portid; | ||||
|     foreach $portid (keys %{$namemap}) { | ||||
| @@ -386,13 +469,14 @@ sub refresh_switch { | ||||
|  | ||||
|   my $vlan; | ||||
|   my $iscisco=0; | ||||
|   foreach $vlan (sort keys %vlans_to_check) { #Sort, because if numbers, we want 1 first | ||||
|   foreach $vlan (sort keys %vlans_to_check) { #Sort, because if numbers, we want 1 first, because that vlan should not get communiy string indexed query | ||||
|     unless (not $vlan or $vlan eq 'NA' or $vlan eq '1') { #don't subject users to the context pain unless needed | ||||
|         $iscisco=1; | ||||
|         $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 $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); | ||||
|     unless (defined($mactoindexmap)) { #if no qbridge defined, try bridge mib, probably cisco | ||||
| @@ -410,6 +494,10 @@ sub refresh_switch { | ||||
|         #if still running, we have match | ||||
|         foreach my $boid (keys %$bridgetoifmap) { | ||||
|           unless ($bridgetoifmap->{$boid} == $ifindex) { next; } | ||||
|           $self->{switchinfo}->{$switch}->{bridgeidxtoifname}->{$boid}=$portname; | ||||
|           $self->{switchinfo}->{$switch}->{ifnametobridgeidx}->{$portname}=$boid; | ||||
|           $self->{nodeinfo}->{$self->{switches}->{$switch}->{$portname}}->{portnametobridgeindex}->{$portname}=$boid; | ||||
|           $self->{nodeinfo}->{$self->{switches}->{$switch}->{$portname}}->{bridgeindextoportname}->{$boid}=$portname; | ||||
|           my $bridgeport = $boid; | ||||
|           foreach (keys %$mactoindexmap) {  | ||||
|             if ($mactoindexmap->{$_} == $bridgeport) { | ||||
| @@ -426,6 +514,7 @@ sub refresh_switch { | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   $self->{switchsessions}->{$switch}=$session; #save session for future use | ||||
| } | ||||
|                  | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user