Commit 3dcbc68c authored by Leigh B Stoller's avatar Leigh B Stoller
Browse files

Make copies of the snmpit libraries in a different directory before

attempting the Port merge again. There is no git "fork" so we end up
losing history, but so be it.
parent 0556b072
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2011 University of Utah and the Flux Group.
# All rights reserved.
#
SRCDIR = @srcdir@
TESTBED_SRCDIR = @top_srcdir@
OBJDIR = ../..
SUBDIR = tbsetup/snmpit_test
ISMAINSITE = @TBMAINSITE@
SYSTEM := $(shell uname -s)
include $(OBJDIR)/Makeconf
SUBDIRS =
LIB_STUFF = snmpit_intel.pm \
snmpit_cisco.pm snmpit_lib.pm snmpit_apc.pm \
snmpit_cisco_stack.pm snmpit_intel_stack.pm \
snmpit_foundry.pm snmpit_stack.pm snmpit_remote.pm \
snmpit_nortel.pm snmpit_hp.pm snmpit_apcon.pm
#
# Force dependencies on the scripts so that they will be rerun through
# configure if the .in file is changed.
#
all: $(LIB_STUFF)
include $(TESTBED_SRCDIR)/GNUmakerules
install: all script-install
script-install: $(addprefix $(INSTALL_LIBDIR)/snmpit_test/, $(LIB_STUFF))
control-install:
fs-install:
tipserv-install:
clrhouse-install:
clean:
$(INSTALL_DIR)/lib/snmpit_test/%: %
@echo "Installing $<"
-mkdir -p $(INSTALL_DIR)/lib/snmpit_test
$(INSTALL) $< $@
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2009 University of Utah and the Flux Group.
# All rights reserved.
#
#
# snmpit module for APC MasterSwitch power controllers
#
# supports new(ip), power(on|off|cyc[le],port), status
#
package snmpit_apc;
$| = 1; # Turn off line buffering on output
use SNMP;
use strict;
sub new($$;$) {
# The next two lines are some voodoo taken from perltoot(1)
my $proto = shift;
my $class = ref($proto) || $proto;
my $devicename = shift;
my $debug = shift;
if (!defined($debug)) {
$debug = 0;
}
if ($debug) {
print "snmpit_apm module initializing... debug level $debug\n";
}
$SNMP::debugging = ($debug - 5) if $debug > 5;
my $mibpath = "/usr/local/share/snmp/mibs";
&SNMP::addMibDirs($mibpath);
&SNMP::addMibFiles("$mibpath/SNMPv2-SMI.txt",
"$mibpath/SNMPv2-MIB.txt",
"$mibpath/RFC1155-SMI.txt",
"$mibpath/PowerNet-MIB.txt");
$SNMP::save_descriptions = 1; # must be set prior to mib initialization
SNMP::initMib(); # parses default list of Mib modules
$SNMP::use_enums = 1; #use enum values instead of only ints
print "Opening SNMP session to $devicename..." if $debug;
my $sess =new SNMP::Session(DestHost => $devicename, Community => 'private', Version => '1');
if (!defined($sess)) {
warn("ERROR: Unable to connect to $devicename via SNMP\n");
return undef;
}
my $self = {};
$self->{SESS} = $sess;
$self->{DEBUG} = $debug;
$self->{DEVICENAME} = $devicename;
bless($self,$class);
return $self;
}
my %CtlOIDS = (
default => ["sPDUOutletCtl",
"outletOn", "outletOff", "outletReboot"],
rPDU => ["rPDUOutletControlOutletCommand",
"immediateOn", "immediateOff", "immediateReboot"]
);
sub power {
my $self = shift;
my $op = shift;
my @ports = @_;
my $oids = $CtlOIDS{"default"};
my $type = SNMP::translateObj($self->{SESS}->get("sysObjectID.0"));
if (defined($type) &&
$type eq "masterSwitchrPDU") { $oids = $CtlOIDS{"rPDU"}; }
# "sPDUOutletCtl" is ".1.3.6.1.4.1.318.1.1.4.4.2.1.3";
if ($op eq "on") { $op = @$oids[1]; }
elsif ($op eq "off") { $op = @$oids[2]; }
elsif ($op =~ /cyc/) { $op = @$oids[3]; }
my $errors = 0;
foreach my $port (@ports) {
print STDERR "**** Controlling port $port\n" if ($self->{DEBUG} > 1);
if ($self->UpdateField(@$oids[0],$port,$op)) {
print STDERR "Outlet #$port control failed.\n";
$errors++;
}
}
return $errors;
}
sub status {
my $self = shift;
my $statusp = shift;
my %status;
my $StatOID = ".1.3.6.1.4.1.318.1.1.4.2.2";
my $Status = 0;
$Status = $self->{SESS}->get([[$StatOID,0]]);
if (!defined $Status) {
print STDERR $self->{DEVICENAME}, ": no answer from device\n";
return 1;
}
print("Status is '$Status'\n") if $self->{DEBUG};
if ($statusp) {
my @stats = split '\s+', $Status;
my $o = 1;
foreach my $ostat (@stats) {
my $outlet = "outlet$o";
$status{$outlet} = $ostat;
$o++;
}
%$statusp = %status;
}
#
# We can retrieve the total amperage in use (in tenths of amps)
# on an APC by retrieving the rPDULoadStatusLoad. There are
# entries for each of the phases of power that the device supports,
# and for each of the banks of power it provides.
#
# We could add either the phases or the banks, but since the phases
# come first, we use them. We grab the number of phases supported,
# then use that as a limit on how many status load values we retrieve.
#
# The OID to retrieve the phases is: ".1.3.6.1.4.1.318.1.1.12.1.9"
# for more recent units, or: ".1.3.6.1.4.1.318.1.1.12.2.1.2"
# for older ones;
# the load status table OID is: ".1.3.6.1.4.1.318.1.1.12.2.3.1.1.2".
#
my $phases;
$phases = $self->{SESS}->get([["rPDUIdentDeviceNumPhases",0]]);
if (!$phases) {
# not all models support this MIB, try another
$phases = $self->{SESS}->get([["rPDULoadDevNumPhases",0]]);
if (!$phases) {
# some don't support either, bail.
print STDERR "Query phase: IdentDeviceNumPhases/LoadDevNumPhases failed\n"
if $self->{DEBUG};
return 0;
}
}
print "Okay.\nPhase report was '$phases'\n" if $self->{DEBUG};
my ($varname, $index, $power, $val, $done);
my $oid = ["rPDULoadStatusLoad",1];
$self->{SESS}->get($oid);
while ($$oid[0] =~ /rPDULoad/) {
($varname, $index, $val) = @{$oid};
if ($varname eq "rPDULoadStatusLoad") {
if ($index <= $phases) {
print "Raw current value $val\n" if $self->{DEBUG};
$status{current} += $val;
}
}
$self->{SESS}->getnext($oid);
}
print "Total raw current is $status{current}\n" if $self->{DEBUG};
$status{current} /= 10;
if ($statusp) {
%$statusp = %status;
}
return 0;
}
sub UpdateField {
my ($self,$OID,$port,$val) = @_;
print "sess=$self->{SESS} $OID $port $val\n" if $self->{DEBUG} > 1;
my $Status = 0;
my $retval;
print "Checking port $port of $self->{DEVICENAME} for $val..." if $self->{DEBUG};
$Status = $self->{SESS}->get([[$OID,$port]]);
if (!defined $Status) {
print STDERR "Port $port, change to $val: No answer from device\n";
return 1;
} else {
print "Okay.\nPort $port was $Status\n" if $self->{DEBUG};
if ($Status ne $val) {
print "Setting $port to $val..." if $self->{DEBUG};
$retval = $self->{SESS}->set([[$OID,$port,$val,"INTEGER"]]);
print "Set returned '$retval'" if $self->{DEBUG};
if ($retval) { return 0; } else { return 1; }
}
return 0;
}
}
# End with true
1;
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#!/usr/bin/perl -w
#
# EMULAB-LGPL
# Copyright (c) 2000-2003 University of Utah and the Flux Group.
# All rights reserved.
#
#
# snmpit module for Intel EtherExpress 510T switches. This module is largely
# just a wrapper around snmpit_intel, but is here just in case we ever need to
# contact multiple switches (which may happen if we move to port-based (instead
# of MAC-based) VLANs.) For now, though, pretty much everything just calls
# $self->{LEADER}->foo()
#
package snmpit_intel_stack;
use strict;
$| = 1; # Turn off line buffering on output
use English;
use SNMP;
use snmpit_lib;
use libdb;
#
# Creates a new object. A list of devices that will be operated on is given
# so that the object knows which to connect to. A future version may not
# require the device list, and dynamically connect to devices as appropriate
#
# For an Intel stack, the stack_id happens to also be the name of the stack
# leader.
#
# usage: new(string name, string stack_id, int debuglevel list of devicenames)
# returns a new object blessed into the snmpit_intel_stack class
#
sub new($$$@) {
# The next two lines are some voodoo taken from perltoot(1)
my $proto = shift;
my $class = ref($proto) || $proto;
my $stack_id = shift;
my $debuglevel = shift;
my @devicenames = @_; # Devicenames are not presently needed for Intel
# stacks
#
# Create the actual object
#
my $self = {};
#
# Set up some defaults
#
if (defined $debuglevel) {
$self->{DEBUG} = $debuglevel;
} else {
$self->{DEBUG} = 0;
}
#
# The stackid just happens to also be leader of the stack
#
$self->{STACKID} = $stack_id;
#
# We only need to create 1 snmpit_intel object, since we only have to
# talk to one (for now) to do all the setup we need. We fall back on the
# old behavior of using the stack name as the leader if the leader is not
# set
#
my $leader_name = getStackLeader($stack_id);
if (!$leader_name) {
$leader_name = $stack_id;
}
$self->{LEADERNAME} = $leader_name;
use snmpit_intel;
$self->{LEADER} = new snmpit_intel($leader_name,$self->{DEBUG});
#
# Check for failed object creation
#
if (!$self->{LEADER}) {
#
# The snmpit_intel object has already printed an error message,
# so we'll just return an error
#
return undef;
}
bless($self,$class);
return $self;
}
#
# NOTE: See snmpit_cisco_stack for descriptions of these functions.
# XXX: Document these functions
#
sub listVlans($) {
my $self = shift;
return $self->{LEADER}->listVlans();
}
sub listPorts($) {
my $self = shift;
return $self->{LEADER}->listPorts();
}
sub setPortVlan($$@) {
my $self = shift;
my $vlan_id = shift;
my @ports = @_;
return $self->{LEADER}->setPortVlan($vlan_id,@ports);
}
sub createVlan($$$;@) {
my $self = shift;
my $vlan_id = shift;
my @ports = @{shift()};
#
# We ignore other args for now, since Intels don't support private VLANs
#
return $self->{LEADER}->createVlan($vlan_id,@ports);
}
sub addDevicesToVlan($$@) {
my $self = shift;
my $vlan_id = shift;
my @devicenames = @_; # Note: This is not used for Intel switches
#
# This function is not needed on Intel stacks, but it may be someday
#
if (!$self->vlanExists($vlan_id)) {
return 1;
}
return 0;
}
sub vlanExists($$) {
my $self = shift;
my $vlan_id = shift;
if ($self->{LEADER}->findVlan($vlan_id,1)) {
return 1;
} else {
return 0;
}
}
#
# Return a list of which VLANs from the input set exist on this stack
#
# usage: existantVlans(self, vlan identifiers)
#
# returns: a list containing the VLANs from the input set that exist on this
# stack
#
sub existantVlans($@) {
my $self = shift;
my @vlan_ids = @_;
#
# The leader holds the list of which VLANs exist
#
my %mapping = $self->{LEADER}->findVlans(@vlan_ids);
my @existant = ();
foreach my $vlan_id (@vlan_ids) {
if (defined $mapping{$vlan_id}) {
push @existant, $vlan_id;
}
}
return @existant;
}
sub removeVlan($@) {
my $self = shift;
my @vlan_ids = @_;
my $errors = 0;
foreach my $vlan_id (@vlan_ids) {
#
# First, make sure that the VLAN really does exist
#
my $vlan_number = $self->{LEADER}->findVlan($vlan_id);
if (!$vlan_number) {
warn "ERROR: VLAN $vlan_id not found on switch!";
$errors++;
}
my $ok = $self->{LEADER}->removeVlan($vlan_id);
if (!$ok) {
$errors++;
}
}
return ($errors == 0);
}
sub portControl ($$@) {
my $self = shift;
my $cmd = shift;
my @ports = @_;
return $self->{LEADER}->portControl($cmd,@ports);
}
sub getStats($) {
my $self = shift;
return $self->{LEADER}->getStats();
}
#
# Openflow enable function for Intel stack
# Till now it just report an error.
#
# enableOpenflow(self, vlan_id)
# return # of errors
#
sub enableOpenflow($$) {
my $self = shift;
my $vlan_id = shift;
my $errors = 0;
foreach my $devicename (keys %{$self->{DEVICES}})
{
my $device = $self->{DEVICES}{$devicename};
my $vlan_number = $device->findVlan($vlan_id, 2);
if (!$vlan_number) {
#
# Not sure if this is an error or not.
# It might be possible that not all devices in a stack have the given VLAN.
#
print "$device has no VLAN $vlan_id, ignore it. \n" if $self->{DEBUG};
} else {
if ($device->isOpenflowSupported()) {
print "Enabling Openflow on $devicename for VLAN $vlan_id".
"..." if $self->{DEBUG};
my $ok = $device->enableOpenflow($vlan_number);
if (!$ok) { $errors++; }
else {print "Done! \n" if $self->{DEBUG};}
} else {
#
# TODO: Should this be an error?
#
warn "ERROR: Openflow is not supported on $devicename \n";
$errors++;
}
}
}
return $errors;
}
#
# Disable Openflow
#
# disableOpenflow(self, vlan_id);
# return # of errors
#
sub disableOpenflow($$) {
my $self = shift;
my $vlan_id = shift;
my $errors = 0;
foreach my $devicename (keys %{$self->{DEVICES}})
{
my $device = $self->{DEVICES}{$devicename};
my $vlan_number = $device->findVlan($vlan_id, 2);
if (!$vlan_number) {
#
# Not sure if this is an error or not.
# It might be possible that not all devices in a stack have the given VLAN.
#
print "$device has no VLAN $vlan_id, ignore it. \n" if $self->{DEBUG};
} else {
if ($device->isOpenflowSupported()) {
print "Disabling Openflow on $devicename for VLAN $vlan_id".
"..." if $self->{DEBUG};
my $ok = $device->disableOpenflow($vlan_number);
if (!$ok) { $errors++; }
else {print "Done! \n" if $self->{DEBUG};}
} else {
#
# TODO: Should this be an error?
#
warn "ERROR: Openflow is not supported on $devicename \n";
$errors++;
}
}
}
return $errors;
}
#
# Set Openflow controller on VLAN
#
# setController(self, vlan_id, controller);
# return # of errors
#
sub setOpenflowController($$$) {
my $self = shift;
my $vlan_id = shift;
my $controller = shift;
my $errors = 0;
foreach my $devicename (keys %{$self->{DEVICES}})
{
my $device = $self->{DEVICES}{$devicename};
my $vlan_number = $device->findVlan($vlan_id, 2);
if (!$vlan_number) {
#
# Not sure if this is an error or not.
# It might be possible that not all devices in a stack have the given VLAN.
#
print "$device has no VLAN $vlan_id, ignore it. \n" if $self->{DEBUG};
} else {
if ($device->isOpenflowSupported()) {
print "Setting Openflow controller on $devicename for VLAN $vlan_id".
"..." if $self->{DEBUG};