mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-10-31 03:12:30 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			671 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			671 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/perl
 | |
| package xCAT_plugin::vlan::CiscoSwitch;
 | |
| 
 | |
| BEGIN
 | |
| {
 | |
|     $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
 | |
| }
 | |
| use lib "$::XCATROOT/lib/perl";
 | |
| use strict;
 | |
| use xCAT::MacMap;
 | |
| use Data::Dumper;
 | |
| use xCAT::SwitchHandler;
 | |
| use SNMP;
 | |
| 
 | |
| #IF-MIB
 | |
| my $ifName       = '.1.3.6.1.2.1.31.1.1.1.1';
 | |
| my $ifDescr      = '.1.3.6.1.2.1.2.2.1.2';
 | |
| my $ifOperStatus = '.1.3.6.1.2.1.2.2.1.8';
 | |
| 
 | |
| #CISCO-VTP-MIB
 | |
| my $vtpVlanEditTable               = '.1.3.6.1.4.1.9.9.46.1.4.2';
 | |
| my $vtpVlanEditOperation           = '.1.3.6.1.4.1.9.9.46.1.4.1.1.1';
 | |
| my $vtpVlanEditBufferOwner         = '.1.3.6.1.4.1.9.9.46.1.4.1.1.3';
 | |
| my $vtpVlanEditRowStatus           = '.1.3.6.1.4.1.9.9.46.1.4.2.1.11.1';
 | |
| my $vtpVlanEditType                = '.1.3.6.1.4.1.9.9.46.1.4.2.1.3.1';
 | |
| my $vtpVlanEditName                = '.1.3.6.1.4.1.9.9.46.1.4.2.1.4.1';
 | |
| my $vtpVlanEditDot10Said           = '.1.3.6.1.4.1.9.9.46.1.4.2.1.6.1';
 | |
| my $vtpVlanState                   = '.1.3.6.1.4.1.9.9.46.1.3.1.1.2';
 | |
| my $vlanTrunkPortDynamicStatus     = '.1.3.6.1.4.1.9.9.46.1.6.1.1.14';
 | |
| my $vlanTrunkPortDynamicState      = '.1.3.6.1.4.1.9.9.46.1.6.1.1.13';
 | |
| my $vlanTrunkPortNativeVlan        = '.1.3.6.1.4.1.9.9.46.1.6.1.1.5';
 | |
| my $vlanTrunkPortVlansEnabled      = '.1.3.6.1.4.1.9.9.46.1.6.1.1.4';
 | |
| my $vlanTrunkPortEncapsulationType = '.1.3.6.1.4.1.9.9.46.1.6.1.1.3';
 | |
| 
 | |
| #CISCO-VLAN-MEMBERSHIP-MIB
 | |
| my $vmVlan     = '.1.3.6.1.4.1.9.9.68.1.2.2.1.2';
 | |
| my $vmVlanType = '.1.3.6.1.4.1.9.9.68.1.2.2.1.1';    #1:static 2:dynamic 3:trunk
 | |
| 
 | |
| #CISCI-STP-EXTENSION-MIB
 | |
| my $stpxRootGuardConfigEnabled = '1.3.6.1.4.1.9.9.82.1.5.1.1.2'; #1:enable 2:disable
 | |
| my $stpxFastStartPortBpduGuardMode = '1.3.6.1.4.1.9.9.82.1.9.3.1.4'; #1:enable 2:disable 3:default
 | |
| 
 | |
| 
 | |
| my %HexConv = (0 => 0x80, 1 => 0x40, 2 => 0x20, 3 => 0x10,
 | |
|     4 => 0x08, 5 => 0x04, 6 => 0x02, 7 => 0x01);
 | |
| 
 | |
| #--------------------------------------------------------------
 | |
| 
 | |
| =head3 filter_string 
 | |
|   
 | |
|     Every switch plugin must implement this subroutine.
 | |
| 
 | |
|     The return value will be used comare against the string 
 | |
|     from sysDescr value from snmpget. If the latter contains
 | |
|     this string, then this mudule will be used to handle the 
 | |
|     requests for vlan configuration.
 | |
| 
 | |
| =cut
 | |
| 
 | |
| #-------------------------------------------------------------
 | |
| sub filter_string {
 | |
|     return "Cisco ";
 | |
| }
 | |
| 
 | |
| #--------------------------------------------------------------
 | |
| 
 | |
| =head3 get_vlan_ids  
 | |
|   
 | |
|   Every switch plugin must implement this subroutine.
 | |
| 
 | |
|   It gets the existing vlan IDs for the switch.
 | |
|   Returns:  an array containing all the vlan ids for the switch
 | |
| =cut
 | |
| 
 | |
| #-------------------------------------------------------------
 | |
| sub get_vlan_ids {
 | |
|     my $session = shift;
 | |
| 
 | |
|     my $vlanmap = xCAT::MacMap::walkoid($session, "$vtpVlanState.1", silentfail => 1);
 | |
|     my %vlanids = ();
 | |
|     foreach (keys(%$vlanmap)) {
 | |
|         $vlanids{$_} = 1;
 | |
|     }
 | |
| 
 | |
|     my @ret = (sort keys(%vlanids));
 | |
|     print "ids=@ret\n";
 | |
|     return @ret;
 | |
| }
 | |
| 
 | |
| 
 | |
| #--------------------------------------------------------------
 | |
| 
 | |
| =head3 get_vlanids_for_ports 
 | |
|   
 | |
|     Every switch plugin must implement this subroutine.
 | |
| 
 | |
|     It returns a hash pointer that contains the vlan ids for each given port.
 | |
|     The kay is the port, the vlaue is a pointer to an array.
 | |
| =cut
 | |
| 
 | |
| #-------------------------------------------------------------
 | |
| sub get_vlanids_for_ports {
 | |
|     my $session = shift;
 | |
|     my @ports   = @_;
 | |
| 
 | |
|     my $namemap = xCAT::MacMap::walkoid($session, $ifName);
 | |
| 
 | |
|     #namemap is the mapping of ifIndex->(human readable name)
 | |
|     if ($namemap) {
 | |
|         my $ifnamesupport = 0;
 | |
|         foreach (keys %{$namemap}) {
 | |
|             if ($namemap->{$_}) {
 | |
|                 $ifnamesupport = 1;
 | |
|                 last;
 | |
|             }
 | |
|         }
 | |
|         unless ($ifnamesupport) {
 | |
|             $namemap = 0;
 | |
|         }
 | |
|     }
 | |
|     unless ($namemap) { #Failback to ifDescr.  ifDescr is close, but not perfect on some switches
 | |
|         $namemap = xCAT::MacMap::walkoid($session, $ifDescr);
 | |
|     }
 | |
|     unless ($namemap) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     #print "namemap=" . Dumper($namemap) . "\n";
 | |
| 
 | |
|     my $iftovlanmap = xCAT::MacMap::walkoid($session, $vmVlan, silentfail => 1);
 | |
| 
 | |
|     #print "iftovlanmap=" . Dumper($iftovlanmap) . "\n";
 | |
| 
 | |
|     my $trunktovlanmap = xCAT::MacMap::walkoid($session, $vlanTrunkPortNativeVlan, silentfail => 1); #for trunk ports, we are interested in the native vlan
 | |
|             #print "trunktovlanmap=" . Dumper($trunktovlanmap) . "\n";
 | |
| 
 | |
|     my %ret = ();
 | |
|     if (defined($iftovlanmap) or defined($trunktovlanmap)) {
 | |
|         foreach my $portid (keys %{$namemap}) {
 | |
|             my $switchport = $namemap->{$portid};
 | |
|             foreach my $portname (@ports) {
 | |
|                 unless (xCAT::MacMap::namesmatch($portname, $switchport)) {
 | |
|                     next;
 | |
|                 }
 | |
| 
 | |
|                 if (defined $iftovlanmap->{$portid}) {
 | |
|                     $ret{$portname} = [ $iftovlanmap->{$portid} ];
 | |
|                 } elsif (defined $trunktovlanmap->{$portid}) {
 | |
|                     $ret{$portname} = [ $trunktovlanmap->{$portid} ];
 | |
|                 } else {
 | |
|                     $ret{$portname} = ['NA'];
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return \%ret;
 | |
| }
 | |
| 
 | |
| 
 | |
| #--------------------------------------------------------------
 | |
| 
 | |
| =head3 create_vlan
 | |
|   
 | |
|     Every switch plugin must implement this subroutine.
 | |
|  
 | |
|     Creates a new vlan on the switch
 | |
|     Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
 | |
| =cut
 | |
| 
 | |
| #-------------------------------------------------------------
 | |
| sub create_vlan {
 | |
|     my $session   = shift;
 | |
|     my $vlan_id   = shift;
 | |
|     my $vlan_name = "xcat_vlan_" . $vlan_id;
 | |
| 
 | |
|     print "Cisco\n";
 | |
| 
 | |
|     #Verify if the edition is in use by another NMS station or device.
 | |
|     #The edition is not in use if you see this message: no MIB objects contained under subtree:
 | |
|     my $tmp = xCAT::MacMap::walkoid($session, $vtpVlanEditTable);
 | |
| 
 | |
|     #print "tmp=" . Dumper($tmp) . "\n";
 | |
| 
 | |
|     #Set the vtpVlanEditOperation to the copy state(2). This allows to create the VLAN.
 | |
|     my @ret = xCAT::SwitchHandler::setoid($session, $vtpVlanEditOperation, 1, 2, 'INTEGER');
 | |
| 
 | |
|     #if ($ret[0] != 0) { return @ret; }
 | |
| 
 | |
|     #set vtpVlanEditBufferOwner in order to makethe current owner of the edit permission visible
 | |
|     my $username = "xcat";
 | |
|     my @ret = xCAT::SwitchHandler::setoid($session, $vtpVlanEditBufferOwner, 1, $username, 'OCTET');
 | |
|     if ($ret[0] != 0) {
 | |
|         $ret[1] = "Set vtpVlanEditBufferOwner $vtpVlanEditBufferOwner.1 to $username.\n" . $ret[1];
 | |
|         return @ret;
 | |
|     }
 | |
| 
 | |
|     #my $tmp = xCAT::MacMap::walkoid($session, $vtpVlanEditOperation);
 | |
|     #print "tmp=" . Dumper($tmp) . "\n";
 | |
| 
 | |
|     #my $tmp = xCAT::MacMap::walkoid($session, $vtpVlanEditBufferOwner);
 | |
|     #print "tmp=" . Dumper($tmp) . "\n";
 | |
| 
 | |
|     #set vtpVlanEditRowStatus to createAndGo(4)
 | |
|     my @ret = xCAT::SwitchHandler::setoid($session, $vtpVlanEditRowStatus, $vlan_id, 4, 'INTEGER');
 | |
|     if ($ret[0] != 0) {
 | |
|         $ret[1] = "Set vtpVlanEditRowStatus $vtpVlanEditRowStatus.$vlan_id to 4.\n" . $ret[1];
 | |
|         return @ret;
 | |
|     }
 | |
| 
 | |
|     #set vtpVlanEditType to ethernet (1)
 | |
|     my @ret = xCAT::SwitchHandler::setoid($session, $vtpVlanEditType, $vlan_id, 1, 'INTEGER');
 | |
|     if ($ret[0] != 0) {
 | |
|         $ret[1] = "Set vtpVlanEditType $vtpVlanEditType.$vlan_id to 1.\n" . $ret[1];
 | |
|         return @ret;
 | |
|     }
 | |
| 
 | |
|     #set vtpVlanEditName to xcat_vlan_#
 | |
|     my @ret = xCAT::SwitchHandler::setoid($session, $vtpVlanEditName, $vlan_id, $vlan_name, 'OCTET');
 | |
|     if ($ret[0] != 0) {
 | |
|         $ret[1] = "Set vtpVlanEditName $vtpVlanEditName.$vlan_id to $vlan_name.\n" . $ret[1];
 | |
|         return @ret;
 | |
|     }
 | |
| 
 | |
|     #Set the vtpVlanEditDot10Said. This is the VLAN number + 100000 translated to hexadecimal.
 | |
|     my $num = 100000 + $vlan_id;
 | |
|     my $hex_num = sprintf("%x", $num);
 | |
|     my @ret = xCAT::SwitchHandler::setoid($session, $vtpVlanEditDot10Said, $vlan_id, $hex_num, 'OCTETHEX');
 | |
| 
 | |
|     #if ($ret[0] != 0) {
 | |
|     #	$ret[1]="Set vtpVlanEditDot10Said $vtpVlanEditDot10Said.$vlan_id to $hex_num.\n" . $ret[1];
 | |
|     #return @ret;
 | |
|     #}
 | |
| 
 | |
|     #apply the changes, set vtpVlanEditOperation.1 to apply (3)
 | |
|     my @ret = xCAT::SwitchHandler::setoid($session, $vtpVlanEditOperation, 1, 3, 'INTEGER');
 | |
|     if ($ret[0] != 0) {
 | |
|         $ret[1] = "Set vtpVlanEditOperation $vtpVlanEditOperation.1 to 3.\n" . $ret[1];
 | |
|         return @ret;
 | |
|     }
 | |
| 
 | |
|     #release the edition buffer, set vtpVlanEditOperation.1 to release (4)
 | |
|     my @ret = xCAT::SwitchHandler::setoid($session, $vtpVlanEditOperation, 1, 4, 'INTEGER');
 | |
|     if ($ret[0] != 0) {
 | |
|         $ret[1] = "Set vtpVlanEditOperation $vtpVlanEditOperation.1 to 4.\n" . $ret[1];
 | |
|         return @ret;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     return (0, "");
 | |
| }
 | |
| 
 | |
| #--------------------------------------------------------------
 | |
| 
 | |
| =head3 add_ports_to_vlan   
 | |
| 
 | |
|     Every switch plugin must implement this subroutine.
 | |
| 
 | |
|     Adds the given ports to the existing vlan
 | |
|     Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
 | |
| =cut
 | |
| 
 | |
| #-------------------------------------------------------------
 | |
| sub add_ports_to_vlan {
 | |
|     my $session = shift;
 | |
|     my $vlan_id = shift;
 | |
| 
 | |
|     # If portmode is set, we'll set the switchport to untagged(access) mode.
 | |
|     my $portmode = shift;
 | |
|     my @ports    = @_;
 | |
| 
 | |
|     #print "Add ports @ports to vla $vlan_id.\n";
 | |
| 
 | |
|     #add ports to the vlan.
 | |
|     if (@ports > 0) {
 | |
|         my $namemap = xCAT::MacMap::walkoid($session, $ifName);
 | |
| 
 | |
|         #namemap is the mapping of ifIndex->(human readable name)
 | |
|         if ($namemap) {
 | |
|             my $ifnamesupport = 0; #Assume broken ifnamesupport until proven good... (Nortel switch)
 | |
|             foreach (keys %{$namemap}) {
 | |
|                 if ($namemap->{$_}) {
 | |
|                     $ifnamesupport = 1;
 | |
|                     last;
 | |
|                 }
 | |
|             }
 | |
|             unless ($ifnamesupport) {
 | |
|                 $namemap = 0;
 | |
|             }
 | |
|         }
 | |
|         unless ($namemap) { #Failback to ifDescr.  ifDescr is close, but not perfect on some switches
 | |
|             $namemap = xCAT::MacMap::walkoid($session, $ifDescr);
 | |
|         }
 | |
|         unless ($namemap) {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         #print "namemap=" . Dumper($namemap) . "\n";
 | |
| 
 | |
|         my $trunkportstate = xCAT::MacMap::walkoid($session, $vlanTrunkPortDynamicState);
 | |
| 
 | |
|         #print "trunkportstate=" . Dumper($trunkportstate) . "\n";
 | |
| 
 | |
|         my $iftovlanmap = xCAT::MacMap::walkoid($session, $vmVlan, silentfail => 1);
 | |
| 
 | |
|         #print "iftovlanmap=" . Dumper($iftovlanmap) . "\n";
 | |
|         my $trunktovlanmap = xCAT::MacMap::walkoid($session, $vlanTrunkPortNativeVlan, silentfail => 1);
 | |
| 
 | |
|         #print "trunktovlanmap=" . Dumper($trunktovlanmap) . "\n";
 | |
| 
 | |
|         #get current vlan type (static, dynamic or trunk)
 | |
|         my $vlantypemap = xCAT::MacMap::walkoid($session, $vmVlanType, silentfail => 1);
 | |
| 
 | |
|         #print "vlantypemap=" . Dumper($vlantypemap) . "\n";
 | |
| 
 | |
| 
 | |
|         foreach my $portid (keys %{$namemap}) {
 | |
|             my $switchport = $namemap->{$portid};
 | |
|             foreach my $portname (@ports) {
 | |
|                 unless (xCAT::MacMap::namesmatch($portname, $switchport)) {
 | |
|                     next;
 | |
|                 }
 | |
| 
 | |
| 
 | |
|                 ### set the port to trunk mode
 | |
|                 print "portid=$portid\n";
 | |
| 
 | |
|                 # TODO: need testing in cisco's env for how to set a port as access mode through snmpset?
 | |
|                 # Can setting vlanTrunkPortDot1qTunnel or cltcDot1qTunnelMode helps?
 | |
|                 if ($trunkportstate->{$portid} != 1) {
 | |
|                     my @ret = xCAT::SwitchHandler::setoid($session, $vlanTrunkPortEncapsulationType, $portid, 4, 'INTEGER');
 | |
|                     if ($ret[0] != 0) {
 | |
|                         $ret[1] = "Set vlanTrunkPortEncapsulationType $vlanTrunkPortEncapsulationType.$portid to 4(dot1Q).\n" . $ret[1];
 | |
|                         return @ret;
 | |
|                     }
 | |
|                     my @ret = xCAT::SwitchHandler::setoid($session, $vlanTrunkPortDynamicState, $portid, 1, 'INTEGER');
 | |
|                     if ($ret[0] != 0) {
 | |
|                         $ret[1] = "Set vlanTrunkPortDynamicState $vlanTrunkPortDynamicState.$portid to 1.\n" . $ret[1];
 | |
|                         return @ret;
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 ### set trunk native vlan id
 | |
|                 my $native_vlanid = 1;
 | |
|                 if ((exists($vlantypemap->{$portid})) && ($vlantypemap->{$portid} < 3)) { #the port was set to access mode before
 | |
|                     if ((exists($iftovlanmap->{$portid})) && ($iftovlanmap->{$portid} > 0)) {
 | |
|                         $native_vlanid = $iftovlanmap->{$portid};
 | |
|                     }
 | |
|                 } else {    #the port is originally set to trunk mode
 | |
|                     if ((exists($trunktovlanmap->{$portid})) && ($trunktovlanmap->{$portid} > 0)) {
 | |
|                         $native_vlanid = $trunktovlanmap->{$portid};
 | |
|                     } elsif ((exists($iftovlanmap->{$portid})) && ($iftovlanmap->{$portid} > 0)) {
 | |
|                         $native_vlanid = $iftovlanmap->{$portid};
 | |
|                     }
 | |
|                 }
 | |
|                 print "*** native_vlanid=$native_vlanid\n";
 | |
|                 my @ret = xCAT::SwitchHandler::setoid($session, $vlanTrunkPortNativeVlan, $portid, $native_vlanid, 'INTEGER');
 | |
|                 if ($ret[0] != 0) {
 | |
|                     $ret[1] = "Set native vlan for port $portid to $native_vlanid ($vlanTrunkPortNativeVlan.$portid to $native_vlanid).\n" . $ret[1];
 | |
|                     return @ret;
 | |
|                 }
 | |
| 
 | |
| 
 | |
|                 ### allow this vlan on the port
 | |
|                 my $data = $session->get([ $vlanTrunkPortVlansEnabled, $portid ]);
 | |
|                 my @a = split(//, $data);
 | |
|                 foreach (@a) {
 | |
|                     my $num = unpack("C*", $_);
 | |
|                     $_ = sprintf("%02x", $num);
 | |
|                 }
 | |
|                 if ((exists($vlantypemap->{$portid})) && ($vlantypemap->{$portid} < 3)) {
 | |
| 
 | |
|                     #if originally this port was in access or dynamic mode, only enable original vlan and this tagged vlan
 | |
|                     #reset the matrix
 | |
|                     #print "***was access mode\n";
 | |
|                     foreach (@a) {
 | |
|                         $_ = "00";
 | |
|                     }
 | |
| 
 | |
|                     #add native vlan id in the matrix
 | |
|                     my $index  = int($native_vlanid / 8);
 | |
|                     my $offset = $native_vlanid % 8;
 | |
|                     my $num    = hex($a[$index]) | $HexConv{$offset};
 | |
|                     $a[$index] = sprintf("%02x", $num);
 | |
| 
 | |
|                     #print "index=$index, offset=$offset\n";
 | |
| 
 | |
|                     #add current vlan id in the matrix
 | |
|                     $index  = int($vlan_id / 8);
 | |
|                     $offset = $vlan_id % 8;
 | |
|                     $num    = hex($a[$index]) | $HexConv{$offset};
 | |
|                     $a[$index] = sprintf("%02x", $num);
 | |
|                 } else {
 | |
| 
 | |
|                     #if this port was trunk mode before, add this tagged vlan in the matrix
 | |
|                     # print "***was trunk mode\n";
 | |
|                     my $index  = int($vlan_id / 8);
 | |
|                     my $offset = $vlan_id % 8;
 | |
|                     my $num    = hex($a[$index]) | $HexConv{$offset};
 | |
|                     $a[$index] = sprintf("%02x", $num);
 | |
|                 }
 | |
| 
 | |
|                 #print "a=@a\n";
 | |
|                 foreach (@a) {
 | |
|                     $_ = hex($_);
 | |
|                     $_ = pack("C*", $_);
 | |
|                 }
 | |
|                 my $s = join(//, @a);
 | |
|                 my @ret = xCAT::SwitchHandler::setoid($session, $vlanTrunkPortVlansEnabled, $portid, $s, 'OCTET');
 | |
| 
 | |
|                 #print "**** ret=@ret\n";
 | |
|                 if ($ret[0] != 0) {
 | |
|                     $ret[1] = "Allow vlan on port $portid ($vlanTrunkPortVlansEnabled.$portid=$s).\n" . $ret[1];
 | |
|                     return @ret;
 | |
|                 }
 | |
| 
 | |
| 
 | |
|                 ### security feature
 | |
|                 if ($::XCATSITEVALS{vlansecurity} eq '1') {
 | |
| 
 | |
|                     #set root guard on the port
 | |
|                     my @ret = xCAT::SwitchHandler::setoid($session, $stpxRootGuardConfigEnabled, $portname, 1, 'INTEGER');
 | |
|                     if ($ret[0] != 0) {
 | |
|                         $ret[1] = "Set root guard for port $portname to enable ($stpxRootGuardConfigEnabled.$portname=1).\n" . $ret[1];
 | |
|                         return @ret;
 | |
|                     }
 | |
| 
 | |
|                     #set bpdu guard on the port
 | |
|                     my @ret = xCAT::SwitchHandler::setoid($session, $stpxFastStartPortBpduGuardMode, $portname, 1, 'INTEGER');
 | |
|                     if ($ret[0] != 0) {
 | |
|                         $ret[1] = "Set bpdu guard for port $portname to enalbe ($stpxFastStartPortBpduGuardMode.$portname=1).\n" . $ret[1];
 | |
|                         return @ret;
 | |
|                     }
 | |
|                 }
 | |
|                 last;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return (0, "");
 | |
| }
 | |
| 
 | |
| #-------------------------------------------------------
 | |
| 
 | |
| =head3  add_crossover_ports_to_vlan
 | |
|   It enables the vlan on the cross-over links.
 | |
|     Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
 | |
| =cut
 | |
| 
 | |
| #-------------------------------------------------------
 | |
| sub add_crossover_ports_to_vlan {
 | |
|     my $session  = shift;
 | |
|     my $vlan_id  = shift;
 | |
|     my $switch   = shift;
 | |
|     my @switches = @_;
 | |
|     my @ret      = (0, "");
 | |
|     my $msg;
 | |
| 
 | |
|     if (@switches == 0) { return (0, ""); }
 | |
| 
 | |
|     #get the ports that are connects to the switches
 | |
|     my $switchestab = xCAT::Table->new('switches', -create => 0);
 | |
|     my $ent = $switchestab->getNodeAttribs($switch, [qw(switch linkports)]);
 | |
|     if ((!$ent) || (!$ent->{linkports})) { return (0, $msg); }
 | |
| 
 | |
|     my %linkports = ();
 | |
|     foreach my $item (split(',', $ent->{linkports})) {
 | |
|         my @a = split(':', $item);
 | |
|         if (@a > 1) {
 | |
|             $linkports{ $a[1] } = $a[0];
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     #print Dumper(%linkports);
 | |
| 
 | |
|     my @ports = ();
 | |
|     foreach my $sw (@switches) {
 | |
|         if (exists($linkports{$sw})) {
 | |
|             push(@ports, $linkports{$sw});
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     #print "ports=@ports\n";
 | |
| 
 | |
|     #now add the ports to the vlan
 | |
|     if (@ports > 0) {
 | |
|         my ($code, $msg1) = add_ports_to_vlan($session, $vlan_id, @ports);
 | |
|         if ($msg) {
 | |
|             $msg1 = $msg . $msg1;
 | |
|         }
 | |
| 
 | |
|         return ($code, $msg1);
 | |
|     }
 | |
| 
 | |
|     return (0, $msg);
 | |
| }
 | |
| 
 | |
| #--------------------------------------------------------------
 | |
| 
 | |
| =head3 remove_vlan   
 | |
| 
 | |
|     Every switch plugin must implement this subroutine.
 | |
| 
 | |
|     Remove a vlan from the switch
 | |
|     Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
 | |
| =cut
 | |
| 
 | |
| #-------------------------------------------------------------
 | |
| sub remove_vlan {
 | |
|     my $session = shift;
 | |
|     my $vlan_id = shift;
 | |
| 
 | |
|     #Verify if the edition is in use by another NMS station or device.
 | |
|     #The edition is not in use if you see this message: no MIB objects contained under subtree:
 | |
|     my $tmp = xCAT::MacMap::walkoid($session, $vtpVlanEditTable);
 | |
| 
 | |
|     #print "tmp=" . Dumper($tmp) . "\n";
 | |
| 
 | |
|     #Set the vtpVlanEditOperation to the copy state(2). This allows to delete the VLAN.
 | |
|     my @ret = xCAT::SwitchHandler::setoid($session, $vtpVlanEditOperation, 1, 2, 'INTEGER');
 | |
|     if ($ret[0] != 0) {
 | |
|         $ret[1] = "Set vtpVlanEditOperation $vtpVlanEditOperation.1 to 3 (copy state).\n" . $ret[1];
 | |
|         return @ret;
 | |
|     }
 | |
| 
 | |
|     #set vtpVlanEditBufferOwner in order to makethe current owner of the edit permission visible
 | |
|     my $username = "xcat";
 | |
|     my @ret = xCAT::SwitchHandler::setoid($session, $vtpVlanEditBufferOwner, 1, $username, 'OCTET');
 | |
|     if ($ret[0] != 0) {
 | |
|         $ret[1] = "Set vtpVlanEditBufferOwner $vtpVlanEditBufferOwner.1 to $username.\n" . $ret[1];
 | |
|         return @ret;
 | |
|     }
 | |
| 
 | |
|     #set vtpVlanEditRowStatus to destroy(6)
 | |
|     my @ret = xCAT::SwitchHandler::setoid($session, $vtpVlanEditRowStatus, $vlan_id, 6, 'INTEGER');
 | |
|     if ($ret[0] != 0) {
 | |
|         $ret[1] = "Set vtpVlanEditRowStatus $vtpVlanEditRowStatus.$vlan_id to 6 (destroy).\n" . $ret[1];
 | |
|         return @ret;
 | |
|     }
 | |
| 
 | |
|     #apply the changes, set vtpVlanEditOperation.1 to apply (3)
 | |
|     my @ret = xCAT::SwitchHandler::setoid($session, $vtpVlanEditOperation, 1, 3, 'INTEGER');
 | |
|     if ($ret[0] != 0) {
 | |
|         $ret[1] = "Set $vtpVlanEditOperation.1 to 3 (apply).\n" . $ret[1];
 | |
|         return @ret;
 | |
|     }
 | |
| 
 | |
|     #release the edition buffer, set vtpVlanEditOperation.1 to release (4)
 | |
|     my @ret = xCAT::SwitchHandler::setoid($session, $vtpVlanEditOperation, 1, 4, 'INTEGER');
 | |
|     if ($ret[0] != 0) {
 | |
|         $ret[1] = "Set vtpVlanEditOperation $vtpVlanEditOperation.1 to 4 (release).\n" . $ret[1];
 | |
|         return @ret;
 | |
|     }
 | |
| 
 | |
|     #my $iftovlanmap = xCAT::MacMap::walkoid($session, $vmVlan, silentfail=>1);
 | |
|     #print "iftovlanmap=" . Dumper($iftovlanmap) . "\n";
 | |
|     #foreach (keys(%$iftovlanmap)) {
 | |
|     #	if($iftovlanmap->{$_} == $vlan_id) {
 | |
|     #my @ret= xCAT::SwitchHandler::setoid($session, $vmVlan, $_, 1, 'INTEGER');
 | |
|     #if ($ret[0] != 0) {
 | |
|     #	$ret[1]="Set $vmVlan.$_ to 1.\n" . $ret[1];
 | |
|     #   return @ret;
 | |
|     #}
 | |
|     #	}
 | |
|     #}
 | |
|     #my $trunktovlanmap = xCAT::MacMap::walkoid($session, $vlanTrunkPortNativeVlan, silentfail=>1); #for trunk ports, we are interested in the native vlan
 | |
|     #print "trunktovlanmap=" . Dumper($trunktovlanmap) . "\n";
 | |
|     #foreach (keys(%$trunktovlanmap)) {
 | |
|     #	if($trunktovlanmap->{$_} == $vlan_id) {
 | |
|     # my @ret= xCAT::SwitchHandler::setoid($session, $vlanTrunkPortNativeVlan, $_, 1, 'INTEGER');
 | |
|     # if ($ret[0] != 0) {
 | |
|     #	$ret[1]="Set $vlanTrunkPortNativeVlan.$_ to 1.\n" . $ret[1];
 | |
|     #	return @ret;
 | |
|     # }
 | |
|     #	}
 | |
|     #}
 | |
| 
 | |
| 
 | |
|     return (0, "");
 | |
| }
 | |
| 
 | |
| 
 | |
| #--------------------------------------------------------------
 | |
| 
 | |
| =head3 remove_ports_from_vlan  
 | |
| 
 | |
|     Every switch plugin must implement this subroutine.
 | |
| 
 | |
|     Remove ports from a vlan
 | |
|     Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
 | |
| =cut
 | |
| 
 | |
| #-------------------------------------------------------------
 | |
| sub remove_ports_from_vlan {
 | |
|     my $session = shift;
 | |
|     my $vlan_id = shift;
 | |
|     my @ports   = @_;
 | |
| 
 | |
| 
 | |
|     if (@ports > 0) {
 | |
|         my $namemap = xCAT::MacMap::walkoid($session, $ifName);
 | |
| 
 | |
|         #namemap is the mapping of ifIndex->(human readable name)
 | |
|         if ($namemap) {
 | |
|             my $ifnamesupport = 0;
 | |
|             foreach (keys %{$namemap}) {
 | |
|                 if ($namemap->{$_}) {
 | |
|                     $ifnamesupport = 1;
 | |
|                     last;
 | |
|                 }
 | |
|             }
 | |
|             unless ($ifnamesupport) {
 | |
|                 $namemap = 0;
 | |
|             }
 | |
|         }
 | |
|         unless ($namemap) { #Failback to ifDescr.  ifDescr is close, but not perfect on some switches
 | |
|             $namemap = xCAT::MacMap::walkoid($session, $ifDescr);
 | |
|         }
 | |
|         unless ($namemap) {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         #print "namemap=" . Dumper($namemap) . "\n";
 | |
| 
 | |
|         foreach my $portid (keys %{$namemap}) {
 | |
|             my $switchport = $namemap->{$portid};
 | |
|             foreach my $portname (@ports) {
 | |
|                 unless (xCAT::MacMap::namesmatch($portname, $switchport)) {
 | |
|                     next;
 | |
|                 }
 | |
| 
 | |
|                 #remove the vlan id from the vlanTrunkPortVlansEnabled.port  matrix
 | |
|                 my $data = $session->get([ $vlanTrunkPortVlansEnabled, $portid ]);
 | |
|                 my @a = split(//, $data);
 | |
|                 foreach (@a) {
 | |
|                     my $num = unpack("C*", $_);
 | |
|                     $_ = sprintf("%02x", $num);
 | |
|                 }
 | |
| 
 | |
|                 #print "a=@a\n";
 | |
|                 my $index  = int($vlan_id / 8);
 | |
|                 my $offset = $vlan_id % 8;
 | |
|                 my $num    = hex($a[$index]) & (~$HexConv{$offset});
 | |
|                 $a[$index] = sprintf("%02x", $num);
 | |
| 
 | |
|                 #print "a=@a\n";
 | |
| 
 | |
|                 foreach (@a) {
 | |
|                     $_ = hex($_);
 | |
|                     $_ = pack("C*", $_);
 | |
|                 }
 | |
| 
 | |
|                 my $s = join(//, @a);
 | |
|                 my @ret = xCAT::SwitchHandler::setoid($session, $vlanTrunkPortVlansEnabled, $portid, $s, 'OCTET');
 | |
|                 if ($ret[0] != 0) {
 | |
|                     $ret[1] = "Set vlanTrunkPortVlansEnabled $vlanTrunkPortVlansEnabled.$portid to $s.\n" . $ret[1];
 | |
|                     return @ret;
 | |
|                 }
 | |
| 
 | |
|                 last;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return (0, "");
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 1;
 |