Commit cda9ed7a authored by Kirk Webb's avatar Kirk Webb

Rework how OpenFlow setup is handled on the front-end

Previously OF would be setup after vlan creation, but before checking to
see if all switches in scope actually support it.  This would lead to
failures where the vlan was created and logged in the DB, but snmpit
failed to setup OF, and so exit with a failure.  This in turn causes
swap-in to fail, and leaves stale state on the switches and in the DB.

Now when OF is requested for a vlan in an experiment, we first check
to see if it is supported, then proceed.  We error out early before
any OF-enabled vlan is created.
parent 1a0f4cac
......@@ -1346,6 +1346,37 @@ sub reapCall($$) {
return snmpit_jitdev::reapCall($proc);
}
#
# Check to see if OpenFlow is supported on switches in this stack that
# own any of the ports passed in, or all switches in the stack if no
# port list is supplied.
#
sub isOpenflowSupported($;@) {
my $self = shift;
my @ports = @_;
my $supported = 0;
my @devicenames = ();
if (@ports) {
my %map = mapPortsToDevices(@ports);
@devicenames = keys %map;
} else {
@devicenames = keys %{$self->{DEVICES}}
}
foreach my $devicename (@devicenames) {
my $device = $self->{DEVICES}{$devicename};
if ($device->isOpenflowSupported()) {
$supported++;
} else {
warn "WARNING: snmpit_stack::isOpenflowSupported: Device ".
"$devicename does not support OpenFlow.\n";
}
}
return ($supported == scalar(@devicenames)) ? 1 : 0;
}
#
# Enable Openflow
#
......
......@@ -1988,35 +1988,7 @@ sub doVlansFromTables($$@) {
delete($trunkedPorts{$port->toString()});
}
}
#
# Set openflow
#
# A much more right place for the openflow settings is CreateOneVlan,
# however, it is called by sync vlan function and others, which don't destroy
# the existing lan_attributes rows.
#
# TODO: Move this part to CreateOneVlan and Make sure the existed
# vlan_attributes rows are deleted
#
my $ofenabled;
$vlan->GetAttribute("ofenabled", \$ofenabled);
if (defined($ofenabled) && $ofenabled == 1) {
my $ofcontroller;
$vlan->GetAttribute("ofcontroller", \$ofcontroller);
if (defined($ofcontroller) && $ofcontroller ne "") {
$errors += doSetOpenflowController($stacks, $vlanid,
$ofcontroller);
}
$errors += doEnableOpenflowListener($stacks, $vlanid);
$errors += doOpenflowEnable($stacks, $vlanid);
# doEnableOpenflowListener updates the lan_arrtibutes table,
# so vlan should refresh itself. But here vlan will not be
# used any more, so maybe we can comment this refresh.
$vlan->Refresh();
}
# Delete this vlan from the list that will be created below.
delete($vlans{"$vlanid"});
}
......@@ -2057,34 +2029,7 @@ sub doVlansFromTables($$@) {
my $vlanid = $vlan->id();
my @ports = getVlanPorts($vlanid);
$errors += CreateOneVlan($experiment, $stack, $vlanid, @ports);
#
# Set openflow
#
# A much more right place for the openflow settings is CreateOneVlan,
# however, it is called by sync vlan function and others, which\
# don't destroy the existing lan_attributes rows.
#
# TODO: Move this part to CreateOneVlan and Make sure the existed
# vlan_attributes rows are deleted
#
my $ofenabled;
$vlan->GetAttribute("ofenabled", \$ofenabled);
if (defined($ofenabled) && $ofenabled == 1) {
my $ofcontroller;
$vlan->GetAttribute("ofcontroller", \$ofcontroller);
if (defined($ofcontroller) && $ofcontroller ne "") {
$errors += doSetOpenflowController($stacks, $vlanid, $ofcontroller);
}
$errors += doEnableOpenflowListener($stacks, $vlanid);
$errors += doOpenflowEnable($stacks, $vlanid);
# doEnableOpenflowListener updates the lan_attributes table, so
# vlan should refresh itself. But here vlan will not be
# used any more, so maybe we can comment this refresh.
$vlan->Refresh();
}
$errors += CreateOneVlan($experiment, $stack, $vlanid, @ports);
}
return $errors;
}
......@@ -2108,6 +2053,27 @@ sub CreateOneVlan($$$@)
}
}
else {
#
# Check and see if OF was requested. If so, check to make sure
# all switches in scope support it. Fail early if not.
#
my $vlan = VLan->Lookup($vlanid);
if (!defined($vlan)) {
die("Could not locate vlan $vlanid in the DB\n");
}
my $ofenabled;
$vlan->GetAttribute("ofenabled", \$ofenabled);
$ofenabled = (defined($ofenabled) && $ofenabled == 1) ? 1 : 0;
if ($ofenabled) {
if (!$stack->isOpenflowSupported(@ports)) {
tberror({type => 'secondary', severity => SEV_SECONDARY,
error => ['create_vlan_failed', $vlanid]},
"OpenFlow requested for VLAN $vlanid, but ".
"is not supported on all switches in scope.\n");
return 1;
}
}
my $vlan_number = $stack->createVlan($vlanid, $vlanid, \@ports);
if (!$vlan_number) {
tberror({type => 'secondary', severity => SEV_SECONDARY,
......@@ -2122,6 +2088,24 @@ sub CreateOneVlan($$$@)
print STDERR "*** Could not remove failed vlan: $vlanid\n";
}
$errors++;
} else {
#
# Set up and enable openflow, if requested.
#
if ($ofenabled) {
my $ofcontroller;
$vlan->GetAttribute("ofcontroller", \$ofcontroller);
if (defined($ofcontroller) && $ofcontroller ne "") {
$errors += doSetOpenflowController([$stack], $vlanid,
$ofcontroller);
}
$errors += doEnableOpenflowListener([$stack], $vlanid);
$errors += doOpenflowEnable([$stack], $vlanid);
# doEnableOpenflowListener updates the lan_attributes table,
# so vlan should refresh itself.
$vlan->Refresh();
}
}
}
return $errors
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment