337 lines
10 KiB
Perl
Executable File
337 lines
10 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
package xCAT::SwitchHandler;
|
|
BEGIN
|
|
{
|
|
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
|
|
}
|
|
use lib "$::XCATROOT/lib/perl";
|
|
use strict;
|
|
use xCAT::Table;
|
|
use xCAT::Utils;
|
|
use xCAT::MsgUtils;
|
|
use xCAT::MacMap;
|
|
use IO::Select;
|
|
use IO::Handle;
|
|
use Sys::Syslog;
|
|
use Data::Dumper;
|
|
use POSIX qw/WNOHANG/;
|
|
use SNMP;
|
|
|
|
my $sysDescr='.1.3.6.1.2.1.1.1';
|
|
|
|
sub new {
|
|
my $self = {};
|
|
my $proto = shift;
|
|
my $class = ref($proto) || $proto;
|
|
$self->{switch} = shift;
|
|
|
|
bless ($self, $class);
|
|
return $self;
|
|
}
|
|
|
|
|
|
sub fill_sessionparms {
|
|
my $self = shift;
|
|
my %args = @_;
|
|
my $community=$args{community};
|
|
$self->{sessionparms}=$args{sessionents};
|
|
if ($self->{sessionparms}->{snmpversion}) {
|
|
if ($self->{sessionparms}->{snmpversion} =~ /3/) { #clean up to accept things like v3 or ver3 or 3, whatever.
|
|
$self->{sessionparms}->{snmpversion}=3;
|
|
unless ($self->{sessionparms}->{auth}) {
|
|
$self->{sessionparms}->{auth}='md5'; #Default to md5 auth if not specified but using v3
|
|
}
|
|
} elsif ($self->{sessionparms}->{snmpversion} =~ /2/) {
|
|
$self->{sessionparms}->{snmpversion}=2;
|
|
} else {
|
|
$self->{sessionparms}->{snmpversion}=1; #Default to lowest common denominator, snmpv1
|
|
}
|
|
}
|
|
unless (defined $self->{sessionparms}->{password}) { #if no password set, inherit the community
|
|
$self->{sessionparms}->{password}=$community;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
sub setoid {
|
|
my $session = shift;
|
|
my $oid = shift;
|
|
my $offset = shift;
|
|
my $value = shift;
|
|
my $type = shift;
|
|
unless ($type) { $type = 'INTEGER'; }
|
|
my $varbind = new SNMP::Varbind([$oid,$offset,$value,$type]);
|
|
my $data = $session->set($varbind);
|
|
if ($session->{ErrorStr}) { return (1,$session->{ErrorStr}); }
|
|
return 0,$varbind;
|
|
}
|
|
|
|
#---------------------------------------------------------
|
|
=head3 getsnmpsession
|
|
It gets an snmp session appropriate for a switch using the switches table
|
|
for guidance on the hows.
|
|
Arguments: vlan=> $vid if needed for community string indexing (optional)
|
|
=cut
|
|
#------------------------------------------------------------
|
|
sub getsnmpsession {
|
|
my $self = shift;
|
|
my $community=shift;
|
|
my $vlanid = shift;
|
|
my $switch = $self->{switch};
|
|
my $session;
|
|
my $sessionparams;
|
|
|
|
if (!$community) { $community="private"; }
|
|
|
|
$self->{sitetab} = xCAT::Table->new('site');
|
|
my $tmp = $self->{sitetab}->getAttribs({key=>'snmpc'},'value');
|
|
if ($tmp and $tmp->{value}) { $community = $tmp->{value} }
|
|
|
|
my $switchestab=xCAT::Table->new('switches',-create=>0);
|
|
my $ent = $switchestab->getNodeAttribs($switch, [qw(switch snmpversion username password privacy auth)]);
|
|
if ($ent) {
|
|
$self->fill_sessionparms(community=>$community, sessionents=>$ent);
|
|
}
|
|
|
|
$sessionparams=$self->{sessionparms};
|
|
|
|
my $snmpver='1';
|
|
if ($sessionparams) {
|
|
$snmpver=$sessionparams->{snmpversion};
|
|
$community=$sessionparams->{password};
|
|
}
|
|
|
|
if ($snmpver ne '3') {
|
|
if ($vlanid) { $community .= '@'.$vlanid; }
|
|
$session = new SNMP::Session(
|
|
DestHost => $switch,
|
|
Version => $snmpver,
|
|
Community => $community,
|
|
UseNumeric => 1
|
|
);
|
|
} else { #we have snmp3
|
|
my %args= (
|
|
DestHost => $switch,
|
|
SecName => $sessionparams->{username},
|
|
AuthProto => uc($sessionparams->{auth}),
|
|
AuthPass => $community,
|
|
Version => $snmpver,
|
|
SecLevel => 'authNoPriv',
|
|
UseNumeric => 1
|
|
);
|
|
if ($vlanid) { $args{Context}="vlan-".$vlanid; }
|
|
if ($sessionparams->{privacy}) {
|
|
$args{SecLevel}='authPriv';
|
|
$args{PrivProto} = uc($sessionparams->{privacy});
|
|
$args{PrivPass} = $community;
|
|
$args{Retries} = 4;
|
|
$args{Timeout}=1500000;
|
|
}
|
|
|
|
#print "args=" . Dumper(%args) . "\n";
|
|
$session = new SNMP::Session(%args);
|
|
}
|
|
|
|
#print "switch=$switch\n";
|
|
if (!$session) { return $session;}
|
|
|
|
#get the the switch brand name
|
|
my $tmp = xCAT::MacMap::walkoid($session, "$sysDescr", silentfail=>1);
|
|
my $swbrand;
|
|
if ($tmp->{0}) {
|
|
#print "Desc=" . $tmp->{0} . "\n";
|
|
my @switch_plugins=glob("$::XCATROOT/lib/perl/xCAT_plugin/vlan/*.pm");
|
|
foreach my $fn (@switch_plugins) {
|
|
$fn =~ /.*\/([^\/]*).pm$/;
|
|
my $module = $1;
|
|
#print "fn=$fn,modele=$module\n";
|
|
if ( ! eval { require "$fn" }) {
|
|
xCAT::MsgUtils->message("S", "Cannot load module $fn");
|
|
next;
|
|
} else {
|
|
no strict 'refs';
|
|
my $filter=${"xCAT_plugin::vlan::".$module."::"}{filter_string}->();
|
|
my $descr=$tmp->{0};
|
|
if ($descr =~ /$filter/) {
|
|
$self->{module}=$module;
|
|
#print "found it:$module\n";
|
|
last;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!exists($self->{module})) {
|
|
$self->{session}=0;
|
|
return 0;
|
|
} else {
|
|
$self->{session}=$session;
|
|
return $session;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#--------------------------------------------------------------
|
|
=head3 get_vlan_ids
|
|
|
|
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 $self = shift;
|
|
my $session=$self->{session};
|
|
if (! $self->{session}) {
|
|
$session = $self->getsnmpsession();
|
|
}
|
|
unless ($session) { xCAT::MsgUtils->message("S","Failed to communicate with " . $self->{switch} . " or find a plugin module for the switch."); return; }
|
|
|
|
no strict 'refs';
|
|
return ${"xCAT_plugin::vlan::".$self->{module}."::"}{get_vlan_ids}->($session);
|
|
}
|
|
|
|
|
|
#--------------------------------------------------------------
|
|
=head3 get_vlanids_for_ports
|
|
It returns a hash pointer that contains the vlan id for each given port.
|
|
=cut
|
|
#-------------------------------------------------------------
|
|
sub get_vlanids_for_ports {
|
|
my $self = shift;
|
|
my @ports=@_;
|
|
|
|
my $session=$self->{session};
|
|
if (! $self->{session}) {
|
|
$session = $self->getsnmpsession();
|
|
}
|
|
unless ($session) { xCAT::MsgUtils->message("S","Failed to communicate with " . $self->{switch} . " or find a plugin module for the switch."); return; }
|
|
|
|
no strict 'refs';
|
|
return ${"xCAT_plugin::vlan::".$self->{module}."::"}{get_vlanids_for_ports}->($session, @ports);
|
|
|
|
}
|
|
|
|
|
|
#--------------------------------------------------------------
|
|
=head3 create_vlan
|
|
Creates a new vlan on the switch
|
|
Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
|
|
=cut
|
|
#-------------------------------------------------------------
|
|
sub create_vlan {
|
|
my $self = shift;
|
|
my $vlan_id=shift;
|
|
my $vlan_name="xcat_vlan_" . $vlan_id;
|
|
|
|
#print "create vlan get called.\n";
|
|
|
|
my $session=$self->{session};
|
|
if (! $self->{session}) {
|
|
$session = $self->getsnmpsession();
|
|
}
|
|
#my $session = $self->getsnmpsession();
|
|
unless ($session) { xCAT::MsgUtils->message("S","Failed to communicate with " . $self->{switch}. " or find a plugin module for the switch."); return; }
|
|
#print Dumper($self->{sessionparms});
|
|
|
|
no strict 'refs';
|
|
return ${"xCAT_plugin::vlan::".$self->{module}."::"}{create_vlan}->($session, $vlan_id);
|
|
}
|
|
|
|
#--------------------------------------------------------------
|
|
=head3 add_ports_to_vlan
|
|
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 $self = shift;
|
|
my $vlan_id=shift;
|
|
my $portmode=shift;
|
|
my @ports=@_;
|
|
|
|
#print "vlan=$vlan_id, ports=@ports\n";
|
|
|
|
my $session=$self->{session};
|
|
if (! $self->{session}) {
|
|
$session = $self->getsnmpsession();
|
|
}
|
|
#my $session = $self->getsnmpsession();
|
|
unless ($session) { xCAT::MsgUtils->message("S","Failed to communicate with " . $self->{switch}. " or find a plugin module for the switch."); return; }
|
|
|
|
no strict 'refs';
|
|
return ${"xCAT_plugin::vlan::".$self->{module}."::"}{add_ports_to_vlan}->($session, $vlan_id, $portmode, @ports);
|
|
}
|
|
|
|
#-------------------------------------------------------
|
|
=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 $self = shift;
|
|
my $vlan_id=shift;
|
|
my @switches=@_;
|
|
|
|
if (@switches == 0) { return (0, ""); }
|
|
|
|
my $session=$self->{session};
|
|
if (! $self->{session}) {
|
|
$session = $self->getsnmpsession();
|
|
}
|
|
#my $session = $self->getsnmpsession();
|
|
unless ($session) { xCAT::MsgUtils->message("S","Failed to communicate with " . $self->{switch}. " or find a plugin module for the switch."); return; }
|
|
|
|
no strict 'refs';
|
|
return ${"xCAT_plugin::vlan::".$self->{module}."::"}{add_crossover_ports_to_vlan}->($session, $vlan_id, $self->{switch}, @switches);
|
|
}
|
|
|
|
#--------------------------------------------------------------
|
|
=head3 remove_vlan
|
|
Remove a vlan from the switch
|
|
Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
|
|
=cut
|
|
#-------------------------------------------------------------
|
|
sub remove_vlan {
|
|
my $self = shift;
|
|
my $vlan_id=shift;
|
|
|
|
my $session=$self->{session};
|
|
if (! $self->{session}) {
|
|
$session = $self->getsnmpsession();
|
|
}
|
|
#my $session = $self->getsnmpsession();
|
|
unless ($session) { xCAT::MsgUtils->message("S","Failed to communicate with " . $self->{switch}. " or find a plugin module for the switch."); return; }
|
|
|
|
no strict 'refs';
|
|
return ${"xCAT_plugin::vlan::".$self->{module}."::"}{remove_vlan}->($session, $vlan_id);
|
|
}
|
|
|
|
#--------------------------------------------------------------
|
|
=head3 remove_ports_from_vlan
|
|
Remove ports from a vlan
|
|
Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
|
|
=cut
|
|
#-------------------------------------------------------------
|
|
sub remove_ports_from_vlan {
|
|
my $self = shift;
|
|
my $vlan_id=shift;
|
|
my @ports = @_;
|
|
|
|
my $session=$self->{session};
|
|
if (! $self->{session}) {
|
|
$session = $self->getsnmpsession();
|
|
}
|
|
#my $session = $self->getsnmpsession();
|
|
unless ($session) { xCAT::MsgUtils->message("S","Failed to communicate with " . $self->{switch}. " or find a plugin module for the switch."); return; }
|
|
|
|
no strict 'refs';
|
|
return ${"xCAT_plugin::vlan::".$self->{module}."::"}{remove_ports_from_vlan}->($session, $vlan_id, @ports);
|
|
}
|
|
|
|
|
|
|
|
1;
|