Commit abe2c7c7 authored by Kirk Webb's avatar Kirk Webb

Create a new directory for the "portfix" version of snmpit.

In order to test the portfix changes to snmpit, a new version of
the tool and its modules has been split off here.  This new version
will be selected via a site variable / emulab feature.  This also
reverts changes to the mainline Ports module and snmpit modules
in the snmpit_test subdirectory.  The modified Port module will
go by the name of Ports_portfix.pm, and will ultimately disappear
once these changes have been vetted at the Utah Emulab site.
parent 08f71970
...@@ -55,15 +55,10 @@ use vars qw(@ISA @EXPORT); ...@@ -55,15 +55,10 @@ use vars qw(@ISA @EXPORT);
@EXPORT = qw ( ); @EXPORT = qw ( );
use libdb; use libdb;
use EmulabConstants;
use English; use English;
use Data::Dumper; use Data::Dumper;
use overload ('""' => 'Stringify'); use overload ('""' => 'Stringify');
# Local constants
my $WIRE_END_NODE = "node";
my $WIRE_END_SWITCH = "switch";
# Cache of port instances # Cache of port instances
# node:iface OR node:card.port => Port Instance # node:iface OR node:card.port => Port Instance
my %allports = (); my %allports = ();
...@@ -350,11 +345,6 @@ sub fake_IfaceString2TripleTokens($;$) ...@@ -350,11 +345,6 @@ sub fake_IfaceString2TripleTokens($;$)
# This is useful when a port string is derived from the switch, but # 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) # 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($$) sub LookupByStringForced($$)
{ {
my ($class, $str) = @_; my ($class, $str) = @_;
...@@ -391,34 +381,25 @@ sub LookupByStringForced($$) ...@@ -391,34 +381,25 @@ sub LookupByStringForced($$)
} }
if (defined($port)) { if (defined($port)) {
my $irowref = {}; my $rowref = {};
my $wrowref = {};
$inst->{"RAW_STRING"} = $str; $inst->{"RAW_STRING"} = $str;
$inst->{"FORCED"} = 1; $inst->{"FORCED"} = 1;
$inst->{"HAS_FIELDS"} = 1; $inst->{"HAS_FIELDS"} = 1;
$irowref->{'iface'} = $iface; $rowref->{'iface'} = $iface;
$irowref->{'node_id'} = $nodeid; $rowref->{'node_id'} = $nodeid;
$irowref->{'card'} = $card; $rowref->{'card'} = $card;
$irowref->{'port'} = $port; $rowref->{'port'} = $port;
$irowref->{'mac'} = ""; $rowref->{'mac'} = "";
$irowref->{'IP'} = ""; $rowref->{'IP'} = "";
$irowref->{'role'} = ""; $rowref->{'role'} = "";
$irowref->{'interface_type'} = ""; $rowref->{'interface_type'} = "";
$irowref->{'mask'} = ""; $rowref->{'mask'} = "";
$irowref->{'uuid'} = ""; $rowref->{'uuid'} = "";
$irowref->{'trunk'} = 0; $rowref->{'trunk'} = 0;
$irowref->{'trunk_mode'} = "equal"; $rowref->{'trunk_mode'} = "equal";
$inst->{"INTERFACES_ROW"} = $irowref; $inst->{"INTERFACES_ROW"} = $rowref;
# 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 { else {
$inst->{"RAW_STRING"} = $str; $inst->{"RAW_STRING"} = $str;
...@@ -430,7 +411,7 @@ sub LookupByStringForced($$) ...@@ -430,7 +411,7 @@ sub LookupByStringForced($$)
# We should determine this according to the query result # We should determine this according to the query result
# in nodes table by nodeid. # in nodes table by nodeid.
# #
$inst->{"WIRE_END"} = $WIRE_END_SWITCH; $inst->{"WIRE_END"} = "switch";
bless($inst, $class); bless($inst, $class);
return $inst; return $inst;
...@@ -486,27 +467,24 @@ sub LookupByIface($$;$) ...@@ -486,27 +467,24 @@ sub LookupByIface($$;$)
# wire mapping # wire mapping
$query_result = $query_result =
DBQueryWarn("select * from wires ". DBQueryWarn("select * from wires ".
"where (node_id1='$nodeid' AND card1='$card' AND port1='$port') OR (node_id2='$nodeid' AND card2='$card' AND port2='$port')"); "where node_id1='$nodeid' AND card1='$card' AND port1='$port'");
return undef return undef
if (!$query_result or !$query_result->numrows); if (!$query_result);
$rowref = $query_result->fetchrow_hashref(); $inst->{"WIRE_END"} = "pc";
if ($rowref->{'type'} eq TBDB_WIRETYPE_NODE() ||
$rowref->{'type'} eq TBDB_WIRETYPE_CONTROL()) { if (!$query_result->numrows) {
if ($rowref->{'node_id1'} eq $nodeid) { $query_result =
$inst->{"WIRE_END"} = $WIRE_END_NODE; DBQueryWarn("select * from wires ".
} else { "where node_id2='$nodeid' AND card2='$card' AND port2='$port'");
$inst->{"WIRE_END"} = $WIRE_END_SWITCH; return undef
} if (!$query_result);
} elsif ($rowref->{'type'} eq TBDB_WIRETYPE_TRUNK()) { return undef
$inst->{"WIRE_END"} = $WIRE_END_SWITCH; if (!$query_result->numrows);
} elsif ($rowref->{'node_id2'} eq $nodeid) { $inst->{"WIRE_END"} = "switch";
$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->{"WIRES_ROW"} = $rowref;
$inst->{"FORCED"} = 0; $inst->{"FORCED"} = 0;
$inst->{"HAS_FIELDS"} = 1; $inst->{"HAS_FIELDS"} = 1;
...@@ -544,36 +522,28 @@ sub LookupByTriple($$;$$) ...@@ -544,36 +522,28 @@ sub LookupByTriple($$;$$)
return $allports{$strtriple}; return $allports{$strtriple};
} }
my $inst = {};
# wire mapping: # wire mapping:
my $query_result = my $query_result =
DBQueryWarn("select * from wires ". DBQueryWarn("select * from wires ".
"where (node_id1='$nodeid' AND card1='$card' AND port1='$port') OR (node_id2='$nodeid' AND card2='$card' AND port2='$port')"); "where node_id1='$nodeid' AND card1='$card' AND port1='$port'");
return undef return undef
if (!$query_result or !$query_result->numrows); if (!$query_result);
my $rowref = $query_result->fetchrow_hashref(); my $inst = {};
if ($rowref->{'type'} eq TBDB_WIRETYPE_NODE() || $inst->{"WIRE_END"} = "pc";
$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;
}
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";
}
my $rowref = $query_result->fetchrow_hashref();
$inst->{"WIRES_ROW"} = $rowref; $inst->{"WIRES_ROW"} = $rowref;
$query_result = $query_result =
...@@ -581,10 +551,6 @@ sub LookupByTriple($$;$$) ...@@ -581,10 +551,6 @@ sub LookupByTriple($$;$$)
"where node_id='$nodeid' AND card='$card' AND port='$port'"); "where node_id='$nodeid' AND card='$card' AND port='$port'");
return undef return undef
if (!$query_result); 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) { if (!$query_result->numrows) {
$rowref = {}; $rowref = {};
my $iface = fake_CardPort2Iface($card, $port); my $iface = fake_CardPort2Iface($card, $port);
...@@ -680,10 +646,10 @@ sub trunk($) { return field($_[0], 'trunk'); } ...@@ -680,10 +646,10 @@ sub trunk($) { return field($_[0], 'trunk'); }
sub trunk_mode($) { return field($_[0], 'trunk_mode'); } sub trunk_mode($) { return field($_[0], 'trunk_mode'); }
sub wire_end($) { return $_[0]->{'WIRE_END'}; } sub wire_end($) { return $_[0]->{'WIRE_END'}; }
sub is_switch_side($) { return $_[0]->wire_end() eq $WIRE_END_SWITCH; } sub is_switch_side($) { return $_[0]->wire_end() eq "switch"; }
sub wire_type($) { return $_[0]->{'WIRES_ROW'}->{'type'}; } sub wire_type($) { return $_[0]->{'WIRES_ROW'}->{'type'}; }
sub is_trunk_port($) { return $_[0]->wire_type() eq TBDB_WIRETYPE_TRUNK(); } sub is_trunk_port($) { return $_[0]->wire_type() eq "Trunk"; }
sub is_forced($) { return $_[0]->{"FORCED"};} sub is_forced($) { return $_[0]->{"FORCED"};}
sub has_fields($) { return $_[0]->{"HAS_FIELDS"};} sub has_fields($) { return $_[0]->{"HAS_FIELDS"};}
...@@ -732,8 +698,7 @@ sub switch_iface($) ...@@ -732,8 +698,7 @@ sub switch_iface($)
sub pc_node_id($) sub pc_node_id($)
{ {
my $self = shift; my $self = shift;
if (!$self->is_switch_side() || if (!$self->is_switch_side()) {
$self->is_trunk_port()) {
return $self->node_id(); return $self->node_id();
} else { } else {
return $self->other_end_node_id(); return $self->other_end_node_id();
...@@ -743,8 +708,7 @@ sub pc_node_id($) ...@@ -743,8 +708,7 @@ sub pc_node_id($)
sub pc_card($) sub pc_card($)
{ {
my $self = shift; my $self = shift;
if (!$self->is_switch_side() || if (!$self->is_switch_side()) {
$self->is_trunk_port()) {
return $self->card(); return $self->card();
} else { } else {
return $self->other_end_card(); return $self->other_end_card();
...@@ -754,8 +718,7 @@ sub pc_card($) ...@@ -754,8 +718,7 @@ sub pc_card($)
sub pc_port($) sub pc_port($)
{ {
my $self = shift; my $self = shift;
if (!$self->is_switch_side() || if (!$self->is_switch_side()) {
$self->is_trunk_port()) {
return $self->port(); return $self->port();
} else { } else {
return $self->other_end_port(); return $self->other_end_port();
...@@ -765,8 +728,7 @@ sub pc_port($) ...@@ -765,8 +728,7 @@ sub pc_port($)
sub pc_iface($) sub pc_iface($)
{ {
my $self = shift; my $self = shift;
if (!$self->is_switch_side() || if (!$self->is_switch_side()) {
$self->is_trunk_port()) {
return $self->iface(); return $self->iface();
} else { } else {
return $self->other_end_iface(); return $self->other_end_iface();
...@@ -788,7 +750,7 @@ sub other_end_node_id($) ...@@ -788,7 +750,7 @@ sub other_end_node_id($)
} }
} }
if ($self->node_id() eq $self->{'WIRES_ROW'}->{'node_id1'}) { if ($self->wire_end() eq "pc") {
return $self->{'WIRES_ROW'}->{'node_id2'}; return $self->{'WIRES_ROW'}->{'node_id2'};
} else { } else {
return $self->{'WIRES_ROW'}->{'node_id1'}; return $self->{'WIRES_ROW'}->{'node_id1'};
...@@ -810,7 +772,7 @@ sub other_end_card($) ...@@ -810,7 +772,7 @@ sub other_end_card($)
} }
} }
if ($self->node_id() eq $self->{'WIRES_ROW'}->{'node_id1'}) { if ($self->wire_end() eq "pc") {
return $self->{'WIRES_ROW'}->{'card2'}; return $self->{'WIRES_ROW'}->{'card2'};
} else { } else {
return $self->{'WIRES_ROW'}->{'card1'}; return $self->{'WIRES_ROW'}->{'card1'};
...@@ -832,7 +794,7 @@ sub other_end_port($) ...@@ -832,7 +794,7 @@ sub other_end_port($)
} }
} }
if ($self->node_id() eq $self->{'WIRES_ROW'}->{'node_id1'}) { if ($self->wire_end() eq "pc") {
return $self->{'WIRES_ROW'}->{'port2'}; return $self->{'WIRES_ROW'}->{'port2'};
} else { } else {
return $self->{'WIRES_ROW'}->{'port1'}; return $self->{'WIRES_ROW'}->{'port1'};
...@@ -854,7 +816,7 @@ sub other_end_iface($) ...@@ -854,7 +816,7 @@ sub other_end_iface($)
} }
} }
if ($self->node_id() eq $self->{'WIRES_ROW'}->{'node_id1'}) { if ($self->wire_end() eq "pc") {
return Port->LookupByTriple( return Port->LookupByTriple(
$self->{'WIRES_ROW'}->{'node_id2'}, $self->{'WIRES_ROW'}->{'node_id2'},
$self->{'WIRES_ROW'}->{'card2'}, $self->{'WIRES_ROW'}->{'card2'},
...@@ -949,10 +911,7 @@ sub getOtherEndPort($) { ...@@ -949,10 +911,7 @@ sub getOtherEndPort($) {
} }
# #
# get the PC side of a port instance. It is bogus to call this on an # get the PC side of a port instance
# 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($) { sub getPCPort($) {
my $self = $_[0]; my $self = $_[0];
...@@ -961,8 +920,7 @@ sub getPCPort($) { ...@@ -961,8 +920,7 @@ sub getPCPort($) {
return $self; return $self;
} }
if (!$self->is_switch_side() || if ($self->wire_end() eq "pc") {
$self->is_trunk_port()) {
return $self; return $self;
} else { } else {
return $self->getOtherEndPort(); return $self->getOtherEndPort();
...@@ -970,9 +928,7 @@ sub getPCPort($) { ...@@ -970,9 +928,7 @@ sub getPCPort($) {
} }
# #
# get the switch side of a port instance. This call is ambiguous in # get the switch side of a port instance
# the case of an inter-switch trunk port, and will always return "this"
# port.
# #
sub getSwitchPort($) { sub getSwitchPort($) {
my $self = $_[0]; my $self = $_[0];
...@@ -981,7 +937,7 @@ sub getSwitchPort($) { ...@@ -981,7 +937,7 @@ sub getSwitchPort($) {
return $self; return $self;
} }
if ($self->is_switch_side()) { if ($self->wire_end() ne "pc") {
return $self; return $self;
} else { } else {
return $self->getOtherEndPort(); return $self->getOtherEndPort();
......
#
# This is the Port class that represent a port in VLAN.
# It aims at providing all avaialble information of a
# port rather than just a string representation consisting
# of node and card or port only, which is used by most snmpit
# code.
#
# Previous string representation only has node and card for
# a PC port, which can not be unique when representing a port
# on a test node switch, such as our hp5406 nodes.
# A Port class instance uniquely identifies a port with
# all of its properties, such as node_id, card, port and iface.
#
# Some important terms used:
# - Tokens: seperated fields of a port, e.g. "node1", "card2", "iface3", etc.
# - Iface: interface on a node, or a full representation of
# an interface, say "iface2", "node1:iface4".
# - Triple: a port representation that uses three fields:
# node, card and port, like "node1:card2.port1".
# - String: a string representation of a port, ususally a
# combination of tokens, e.g. "node1:iface3", "node1:card3.port4".
#
# All code that needs to convert between different representations
# or merely parse tokens from string and vice-verse must
# use the converters provided in this class.
#
# Copyright (c) 2011-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/>.
#
# }}}
#
package Port;
use strict;
use Exporter;
use vars qw(@ISA @EXPORT);
@ISA = "Exporter";
@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 = ();
# Ends of wires, node:iface OR node:card.port => Port Instance
my %wiredports = ();
#
# check if a var is a Port instance
#
sub isPort($$)
{
my ($c, $p) = @_;
if (ref($p) eq "Port") {
return 1;
}
return 0;
}
#
# Get the other end port of a wire by triple representation of this end port
# the classname can be ignored
# the representation can be a triple-port string or triple tokens
#
sub GetOtherEndByTriple($;$$$)
{
my ($c, $node, $card, $port) = @_;
my $str;
if (!defined($node)) {
$str = $c;
} elsif (!defined($card)) {
$str = $node;
} elsif (!defined($port)) {
$str = Port->Tokens2TripleString($c, $node, $card);
} else {
$str = Port->Tokens2TripleString($node, $card, $port);
}
if (exists($wiredports{$str})) {
return $wiredports{$str};
}
my $p = Port->LookupByTriple($str);
if (defined($p)) {
$wiredports{$p->toTripleString()} = $p->getOtherEndPort();
$wiredports{$p->toIfaceString()} = $p->getOtherEndPort();
return $p->getOtherEndPort();
} else {
return undef;
}
}
#
# Get the other end port of a wire by iface representation of this end port
# the classname can be ignored
# the representation can be a iface-port string or iface tokens
#
sub GetOtherEndByIface($;$$)
{
my ($c, $node, $iface) = @_;
my $str;
my $p;
if (defined($iface)) {
$str = Port->Tokens2IfaceString($node, $iface);
} elsif (!defined($node)) {
$str = $c;
} else {
$str = $node;
$p = Port->LookupByIface($str);
if (!defined($p)) {
$str = Port->Tokens2IfaceString($c, $node);
$p = Port->LookupByIface($str);
if (!defined($p)) {
return undef;
}
}
}
if (!defined($p)) {
$p = Port->LookupByIface($str);
}
if (defined($p)) {
$wiredports{$p->toTripleString()} = $p->getOtherEndPort();
$wiredports{$p->toIfaceString()} = $p->getOtherEndPort();
return $p->getOtherEndPort();
} else {
return undef;
}
}
#
# Parse node:iface string into tokens
# classname can be ignored
#
sub ParseIfaceString($;$)
{
my ($c, $striface) = @_;
if (!defined($striface)) {
$striface = $c;
}
if ($striface =~ /^(.+):(.+)$/) {
return ($1, $2);
}
return (undef, undef);
}
#
# Parse node:card.port string into tokens
# can be called without the classname
#
sub ParseTripleString($;$)
{
my ($c, $triplestring) = @_;
if (!defined($triplestring)) {
$triplestring = $c;
}
if ($triplestring =~ /^(.+):(.+)\.(.+)$/) {
return ($1, $2, $3);
}
return (undef, undef, undef);
}
sub ParseCardPortString($;$)
{
my ($c, $cp) = @_;
if (!defiend($cp)) {
$cp = $c;