Commit 264500e2 authored by Kirk Webb's avatar Kirk Webb

Commit portfix version of snmpit and the Port module.

This commit pushes the changes located in the temporary snmpit_portfix
subdirectory into the mainline snmpit_test directory, and updates
db/Ports.pm with the 'portfix' changes.  These changes ensure better
consistency with port lookup/resolution.  In particular, interswitch
trunk lookup will return the switch-local side of the link.

This commit also adds an installer script to cleanup the temporary files
introduced for burning in the snmpit_portfix changes.
parent 7e1d123e
......@@ -55,10 +55,15 @@ use vars qw(@ISA @EXPORT);
@EXPORT = qw ( );
use libdb;
use EmulabConstants;
use English;
use Data::Dumper;
use overload ('""' => 'Stringify');
# Local constants
my $WIRE_END_NODE = "node";
my $WIRE_END_SWITCH = "switch";
# Cache of port instances
# node:iface OR node:card.port => Port Instance
my %allports = ();
......@@ -345,6 +350,11 @@ sub fake_IfaceString2TripleTokens($;$)
# This is useful when a port string is derived from the switch, but
# it is not stored in DB. (eg. listing all ports on a switch)
#
# Note from RPR: We have never represented the switch side of
# [interfaces] (except trunks) in the database. Most 'wires' table
# entries have a "real" [interface] on the PC side, but are just
# dangling references on the switch side.
#
sub LookupByStringForced($$)
{
my ($class, $str) = @_;
......@@ -381,25 +391,34 @@ sub LookupByStringForced($$)
}
if (defined($port)) {
my $rowref = {};
my $irowref = {};
my $wrowref = {};
$inst->{"RAW_STRING"} = $str;
$inst->{"FORCED"} = 1;
$inst->{"HAS_FIELDS"} = 1;
$rowref->{'iface'} = $iface;
$rowref->{'node_id'} = $nodeid;
$rowref->{'card'} = $card;
$rowref->{'port'} = $port;
$rowref->{'mac'} = "";
$rowref->{'IP'} = "";
$rowref->{'role'} = "";
$rowref->{'interface_type'} = "";
$rowref->{'mask'} = "";
$rowref->{'uuid'} = "";
$rowref->{'trunk'} = 0;
$rowref->{'trunk_mode'} = "equal";
$inst->{"INTERFACES_ROW"} = $rowref;
$irowref->{'iface'} = $iface;
$irowref->{'node_id'} = $nodeid;
$irowref->{'card'} = $card;
$irowref->{'port'} = $port;
$irowref->{'mac'} = "";
$irowref->{'IP'} = "";
$irowref->{'role'} = "";
$irowref->{'interface_type'} = "";
$irowref->{'mask'} = "";
$irowref->{'uuid'} = "";
$irowref->{'trunk'} = 0;
$irowref->{'trunk_mode'} = "equal";
$inst->{"INTERFACES_ROW"} = $irowref;
# XXX: Incomplete, but if the port isn't in the wires table,
# what are we to do? We know nothing about the other end.
$wrowref->{'type'} = TBDB_WIRETYPE_UNUSED();
$wrowref->{'node_id1'} = $nodeid;
$wrowref->{'card1'} = $card;
$wrowref->{'port1'} = $port;
$inst->{"WIRES_ROW"} = $wrowref;
}
else {
$inst->{"RAW_STRING"} = $str;
......@@ -411,7 +430,7 @@ sub LookupByStringForced($$)
# We should determine this according to the query result
# in nodes table by nodeid.
#
$inst->{"WIRE_END"} = "switch";
$inst->{"WIRE_END"} = $WIRE_END_SWITCH;
bless($inst, $class);
return $inst;
......@@ -467,24 +486,27 @@ sub LookupByIface($$;$)
# wire mapping
$query_result =
DBQueryWarn("select * from wires ".
"where node_id1='$nodeid' AND card1='$card' AND port1='$port'");
"where (node_id1='$nodeid' AND card1='$card' AND port1='$port') OR (node_id2='$nodeid' AND card2='$card' AND port2='$port')");
return undef
if (!$query_result);
if (!$query_result or !$query_result->numrows);
$inst->{"WIRE_END"} = "pc";
if (!$query_result->numrows) {
$query_result =
DBQueryWarn("select * from wires ".
"where node_id2='$nodeid' AND card2='$card' AND port2='$port'");
return undef
if (!$query_result);
return undef
if (!$query_result->numrows);
$inst->{"WIRE_END"} = "switch";
$rowref = $query_result->fetchrow_hashref();
if ($rowref->{'type'} eq TBDB_WIRETYPE_NODE() ||
$rowref->{'type'} eq TBDB_WIRETYPE_CONTROL()) {
if ($rowref->{'node_id1'} eq $nodeid) {
$inst->{"WIRE_END"} = $WIRE_END_NODE;
} else {
$inst->{"WIRE_END"} = $WIRE_END_SWITCH;
}
} elsif ($rowref->{'type'} eq TBDB_WIRETYPE_TRUNK()) {
$inst->{"WIRE_END"} = $WIRE_END_SWITCH;
} elsif ($rowref->{'node_id2'} eq $nodeid) {
$inst->{"WIRE_END"} = $WIRE_END_SWITCH;
} else {
# XXX: Other cases are unhandled for now...
return undef;
}
$rowref = $query_result->fetchrow_hashref();
$inst->{"WIRES_ROW"} = $rowref;
$inst->{"FORCED"} = 0;
$inst->{"HAS_FIELDS"} = 1;
......@@ -522,28 +544,36 @@ sub LookupByTriple($$;$$)
return $allports{$strtriple};
}
my $inst = {};
# wire mapping:
my $query_result =
DBQueryWarn("select * from wires ".
"where node_id1='$nodeid' AND card1='$card' AND port1='$port'");
"where (node_id1='$nodeid' AND card1='$card' AND port1='$port') OR (node_id2='$nodeid' AND card2='$card' AND port2='$port')");
return undef
if (!$query_result);
my $inst = {};
$inst->{"WIRE_END"} = "pc";
if (!$query_result->numrows) {
$query_result =
DBQueryWarn("select * from wires ".
"where node_id2='$nodeid' AND card2='$card' AND port2='$port'");
return undef
if (!$query_result);
return undef
if (!$query_result->numrows);
$inst->{"WIRE_END"} = "switch";
}
if (!$query_result or !$query_result->numrows);
my $rowref = $query_result->fetchrow_hashref();
if ($rowref->{'type'} eq TBDB_WIRETYPE_NODE() ||
$rowref->{'type'} eq TBDB_WIRETYPE_CONTROL()) {
# Emulab is consistent about using the node_id1, etc. fields for the
# endpoint for the above wire types. If it were not, we would need
# to consult the 'nodes' table to see what role the node has.
if ($rowref->{'node_id1'} eq $nodeid) {
$inst->{"WIRE_END"} = $WIRE_END_NODE;
} else {
$inst->{"WIRE_END"} = $WIRE_END_SWITCH;
}
} elsif ($rowref->{'type'} eq TBDB_WIRETYPE_TRUNK()) {
$inst->{"WIRE_END"} = $WIRE_END_SWITCH;
} elsif ($rowref->{'node_id2'} eq $nodeid) {
# This is a failsafe case for wire types that are 'exotic'.
$inst->{"WIRE_END"} = $WIRE_END_SWITCH;
} else {
# XXX: Other cases are unhandled for now...
return undef;
}
$inst->{"WIRES_ROW"} = $rowref;
$query_result =
......@@ -551,6 +581,10 @@ sub LookupByTriple($$;$$)
"where node_id='$nodeid' AND card='$card' AND port='$port'");
return undef
if (!$query_result);
# Note: The code will almost always fall into this conditional
# block for switch ports because we typically do not have entries
# for them in the 'interfaces' table.
if (!$query_result->numrows) {
$rowref = {};
my $iface = fake_CardPort2Iface($card, $port);
......@@ -646,10 +680,10 @@ sub trunk($) { return field($_[0], 'trunk'); }
sub trunk_mode($) { return field($_[0], 'trunk_mode'); }
sub wire_end($) { return $_[0]->{'WIRE_END'}; }
sub is_switch_side($) { return $_[0]->wire_end() eq "switch"; }
sub is_switch_side($) { return $_[0]->wire_end() eq $WIRE_END_SWITCH; }
sub wire_type($) { return $_[0]->{'WIRES_ROW'}->{'type'}; }
sub is_trunk_port($) { return $_[0]->wire_type() eq "Trunk"; }
sub is_trunk_port($) { return $_[0]->wire_type() eq TBDB_WIRETYPE_TRUNK(); }
sub is_forced($) { return $_[0]->{"FORCED"};}
sub has_fields($) { return $_[0]->{"HAS_FIELDS"};}
......@@ -698,7 +732,8 @@ sub switch_iface($)
sub pc_node_id($)
{
my $self = shift;
if (!$self->is_switch_side()) {
if (!$self->is_switch_side() ||
$self->is_trunk_port()) {
return $self->node_id();
} else {
return $self->other_end_node_id();
......@@ -708,7 +743,8 @@ sub pc_node_id($)
sub pc_card($)
{
my $self = shift;
if (!$self->is_switch_side()) {
if (!$self->is_switch_side() ||
$self->is_trunk_port()) {
return $self->card();
} else {
return $self->other_end_card();
......@@ -718,7 +754,8 @@ sub pc_card($)
sub pc_port($)
{
my $self = shift;
if (!$self->is_switch_side()) {
if (!$self->is_switch_side() ||
$self->is_trunk_port()) {
return $self->port();
} else {
return $self->other_end_port();
......@@ -728,7 +765,8 @@ sub pc_port($)
sub pc_iface($)
{
my $self = shift;
if (!$self->is_switch_side()) {
if (!$self->is_switch_side() ||
$self->is_trunk_port()) {
return $self->iface();
} else {
return $self->other_end_iface();
......@@ -750,7 +788,7 @@ sub other_end_node_id($)
}
}
if ($self->wire_end() eq "pc") {
if ($self->node_id() eq $self->{'WIRES_ROW'}->{'node_id1'}) {
return $self->{'WIRES_ROW'}->{'node_id2'};
} else {
return $self->{'WIRES_ROW'}->{'node_id1'};
......@@ -772,7 +810,7 @@ sub other_end_card($)
}
}
if ($self->wire_end() eq "pc") {
if ($self->node_id() eq $self->{'WIRES_ROW'}->{'node_id1'}) {
return $self->{'WIRES_ROW'}->{'card2'};
} else {
return $self->{'WIRES_ROW'}->{'card1'};
......@@ -794,7 +832,7 @@ sub other_end_port($)
}
}
if ($self->wire_end() eq "pc") {
if ($self->node_id() eq $self->{'WIRES_ROW'}->{'node_id1'}) {
return $self->{'WIRES_ROW'}->{'port2'};
} else {
return $self->{'WIRES_ROW'}->{'port1'};
......@@ -816,7 +854,7 @@ sub other_end_iface($)
}
}
if ($self->wire_end() eq "pc") {
if ($self->node_id() eq $self->{'WIRES_ROW'}->{'node_id1'}) {
return Port->LookupByTriple(
$self->{'WIRES_ROW'}->{'node_id2'},
$self->{'WIRES_ROW'}->{'card2'},
......@@ -911,7 +949,10 @@ sub getOtherEndPort($) {
}
#
# get the PC side of a port instance
# get the PC side of a port instance. It is bogus to call this on an
# inter-switch trunk port, but we return the local ("this") side
# anyway in this case since some snmpit code using this method doesn't
# check the link type.
#
sub getPCPort($) {
my $self = $_[0];
......@@ -920,7 +961,8 @@ sub getPCPort($) {
return $self;
}
if ($self->wire_end() eq "pc") {
if (!$self->is_switch_side() ||
$self->is_trunk_port()) {
return $self;
} else {
return $self->getOtherEndPort();
......@@ -928,7 +970,9 @@ sub getPCPort($) {
}
#
# get the switch side of a port instance
# get the switch side of a port instance. This call is ambiguous in
# the case of an inter-switch trunk port, and will always return "this"
# port.
#
sub getSwitchPort($) {
my $self = $_[0];
......@@ -937,7 +981,7 @@ sub getSwitchPort($) {
return $self;
}
if ($self->wire_end() ne "pc") {
if ($self->is_switch_side()) {
return $self;
} else {
return $self->getOtherEndPort();
......
#
# Delete an obsolete interim snmpit directory used during code burn-in at Utah.
#
use strict;
use libinstall;
use installvars;
sub InstallUpdate($$)
{
my ($version, $phase) = @_;
if ($phase eq "post") {
my $file = "$TBROOT/bin/snmpit_portfix";
if (-e $file) {
Phase "$file", "Deleting $file", sub {
DeleteFileFatal($file);
};
}
my $dir = "$TBROOT/lib/snmpit_portfix";
if (-e $dir) {
Phase "$dir", "Deleting $dir", sub {
ExecQuietFatal("/bin/rm -rf $dir");
};
}
}
return 0;
}
1;
# Local Variables:
# mode:perl
# End:
......@@ -35,7 +35,7 @@ SYSTEM := $(shell uname -s)
include $(OBJDIR)/Makeconf
SUBDIRS = checkpass ns2ir nseparse checkup template_cvsroot \
snmpit_test snmpit_old snmpit_portfix
snmpit_test snmpit_old
ifeq ($(NSVERIFY),1)
SUBDIRS += nsverify
endif
......
......@@ -62,25 +62,6 @@ if (EmulabFeatures->FeatureEnabled("OldSnmpit", $this_user, undef, undef)) {
" Could not exec $newpath: $!");
}
# Check feature access for both the user and the projects they belong to
# for the portfix version of portstats. The user should be a member of at least
# one project, so we will get into the foreach loop to check 'global' and
# 'user' permissions as well.
my @user_projects = ();
$this_user->ProjectMembershipList(\@user_projects);
foreach my $proj (@user_projects) {
if (EmulabFeatures->FeatureEnabled("PortfixSnmpit",
$this_user,
$proj,
undef)) {
my $newpath = "$TB/lib/snmpit_portfix/portstats";
print STDERR "Invoking alternate portstats from $newpath\n";
exec $newpath, @ARGV;
die("*** $0:\n".
" Could not exec $newpath: $!");
}
}
my $newpath = "$TB/lib/snmpit_test/portstats";
exec $newpath, @ARGV;
die("*** $0:\n".
......
......@@ -62,25 +62,6 @@ if (EmulabFeatures->FeatureEnabled("OldSnmpit", $this_user, undef, undef)) {
" Could not exec $newpath: $!");
}
# Check feature access for both the user and the projects they belong to
# for the portfix version of snmpit. The user should be a member of at least
# one project, so we will get into the foreach loop to check 'global' and
# 'user' permissions as well.
my @user_projects = ();
$this_user->ProjectMembershipList(\@user_projects);
foreach my $proj (@user_projects) {
if (EmulabFeatures->FeatureEnabled("PortfixSnmpit",
$this_user,
$proj,
undef)) {
my $newpath = "$TB/bin/snmpit_portfix";
print STDERR "Invoking alternate snmpit from $newpath\n";
exec $newpath, @ARGV;
die("*** $0:\n".
" Could not exec $newpath: $!");
}
}
my $newpath = "$TB/bin/snmpit_test";
exec $newpath, @ARGV;
die("*** $0:\n".
......
#
# Copyright (c) 2000-2013 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this file. If not, see <http://www.gnu.org/licenses/>.
#
# }}}
#
SRCDIR = @srcdir@
TESTBED_SRCDIR = @top_srcdir@
OBJDIR = ../..
SUBDIR = tbsetup/snmpit_portfix
ISMAINSITE = @TBMAINSITE@
SYSTEM := $(shell uname -s)
include $(OBJDIR)/Makeconf
SUBDIRS =
BIN_STUFF = snmpit_portfix
LIB_STUFF = portstats snmpit_intel.pm \
snmpit_cisco.pm snmpit_lib.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 \
snmpit_arista.pm snmpit_arista_switch_daemon.py \
snmpit_mellanox.pm MLNX_XMLGateway.pm Port_portfix.pm
#
# Force dependencies on the scripts so that they will be rerun through
# configure if the .in file is changed.
#
all: $(LIB_STUFF) $(BIN_STUFF)
include $(TESTBED_SRCDIR)/GNUmakerules
install: all script-install
script-install: $(addprefix $(INSTALL_LIBDIR)/snmpit_portfix/, $(LIB_STUFF)) \
$(addprefix $(INSTALL_BINDIR)/, $(BIN_STUFF))
control-install:
fs-install:
tipserv-install:
clrhouse-install:
clean:
rm -f snmpit_arista_switch_daemon.py snmpit_remote.pm \
snmpit_portfix portstats snmpit_arista.pm
$(INSTALL_DIR)/lib/snmpit_portfix/%: %
@echo "Installing $<"
-mkdir -p $(INSTALL_DIR)/lib/snmpit_portfix
$(INSTALL) $< $@
$(INSTALL_DIR)/lib/snmpit_portfix/portstats: portstats
@echo "Installing $<"
-mkdir -p $(INSTALL_DIR)/lib/snmpit_portfix
$(INSTALL_PROGRAM) $< $@
#!/usr/bin/perl -w
#
# Copyright (c) 2013 University of Utah and the Flux Group.
#
# {{{EMULAB-LGPL
#
# This file is part of the Emulab network testbed software.
#
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
# License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this file. If not, see <http://www.gnu.org/licenses/>.
#
# }}}
#
# Simple test harness for the MLNX-gateway module.
use MLNX_XMLGateway;
use Getopt::Std;
use strict;
my @get_test1 = (
["name", "Basic 'get' Test #1"],
["get","/mlnxos/v1/api_version"],
["get","/mlnxos/v1/chassis/model"],
["get","/mlnxos/v1/chassis/pn"],
["get","/mlnxos/v1/chassis/fans/FAN/1/speed"],
["get","/mlnxos/v1/vsr/default_vsr/vlans/*"],
["submit"]
);
my @get_test2 = (
["name","Interface name 'get' Test #2"],
["get","/mlnxos/v1/vsr/default_vsr/interfaces_by_name/*"],
["submit"]
);
my @pget_test1 = (
["name", "Port 'get' Test (Eth1/8) #1"],
["get","/mlnxos/v1/vsr/default_vsr/interfaces/101/enabled"],
["get","/mlnxos/v1/vsr/default_vsr/interfaces/101/type"],
["get","/mlnxos/v1/vsr/default_vsr/interfaces/101/mtu"],
["get","/mlnxos/v1/vsr/default_vsr/interfaces/101/vlans/pvid"],
["get","/mlnxos/v1/vsr/default_vsr/interfaces/101/vlans/mode"],
["get","/mlnxos/v1/vsr/default_vsr/interfaces/101/vlans/allowed/*"],
["get","/mlnxos/v1/vsr/default_vsr/interfaces/101/physical_location"],
["get","/mlnxos/v1/vsr/default_vsr/interfaces/101/supported_speed"],
["get","/mlnxos/v1/vsr/default_vsr/interfaces/101/configured_speed"],
["get","/mlnxos/v1/vsr/default_vsr/interfaces/101/actual_speed"],
["get","/mlnxos/v1/vsr/default_vsr/interfaces/101/lag/membership"],
["submit"]
);
my @pget_test2 = (
["name", "Port 'get' Test (Po1) #2"],
["get","/mlnxos/v1/vsr/default_vsr/interfaces/13826/enabled"],
["get","/mlnxos/v1/vsr/default_vsr/interfaces/13826/type"],
["get","/mlnxos/v1/vsr/default_vsr/interfaces/13826/vlans/pvid"],
["get","/mlnxos/v1/vsr/default_vsr/interfaces/13826/vlans/mode"],
["get","/mlnxos/v1/vsr/default_vsr/interfaces/13826/vlans/allowed/*"],
["submit"]
);
my @vlan_test1 = (
["name", "Vlan Creation Test #1"],
["action","/mlnxos/v1/vsr/default_vsr/vlans/add",{vlan_id => 666}],
["set-modify","/mlnxos/v1/vsr/default_vsr/vlans/666/name=testvlan"],
["get","/mlnxos/v1/vsr/default_vsr/vlans/*"],
["submit"],
["action","/mlnxos/v1/vsr/default_vsr/vlans/delete",{vlan_id => 666}],
["get","/mlnxos/v1/vsr/default_vsr/vlans/*"],
["submit"]
);
my @port_test1 = (
["name", "Port Toggle Test (Eth1/8) #1"],
["set-modify","/mlnxos/v1/vsr/default_vsr/interfaces/101/enabled=false"],
["get","/mlnxos/v1/vsr/default_vsr/interfaces/101/enabled"],
["submit"],
["set-modify","/mlnxos/v1/vsr/default_vsr/interfaces/101/enabled=true"],
["get","/mlnxos/v1/vsr/default_vsr/interfaces/101/enabled"],
["submit"]
);
my @vport_test1 = (
["name", "Vlan + Port Test (Eth1/8) #1"],
["action","/mlnxos/v1/vsr/default_vsr/vlans/add",{vlan_id => 666}],
["set-modify","/mlnxos/v1/vsr/default_vsr/vlans/666/name=testvlan"],
["set-modify","/mlnxos/v1/vsr/default_vsr/interfaces/101/vlans/pvid=666"],
["get","/mlnxos/v1/vsr/default_vsr/vlans/*"],
["get","/mlnxos/v1/vsr/default_vsr/interfaces/101/vlans/pvid"],
["submit"],
["action","/mlnxos/v1/vsr/default_vsr/vlans/delete",{vlan_id => 666}],
["set-modify","/mlnxos/v1/vsr/default_vsr/interfaces/101/vlans/pvid=53"],
["get","/mlnxos/v1/vsr/default_vsr/vlans/*"],
["get","/mlnxos/v1/vsr/default_vsr/interfaces/101/vlans/pvid"],
["submit"]
);
my @trunk_test1 = (
["name", "Trunk Test (Eth1/8) #1"],
["action","/mlnxos/v1/vsr/default_vsr/vlans/add",{vlan_id => 666}],
["set-modify","/mlnxos/v1/vsr/default_vsr/vlans/666/name=testvlan1"],
["action","/mlnxos/v1/vsr/default_vsr/vlans/add",{vlan_id => 777}],
["set-modify","/mlnxos/v1/vsr/default_vsr/vlans/666/name=testvlan2"],
["set-modify","/mlnxos/v1/vsr/default_vsr/interfaces/101/vlans/mode=trunk"],
["action","/mlnxos/v1/vsr/default_vsr/interfaces/101/vlans/allowed/add",{vlan_ids => "666"}],
["action","/mlnxos/v1/vsr/default_vsr/interfaces/101/vlans/allowed/add",{vlan_ids => "777"}],
["submit"],
["get","/mlnxos/v1/vsr/default_vsr/interfaces/101/vlans/allowed/*"],
["get","/mlnxos/v1/vsr/default_vsr/interfaces/101/vlans/mode"],
["submit"],
["action","/mlnxos/v1/vsr/default_vsr/interfaces/101/vlans/allowed/delete",{vlan_ids => "666"}],
["action","/mlnxos/v1/vsr/default_vsr/interfaces/101/vlans/allowed/delete",{vlan_ids => "777"}],
["set-modify","/mlnxos/v1/vsr/default_vsr/interfaces/101/vlans/mode=access"],
["action","/mlnxos/v1/vsr/default_vsr/vlans/delete",{vlan_id => 666}],
["action","/mlnxos/v1/vsr/default_vsr/vlans/delete",{vlan_id => 777}],
["submit"]
);
# List the tests to run here.
my @testsets = (\@pget_test1,);
my %opts = ();
if (!getopts("a:d:",\%opts)) {
print "Usage: $0 -a <uri_auth_string> -d <level>\n";
exit 1;
}
my $auth = "";
my $debug = 0;
$auth = $opts{'a'} or die "Must specify an auth string!";
$debug = $opts{'d'} if $opts{'d'};
my $gateway = MLNX_XMLGateway->new($auth);
$gateway->debug($debug) if $debug;
foreach my $tlist (@testsets) {
my @cmdset = ();
my @results = ();
my $testname = "unnamed";