2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2025-05-31 18:16:39 +00:00
xcat-core/xCAT-vlan/xCAT/SwitchHandler.pm
2016-07-20 11:40:27 -04:00

363 lines
11 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;