Commit 6e37a59a authored by Leigh B Stoller's avatar Leigh B Stoller

Kill off more obsolete files.

parent 02c9af99
......@@ -62,9 +62,9 @@ SBIN_STUFF = resetvlans console_setup.proxy sched_reload named_setup \
exports_setup.proxy vnode_setup eventsys_start \
sfskey_update sfskey_update.proxy rmuser idleswap idlepower \
newnode_reboot savelogs.proxy eventsys.proxy \
elabinelab snmpit.proxy panic node_attributes \
elabinelab panic node_attributes \
nfstrace plabinelab smbpasswd_setup smbpasswd_setup.proxy \
rmproj snmpit.proxynew snmpit.proxyv2 pool_daemon \
rmproj pool_daemon \
checknodes_daemon snmpit.proxyv3 image_setup tcpp \
arplockdown bscontrol reportboot reportboot_daemon \
nfsmfs_setup nfsmfs_setup.proxy
......
#!/usr/bin/perl -w
#
# Copyright (c) 2000-2008 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/>.
#
# }}}
#
use English;
use Getopt::Std;
#
# Snmpit proxy for ElabInElab.
#
sub usage()
{
print STDOUT "Usage: snmpit.proxy [-d] -p <pid> -e <eid> ".
"setup|destroy|trunk|list arg [arg ...]\n";
exit(-1);
}
my $optlist = "dnp:e:";
my $debug = 0;
my $impotent = 0;
my $pid;
my $eid;
my @inner_ids = ();
my @outer_ids = ();
my %outer_vlans = ();
my %mapping = ();
#
# Configure variables
#
my $TB = "@prefix@";
my $TBOPS = "@TBOPSEMAIL@";
# un-taint path
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin:/usr/site/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
#
# Turn off line buffering on output
#
$| = 1;
# Load the Testbed support stuff.
use lib "@prefix@/lib";
use libdb;
use libtestbed;
use Experiment;
use Lan;
# Locals
my $exptidx;
# Protos
sub SetupVlans();
sub DestroyVlans();
sub Trunk();
sub List();
sub Map();
#
# Parse command arguments. Once we return from getopts, all that should
# left are the required arguments.
#
%options = ();
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{"d"})) {
$debug = 1;
}
if (defined($options{"n"})) {
$impotent = 1;
}
if (defined($options{"p"})) {
$pid = $options{"p"};
#
# Untaint the arguments.
#
if ($pid =~ /^([-\w\.]+)$/) {
$pid = $1;
}
else {
die("Tainted argument $pid!\n");
}
}
if (defined($options{"e"})) {
$eid = $options{"e"};
if ($eid =~ /^([-\w\.]+)$/) {
$eid = $1;
}
else {
die("Tainted argument $eid!\n");
}
}
usage()
if (!@ARGV || !defined($pid) || !defined($eid));
my $op = shift(@ARGV);
#
# Sanity check. Must be an ElabInElab experiment and user must have
# permission (be the creator).
#
my $experiment = Experiment->Lookup($pid, $eid);
if (!defined($experiment)) {
die("*** $0:\n",
" Experiment $pid/$eid is not active!\n");
}
$exptidx = $experiment->idx();
if (!TBExptAccessCheck($UID, $pid, $eid, TB_EXPT_MODIFY)) {
die("*** $0:\n".
" You do not have permission to swap or modify this experiment!\n");
}
#
# I'm going to serialize this for now. When the script exits, the lock
# will be released.
#
DBQueryFatal("select get_lock('snmpit.proxy', 999999)");
if ($op eq "setup") {
exit(SetupVlans());
}
elsif ($op eq "destroy") {
exit(DestroyVlans());
}
elsif ($op eq "trunk") {
exit(Trunk());
}
elsif ($op eq "list") {
exit(List());
}
#
# Setup vlans for an inner emulab. ARGV holds a set of strings that look
# like:
# id,node:iface,speed,duplex,vtag
# which came in from the XMLRPC server. For each vlan id, gather up all
# if its member ports (node:iface), along with the speed and duplex for
# each port, which goes into the interfaces table so that the real snmpit
# can find the right values.
#
sub SetupVlans()
{
my $vlantable = {};
my %vmaptable = ();
my %vtagtable = ();
my %nodes = ();
my @outer_ids = ();
my $errors = 0;
while (@ARGV) {
my $str = shift(@ARGV);
if ($str =~ /^(\d+),([\w:]+),(\d*),(full|half),([-\w]+)$/) {
my $id = $1;
my $port = $2;
my $speed = $3;
my $duplex = $4;
my $vtag = $5;
my $node;
my $iface;
if (! exists($vlantable->{$id})) {
$vlantable->{$id} = {};
$vtagtable{$id} = $vtag;
}
$vlantable->{$id}->{$port} = [$speed, $duplex];
# For doing access and sanity checks below.
if ($port =~ /^(.+):(.+)$/) {
($node,$iface) = ($1, $2);
}
$nodes{$node} = []
if (!exists($nodes{$node}));
push(@{ $nodes{$node} }, $iface);
}
else {
die("*** $0:\n",
" SetupVlans: Cannot parse '$str'!\n");
}
}
#
# First check permission on the nodes. snmpit is going to repeat this
# operation, but we have to do it here cause we first mess with the
# speed and duplex values in the interfaces table for each node, cause
# snmpit uses those values when setting up the vlan.
#
if (!TBNodeAccessCheck($UID, TB_NODEACCESS_MODIFYVLANS, keys(%nodes))) {
die("*** $0:\n",
" You do not have permission to modify some of the nodes\n" .
" that will be affected by the operation you requested\n");
}
# Stoller wrote:
# Sanity check the inner id numbers. If they already exist in the
# mapping table, then bail now. We could probably support this, but
# I do not see a reason to yet.
# Sklower explains:
# for the federation boss, in order to calculate which
# vlans go on which inter site trunks it's convenient to
# push the vlan handling for master site's parent into
# a pseudo-switch-module, but that will cause the parent
# to be asked to add groups of interfaces in chunks.
# my $query_result =
# DBQueryFatal("select * from elabinelab_vlans ".
# "where pid='$pid' and eid='$eid' and ".
# # Join "id='foo'" with ORs
# "(" .
# join(' OR ', map("inner_id='$_'", keys(%$vlantable))) .
# ")");
# if ($query_result->numrows) {
# my @ids = keys(%$vlantable);
#
# die("*** $0:\n",
# " One of the inner vlan ids (@ids) already exists!\n");
# }
#
# Okay, sanity check the interfaces for each node. They have to be real
# interfaces, marked as TBDB_IFACEROLE_EXPERIMENT(), nothing else. Also,
# the IP must not be set; if the IP is set, its being used for the inner
# control network, and we do not let those interfaces change.
#
foreach my $node (keys(%nodes)) {
my @ifaces = @{ $nodes{$node} };
# Sklower chimes in again
# In Mike's canonical experiment about running two interfaces in
# multiplexed mode the query that was here returned more than
# one result, because the same interface was presented twice.
# this check is going to become a lot more elaborate if we allow
# an elabinelab to have firewalls within it ... let's *table* that
# motion for now ...
my $query_result =
DBQueryFatal("select iface,role,IP from interfaces ".
"where node_id='$node' and ".
# Join "iface='foo'" with ORs
"(" . join(' OR ', map("iface='$_'", @ifaces)) . ")");
if ($query_result) {
while (my ($iface, $role, $IP) = $query_result->fetchrow()) {
if (($role ne "expt") || ($IP ne "")) {
die("*** $0:\n",
"Iface $iface for $node cannot be changed\n");
}
}
}
}
#
# Okay, set the speed and duplex for all the interfaces.
#
foreach my $id (keys(%$vlantable)) {
foreach my $port (keys(%{ $vlantable->{$id} })) {
my ($speed, $duplex) = @{ $vlantable->{$id}->{$port} };
my ($node,$iface) = ($port =~ /^(.+):(.+)$/);
if ($debug) {
print STDERR "$id $node:$iface $speed $duplex\n";
}
if (! $impotent) {
DBQueryFatal("update interfaces set ".
" current_speed=$speed,duplex='$duplex'".
"where node_id='$node' and iface='$iface'");
}
}
}
#
# Okay, create an actual members list to insert into the DB vlans table.
# We need to remember the association between the inner id and the outer
# id, so after we insert the vlans entry, get the ID that was assigned and
# remember it in the elabinelab_vlans table for later when the inner elab
# requests deletion (see DestroyVlans() below).
#
# Note that on failure we keep going, which mirrors how snmpit operates.
# Not sure if this is the right approach though.
#
foreach my $id (keys(%$vlantable)) {
my $vtag = $vtagtable{$id};
my @members = keys(%{ $vlantable->{$id} });
my $mstring = "@members";
my $outer_id;
my $vlan;
if ($debug) {
print STDERR "$pid $eid $id $mstring\n";
}
next
if ($impotent);
# Insert (or modify) outer vlans entry.
my $query_result =
DBQueryFatal("select outer_id from elabinelab_vlans ".
"where pid='$pid' and eid='$eid' and inner_id='$id'");
if ($query_result->numrows == 1) {
($outer_id) = $query_result->fetchrow();
$vlan = VLan->Lookup($outer_id);
if (!defined($vlan)) {
print STDERR "*** $0:\n".
" Could not lookup vlan for $outer_id\n";
$errors++;
next;
}
}
else {
$vlan = VLan->Create($experiment, $vtag);
if (!defined($vlan)) {
print STDERR "*** $0:\n".
" Could not insert vlan table entry for $id\n";
$errors++;
next;
}
$outer_id = $vlan->lanid();
# Insert mapping between inner and outer vlan entries.
$query_result = DBQueryWarn("insert into elabinelab_vlans ".
" (exptidx,pid,eid,inner_id,outer_id) ".
"values ($exptidx, '$pid', '$eid', $id, $outer_id)");
if (!$query_result || !$query_result->numrows) {
#
# Failed, must remove vlans entry too. We keep going though
#
print STDERR "*** $0:\n".
" Could not insert elabinelab_vlans table entry ".
"for $id/$outer_id\n";
$vlan->Destroy();
$errors++;
next;
}
}
if ($debug) {
print STDERR "Mapping inner id $id to outer id $outer_id\n";
print STDERR " $mstring\n";
}
foreach my $port (@members) {
my ($nodeid, $iface) = split(":", $port);
if (!$vlan->IsMember($nodeid, $iface) &&
!$vlan->AddMember($nodeid, $iface)) {
print STDERR "*** $0:\n".
" Could not $port to $vlan\n";
$errors++;
}
}
$vmaptable{$id} = $outer_id;
# Okay, save outer_id up for passing to snmpit below.
push(@outer_ids, $outer_id);
# And save vlan object for getting the tag.
$outer_vlans{$outer_id} = $vlan;
}
# Now call snmpit to create the actual vlans.
if ($debug) {
print STDERR "Running 'snmpit -t $pid $eid @outer_ids'\n";
}
return $errors
if ($impotent);
system("$TB/bin/snmpit -t $pid $eid @outer_ids > /dev/null");
if ($?) {
#
# Yuck failed. We leave things as is, and wait for experiment
# teardown to destroy any vlans that managed to get set up.
# Obviously, we must leave the vlans in the DB or else we will not
# be able to clean up later.
# This mirrors what happens when snmpit fails during a normal setup.
#
print STDERR "*** $0:\n".
" snmpit -t failed!\n";
$errors = $? >> 8;
}
my @results = ();
foreach $id (keys %vmaptable) {
my $outer_vlan = $outer_vlans{$vmaptable{$id}};
if ($outer_vlan->Refresh() != 0) {
print STDERR "*** Could not refresh $outer_vlan\n";
$errors++;
next;
}
my $tagnum;
if ($outer_vlan->GetTag(\$tagnum) != 0) {
print STDERR "*** Could not get vlan tag for $outer_vlan\n";
$errors++;
next;
}
push (@results, "$id#$tagnum");
}
print join(",", @results);
return $errors;
}
#
# This is common to list and destroy and trunk.
#
sub Map()
{
my $query_result =
DBQueryFatal("select inner_id,outer_id from elabinelab_vlans ".
"where pid='$pid' and eid='$eid'");
while (my ($inner_id,$outer_id) = $query_result->fetchrow()) {
$mapping{$inner_id} = $outer_id;
}
#
# Sanity check; make sure the set of vlans we got on the command line
# (from the inner elab via the RPC server) are really vlans we have
# already setup. Anything that does not match, skip with a warning, but
# go ahead and tear down ones that match.
#
while (@ARGV) {
my $id = shift(@ARGV);
if ($id eq "") { next ; }
if (! ($id =~ /^\d+$/)) {
print STDERR "*** $0:\n".
" Illegal characters in id: $id\n";
next;
}
if (!exists($mapping{$id})) {
print STDERR "*** $0:\n".
" No such elabinelab_vlans table entry: $id\n";
next;
}
my $vlan = VLan->Lookup($mapping{$id});
if (!defined($vlan)) {
print STDERR "*** $0:\n".
" Cannot find vlan object for vlan id: $id\n";
next;
}
push(@inner_ids, $id);
push(@outer_ids, $mapping{$id});
$outer_vlans{$mapping{$id}} = $vlan;
}
return 0;
}
#
# Destroy a set of vlans. We get a list of inner vlan ID numbers for the
# inner elab vlans table. We have to map those to outer vlan table id
# numbers, and then remove those from the DB and from the switches.
#
sub DestroyVlans()
{
Map();
# If no vlans, do nothing! snmpit will end up removing all the vlans!
return 0
if (! @outer_ids);
return 0
if ($impotent);
#
# Okay, ask snmpit to tear down these vlans.
#
if ($debug) {
print STDERR "Running 'snmpit -r $pid $eid @outer_ids'\n";
}
system("$TB/bin/snmpit -r $pid $eid @outer_ids");
if ($?) {
#
# Yuck failed. We leave things as is, and wait for the inner elab
# to request experiment teardown again. This mirrors what happens
# on a normal swapout; snmpit -r can be retried until all of the
# vlans are finally gone; At that point the DB state can be removed.
#
print STDERR "*** $0:\n".
" snmpit -r failed!\n";
return $? >> 8;
}
#
# Okay, remove the outer vlan table entries first.
#
if ($debug) {
print STDERR "Removing @outer_ids from vlans table\n";
}
foreach my $vlan (values(%outer_vlans)) {
if ($vlan->Destroy() != 0) {
print STDERR "*** $0:\n".
" Could not Destroy() $vlan\n";
return -1;
}
}
#
# Since the above worked, we can remove the mappings too.
#
if ($debug) {
print STDERR "Removing @inner_ids from elabinelab_vlans table\n";
}
DBQueryFatal("delete from elabinelab_vlans ".
"where pid='$pid' and eid='$eid' and ".
# Join "id='foo'" with ORs
"(" . join(' OR ', map("inner_id='$_'", @inner_ids)) . ")");
return 0;
}
#
# List a set of vlans. We get a list of inner vlan ID numbers for the
# inner elab vlans table. We have to map those to outer vlan table id
# numbers, and then list.
#
sub List()
{
my @pairs;
Map();
if (!@inner_ids) { @inner_ids = keys %mapping; }
if (!@inner_ids) { return 0; }
foreach my $in (@inner_ids) {
my $out = $mapping{$in};
push @pairs, "$out#$in";
}
my $command = "$TB/bin/snmpit -L " . join(",", @pairs);
system($command);
if ($?) {
# Yuck failed.
print STDERR "*** $0:\n". " snmpit -L failed!\n";
return $? >> 8;
}
return 0;
}
#
# Either put a(n experimental) port into standard, or dual-mode trunking
# or reset to its normal state (snmpit -E , -T or - U).
#
sub Trunk()
{
my $mode = shift(@ARGV);
my $port = shift(@ARGV);
$port =~ /^(.+):(.+)/;
my ($node, $card) = ($1,$2);
my $query =
"select iface from interfaces where node_id='$node' and card='$card'";
my $query_result = DBQueryFatal($query);
if ($query_result->numrows != 1) {
print STDERR "can't determine iface from $port in $pid/$eid\n";
return 1;
}
my ($iface) = ($query_result->fetchrow())[0];
$query_result =
DBQueryFatal("select node_id from reserved where node_id='$node' ".
"and pid='$pid' and eid='$eid'");
if ($query_result->numrows != 1) {
print STDERR "$node not allocated to $pid / $eid\n";
return 1;
}
Map();
if ($mode eq "-U") {
$query_result = DBQueryFatal("select iface from vinterfaces where " .
"node_id='$node' and type='vlan' and iface='$iface'");
if ($query_result->numrows == 0) {
print STDERR "$port not trunked in database\n";
return 1;
}
#
# Okay, ask snmpit to Untrunk
#
if ($debug) {
print STDERR "Running 'snmpit -U $port'\n";
}
system("$TB/bin/snmpit -U $port > /dev/null");
if ($?) {
# Yuck failed.
print STDERR "*** $0:\n". " snmpit -U failed!\n";
return $? >> 8;
}
#
# and clean up the database
#
$query_result = DBQueryFatal("delete from vinterfaces where " .
"node_id='$node' and type='vlan' and iface='$iface'");
return 0;
}
if (($mode eq "-E") || ($mode eq "-T")) {
# First, update the status of the port in the database
# The code here is wrong and needs futher work.
# apparently there is a vinterfaces entry for each vlan
# however in order to figure out which one you have to
# do a join through both the vlans and virt_lans tables.
# There's no convenient way, given the management