Commit 10b116e0 authored by Leigh Stoller's avatar Leigh Stoller

A bunch of ElabInELab changes.

* snmpit: When ElabInELabis true, use the routines in the new
  snmpit_remote.pm library for setting up and tearing down vlans for an
  experiment. At present, only these two operations are proxied out to
  the outer emulab.

* snmpit_remote.pm: A new little library that uses the XMLPRC server on
  the outer emulab to setup and destroy vlans for an inner experiment.
  This code is used from snmpit (see above).

* snmpit_lib.pm: A couple of minor changes for the server side of the
  proxy operation.

* snmpit.proxy.in: A new perl module that is invoked from the RPC
  server.  This proxy sets up and tears down vlans for an inner elab.
  The basic model is that the container experiment will have lots of
  vlans for various individual experiments running on the inner emulab.

* swapexp: A couple of minor elabinelab hacks.

* tbswap: For elabinelab experiments, reconfig/restart dhcpd when
  tearing down the experiment, and call out to new elabinelab script
  when setting up an elabinelab experiment. There is no provision for
  swapmod at this time.

* elabinelab: A new script to create the inner emulab. Does all kinds of
  gross DB stuff then more gross stuff on the inner ops and boss.
parent 9aab7322
......@@ -27,7 +27,8 @@ SBIN_STUFF = resetvlans console_setup.proxy sched_reload named_setup \
rmgroup mkgroup setgroups mkproj \
exports_setup.proxy vnode_setup eventsys_start \
sfskey_update sfskey_update.proxy rmuser idleswap \
newnode_reboot savelogs.proxy eventsys.proxy
newnode_reboot savelogs.proxy eventsys.proxy \
elabinelab snmpit.proxy
CTRLBIN_STUFF = console_setup.proxy exports_setup.proxy sfskey_update.proxy \
savelogs.proxy eventsys.proxy
......@@ -46,7 +47,7 @@ LIBEXEC_STUFF = rmproj wanlinksolve wanlinkinfo \
LIB_STUFF = libtbsetup.pm exitonwarn.pm libtestbed.pm snmpit_intel.pm \
snmpit_cisco.pm snmpit_lib.pm snmpit_apc.pm power_rpc27.pm \
snmpit_cisco_stack.pm snmpit_intel_stack.pm \
snmpit_foundry.pm snmpit_stack.pm \
snmpit_foundry.pm snmpit_stack.pm snmpit_remote.pm \
libaudit.pm libreboot.pm libosload.pm libtestbed.py
#
......@@ -159,6 +160,8 @@ post-install:
chmod u+s $(INSTALL_BINDIR)/tarfiles_setup
chown root $(INSTALL_BINDIR)/savelogs
chmod u+s $(INSTALL_BINDIR)/savelogs
chown root $(INSTALL_SBINDIR)/elabinelab
chmod u+s $(INSTALL_SBINDIR)/elabinelab
#
# Control node installation (okay, plastic)
......
This diff is collapsed.
#!/usr/bin/perl -w
#
# EMULAB-LGPL
# Copyright (c) 2000-2004 University of Utah and the Flux Group.
# All rights reserved.
#
#
# snmpit - A tool for setting up VLANs on SNMP-controllable switches
#
......@@ -17,10 +15,12 @@
use lib '@prefix@/lib';
my $TESTMODE = @TESTMODE@;
my $ELABINELAB = @ELABINELAB@;
my $TB = '@prefix@';
use libdb;
use snmpit_lib;
use snmpit_remote;
use English;
use Getopt::Long;
......@@ -59,6 +59,7 @@ General:
VLAN Control:
-t <pid> <eid> Create all VLANs from database tables for an experiment
-r <pid> <eid> Remove all VLANs from database tables for an experiment
(you can provide an optional list of vlan ids)
-l List all VLANs
-w Used with -l, includes device-specific VLAN number
-M Used with -l, print MAC addresses instead of port numbers
......@@ -113,6 +114,7 @@ if ($opt{v}) {
my $pid;
my $eid;
my @ports;
my @optvlanids = ();
#
# Some operations have mandatory agruments - for others, make sure that
......@@ -128,6 +130,9 @@ if ($opt{t} || $opt{r}) {
} else {
($pid, $eid) = (shift @ARGV, shift @ARGV);
}
if (@ARGV) {
@optvlanids = @ARGV;
}
} elsif ($opt{d} || $opt{e} || $opt{a} || $opt{p} || $opt{u} || $opt{m}) {
#
# Options that take a list of ports
......@@ -357,7 +362,7 @@ foreach my $command (@commands) {
last;
};
(/tables/) && do {
@vlans = getExperimentVlans($pid,$eid);
@vlans = getExperimentVlans($pid,$eid,@optvlanids);
@ports = getVlanPorts(@vlans);
@devicenames = $opt{i}? @{$opt{i}} : getTestSwitches();
last;
......@@ -366,7 +371,7 @@ foreach my $command (@commands) {
#
# When we reset, we operate on all test switches, just to be safe
#
@vlans = getExperimentVlans($pid,$eid);
@vlans = getExperimentVlans($pid,$eid,@optvlanids);
@devicenames = $opt{i}? @{$opt{i}} : getTestSwitches();
last;
};
......@@ -394,10 +399,12 @@ foreach my $command (@commands) {
# Find out which stack each device belongs to
#
my %stacks = ();
foreach my $devicename (@devicenames) {
my $stack = getSwitchStack($devicename);
if (defined($stack)) {
push @{$stacks{$stack}}, $devicename;
if (! $ELABINELAB) {
foreach my $devicename (@devicenames) {
my $stack = getSwitchStack($devicename);
if (defined($stack)) {
push @{$stacks{$stack}}, $devicename;
}
}
}
......@@ -740,6 +747,13 @@ sub doVlansFromTables($@) {
}
my ($stack) = @$stacks;
#
# Hand over to outer boss.
#
if ($ELABINELAB) {
return RemoteDoVlansFromTables(@vlans);
}
foreach my $vlan (@vlans) {
my @ports = getVlanPorts($vlan);
if ($stack->vlanExists($vlan)) {
......@@ -795,6 +809,13 @@ sub doReset($@) {
my $stacks = shift;
my @vlans = @_;
#
# Hand over to outer boss.
#
if ($ELABINELAB) {
return RemoteDoReset(@vlans);
}
my $errors = 0;
#
# Just remove the VLAN from evey stack on which it exists. We keep a
......
This diff is collapsed.
This diff is collapsed.
#!/usr/bin/perl -w
#
# EMULAB-LGPL
# Copyright (c) 2000-2004 University of Utah and the Flux Group.
......@@ -179,13 +178,18 @@ sub getVlanPorts (@) {
}
#
# Returns an array of all VLAN id's used by a given experiment
# Returns an array of all VLAN id's used by a given experiment.
# Optional list of vlan ids restricts operation to just those vlans,
#
sub getExperimentVlans ($$) {
my ($pid, $eid) = @_;
sub getExperimentVlans ($$@) {
my ($pid, $eid, @optvlans) = @_;
my $result =
DBQueryFatal("SELECT id FROM vlans WHERE pid='$pid' AND eid='$eid'");
DBQueryFatal("SELECT id FROM vlans WHERE pid='$pid' AND eid='$eid' ".
(@optvlans ?
"and (" . join(' OR ', map("id='$_'", @optvlans)) . ")" :
""));
my @vlans = ();
while (my @row = $result->fetchrow()) {
push @vlans, $row[0];
......
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2004 University of Utah and the Flux Group.
# All rights reserved.
#
#
# Some ElabInElab support for managing vlans via outer boss node.
#
package snmpit_remote;
use Exporter;
@ISA = ("Exporter");
@EXPORT = qw( RemoteDoVlansFromTables RemoteDoReset );
# Must come after package declaration!
use lib '@prefix@/lib';
use English;
use libdb;
use libtestbed;
use snmpit_lib;
use libxmlrpc;
# Configure variables
my $TB = "@prefix@";
my $TBOPS = "@TBOPSEMAIL@";
my $RPCSERVER = "@OUTERBOSS_NODENAME@";
my $RPCPORT = "@OUTERBOSS_XMLRPCPORT@";
my $RPCCERT = "@OUTERBOSS_SSLCERTNAME@";
# Locals
my $didsetup = 0;
#
# Configure xmlrpc library to talk to outer boss.
#
sub ConfigXMLRPC()
{
return 0
if ($didsetup);
libxmlrpc::Config({"server" => $RPCSERVER,
"verbose" => 1,
"cert" => $RPCCERT,
"portnum" => $RPCPORT});
$didsetup = 1;
return 0;
}
#
# Ask outer boss to setup a bunch of vlans for an experiment.
#
sub RemoteDoVlansFromTables(@)
{
my @vlans = @_;
my $vlantable = {};
return 0
if (! @vlans);
my $result =
DBQueryFatal("select virtual,members,id from vlans where " .
# Join "id='foo'" with ORs
join(' OR ', map("id='$_'",@vlans)));
return 0
if (! $result->numrows);
while (my ($virtual,$members,$id) = $result->fetchrow()) {
# $members is a space-seprated list
$vlantable->{$id} = {};
$vlantable->{$id}->{"virtual"} = $virtual;
$vlantable->{$id}->{"members"} = {};
foreach my $port (split /\s+/,$members) {
# Due to the inconsistent nature of our tables (curses!), we
# have to do some conversion here
$port =~ /^(.+):(.+)/;
my ($node,$iface) = ($1,$2);
if (!defined($node) || !defined($iface)) {
warn "WARNING: Bad node in VLAN: $port - skipping\n";
next;
}
my $result =
DBQueryFatal("select current_speed,duplex from interfaces " .
"where node_id='$node' and iface='$iface'");
if (!$result->num_rows()) {
warn "WARNING: Bad node/iface pair in VLAN: $port - skipping\n";
next;
}
my ($speed,$duplex) = $result->fetchrow();
$vlantable->{$id}->{"members"}->{$port} = {};
$vlantable->{$id}->{"members"}->{$port}->{"speed"} = $speed;
$vlantable->{$id}->{"members"}->{$port}->{"duplex"} = $duplex;
}
}
return 0
if (! keys(%$vlantable));
ConfigXMLRPC();
my $rval = libxmlrpc::CallMethod("elabinelab", "vlans",
{"op" => "setup",
"arg" => $vlantable});
if (!defined($rval)) {
return -1;
}
return $rval;
}
#
# Ask outer boss to tear down a bunch of vlans for an experiment.
#
sub RemoteDoReset(@)
{
my @vlans = @_;
return 0
if (! @vlans);
ConfigXMLRPC();
my $rval = libxmlrpc::CallMethod("elabinelab", "vlans",
{"op" => "destroy",
"arg" => join(",", @vlans)});
if (!defined($rval)) {
return -1;
}
return $rval;
}
# End with true
1;
......@@ -330,6 +330,7 @@ my $noidleswap = $hashrow{'noidleswap_reason'};
my $idleswaptime= $hashrow{'idleswap_timeout'} / 60.0;
my $autoswaptime= $hashrow{'autoswap_timeout'} / 60.0;
my $rendering = $hashrow{'prerender_pid'};
my $elabinelab = $hashrow{'elab_in_elab'};
if ($inout ne "out") {
# I'm going to update this below, so fix the value before I use it.
......@@ -734,7 +735,7 @@ if ($inout ne "restart" && -e $repfile) {
#
if ($inout eq "out") {
my $optarg = (($force || $idleswap) ? "-force" : "");
print STDOUT "Running 'tbswap out $optarg $pid $eid'\n";
if (system("$tbdir/tbswap out $optarg $pid $eid") != 0) {
$errorstat = $? >> 8;
......@@ -744,7 +745,9 @@ if ($inout eq "out") {
or fatal("Failed to set experiment state to " . EXPTSTATE_SWAPPED());
}
elsif ($inout eq "in") {
print STDOUT "Running 'tbswap in $pid $eid'\n";
my $optarg = "";
print STDOUT "Running 'tbswap in $optarg $pid $eid'\n";
if (system("$tbdir/tbswap in $pid $eid") != 0) {
$errorstat = $? >> 8;
fatal("tbswap in failed!");
......@@ -803,9 +806,19 @@ elsif ($inout eq "modify") {
}
else {
SetExpState($pid, $eid, EXPTSTATE_MODIFY_RESWAP);
my $optarg = ($reboot ? "-reboot" : "");
$optarg .= ($eventsys_restart ? " -eventsys_restart" : "");
my $optarg = "";
#
# For elabinelab experiments; ignore reboot/eventsys_restart,
# and force noreconfig; none of it will work or make sense.
#
if ($elabinelab) {
$optarg = "-noreconfig";
}
else {
$optarg = ($reboot ? "-reboot" : "");
$optarg .= ($eventsys_restart ? " -eventsys_restart" : "");
}
print STDOUT "Running 'tbswap update $optarg $pid $eid'\n";
if (system("$tbdir/tbswap update $optarg $pid $eid") == 0) {
......@@ -1054,8 +1067,10 @@ sub cleanup()
# Note: $estate is indeed still set appropriately!
#
if ($estate eq EXPTSTATE_ACTIVE) {
print "Running 'tbswap out -force $pid $eid'\n";
if (system("$tbdir/tbswap out -force $pid $eid") != 0) {
my $optarg = "-force";
print "Running 'tbswap out $optarg $pid $eid'\n";
if (system("$tbdir/tbswap out $optarg $pid $eid") != 0) {
print "tbswap out failed!\n";
$stat = $? >> 8;
}
......
......@@ -67,7 +67,8 @@ $| = 1;
my $updateReboot = 0;
my $updateReconfig = 1;
my $updateEventsys_restart = 0;
my $update_Eventsys_restart = 0;
my $elabinelab = 0;
my $force = 0;
my $errors = 0;
my $updatehosed = 0;
......@@ -102,6 +103,9 @@ while ($#ARGV > 1) {
} elsif ($arg eq "-reboot") {
$updateReboot = 1;
$updateReconfig = 0;
} elsif ($arg eq "-noreconfig") {
$updateReboot = 0;
$updateReconfig = 0;
} elsif ($arg eq "-eventsys_restart" && $swapop eq "update") {
$update_Eventsys_restart = 1;
} else {
......@@ -163,6 +167,11 @@ if (!$force) {
if ($state ne EXPTSTATE_MODIFY_RESWAP);
}
}
# Get elabinelab status. See below.
if (! TBExptIsElabInElab($pid, $eid, \$elabinelab)) {
die("*** $0:\n".
" Could not get elabinelab status for experiment $pid/$eid\n");
}
#
# Do actual swapping
......@@ -322,8 +331,9 @@ sub doSwapout($) {
}
if (! $TESTMODE) {
if (! $DISABLE_EVENTS) {
if ($type >= RETRY || ($update_Eventsys_restart && $type == UPDATE) ) {
if (! ($DISABLE_EVENTS || $elabinelab)) {
if ($type >= RETRY ||
($update_Eventsys_restart && $type == UPDATE) ) {
print "Stopping the event system\n";
if (system("eventsys_control stop $pid $eid")) {
print STDERR "*** Failed to stop the event system.\n";
......@@ -331,7 +341,6 @@ sub doSwapout($) {
}
}
}
#
# Clean up any VLANs in experiment.
#
......@@ -443,6 +452,18 @@ sub doSwapout($) {
}
if (! $TESTMODE) {
#
# Restart DHCPD as soon as possible after freeing the nodes; they
# are going into a reload, so DHCPD better be ready for them!
#
if ($elabinelab) {
print "Regenerating DHCPD config file and restarting daemon.\n";
if (system("dhcpd_makeconf -i -r")) {
print STDERR "*** Failed to reconfig/restart DHCPD.\n";
$swapout_errors = 1;
}
}
#
# If the experiment has no Plab dslice nodes left, but still has
# a Plab slice, destroy the slice
......@@ -860,7 +881,7 @@ sub doSwapin($) {
# Don't do this during an update, since we didn't kill the
# event system previously, so starting it again will fail!
#
if (! $DISABLE_EVENTS) {
if (! ($DISABLE_EVENTS || $elabinelab)) {
if ( $update_Eventsys_restart ||
($type != UPDATE && $type != UPDATE_RECOVER) ) {
print "Starting the event system.\n";
......@@ -873,5 +894,18 @@ sub doSwapin($) {
}
}
#
# ElabinElab setup. This might not be the right place for this!
#
if ($elabinelab && !$TESTMODE && $type == REAL) {
print "Setting up elabinelab. This could take a while!\n";
TBDebugTimeStamp("elabinelab setup started");
if (system("elabinelab $pid $eid")) {
print STDERR "*** Failed to setup elabinelab!\n";
return 1;
}
TBDebugTimeStamp("elabinelab setup finished");
}
return 0;
}
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