Commit 89be15ec authored by Robert Ricci's avatar Robert Ricci

Changed the way that snmpit decides what switches to operate on for the

'tables', 'reset', and 'synctables' commands. Rather than assuming all
VLANs live on the One True Experimental Net Stack (unless -S was given),
they all now check the database to see which stack they should be operating
on.

Changed how stack information is currently stored in the database. The
LAN attribute formerly known as 'stack' is now called 'class', and has
two valid values, 'Experimental' and 'Control'. The idea is to record
whether something is an experimental net or control net LAN, not which
specific stack it's on. The 'stack' column in the VLANs table now
records the actual stack_id on which the VLAN has been created.

This is all in support of testbeds that have multiple experimental-net
stacks, as Utah currently does.
parent 210cb8e4
......@@ -2109,7 +2109,7 @@ sub Create($$$;$)
return undef
if (!defined($vlan));
$vlan->SetStack("Experimental") == 0
$vlan->SetClass("Experimental") == 0
or return undef;
return $vlan;
......@@ -2358,30 +2358,66 @@ sub GetTag($$)
return $tag;
}
sub SetStack($$)
sub SetClass($$)
{
my ($self, $stack) = @_;
my ($self, $class) = @_;
return $self->GetLan()->SetAttribute("stack", $stack);
return $self->GetLan()->SetAttribute("class", $class);
}
sub GetStackNoDefault($) {
sub GetClassNoDefault($) {
my ($self) = @_;
my $stack;
my $class;
return $stack
if ($self->GetAttribute("stack", \$stack) == 0);
return $class
if ($self->GetAttribute("class", \$class) == 0);
return undef;
}
sub GetStack($)
sub GetClass($)
{
my ($self) = @_;
my $stack = $self->GetStackNoDefault();
return $stack if (defined($stack));
my $class = $self->GetClassNoDefault();
return $class if (defined($class));
# Assume experimental stack.
# Assume experimental LAN
return "Experimental";
}
# Find out which stack a VLAN resides on
sub GetStack($) {
my ($self) = @_;
my $query_result =
DBQueryWarn("select stack from vlans ".
"where id='" . $self->lanid() . "'");
if (!$query_result || !$query_result->numrows) {
warn "VLan::GetStack(): Tried to get stack for " . $self->lanid() .
", but missing vlans table entry";
return undef;
}
my ($stack) = $query_result->fetchrow_array();
if (!$stack) {
return undef;
} else {
return $stack;
}
}
# Set the stack that the VLAN resides on
sub SetStack($$) {
my ($self, $stack) = @_;
my $query_result =
DBQueryWarn("select stack from vlans ".
"where id='" . $self->lanid() . "'");
if (!$query_result || !$query_result->numrows) {
warn "VLan::SetStack(): Tried to set for " . $self->lanid() .
", but missing vlans table entry";
return -1;
}
DBQueryWarn("update vlans set stack='$stack' ".
"where id='" . $self->lanid() . "'") or return -1;
return 0;
}
#
# Mark/Get the "manually created" (command line) bit on a vlan.
#
......@@ -2401,6 +2437,21 @@ sub IsManual($)
return 0;
}
#
# Check to see if we think the VLAN actually exists on any switches at the
# moment (ie. has a vlans table entry)
#
sub CreatedOnSwitches() {
my ($self) = @_;
my $query_result =
DBQueryWarn("select * from vlans where id='" . $self->lanid() . "'");
if (!$query_result || !$query_result->numrows) {
return 0;
} else {
return 1;
}
}
#
# List of all vlans. This is a class method.
#
......@@ -2442,7 +2493,7 @@ sub ExperimentVLans($$$)
my $query_result =
DBQueryWarn("select l.lanid from lans as l ".
"left join lan_attributes as la on ".
" la.lanid=l.lanid and la.attrkey='stack' ".
" la.lanid=l.lanid and la.attrkey='class' ".
"where l.type='vlan' and l.exptidx='$exptidx' and ".
" (la.attrvalue='Experimental' or ".
" la.attrvalue is null)");
......@@ -2481,7 +2532,7 @@ sub Instantiate($;$)
my $vname = $self->vname();
my $lanid = $self->lanid();
my $opt = ($quiet ? "-q" : "");
my $stack = $self->GetStack();
my $class = $self->GetClass();
#print "Setting up VLAN $vname ($lanid) in $pid/$eid\n";
system("$SNMPIT $opt -t $pid $eid $lanid");
......@@ -2511,7 +2562,7 @@ sub UnInstantiate($;$)
my $vname = $self->vname();
my $lanid = $self->lanid();
my $opt = ($quiet ? "-q" : "");
my $stack = $self->GetStack();
my $class = $self->GetClass();
#print "Removing VLAN $vname ($lanid) from $pid/$eid\n";
system("$SNMPIT $opt -r $pid $eid $lanid");
......@@ -2524,9 +2575,9 @@ sub UnInstantiate($;$)
# Class methods to maintain the backup vlans table, which records what
# is on the switches.
#
sub RecordVlanInsertion($$$)
sub RecordVlanInsertion($$$$)
{
my ($class, $experiment, $lanid) = @_;
my ($class, $experiment, $lanid, $stack) = @_;
my $pid = $experiment->pid();
my $eid = $experiment->eid();
......@@ -2535,9 +2586,8 @@ sub RecordVlanInsertion($$$)
return -1
if (!defined($vlan));
my $stack = $vlan->GetStack();
my $vname = $vlan->vname();
my $tag = $vlan->GetTag(undef);
my $vname = $vlan->vname();
my $tag = $vlan->GetTag(undef);
return -1
if ($tag <= 0);
......@@ -2660,9 +2710,10 @@ sub StaleVlanList($$$)
my $exptidx = $experiment->idx();
my @result = ();
# XXX: Hack - want to catch all non-Control VLANs
my $query_result =
DBQueryWarn("select id from vlans ".
"where exptidx=$exptidx and stack='Experimental'");
"where exptidx=$exptidx and stack!='Control'");
return -1
if (!$query_result);
......
......@@ -3992,7 +3992,7 @@ CREATE TABLE `vlans` (
`members` text NOT NULL,
`id` int(11) NOT NULL auto_increment,
`tag` smallint(5) NOT NULL default '0',
`stack` enum('Control','Experimental') NOT NULL default 'Experimental',
`stack` varchar(32),
PRIMARY KEY (`id`),
KEY `pid` (`pid`,`eid`,`virtual`),
KEY `exptidx` (`exptidx`,`virtual`)
......
#
# Update to change the meaning of the lan_attributes 'stack' attribute
#
use strict;
use libdb;
sub DoUpdate($$$)
{
my ($dbhandle, $dbname, $version) = @_;
# Changed the name of this attribute
DBQueryFatal("UPDATE lan_attributes SET attrkey='class' " .
"WHERE attrkey='stack';");
# Changed the type of this column
my $type = DBSlotType("vlans", "stack");
if (!$type) {
Fatal("No 'stack' slot in 'vlans' table");
}
if ($type =~ /Experimental/) {
DBQueryFatal("ALTER TABLE vlans MODIFY stack varchar(32);");
}
# Changed the meaning of this column
DBQueryFatal("UPDATE vlans SET stack='' WHERE stack='Experimental';");
return 0;
}
1;
......@@ -548,41 +548,109 @@ COMMAND: foreach my $command (@commands) {
debug("Remove: using supplied switches\n");
@devicenames = @supplied_switches;
} elsif (defined($vlanobj = VLan->Lookup($experiment,$vlan_name)) &&
defined($stack = $vlanobj->GetStackNoDefault())) {
defined($stack = $vlanobj->GetStack())) {
debug("Remove: found stack $stack in database\n");
@devicenames = getSwitchesInStack($stack);
} else {
debug("Remove: using test switches\n");
@devicenames = getTestSwitches();
}
last;
};
(/^tables$/) && do {
@vlans = getExperimentVlans($pid,$eid,@optvlanids);
(/^tables$/) && do {
# Grab all stacks that any ports in the experiment are members
# of.
# (We need the entire stack, since the VLAN may have to traverse
# devices that don't explicitly have a port in the VLAN.)
@vlans = getExperimentVlans($pid,$eid,@optvlanids);
if (!@vlans) {
print "snmpit: $pid/$eid has no VLANs to create, skipping\n";
next COMMAND;
}
@ports = getVlanPorts(@vlans);
@devicenames = $supplied_switches?
@supplied_switches : getTestSwitches();
last;
};
(/synctables/) && do {
@devicenames = $supplied_switches?
@supplied_switches : getTestSwitches();
last;
};
if ($supplied_switches) {
debug("Tables: using supplied switches\n");
@devicenames = @supplied_switches;
} else {
@devicenames =
getSwitchesInStacks(getPlannedStacksForVlans(@vlans));
debug("Tables: list from database: " . join(",",@devicenames) .
"\n");
}
if (scalar(@devicenames == 0)) {
debug("Tables: falling back to test swtiches\n");
@devicenames = getTestSwitches();
}
last;
};
(/reset/) && do {
#
# When we reset, we operate on all test switches, just to be safe
# We operate on all stacks that we have recorded as having VLANs
# that belong to this experiment.
#
@vlans = getExperimentVlans($pid,$eid,@optvlanids);
if (!@vlans) {
print "snmpit: $pid/$eid has no VLANs to remove, skipping\n";
print "snmpit: $pid/$eid has no VLANs, skipping\n";
next COMMAND;
}
@devicenames = $supplied_switches?
@supplied_switches : getTestSwitches();
@vlans = filterPlannedVlans(@vlans);
if (!@vlans) {
print "snmpit: $pid/$eid has VLANs, but none have been " .
"created on switches\n ... skipping\n";
next COMMAND;
}
if ($supplied_switches) {
debug("Reset: using supplied switches\n");
@devicenames = @supplied_switches;
} else {
@devicenames =
getSwitchesInStacks(getActualStacksForVlans(@vlans));
debug("Reset: list from database: " . join(",",@devicenames) .
"\n");
}
# Fallthrough - if we haven't found any switches yet, operate
# on the whole experimetnal net
if (scalar(@devicenames) == 0) {
debug("Reset: falling back to test swtiches\n");
@devicenames = getTestSwitches();
}
last;
};
(/synctables/) && do {
# We operate on all stacks on which we think VLANs do, or should,
# exist
if ($supplied_switches) {
debug("Sync: using supplied switches\n");
@devicenames = @supplied_switches;
} else {
# Get both the VLANs that do exist and the VLANs that should
# exist
my @newvlans = getExperimentVlans($pid,$eid,@optvlanids);
@devicenames =
getSwitchesInStacks(getPlannedStacksForVlans(@newvlans));
debug("Sync: New devices are " . join(",",@devicenames) .
"\n");
my @oldvlans;
VLan->StaleVlanList($experiment,\@oldvlans);
my @oldports;
foreach my $oldvlan (@oldvlans) {
push @oldports, getExperimentVlanPorts($oldvlan);
}
push @devicenames,
getSwitchesInStacks(getStacksForSwitches(getDeviceNames(@oldports)));
debug("Sync: With old devices, list is " .
join(",",@devicenames) . "\n");
@devicenames = uniq(@devicenames);
}
# Fallthrough - if we haven't found any switches yet, operate
# on the whole experimetnal net
if (scalar(@devicenames) == 0) {
debug("Reset: falling back to test swtiches\n");
@devicenames = getTestSwitches();
}
last;
};
(/portcontrol/ || /trunkdisable/ || /portstatus/) && do {
......@@ -1443,7 +1511,7 @@ sub CreateOneVlan($$@)
}
else {
setVlanTag($vlanid, $vlan_number);
VLan->RecordVlanInsertion($experiment, $vlanid);
VLan->RecordVlanInsertion($experiment, $vlanid,$stack->{STACKID});
}
}
return $errors
......@@ -1530,7 +1598,7 @@ sub syncVlansFromTables($$) {
my %expvlans = ();
my %curvlans = ();
my %stale = ();
my $impotent = 1;
my $impotent = 0;
my $errors = 0;
my $vlan_number;
......@@ -1895,9 +1963,14 @@ sub doMakeVlan($$@) {
if (!defined($target_vlan)) {
die("Could not create VLan object for $vlan_name\n");
}
$target_vlan->SetStack($stackid)
if (defined($stackid));
$target_vlan->MarkManual();
# XXX: Need a better way to figure out whether class is
# Experimental or Control
if ($stackid eq "Control") {
$target_vlan->SetClass("Control");
} else {
$target_vlan->SetClass("Experimental");
}
}
$vlan_id = $target_vlan->id();
# This will add the port *only* if not already in the vlan.
......@@ -1958,7 +2031,8 @@ sub doMakeVlan($$@) {
VLan->RecordVLanDeletion($source_vlan->id());
}
if (defined($target_vlan)) {
VLan->RecordVlanInsertion($experiment, $target_vlan->id());
VLan->RecordVlanInsertion($experiment, $target_vlan->id(),
$stack->{STACKID});
}
}
return $errors;
......
......@@ -244,7 +244,7 @@ sub SetupVlans($)
foreach my $id (keys(%{ $argtable })) {
my $vtag = $argtable->{$id}->{'virtual'};
my $stack = $argtable->{$id}->{'stack'};
my $class = $argtable->{$id}->{'stack'};
my $members = $argtable->{$id}->{'members'};
if (! ($id =~ /^[\d]+$/)) {
......@@ -253,11 +253,11 @@ sub SetupVlans($)
if (! ($vtag =~ /^[\-\w]+$/)) {
fatal("SetupVlans: Illegal vname '$vtag'");
}
if (!defined($stack)) {
$stack = "Experimental";
if (!defined($class)) {
$class = "Experimental";
}
elsif ($stack ne "Control" && $stack ne "Experimental") {
fatal("SetupVlans: Illegal stack '$stack'");
elsif ($class ne "Control" && $class ne "Experimental") {
fatal("SetupVlans: Illegal class '$class'");
}
foreach my $port (keys(%{ $members })) {
......@@ -279,7 +279,7 @@ sub SetupVlans($)
if (! exists($vlantable->{$id})) {
$vlantable->{$id} = {};
$vtagtable{$id} = $vtag;
$stacktable{$id} = $stack;
$stacktable{$id} = $class;
}
$vlantable->{$id}->{$port} = [$speed, $duplex];
......@@ -397,14 +397,14 @@ sub SetupVlans($)
#
foreach my $id (keys(%$vlantable)) {
my $vtag = $vtagtable{$id};
my $stack = $stacktable{$id};
my $class = $stacktable{$id};
my @members = keys(%{ $vlantable->{$id} });
my $mstring = "@members";
my $outer_id;
my $vlan;
# Not doing stacks yet.
$stack = "Experimental";
$class = "Experimental";
if ($debug) {
print STDERR "$pid $eid $id $mstring\n";
......@@ -434,7 +434,7 @@ sub SetupVlans($)
$errors++;
next;
}
$vlan->SetStack($stack);
$vlan->SetClass($class);
$outer_id = $vlan->lanid();
# Insert mapping between inner and outer vlan entries.
......@@ -442,7 +442,7 @@ sub SetupVlans($)
DBQueryWarn("insert into elabinelab_vlans ".
" (exptidx,pid,eid,inner_id,outer_id,stack) ".
"values ($exptidx, '$pid', '$eid', '$id', ".
" '$outer_id', '$stack')");
" '$outer_id', '$class')");
if (!$query_result || !$query_result->numrows) {
#
# Failed, must remove vlans entry too. We keep going though
......@@ -593,7 +593,7 @@ sub DestroyVlans($)
my @vlanids = @{ $args->{'vlans'} };
my @done = ();
my $errors = 0;
my $stack;
my $class;
MapVlans(@vlanids);
# If no vlans, do nothing! snmpit will end up removing all the vlans!
......@@ -608,7 +608,7 @@ sub DestroyVlans($)
foreach my $vlanid (@vlanids) {
my $outer_id = $mapping{$vlanid};
my $vlan = $outer_vlans{$outer_id};
my $stack = $vlan->GetStack();
my $class = $vlan->GetClass();
# Not doing stacks yet;
my $stackopt = "";
my $debugopt = ($debug ? "-v $dlevel" : "");
......@@ -718,12 +718,12 @@ sub Trunk($)
fatal("Trunk: Illegal port '$port'");
}
# Not doing stacks yet.
my $stack = "Experimental";
my $class = "Experimental";
my $stackopt = "";
if (0 && exists($args->{'stack'})) {
$stack = $args->{'stack'};
if ($stack ne "Control" && $stack ne "Experimental") {
fatal("Trunk: Improper stack argument: $stack");
$class = $args->{'stack'};
if ($class ne "Control" && $class ne "Experimental") {
fatal("Trunk: Improper class argument: $class");
}
}
my $debugopt = ($debug ? "-v $dlevel" : "");
......@@ -747,7 +747,7 @@ sub Trunk($)
}
MapVlans(@vlanids);
if ($mode eq "-U") {
if ($stack eq "Experimental") {
if ($class eq "Experimental") {
$query_result =
DBQueryFatal("select iface from vinterfaces " .
"where node_id='$node' and type='vlan' and ".
......@@ -770,7 +770,7 @@ sub Trunk($)
#
# and clean up the database
#
if ($stack eq "Experimental") {
if ($class eq "Experimental") {
$query_result =
DBQueryFatal("delete from vinterfaces " .
"where node_id='$node' and type='vlan' and ".
......@@ -789,7 +789,7 @@ sub Trunk($)
# appropriate to stuff. It seems likely that the structure
# of the database will be revised, in this area, but
# for now, we'll just play Joe Isuzu.
if ($stack eq "Experimental") {
if ($class eq "Experimental") {
$query_result =
DBQueryFatal("select iface from vinterfaces where " .
"node_id='$node' and iface='$iface'");
......@@ -833,7 +833,7 @@ sub PortControl($)
my @ports = @{ $args->{'ports'} };
# Not doing stacks yet;
my $stack = "Experimental";
my $class = "Experimental";
my $debugopt = ($debug ? "-v $dlevel" : "");
#
......
......@@ -244,7 +244,7 @@ sub SetupVlans($)
foreach my $id (keys(%{ $argtable })) {
my $vtag = $argtable->{$id}->{'virtual'};
my $stack = $argtable->{$id}->{'stack'};
my $class = $argtable->{$id}->{'stack'};
my $members = $argtable->{$id}->{'members'};
my $trunk_mode = $argtable->{$id}->{'trunk_mode'}
if (exists($argtable->{$id}->{'trunk_mode'}));
......@@ -255,11 +255,11 @@ sub SetupVlans($)
if (! ($vtag =~ /^[\-\w]+$/)) {
fatal("SetupVlans: Illegal vname '$vtag'");
}
if (!defined($stack)) {
$stack = "Experimental";
if (!defined($class)) {
$class = "Experimental";
}
elsif ($stack ne "Control" && $stack ne "Experimental") {
fatal("SetupVlans: Illegal stack '$stack'");
elsif ($class ne "Control" && $class ne "Experimental") {
fatal("SetupVlans: Illegal class '$class'");
}
foreach my $port (keys(%{ $members })) {
......@@ -282,7 +282,7 @@ sub SetupVlans($)
if (! exists($vlantable->{$id})) {
$vlantable->{$id} = {};
$attrtable->{$id} = {"virtual" => $vtag,
"stack" => $stack,
"stack" => $class,
"trunk_mode" => $trunk_mode};
}
$vlantable->{$id}->{$port} = [$speed, $duplex, $trunk];
......@@ -402,7 +402,7 @@ sub SetupVlans($)
#
foreach my $id (keys(%$vlantable)) {
my $vtag = $attrtable->{$id}->{"virtual"};
my $stack = $attrtable->{$id}->{"stack"};
my $class = $attrtable->{$id}->{"stack"};
my $trunk_mode = $attrtable->{$id}->{"trunk_mode"};
my @members = keys(%{ $vlantable->{$id} });
my $mstring = "@members";
......@@ -410,7 +410,7 @@ sub SetupVlans($)
my $vlan;
# Not doing stacks yet.
$stack = "Experimental";
$class = "Experimental";
if ($debug) {
print STDERR "$pid $eid $id $mstring\n";
......@@ -440,7 +440,7 @@ sub SetupVlans($)
$errors++;
next;
}
$vlan->SetStack($stack);
$vlan->SetClass($class);
$outer_id = $vlan->lanid();
$vlan->SetAttribute("trunk_mode", $trunk_mode)
if (defined($trunk_mode));
......@@ -450,7 +450,7 @@ sub SetupVlans($)
DBQueryWarn("insert into elabinelab_vlans ".
" (exptidx,pid,eid,inner_id,outer_id,stack) ".
"values ($exptidx, '$pid', '$eid', '$id', ".
" '$outer_id', '$stack')");
" '$outer_id', '$class')");
if (!$query_result || !$query_result->numrows) {
#
# Failed, must remove vlans entry too. We keep going though
......@@ -602,7 +602,7 @@ sub DestroyVlans($)
my $cleartrunks = $args->{'cleartrunks'};
my @done = ();
my $errors = 0;
my $stack;
my $class;
my $debugopt = ($debug ? "-v $dlevel" : "");
MapVlans(@vlanids);
......@@ -655,7 +655,7 @@ sub DestroyVlans($)
my $outer_id = $mapping{$vlanid};
my $vlan = $outer_vlans{$outer_id};
my $vname =
my $stack = $vlan->GetStack();
my $class = $vlan->GetClass();
# Not doing stacks yet;
my $stackopt = "";
......@@ -764,12 +764,12 @@ sub Trunk($)
fatal("Trunk: Illegal port '$port'");
}
# Not doing stacks yet.
my $stack = "Experimental";
my $class = "Experimental";
my $stackopt = "";
if (0 && exists($args->{'stack'})) {
$stack = $args->{'stack'};
if ($stack ne "Control" && $stack ne "Experimental") {
fatal("Trunk: Improper stack argument: $stack");
$class = $args->{'stack'};
if ($class ne "Control" && $class ne "Experimental") {
fatal("Trunk: Improper class argument: $class");
}
}
my $debugopt = ($debug ? "-v $dlevel" : "");
......@@ -793,7 +793,7 @@ sub Trunk($)
}
MapVlans(@vlanids);
if ($mode eq "-U") {
if ($stack eq "Experimental") {
if ($class eq "Experimental") {
$query_result =
DBQueryFatal("select iface from vinterfaces " .
"where node_id='$node' and type='vlan' and ".
......@@ -816,7 +816,7 @@ sub Trunk($)
#
# and clean up the database
#
if ($stack eq "Experimental") {
if ($class eq "Experimental") {
$query_result =
DBQueryFatal("update interfaces set trunk=0 " .
"where node_id='$node' and iface='$iface'");
......@@ -825,7 +825,7 @@ sub Trunk($)
}
if (($mode eq "-E") || ($mode eq "-T")) {
# First, update the status of the port in the database
if ($stack eq "Experimental") {
if ($class eq "Experimental") {
DBQueryFatal("update interfaces set trunk=1 " .
"where node_id='$node' and iface='$iface'");
}
......@@ -860,7 +860,7 @@ sub PortControl($)
my @ports = @{ $args->{'ports'} };
# Not doing stacks yet;
my $stack = "Experimental";
my $class = "Experimental";
my $debugopt = ($debug ? "-v $dlevel" : "");
#
......
......@@ -15,21 +15,25 @@ use Exporter;
@ISA = ("Exporter");
@EXPORT = qw( macport portnum portiface Dev vlanmemb vlanid
getTestSwitches getControlSwitches getSwitchesInStack
getSwitchesInStacks
getVlanPorts convertPortsFromIfaces convertPortFromIface
getExperimentTrunks setVlanTag
getExperimentTrunks setVlanTag setVlanStack
getExperimentVlans getDeviceNames getDeviceType
getInterfaceSettings mapPortsToDevices getSwitchPrimaryStack
getSwitchStacks
getSwitchStacks getStacksForSwitches
getStackType getStackLeader
getDeviceOptions getTrunks getTrunksFromSwitches
getTrunkHash
getExperimentPorts snmpitGet snmpitGetWarn snmpitGetFatal
getExperimentControlPorts
getPlannedStacksForVlans getActualStacksForVlans
filterPlannedVlans
snmpitSet snmpitSetWarn snmpitSetFatal
snmpitBulkwalk snmpitBulkwalkWarn snmpitBulkwalkFatal
setPortEnabled setPortTagged
printVars tbsort getExperimentCurrentTrunks
getExperimentVlanPorts);
getExperimentVlanPorts
uniq);
use English;
use libdb;
......@@ -256,6 +260,57 @@ sub getExperimentVlanPorts($) {
return convertPortsFromIfaces(@members);
}
#
# Get the list of stacks that the given set of VLANs *will* or *should* exist
# on
#
sub getPlannedStacksForVlans(@) {
my @vlans = @_;
# Get VLAN members, then go from there to devices, then from there to
# stacks
my @ports = getVlanPorts(@vlans);
if ($debug) {
print "getPlannedStacksForVlans: got ports " . join(",",@ports) . "\n";
}
my @devices = getDeviceNames(@ports);
if ($debug) {
print("getPlannedStacksForVlans: got devices " . join(",",@devices)
. "\n");
}
my @stacks = getStacksForSwitches(@devices);
if ($debug) {
print("getPlannedStacksForVlans: got stacks " . join(",",@stacks) . "\n");
}
return @stacks;
}
#
# Get the list of stacks that the given VLANs actually occupy
#
sub getActualStacksForVlans(@) {
my @vlans = @_;
# Run through all the VLANs and make a list of the stacks they
# use
my @stacks;
foreach my $vlan (@vlans) {
my ($vlanobj, $stack);
if ($debug) {
print("getActualStacksForVlans: looking up ($vlan)\n");
}
if (defined($vlanobj = VLan->Lookup($vlan)) &&
defined($stack = $vlanobj->GetStack())) {
if ($debug) {
print("getActualStacksForVlans: found stack $stack in database\n");
}
push @stacks, $stack;
}
}
return uniq(@stacks);
}
#
# Update database to store vlan tag.