Commit cc22200f authored by Leigh B. Stoller's avatar Leigh B. Stoller
Browse files

Out with the vlans table, in with lans, lan_attributes, lan_members,

lan_member_attributes, and ifaces. Making the world safe for protogenis.
parent 96af2532
......@@ -25,7 +25,7 @@ WEB_BIN_SCRIPTS = webnfree
LIBEXEC_SCRIPTS = $(WEB_BIN_SCRIPTS) $(WEB_SBIN_SCRIPTS) xmlconvert
LIB_SCRIPTS = libdb.pm Node.pm libdb.py libadminctrl.pm Experiment.pm \
NodeType.pm Interface.pm User.pm Group.pm Project.pm \
Image.pm OSinfo.pm Archive.pm Logfile.pm
Image.pm OSinfo.pm Archive.pm Logfile.pm Lan.pm
# Stuff installed on plastic.
USERSBINS = genelists.proxy dumperrorlog.proxy
......
This diff is collapsed.
#!/usr/bin/perl
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2002 University of Utah and the Flux Group.
# Copyright (c) 2000-2007 University of Utah and the Flux Group.
# All rights reserved.
#
use strict;
use English;
#
# Turn off line buffering on output
#
$| = 1;
#
# Configure variables
# Set umask for start/swap. We want other members in the project to be
# able to swap/end experiments, so the log and intermediate files need
# to be 664 since some are opened for append.
#
umask(0002);
#
# Untaint the path
#
# un-taint path
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
# Testbed Libraries.
use lib '@prefix@/lib';
use libdb;
use English;
use User;
use Lan;
if (!TBAdmin($UID)) {
#
# Verify user and get his DB uid and other info for later.
#
my $this_user = User->ThisUser();
if (! defined($this_user)) {
die("*** $0:\n".
" You ($UID) do not exist!\n");
}
if (!$this_user->IsAdmin()) {
die("*** $0:\n".
" You must be a TB administrator to use this program\n");
}
my ($virtual,$id,$pideid,$members);
my ($pid,$eid,$virtual,$id,$pideid,$members);
print << "END";
ID Project/Experiment Link/LAN Switches (number of members in parens)
--------------------------------------------------------------------------------
......@@ -35,34 +62,52 @@ $FORMAT_NAME = 'vlanlist';
#
# Get a list of all VLANs for swapped-in experiments
#
my $result = DBQueryFatal("SELECT eid, pid, virtual, members, id FROM vlans " .
"ORDER BY eid,pid,virtual");
my $eid,$pid;
while (($eid, $pid, $virtual, $members, $id) = $result->fetchrow()) {
my @vlans;
if (VLan->AllVLans(\@vlans) != 0) {
die("*** $0:\n".
" Unable to load VLANs for all experiments\n");
}
#
# Split apart the space-separated list of members
#
my @members = split /\s+/, $members;
foreach my $vlan (@vlans) {
my %switches = ();
my @members;
my $pid = $vlan->pid();
my $eid = $vlan->eid();
$id = $vlan->lanid();
$virtual = $vlan->vname();
if ($vlan->MemberList(\@members) != 0) {
die("*** $0:\n".
" Unable to load members for $vlan\n");
}
foreach my $member (@members) {
my ($node,$if) = split /:/, $member;
my $node;
my $iface;
if ($member->GetNodeIface(\$node, \$iface) != 0) {
die("*** $0:\n".
" Missing attributes for $member in $vlan\n");
}
my $nodeid = $node->node_id();
#
# Find out which switch this interface is connected to
#
my $result2 = DBQueryFatal("SELECT node_id2 FROM wires AS w LEFT JOIN ".
"interfaces AS i ON w.node_id1=i.node_id AND w.card1=i.card " .
"WHERE node_id='$node' and iface='$if'");
my $result2 =
DBQueryFatal("select node_id2 from wires as w ".
"left join interfaces as i on ".
" w.node_id1=i.node_id AND w.card1=i.card " .
"where node_id='$nodeid' and iface='$iface'");
# We assume only one response here!
my ($switch) = ($result2->fetchrow());
my ($switch) = $result2->fetchrow_array();
$switches{$switch}++;
}
#
# Report if more than one switch was found
#
if ((keys %switches) > 1) {
if (scalar(keys(%switches)) > 1) {
$pideid = "$pid/$eid";
$members = join(" ", map { "$_ ($switches{$_})" } sort keys %switches);
write;
......
......@@ -2,7 +2,7 @@
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2007 University of Utah and the Flux Group.
# Copyright (c) 2000-2008 University of Utah and the Flux Group.
# All rights reserved.
#
......@@ -247,6 +247,7 @@ require Group;
require Node;
require NodeType;
require Mysql;
require Lan;
use vars qw($DBQUERY_MAXTRIES $DBCONN_MAXTRIES
$DBCONN_EXITONERR $DBQUERY_RECONNECT $DBQUERY_DEBUG
@EXPORT_OK @virtualTables @physicalTables);
......@@ -2449,7 +2450,6 @@ sub TBExptContainsNodeCT($$$)
"ipsubnets");
@physicalTables = ("delays",
"vlans",
"tunnels",
"ipport_ranges",
"v2pmap",
......@@ -2647,6 +2647,13 @@ sub TBExptRemovePhysicalState($$)
my ($pid, $eid) = @_;
my $errors = 0;
my $experiment = Experiment->Lookup($pid, $eid);
return 1
if (!defined($experiment));
return 1
if (Lan->DestroyExperimentLans($experiment) != 0);
foreach my $table (@physicalTables) {
DBQueryWarn("DELETE FROM $table WHERE pid='$pid' AND eid='$eid'")
or $errors++;
......@@ -2697,6 +2704,13 @@ sub TBExptBackupPhysicalState($$)
or return 1;
}
my $experiment = Experiment->Lookup($pid, $eid);
return 1
if (!defined($experiment));
return 1
if (Lan->BackupExperimentLans($experiment, $pstateDir) != 0);
foreach my $table (@physicalTables) {
DBQueryWarn("SELECT * FROM $table WHERE pid='$pid' AND eid='$eid' ".
"INTO OUTFILE '$pstateDir/$table' ")
......
......@@ -521,7 +521,7 @@ CREATE TABLE `experiment_input_data` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
--
-- Table structure for table `experiment_template_inputs`
-- Table structure for table `experiment_inputs`
--
DROP TABLE IF EXISTS `experiment_inputs`;
......@@ -1098,9 +1098,9 @@ CREATE TABLE `firewalls` (
`fwname` varchar(32) NOT NULL default '',
`vlan` int(11) default NULL,
`vlanid` int(11) default NULL,
PRIMARY KEY (`exptidx`,`fwname`),
KEY `pideid` (`pid`,`eid`,`fwname`),
KEY `vlan` (`vlan`)
PRIMARY KEY (`exptidx`,`fwname`),
KEY `vlan` (`vlan`),
KEY `pideid` (`pid`,`eid`,`fwname`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
--
......@@ -1292,6 +1292,28 @@ CREATE TABLE `iface_counters` (
KEY `node_idindex` (`node_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
--
-- Table structure for table `ifaces`
--
DROP TABLE IF EXISTS `ifaces`;
CREATE TABLE `ifaces` (
`lanid` int(11) NOT NULL default '0',
`ifaceid` int(11) NOT NULL default '0',
`exptidx` int(11) NOT NULL default '0',
`pid` varchar(12) NOT NULL default '',
`eid` varchar(32) NOT NULL default '',
`node_id` varchar(32) NOT NULL default '',
`vnode` varchar(32) NOT NULL default '',
`vname` varchar(32) NOT NULL default '',
`vidx` int(11) NOT NULL default '0',
`vport` tinyint(3) NOT NULL default '0',
PRIMARY KEY (`lanid`,`ifaceid`),
KEY `pideid` (`pid`,`eid`),
KEY `exptidx` (`exptidx`),
KEY `lanid` (`lanid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
--
-- Table structure for table `images`
--
......@@ -1458,6 +1480,64 @@ CREATE TABLE `knowledge_base_entries` (
PRIMARY KEY (`idx`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
--
-- Table structure for table `lan_attributes`
--
DROP TABLE IF EXISTS `lan_attributes`;
CREATE TABLE `lan_attributes` (
`lanid` int(11) NOT NULL default '0',
`attrkey` varchar(32) NOT NULL default '',
`attrvalue` tinytext NOT NULL,
`attrtype` enum('integer','float','boolean','string') default 'string',
PRIMARY KEY (`lanid`,`attrkey`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
--
-- Table structure for table `lan_member_attributes`
--
DROP TABLE IF EXISTS `lan_member_attributes`;
CREATE TABLE `lan_member_attributes` (
`lanid` int(11) NOT NULL default '0',
`memberid` int(11) NOT NULL default '0',
`attrkey` varchar(32) NOT NULL default '',
`attrvalue` tinytext NOT NULL,
`attrtype` enum('integer','float','boolean','string') default 'string',
PRIMARY KEY (`lanid`,`memberid`,`attrkey`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
--
-- Table structure for table `lan_members`
--
DROP TABLE IF EXISTS `lan_members`;
CREATE TABLE `lan_members` (
`lanid` int(11) NOT NULL default '0',
`memberid` int(11) NOT NULL auto_increment,
PRIMARY KEY (`lanid`,`memberid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
--
-- Table structure for table `lans`
--
DROP TABLE IF EXISTS `lans`;
CREATE TABLE `lans` (
`lanid` int(11) NOT NULL auto_increment,
`exptidx` int(11) NOT NULL default '0',
`pid` varchar(12) NOT NULL default '',
`eid` varchar(32) NOT NULL default '',
`vname` varchar(64) NOT NULL default '',
`vidx` int(11) NOT NULL default '0',
`type` varchar(32) NOT NULL default '',
`link` int(11) default NULL,
`ready` tinyint(1) default '0',
PRIMARY KEY (`lanid`),
KEY `pideid` (`pid`,`eid`),
KEY `exptidx` (`exptidx`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
--
-- Table structure for table `last_reservation`
--
......@@ -3200,7 +3280,7 @@ CREATE TABLE `vinterfaces` (
`iface` varchar(10) default NULL,
`rtabid` smallint(5) unsigned NOT NULL default '0',
`vnode_id` varchar(32) default NULL,
`exptidx` int(11) NOT NULL default '0',
`exptidx` int(10) NOT NULL default '0',
`virtlanidx` int(11) NOT NULL default '0',
`vlanid` int(11) NOT NULL default '0',
PRIMARY KEY (`node_id`,`unit`),
......@@ -3333,7 +3413,7 @@ CREATE TABLE `virt_lans` (
`nobwshaping` tinyint(4) default '0',
`mustdelay` tinyint(1) default '0',
`usevethiface` tinyint(4) default '0',
`encap_style` enum('alias','veth','veth-ne','vlan','default') NOT NULL default 'default',
`encap_style` enum('alias','veth','veth-ne','vlan','tunnel','default') NOT NULL default 'default',
`trivial_ok` tinyint(4) default '1',
`protocol` varchar(30) NOT NULL default 'ethernet',
`is_accesspoint` tinyint(4) default '0',
......
......@@ -731,7 +731,7 @@ REPLACE INTO table_regex VALUES ('projects','num_pcs','int','redirect','default:
REPLACE INTO table_regex VALUES ('projects','num_pcplab','int','redirect','default:int',0,2048,NULL);
REPLACE INTO table_regex VALUES ('projects','num_ron','int','redirect','default:int',0,1024,NULL);
REPLACE INTO table_regex VALUES ('experiments','encap_style','text','regex','^(alias|veth|veth-ne|vlan|default)$',0,0,NULL);
REPLACE INTO table_regex VALUES ('experiments','encap_style','text','regex','^(alias|veth|veth-ne|vlan|tunnel|default)$',0,0,NULL);
REPLACE INTO table_regex VALUES ('experiments','veth_encapsulate','int','redirect','default:boolean',0,0,NULL);
REPLACE INTO table_regex VALUES ('experiments','allowfixnode','int','redirect','default:boolean',0,0,NULL);
REPLACE INTO table_regex VALUES ('experiments','jail_osname','text','redirect','os_info:osname',0,0,NULL);
......
......@@ -4228,3 +4228,66 @@ last_net_act,last_cpu_act,last_ext_act);
4.139: Change to previous revision; Skip to next entry.
4.140: Big changes to vlans table. That table is deprecated in favor of
these new tables. You want to make these changes while the
system is quiet (disable web interface to prevent swapping).
CREATE TABLE `lans` (
`lanid` int(11) NOT NULL auto_increment,
`exptidx` int(11) NOT NULL default '0',
`pid` varchar(12) NOT NULL default '',
`eid` varchar(32) NOT NULL default '',
`vname` varchar(64) NOT NULL default '',
`vidx` int(11) NOT NULL default 0,
`type` varchar(32) NOT NULL default '',
`link` int(11) default NULL,
`ready` tinyint(1) default '0',
PRIMARY KEY (`lanid`),
KEY `pideid` (`pid`,`eid`),
KEY `exptidx` (`exptidx`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
CREATE TABLE `lan_attributes` (
`lanid` int(11) NOT NULL default '0',
`attrkey` varchar(32) NOT NULL default '',
`attrvalue` tinytext NOT NULL,
`attrtype` enum('integer','float','boolean','string') default 'string',
PRIMARY KEY (`lanid`,`attrkey`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
CREATE TABLE `lan_members` (
`lanid` int(11) NOT NULL default '0',
`memberid` int(11) NOT NULL auto_increment,
PRIMARY KEY (`lanid`,`memberid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
CREATE TABLE `lan_member_attributes` (
`lanid` int(11) NOT NULL default '0',
`memberid` int(11) NOT NULL default '0',
`attrkey` varchar(32) NOT NULL default '',
`attrvalue` tinytext NOT NULL,
`attrtype` enum('integer','float','boolean','string') default 'string',
PRIMARY KEY (`lanid`,`memberid`,`attrkey`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
CREATE TABLE `ifaces` (
`lanid` int(11) NOT NULL default '0',
`ifaceid` int(11) NOT NULL default '0',
`exptidx` int(11) NOT NULL default '0',
`pid` varchar(12) NOT NULL default '',
`eid` varchar(32) NOT NULL default '',
`node_id` varchar(32) NOT NULL default '',
`vnode` varchar(32) NOT NULL default '',
`vname` varchar(32) NOT NULL default '',
`vidx` int(11) NOT NULL default 0,
`vport` tinyint(3) NOT NULL default '0',
PRIMARY KEY (`lanid`,`ifaceid`),
KEY `pideid` (`pid`,`eid`),
KEY `exptidx` (`exptidx`),
KEY `lanid` (`lanid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
Run the following script. The testbed should be quiet (no swaps).
./newlans.pl
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2008 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
use lib "/usr/testbed/lib";
use libdb;
use libtestbed;
use Lan;
#
# Untaint the path
#
$ENV{'PATH'} = '/bin:/usr/bin:/usr/sbin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
exit(VLan->Initialize());
......@@ -113,6 +113,7 @@ use libtestbed;
use Experiment;
use Node;
use NodeType;
use Lan;
use libadminctrl;
use libtblog;
use libtblog qw(*SOUT *SERR);
......@@ -490,6 +491,10 @@ my %plinks = ();
my %virtnodes = ();
my %v2vmap = ();
# for consing up vlan names.
my $vlanid = 0;
my %protovlans = ();
# Admission control counts
my %admission_control = ();
......@@ -1813,13 +1818,27 @@ foreach $plink (keys(%plinks)) {
@{$plinks{"linksdelaydst/$lan/$virtC,$virtA"}};
($nodeC,$portC) = split(":",$nodeportC);
($nodeD,$portD) = split(":",$nodeportD);
($vnodeC,$vportC) = split(":",$virtC);
($vnodeA,$vportA) = split(":",$virtA);
printdb "LINK delay: other end = $nodeportC $nodeportD\n";
# assert nodeB == nodeD
printdb " VLANS:\n";
AddVlan("link", "$lan" . "-delaysrc", $nodeportA, $nodeportB);
AddVlan("link", "$lan" . "-delaydst", $nodeportC, $nodeportD);
my $protolan = ProtoLan->Create($experiment, "$lan");
my $protolansrc = ProtoLan->Create($experiment,
"$lan" . "-delaysrc", $protolan);
my $protolandst = ProtoLan->Create($experiment,
"$lan" . "-delaydst", $protolan);
$protolansrc->SetType("vlan");
$protolandst->SetType("vlan");
$protolansrc->SetRole("delay");
$protolandst->SetRole("delay");
$protolan->SetRole("link/lan");
$protolan->AddInterface($nodeC, $vnodeC, $vportC, $portC);
$protolan->AddInterface($nodeA, $vnodeA, $vportA, $portA);
$protolansrc->AddMember($nodeA, $portA);
$protolansrc->AddMember($nodeB, $portB);
$protolandst->AddMember($nodeC, $portC);
$protolandst->AddMember($nodeD, $portD);
my ($member0,$delay,$bandwidth,$lossrate,
$member1,$rdelay,$rbandwidth,$rlossrate) = @{$delaylinks{$plink}};
......@@ -1860,6 +1879,7 @@ foreach $plink (keys(%plinks)) {
($nodeportC,$nodeportD) = @{$plinks{"linkdelaydst/$lan/$virtA"}};
($nodeC,$portC) = split(":",$nodeportC);
($nodeD,$portD) = split(":",$nodeportD);
($vnodeA,$vportA) = split(":",$virtA);
printdb "LAN delay src: other end = $nodeportC $nodeportD\n";
#
......@@ -1870,10 +1890,28 @@ foreach $plink (keys(%plinks)) {
#
my $dlink = $lan . "/dlink/" . (split(":", $virtA))[0];
printdb " VLANS:\n";
AddVlan("link", $dlink, $nodeportA, $nodeportB);
AddVlan("lan", $lan, $nodeportD);
my $protolan = ProtoLan->Lookup($experiment, $lan);
if (!defined($protolan)) {
$protolan = ProtoLan->Create($experiment, "$lan");
$protolan->SetRole("link/lan");
}
$protolan->AddInterface($nodeA, $vnodeA, $vportA, $portA);
my $protolanlan = ProtoLan->Lookup($experiment, $lan . "-delaylan");
if (!defined($protolanlan)) {
$protolanlan = ProtoLan->Create($experiment, $lan . "-delaylan",
$protolan);
$protolanlan->SetType("vlan");
$protolanlan->SetRole("delay");
}
$protolanlan->AddMember($nodeD, $portD);
my $protolanlink = ProtoLan->Create($experiment, $dlink, $protolan);
$protolanlink->SetType("vlan");
$protolanlink->SetRole("delay");
$protolanlink->AddMember($nodeA, $portA);
$protolanlink->AddMember($nodeB, $portB);
my ($member0,$delay,$bandwidth,$loss,
$member1,$rdelay,$rbandwidth,$rloss) = @{$delaylinks{$plink}};
......@@ -1894,6 +1932,10 @@ foreach $plink (keys(%plinks)) {
SetUpTracing($lan, $member0, $nodeB, $portB, $portD);
}
elsif (($lan,$virtA,$virtB) = ($plink =~ m|^linksimple/(.+)/(.+),(.+)$|)) {
my ($vnodeA,$vportA) = split(":",$virtA);
my ($vnodeB,$vportB) = split(":",$virtB);
my $protolink;
#
# nodeportA and nodeportB are the only two nodes in the LAN.
# If the link is delayed, its with endpoint delays, not a delay node.
......@@ -1905,14 +1947,46 @@ foreach $plink (keys(%plinks)) {
# virtual interfaces on the same node.
#
if (! $trivial) {
AddVlan("link", $lan, $nodeportA, $nodeportB);
if (virtlanusevirtiface($lan)) {
#
# When using virtual interfaces we need to create a
# protolan for the underlying vlan, and then another link
# for the endpoints that run over that vlan. Note though
# that there might be multiple emulated links running on
# on this physical link. Once we have everything created
# there is a postpass to merge the vlans into a single
# supervlan since a nodeport can be in just a single vlan.
#
my $lanid = "v" . "$lan" . $vlanid++;
my $protovlan = ProtoLan->Create($experiment, $lanid);
$protovlan->SetRole("encapsulation");
$protovlan->SetType("vlan");
$protovlan->SetEncapStyle(virtlanencapstyle($lan));
$protovlan->SetAttribute("link/lan", $lan);
$protovlan->AddMember($nodeA, $portA)
if (!$protovlan->IsMember($nodeA, $portA));
$protovlan->AddMember($nodeB, $portB)
if (!$protovlan->IsMember($nodeB, $portB));
#
# Create some new virtual devices.
#
$portA = NewVirtIface($lan, $virtA, $nodeA, $portA);
$portB = NewVirtIface($lan, $virtB, $nodeB, $portB);
$protolink = ProtoLan->Create($experiment, $lan,$protovlan);
$protolink->SetType("emulated");
$protolink->SetRole("link/lan");
$protolink->AddInterface($nodeA, $vnodeA, $vportA, $portA);
$protolink->AddInterface($nodeB, $vnodeB, $vportB, $portB);
}
else {
$protolink = ProtoLan->Create($experiment, $lan);
$protolink->SetType("vlan");
$protolink->SetRole("link/lan");
$protolink->AddInterface($nodeA, $vnodeA, $vportA, $portA);
$protolink->AddInterface($nodeB, $vnodeB, $vportB, $portB);
}
}
else {
......@@ -1925,11 +1999,17 @@ foreach $plink (keys(%plinks)) {
$nodeB = $v2pmap{(split(":", $virtB))[0]};
$portA = NewVirtIface($lan, $virtA, $nodeA);
$portB = NewVirtIface($lan, $virtB, $nodeB);
} else {
$protolink = ProtoLan->Create($experiment, $lan);
$protolink->SetRole("link/lan");
$protolink->AddInterface($nodeA, $vnodeA, $vportA, $portA);
$protolink->AddInterface($nodeB, $vnodeB, $vportB, $portB);
}
else {
# next plink
next;
}
}
#
# Setup portmap using virt members in plink name.
#
......@@ -1975,19 +2055,48 @@ foreach $plink (keys(%plinks)) {
# No delays
printdb " LAN:";
my ($vnodeA,$vportA) = split(":",$virtA);
my $protolan;
#
# trivial links do not have physical links, but could be using
# virtual interfaces on the same node.
#
if (! $trivial) {
AddVlan("lan", $lan, $nodeportA);
if (virtlanusevirtiface($lan)) {
#
# Look for the underlying protovlan for this lan. Create
# new one otherwise.
#
my $protovlan;
if (exists($protovlans{$lan})) {
$protovlan = $protovlans{$lan};
}
else {
my $lanid = "v" . "$lan" . $vlanid++;
$protovlan = ProtoLan->Create($experiment, $lanid);
$protovlan->SetRole("encapsulation");