Commit bf96fd50 authored by Leigh Stoller's avatar Leigh Stoller

Bring control network firewalls back from the dead.

parent 8ce897fc
#!/usr/bin/perl -wT
#
# Copyright (c) 2005-2014, 2016 University of Utah and the Flux Group.
# Copyright (c) 2005-2014, 2016, 2017 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
......@@ -473,7 +473,29 @@ sub Counts($)
($free) = $query_result->fetchrow_array();
}
return {"total" => $total, "free" => $free};
}
}
#
# Utility function to look up a global vtype and return the list.
#
sub GlobalVtypeTypes($$)
{
my ($class, $vtype) = @_;
my @result = ();
my $query_result =
DBQueryWarn("select types from global_vtypes where vtype='$vtype'");
return ()
if (!defined($query_result) || !$query_result->numrows);
my ($typestring) = $query_result->fetchrow_array();
foreach my $t (split(/\s+/, $typestring)) {
my $type = NodeType->Lookup($t);
push(@result, $type)
if (defined($type));
}
return @result;
}
# _Always_ make sure that this 1 is at the end of the file...
......
......@@ -1023,12 +1023,17 @@ sub Action($$$;$)
#
# Look for a firewall that needs to be setup first.
#
my ($firewall, $firewall_sliver);
my $firewalled = $experiment->IsFirewalled(\$firewall);
if ($firewalled && !defined($firewall)) {
my %firewallinfo = (
"node_id" => undef,
"node" => undef,
"sliver" => undef,
"image" => undef,
);
my $firewalled = $experiment->IsFirewalled(\$firewallinfo{"node_id"});
if ($firewalled && !defined($firewallinfo{"node_id"})) {
$msg .= "Could not determine firewall for experiment";
goto bad;
}
}
my @slivers = ();
if ($self->SliverList(\@slivers) != 0) {
......@@ -1097,11 +1102,6 @@ sub Action($$$;$)
or return -1;
next;
}
# Remember which sliver is the firewall.
if ($firewalled && $firewall eq $sliver->resource_id()) {
$firewall_sliver = $sliver;
}
my $node = Node->Lookup($sliver->resource_id());
if (!defined($node)) {
$msg .= "Could not map $sliver to a node";
......@@ -1117,6 +1117,12 @@ sub Action($$$;$)
# Backpointer used in WaitForNodes().
$node->_sliver($sliver);
$node->_image(undef);
# Remember firewall stuff;
if ($firewalled && $firewallinfo{"node_id"} eq $node->node_id()) {
$firewallinfo{"sliver"} = $sliver;
$firewallinfo{"node"} = $node;
}
if ($reservation->SameExperiment($experiment)) {
my $vnode;
......@@ -1317,10 +1323,16 @@ sub Action($$$;$)
"but it has been deleted";
goto bad;
}
if (!exists($reloads{$image->versid()})) {
$reloads{$image->versid()} = [ ];
}
push(@{ $reloads{$image->versid()} }, $node);
if ($firewalled &&
$firewallinfo{"node_id"} eq $node->node_id()) {
$firewallinfo{"image"} = $image;
}
else {
if (!exists($reloads{$image->versid()})) {
$reloads{$image->versid()} = [ ];
}
push(@{ $reloads{$image->versid()} }, $node);
}
$node->_reloaded(1);
$node->_image($image);
......@@ -1331,7 +1343,11 @@ sub Action($$$;$)
# Reload means reboot or power on.
# But skip the firewall; that is done specially since
# it has to come up before everything else.
if (!defined($vnode) && $sliver->state() eq "stopped") {
if ($firewalled &&
$firewallinfo{"node_id"} eq $node->node_id()) {
print STDERR "Skipping reboot/poweron of firewall node\n";
}
elsif (!defined($vnode) && $sliver->state() eq "stopped") {
$poweron{$node->node_id} = $node;
}
else {
......@@ -1513,50 +1529,58 @@ sub Action($$$;$)
}
#
# Before anything, the firewall has to be turned on or rebooted.
# Then we have to wait for it to come up before we can let the
# rest of the nodes go.
# Before anything, the firewall has to be reload or powered on or
# rebooted. Then we have to wait for it to come up before we can
# let the rest of the nodes go.
#
if ($firewalled &&
(exists($poweron{$firewall}) || exists($reboots{$firewall}))) {
my $node_id;
(defined($firewallinfo{"image"}) ||
exists($poweron{$firewallinfo{"node_id"}}) ||
exists($reboots{$firewallinfo{"node_id"}}))) {
my $node_id = $firewallinfo{"node_id"};
my $node = $firewallinfo{"node"};
require StateWait;
require EmulabConstants;
if (exists($poweron{$firewall})) {
my $node = $poweron{$firewall};
$node_id = $node->node_id();
if (defined($firewallinfo{"image"})) {
my $image = $firewallinfo{"image"};
my $imageid = $image->versid();
# Normal reload for firewall, let it do reboot/wait
system("$OSLOAD -m $imageid $node_id");
if ($?) {
$msg .= "Failed to reload firewall: $imageid on $node_id";
goto bad;
}
}
elsif (exists($poweron{$node_id})) {
print STDERR "Powering on the firewall: $node_id\n";
system("$POWER on $node_id");
if ($?) {
$msg .= "Failed to power on firewall: $node_id";
$firewall_sliver->SetStatus("failed");
$firewallinfo{"sliver"}->SetStatus("failed");
goto bad;
}
delete($poweron{$firewall});
delete($poweron{$node_id});
}
else {
my $node = $reboots{$firewall};
$node_id = $node->node_id();
elsif (exists($reboots{$node_id})) {
print STDERR "Rebooting the firewall: $node_id\n";
system("$NODEREBOOT $node_id");
if ($?) {
$msg .= "Failed to reboot firewall: $node_id";
$firewall_sliver->SetStatus("failed");
$firewallinfo{"sliver"}->SetStatus("failed");
goto bad;
}
delete($reboots{$firewall});
delete($reboots{$node_id});
}
$StateWait::debug = 0;
my @states = (EmulabConstants::TBDB_NODESTATE_ISUP());
if (StateWait::initStateWait(\@states, $node_id)) {
$msg .= "Failed to initialize the statewait library!";
$firewall_sliver->SetStatus("failed");
$firewallinfo{"sliver"}->SetStatus("failed");
goto bad;
}
my @finished = ();
......@@ -1567,7 +1591,7 @@ sub Action($$$;$)
if (StateWait::waitForState(\@finished, \@failed, (15 * 60))) {
$msg .= "Failed in waitForState for firewall: $node_id!";
$firewall_sliver->SetStatus("failed");
$firewallinfo{"sliver"}->SetStatus("failed");
goto bad;
}
StateWait::endStateWait();
......@@ -1582,7 +1606,7 @@ sub Action($$$;$)
if (@failed) {
$msg .= "Firewall failed to boot properly: $node_id!";
$firewall_sliver->SetStatus("failed");
$firewallinfo{"sliver"}->SetStatus("failed");
goto bad;
}
}
......
......@@ -1309,9 +1309,18 @@ sub GetTicketAuxAux($$$$$$$$$$$)
}
elsif ($virtualization_subtype eq "firewall") {
$isfirewall = 1;
$osname = "FW-IPFW2";
$pctype = "pc";
goto raw;
# Corresponds to iptables-vlan, see below.
$osname = "FW-IPTABLES";
# Default firewall type is a global vtype if it exists.
if (scalar(NodeType->GlobalVtypeTypes("pcfw"))) {
$pctype = "pcfw";
}
else {
$pctype = "pc";
}
# Lets force to exclusive node just in case.
GeniXML::SetExclusive($ref, 1);
$exclusive = 1;
}
else {
$response
......@@ -1494,11 +1503,11 @@ sub GetTicketAuxAux($$$$$$$$$$$)
# The slot does not like to be NULL.
$osname = ""
if (!defined($osname));
# Need some kind of default.
$pctype = "pc"
if (!defined($pctype));
my $nodeblob = {"vname" => $node_nickname,
"type" => $pctype,
"osname" => $osname,
......@@ -1522,10 +1531,9 @@ sub GetTicketAuxAux($$$$$$$$$$$)
$response = GeniResponse->Create(GENIRESPONSE_ERROR);
goto bad;
}
$nodeblob->{'cmd_line'} = '/kernel.fw';
if (!defined($virtexperiment->NewTableRow("virt_firewalls",
{"fwname" => $node_nickname,
"type" => "ipfw2-vlan",
"type" => "iptables-vlan",
"style" => "basic"}))) {
$response = GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Error creating firewall definition");
......
......@@ -1506,6 +1506,7 @@ $(function ()
var href = "n/a";
var ssh = "n/a";
var cons = "n/a";
var isfw = 0;
var clone = $(listview_row);
// Cause of nodes in the emulab namespace (vhost).
if (!login.length) {
......@@ -1533,6 +1534,10 @@ $(function ()
$('#listview-row-' + node + " [name=menu]").text("n/a");
return;
}
if (stype.length &&
$(stype).attr("name") === "firewall") {
isfw = 1;
}
if (login.length && dossh) {
var user = window.APT_OPTIONS.thisUid;
......@@ -1590,7 +1595,7 @@ $(function ()
$('#listview-row-' + node + ' [name=console]')
.parent().addClass('disabled');
}
if (!isvhost) {
if (!isvhost && !isfw) {
//
// And a handler for the snapshot action.
//
......@@ -1631,7 +1636,7 @@ $(function ()
$(clone).find("li[id=consolelog]").addClass("disabled");
}
// If a vhost, then grey out options.
if (isvhost) {
if (isvhost || isfw) {
$(clone).find("li[id=snapshot]").addClass("disabled");
$(clone).find("li[id=delete]").addClass("disabled");
}
......
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