All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

Commit c75427ef authored by Jonathon Duerig's avatar Jonathon Duerig

Merge branch 'master' of git-public.flux.utah.edu:/flux/git/emulab-devel

parents 46828187 3bb55572
......@@ -2672,6 +2672,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
backend/editnodetype backend/editsitevars backend/newimageid \
backend/editgroup backend/newimageid_ez \
tbsetup/GNUmakefile tbsetup/console_setup tbsetup/spewlogfile \
tbsetup/snmpit_test/GNUmakefile \
tbsetup/spewrpmtar tbsetup/gentopofile tbsetup/power_sgmote.pm \
tbsetup/console_reset tbsetup/bwconfig tbsetup/power_rpc27.pm \
tbsetup/power_mail.pm tbsetup/power_whol.pm \
......
......@@ -903,6 +903,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
backend/editnodetype backend/editsitevars backend/newimageid \
backend/editgroup backend/newimageid_ez \
tbsetup/GNUmakefile tbsetup/console_setup tbsetup/spewlogfile \
tbsetup/snmpit_test/GNUmakefile \
tbsetup/spewrpmtar tbsetup/gentopofile tbsetup/power_sgmote.pm \
tbsetup/console_reset tbsetup/bwconfig tbsetup/power_rpc27.pm \
tbsetup/power_mail.pm tbsetup/power_whol.pm \
......
This diff is collapsed.
......@@ -596,6 +596,39 @@ sub GotTrunks($$)
return $query_result->numrows;
}
#
# Get the set of lans that are linked to this lan. Optionally provide the
# type, say to look for just vlans.
#
sub GetLinkedTo($$;$)
{
my ($class, $lan, $type) = @_;
if (! ref($lan)) {
$lan = Lan->Lookup($lan);
return ()
if (!defined($lan));
}
my $exptidx = $lan->exptidx();
my $lanid = $lan->lanid();
my @result = ();
my $query_result =
DBQueryWarn("select lanid from lans ".
"where link='$lanid' ".
(defined($type) ? "and type='$type'" : ""));
return ()
if (!$query_result || !$query_result->numrows);
while (my ($id) = $query_result->fetchrow_array()) {
my $vlan = Lan->Lookup($id);
return undef
if (!defined($vlan));
push(@result, $vlan);
}
return @result;
}
#
# Stringify for output.
#
......@@ -1883,6 +1916,7 @@ sub Instantiate($)
my $vport = $protomember->{'vport'};
my $iface = $protomember->{'iface'};
my $pport = $protomember->{'pport'};
my $attributes = $protomember->{'attrs'};
my $member;
if (defined($pport)) {
......@@ -1900,6 +1934,13 @@ sub Instantiate($)
$lan->Destroy();
return -1;
}
if (defined($attributes)) {
foreach my $attrkey (keys(%{$attributes})) {
my $attrvalue = $attributes->{$attrkey};
$interface->SetAttribute($attrkey, $attrvalue);
}
}
}
$self->{'INSTANCE'} = $lan;
return 0;
......@@ -2009,9 +2050,9 @@ sub Dump($)
#
# Add an interface to a protolan.
#
sub AddInterface($$$$$;$)
sub AddInterface($$$$$;$$)
{
my ($self, $node, $vnode, $vport, $iface, $pport) = @_;
my ($self, $node, $vnode, $vport, $iface, $pport, $attributes) = @_;
if (!ref($node)) {
$node = Node->Lookup($node);
......@@ -2030,6 +2071,7 @@ sub AddInterface($$$$$;$)
"vport" => $vport,
"iface" => $iface,
"pport" => $pport,
"attrs" => $attributes,
};
return 0;
}
......@@ -2252,6 +2294,7 @@ sub id($) { return $_[0]->GetLan()->lanid(); }
sub vname($) { return $_[0]->GetLan()->vname(); }
sub ready($) { return $_[0]->GetLan()->ready(); }
sub type($) { return $_[0]->GetLan()->type(); }
sub link($) { return $_[0]->GetLan()->link(); }
sub GetLan($) { return $_[0]->{'LAN'}; }
sub GetExperiment($) { return $_[0]->GetLan()->GetExperiment(); }
sub vlanid($) { return $_[0]->lanid(); }
......@@ -2968,6 +3011,29 @@ sub ExperimentVLans($$$)
return 0;
}
#
# Find a vlan by looking an interface in the vlan.
#
sub FindVlanByInterface($$$)
{
my ($class, $experiment, $interface) = @_;
my $exptidx = $experiment->idx();
my $iface = $interface->iface();
my @vlans = ();
#
# We do not do this often, so worry about optimizing later.
#
return undef
if (VLan->ExperimentVLans($experiment, \@vlans) != 0);
foreach my $vlan (@vlans) {
return $vlan
if ($vlan->IsMember($interface->node_id(), $interface->iface()));
}
return undef;
}
#
# Utility function to add a vlan to the switch infrastructure.
#
......@@ -3237,6 +3303,27 @@ sub StaleVlanList($$$)
return 0;
}
#
# Get the set of lans that are linked to this lan. Optionally provide the
# type, say to look for just vlans.
#
sub GetLinkedTo($$;$)
{
my ($class, $lan, $type) = @_;
my @result = Lan->GetLinkedTo($lan, $type);
return @result
if (!@result);
# Convert to VLan;
my @tmp = ();
foreach my $lan (@result) {
bless($lan, $class);
push(@tmp, $lan);
}
return @tmp;
}
############################################################################
#
# Another convenience package, for tunnels.
......
......@@ -1694,16 +1694,23 @@ sub LoadInterfaces($)
sub GetInterface($$$)
{
my ($self, $iface, $pref) = @_;
my $interface;
# Must be a real reference.
return -1
if (! (ref($self) && ref($pref)));
$self->LoadInterfaces() == 0
or return -1;
if (exists($self->{'IFACES'}->{$iface})) {
# Might be undef if we already tried.
$interface = $self->{'IFACES'}->{$iface};
}
else {
$interface = Interface->LookupByIface($self, $iface);
$self->{'IFACES'}->{$iface} = $interface;
}
$$pref = $interface;
return -1
if (!exists($self->{'IFACES'}->{$iface}));
$$pref = $self->{'IFACES'}->{$iface};
if (!defined($interface));
return 0;
}
......
......@@ -2,6 +2,7 @@ package TraceUse;
use Time::HiRes qw( gettimeofday tv_interval );
use Data::Dumper;
use English;
BEGIN
{
......@@ -54,6 +55,7 @@ sub trace_use
'line' => $line,
'time' => $elapsed,
'module' => $mod_name,
'inc' => "@INC",
};
return;
......@@ -83,6 +85,7 @@ END
my $indent = ' ' x $pos;
$message .= "$indent$mod->{module}, line $mod->{line}";
$message .= sprintf(" (%lf)", $mod->{'time'}) if $mod->{time};
# $message .= " " . $mod->{inc};
warn "$message\n";
}
}
......
......@@ -43,9 +43,10 @@ void usage(char * name);
// structure, and sets up the two subscription strings for events.
void writePidFile(string const & pidFile);
void initEvents(string const & server, string const & port,
string const & keyFile, string const & subscription);
string const & keyFile, string const & subscription,
string const & group);
void subscribe(event_handle_t handle, address_tuple_t eventTuple,
string const & subscription);
string const & subscription, string const & group);
void callback(event_handle_t handle,
event_notification_t notification, void *data);
......@@ -63,12 +64,13 @@ void readArgs(int argc, char * argv[])
string port;
string keyFile;
string subscription;
string group;
// Prevent getopt from printing an error message.
opterr = 0;
/* get params from the optstring */
char const * argstring = "s:p:dE:k:u:";
char const * argstring = "s:p:dE:k:u:g:";
int option = getopt(argc, argv, argstring);
while (option != -1)
{
......@@ -93,6 +95,9 @@ void readArgs(int argc, char * argv[])
case 'u':
subscription = optarg;
break;
case 'g':
group = optarg;
break;
case '?':
default:
usage(argv[0]);
......@@ -106,18 +111,19 @@ void readArgs(int argc, char * argv[])
usage(argv[0]);
initEvents(server, port, keyFile, subscription);
initEvents(server, port, keyFile, subscription, group);
}
void usage(char * name)
{
cerr << "Usage: " << name << " -E proj/exp -s server [-d] [-p port] "
<< "[-i pidFile] [-k keyFile] [-u subscription]" << endl;
<< "[-i pidFile] [-k keyFile] [-u subscription] [-g group]" << endl;
exit(-1);
}
void initEvents(string const & server, string const & port,
string const & keyFile, string const & subscription)
string const & keyFile, string const & subscription,
string const & group)
{
cerr << "Initializing event system" << endl;
string serverString = "elvin://" + server;
......@@ -144,7 +150,7 @@ void initEvents(string const & server, string const & port,
address_tuple_t eventTuple = address_tuple_alloc();
subscribe(handle, eventTuple, subscription);
subscribe(handle, eventTuple, subscription, group);
address_tuple_free(eventTuple);
......@@ -152,10 +158,15 @@ void initEvents(string const & server, string const & port,
}
void subscribe(event_handle_t handle, address_tuple_t eventTuple,
string const & subscription)
string const & subscription, string const & group)
{
cerr << "Link subscription names: " << subscription << endl;
eventTuple->objname = const_cast<char *>(subscription.c_str());
string name = subscription;
if (group != "")
{
name += "," + group;
}
cerr << "Link subscription names: " << name << endl;
eventTuple->objname = const_cast<char *>(name.c_str());
// eventTuple->objtype = TBDB_OBJECTTYPE_LINK;
eventTuple->objtype = ADDRESSTUPLE_ANY;
// eventTuple->eventtype = TBDB_EVENTTYPE_MODIFY;
......
system("../../../pubsub/pubsubd -v -d -p 4001");
system("./simple-agent -E delay-agent/single-node -s localhost -k /var/emulab/boot/eventkey -u foobar -p 4001");
......@@ -1825,9 +1825,12 @@ sub StartEvents()
print STDERR "Caught a USR2 in child\n";
# Only STDERR can be redirected to the newfile. STDOUT is writing
# to the parent process.
close(STDERR);
open(STDERR, ">> $LOGFILE") or fatal("reopening $LOGFILE: $!");
select STDERR;
$OUTPUT_AUTOFLUSH = 1;
# restore default output.
select STDOUT;
print STDERR "Opened new logfile in child\n";
};
......@@ -1882,22 +1885,35 @@ sub PollEvents($$)
}
if ($pollval > 0) {
my $buf;
my $lastline = "";
while (sysread($childpipe, $buf, 8192)) {
#
# It is possible that we will get multiple lines
# of output in one read. Hopefully not so much that we get
# a partial line. Will need to deal with that at some
# point.
# It is possible that we will get multiple lines of output
# in one read, so we split the input and loop over that.
# It is also possible that we will read a partial line at
# the end. We make a less-than heroic attempt to catch these
# by remembering any unrecognized line that starts with "O"
# and prepending that to the next set of lines read.
#
my @foo = split(/^/m, $buf);
if ($lastline ne "") {
$foo[0] = $lastline . $foo[0];
debug("reconstruct split line: '" . $foo[0] . "'\n");
$lastline = "";
}
foreach my $line (@foo) {
if ($line =~
/^OBJTYPE='([^\']*)', OBJNAME='([^\']*)', EVENTTYPE='([^\']*)'$/) {
handleEvent($1, $2, $3);
}
elsif ($lastline eq "" && $line =~ /^O/) {
# probably an incomplete read
debug("remembering possible split line: '$line'\n");
$lastline = $line;
}
else {
fatal("unrecognizable line $line from event reader");
fatal("unrecognizable line '$line' from event reader");
}
}
#
......
#
# Remove stated from syslog.conf, since we no longer use syslog.
# It holds open the log file when it is rolled.
#
use strict;
use libinstall;
my $SYSLOG_CONF = "/etc/syslog.conf";
sub InstallUpdate($$)
{
my ($version, $phase) = @_;
#
# If something should run in the pre-install phase.
#
if ($phase eq "pre") {
Phase "stated", "Updating stated logging", sub {
Phase "syslog.conf", "Updating $SYSLOG_CONF", sub {
PhaseSkip("Already updated")
if !`grep 'stated' $SYSLOG_CONF`;
BackUpFileFatal($SYSLOG_CONF);
ExecQuietFatal("sed -i .orig -e '/stated/d' $SYSLOG_CONF");
};
Phase "syslogd", "Restarting syslogd", sub {
HUPDaemon("syslog");
};
};
}
#
# If something should run in the post-install phase.
#
if ($phase eq "post") {
}
return 0;
}
1;
......@@ -17,8 +17,6 @@ use vars qw(@ISA @EXPORT);
@ISA = "Exporter";
@EXPORT = qw ( );
# Must come after package declaration!
use lib '@prefix@/lib';
use GeniCMV2;
use GeniResponse;
use GeniCredential;
......
......@@ -17,8 +17,6 @@ use vars qw(@ISA @EXPORT);
@ISA = "Exporter";
@EXPORT = qw ( );
# Must come after package declaration!
use lib '@prefix@/lib';
use GeniDB;
use Genixmlrpc;
use GeniResponse;
......
......@@ -18,7 +18,6 @@ use vars qw(@ISA @EXPORT);
@EXPORT = qw ( );
# Must come after package declaration!
use lib '@prefix@/lib';
use GeniDB;
use GeniResponse;
use GeniTicket;
......
......@@ -17,7 +17,6 @@ use vars qw(@ISA @EXPORT);
@EXPORT = qw ( );
# Must come after package declaration!
use lib '@prefix@/lib';
use GeniDB;
use Genixmlrpc;
use GeniResponse;
......
#!/usr/bin/perl -wT
#
# GENIPUBLIC-COPYRIGHT
# Copyright (c) 2008-2009 University of Utah and the Flux Group.
# Copyright (c) 2008-2011 University of Utah and the Flux Group.
# All rights reserved.
#
package GeniSES;
......@@ -18,7 +18,6 @@ use vars qw(@ISA @EXPORT);
@EXPORT = qw ( );
# Must come after package declaration!
use lib '@prefix@/lib';
use GeniDB;
use User;
use Genixmlrpc;
......
<?xml version="1.0" encoding="UTF-8"?>
<!-- The default namespace for the ptop extension -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.protogeni.net/resources/rspec/ext/emulab/1" xmlns:emulab="http://www.protogeni.net/resources/rspec/ext/emulab/1">
<xs:include schemaLocation="top_extension.xsd"/>
<xs:group name="NodeFlagSpec">
<xs:sequence>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="emulab:trivial_bandwidth"/>
<xs:element ref="emulab:unique"/>
</xs:choice>
</xs:sequence>
</xs:group>
<xs:element name="trivial_bandwidth">
<xs:annotation>
<xs:documentation>Gives the amount of bandwidth this node can forward through its loopback
interface. In the future, we will make the loopback interface/link
explicit in the topology
Valid only for physical nodes</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="value" use="required" type="xs:integer"/>
</xs:complexType>
</xs:element>
<xs:element name="unique">
<xs:annotation>
<xs:documentation>Indicates that this node should never be considered identical to any
other node. Could be done with a property
Valid only for physical nodes</xs:documentation>
</xs:annotation>
<xs:complexType/>
</xs:element>
<xs:element name="policy">
<xs:complexType>
<xs:attributeGroup ref="emulab:PolicySpecContents"/>
</xs:complexType>
</xs:element>
<xs:attributeGroup name="PolicySpecContents">
<xs:attribute name="type" use="required">
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:enumeration value="desire"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="limit" use="required">
<xs:simpleType>
<xs:union>
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:enumeration value="disallow"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType>
<xs:restriction base="xs:float">
<xs:minInclusive value="0.0"/>
</xs:restriction>
</xs:simpleType>
</xs:union>
</xs:simpleType>
</xs:attribute>
</xs:attributeGroup>
<xs:element name="set_type_limit">
<xs:complexType>
<xs:attributeGroup ref="emulab:TypeLimitContents"/>
</xs:complexType>
</xs:element>
<xs:attributeGroup name="TypeLimitContents">
<xs:attribute name="typeclass" use="required"/>
<xs:attribute name="count" use="required" type="xs:integer"/>
</xs:attributeGroup>
<xs:element name="interface">
<xs:complexType>
<xs:attribute name="name" use="required"/>
</xs:complexType>
</xs:element>
</xs:schema>
<?xml version="1.0" encoding="UTF-8"?>
<!--
EMULAB-COPYRIGHT
Copyright (c) 2010 University of Utah and the Flux Group.
All rights reserved.
-->
<!--
Definition of common extensions in topologies -
shared between vtop (virtual topology) and ptop (physical topology)
extensions.
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.protogeni.net/resources/rspec/ext/emulab/1" xmlns:emulab="http://www.protogeni.net/resources/rspec/ext/emulab/1">
<xs:element name="node_type">
<xs:complexType>
<xs:attribute name="type_slots" use="required"/>
<xs:attribute name="static">
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:enumeration value="true"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="fd">
<xs:complexType>
<xs:attribute name="name" use="required">
<xs:annotation>
<xs:documentation>Name of this feature or desire
element fd_name { text },</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="weight" use="required">
<xs:annotation>
<xs:documentation>Weight assocated with the feature or desire
element fd_weight { xsd:float },</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="violatable">
<xs:annotation>
<xs:documentation>A flag indicating whether or not a failure to match the desire with a
a feature is a constraint violation
element violatable { empty }?,</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:enumeration value="true"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="global_operator">
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:enumeration value="OnceOnly"/>
<xs:enumeration value="FirstFree"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="local_operator">
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:enumeration value="+"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:attributeGroup name="GlobalSpec">
<xs:annotation>
<xs:documentation>GlobalSpec = element global {
element operator { "OnceOnly" | "FirstFree" }
}</xs:documentation>
</xs:annotation>
<xs:attribute name="global_operator" use="required">
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:enumeration value="OnceOnly"/>
<xs:enumeration value="FirstFree"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:attributeGroup>
<xs:attributeGroup name="LocalSpec">
<xs:annotation>
<xs:documentation>LocalSpec = element local {
element operator { "+" }
attribute local_operator { "+" }
}</xs:documentation>
</xs:annotation>
<xs:attribute name="local_operator" use="required">
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:enumeration value="+"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:attributeGroup>
<xs:element name="property">