Commit 378bc8bf authored by Jonathon Duerig's avatar Jonathon Duerig

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

parents 3732efdd 45224472
......@@ -121,7 +121,7 @@ use vars qw(@ISA @EXPORT);
TBDB_ALLOCSTATE_RES_REBOOT_DIRTY TBDB_ALLOCSTATE_RES_REBOOT_CLEAN
TBDB_ALLOCSTATE_RES_READY TBDB_ALLOCSTATE_UNKNOWN
TBDB_ALLOCSTATE_RES_TEARDOWN TBDB_ALLOCSTATE_DEAD
TBDB_ALLOCSTATE_RES_RECONFIG
TBDB_ALLOCSTATE_RES_RECONFIG TBDB_ALLOCSTATE_RES_REBOOT
TBDB_STATS_PRELOAD TBDB_STATS_START TBDB_STATS_TERMINATE
TBDB_STATS_SWAPIN TBDB_STATS_SWAPOUT TBDB_STATS_SWAPMODIFY
......@@ -446,6 +446,7 @@ sub TBDB_ALLOCSTATE_RES_INIT_DIRTY() { "RES_INIT_DIRTY"; }
sub TBDB_ALLOCSTATE_RES_INIT_CLEAN() { "RES_INIT_CLEAN"; }
sub TBDB_ALLOCSTATE_RES_READY() { "RES_READY"; }
sub TBDB_ALLOCSTATE_RES_RECONFIG() { "RES_RECONFIG"; }
sub TBDB_ALLOCSTATE_RES_REBOOT() { "RES_REBOOT"; }
sub TBDB_ALLOCSTATE_RES_TEARDOWN() { "RES_TEARDOWN"; }
sub TBDB_ALLOCSTATE_UNKNOWN() { "UNKNOWN"; };
......
......@@ -1623,6 +1623,30 @@ sub WriteEnvVariables($)
return 0;
}
#
# Get value of a specific env variable
#
sub GetEnvVariable($$)
{
my ($self, $var) = @_;
# Must be a real reference.
return -1
if (! ref($self));
my $pid = $self->pid();
my $eid = $self->eid();
my $query_result =
DBQueryWarn("select value from virt_user_environment ".
"where pid='$pid' and eid='$eid' and name='$var'");
return undef
if (!defined($query_result) || !$query_result->numrows);
my ($value) = $query_result->fetchrow_array();
return $value;
}
#
# Experiment locking and state changes.
#
......
......@@ -135,6 +135,7 @@ sub Lookup($$)
$self->{"TYPEINFO"} = undef;
$self->{"ATTRS"} = undef;
$self->{"IFACES"} = undef;
$self->{"WAROW"} = undef;
$self->{"HASH"} = {};
bless($self, $class);
......@@ -153,6 +154,7 @@ sub DESTROY {
$self->{"ATTRS"} = undef;
$self->{"IFACES"} = undef;
$self->{"HASH"} = undef;
$self->{"WAROW"} = undef;
}
#
......@@ -191,6 +193,7 @@ sub MakeFake($$$$)
$self->{"TYPEINFO"} = undef;
$self->{"ATTRS"} = undef;
$self->{"IFACES"} = undef;
$self->{"WAROW"} = undef;
$self->{"HASH"} = {};
bless($self, $class);
......@@ -236,6 +239,7 @@ sub BulkLookup($$$)
$node->{"TYPEINFO"} = undef;
$node->{"ATTRS"} = undef;
$node->{"IFACES"} = undef;
$self->{"WAROW"} = undef;
$node->{"HASH"} = {};
$nodelist{$nodeid} = $node;
......@@ -540,6 +544,7 @@ sub Refresh($)
$self->{"TYPEINFO"} = undef;
$self->{"ATTRS"} = undef;
$self->{"IFACES"} = undef;
$self->{"WAROW"} = undef;
return 0;
}
......@@ -559,6 +564,33 @@ sub FlushAll($)
%nodes = ();
}
#
# Convenience access method for widearea info
#
sub WideAreaInfo($$)
{
my ($self, $slot) = @_;
my $node_id = $self->node_id();
if (!defined($self->{'WAROW'})) {
my $query_result =
DBQueryWarn("select * from widearea_nodeinfo ".
"where node_id='$node_id'");
if (!$query_result || !$query_result->numrows) {
print STDERR "*** $node_id is not a widearea node\n";
return undef;
}
$self->{'WAROW'} = $query_result->fetchrow_hashref();
}
if (!exists($self->{'WAROW'}->{$slot})) {
print STDERR
"*** Nonexistent slot '$slot' request for widearea node $node_id\n";
return undef;
}
return $self->{'WAROW'}->{$slot};
}
#
# Check permissions. Allow for either uid or a user ref until all code
# updated.
......@@ -772,7 +804,7 @@ sub SetAllocState($$)
my $now = time();
my $node_id = $self->node_id();
DBQueryWarn("update nodes set allocstate='$state', " .
" allocstate_timestamp=$now where node_id='$node_id'")
or return -1;
......@@ -1177,6 +1209,8 @@ sub external_resource_index($) {
return L__reservation($_[0], 'external_resource_index'); }
sub external_resource_id($) {
return L__reservation($_[0], 'external_resource_id'); }
sub external_resource_key($) {
return L__reservation($_[0], 'external_resource_key'); }
sub inner_elab_role($) {
return L__reservation($_[0], 'inner_elab_role'); }
......
......@@ -43,6 +43,7 @@ use Node;
use libGeni;
use GeniResource;
use GeniHRN;
use GeniXML;
sub fatal($);
sub AllocNodes();
......@@ -51,7 +52,6 @@ sub Register();
sub UnRegister();
sub ClearAll();
sub StartAll();
sub RestartAll();
sub StopAll();
sub WaitAll();
sub PurgeAll();
......@@ -90,7 +90,7 @@ my $eid = shift;
my $action = shift;
if ($action =~
/^(alloc|free|clear|wait|purge|start|restart|mapnodes|status|stop|register|unregister||manifests|renew)$/) {
/^(alloc|free|clear|wait|purge|start|mapnodes|status|stop|register|unregister||manifests|renew)$/) {
$action = $1;
}
else {
......@@ -176,10 +176,6 @@ SWITCH: for ($action) {
StartAll();
last SWITCH;
};
/^restart$/ && do {
RestartAll();
last SWITCH;
};
/^stop$/ && do {
StopAll();
last SWITCH;
......@@ -280,18 +276,10 @@ sub PurgeAll()
sub StartAll()
{
libGeni::StartSlivers($experiment, $this_user, 0, $debug) == 0 or
libGeni::StartSlivers($experiment, $this_user, $debug) == 0 or
fatal("Cannot start slivers!\n");
}
sub RestartAll()
{
libGeni::StartSlivers($experiment, $this_user, 1, $debug) == 0 or
fatal("Cannot restart slivers!\n");
return 0;
}
sub StopAll()
{
my @resources = GeniResource->LookupAll($experiment);
......@@ -353,8 +341,8 @@ sub GetManifests()
print STDERR "No manifest for $resource\n";
next;
}
print STDERR Dumper($manifest);
print STDERR Dumper(GeniXML::Serialize($manifest, 1));
}
return 0;
......
......@@ -2,7 +2,7 @@
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2002 University of Utah and the Flux Group.
# Copyright (c) 2000-2002,2010 University of Utah and the Flux Group.
# All rights reserved.
#
......@@ -12,6 +12,8 @@
#
use English;
use Getopt::Std;
use strict;
#
# Configure variables
......@@ -19,13 +21,96 @@ use English;
use lib '@prefix@/lib';
use libdb;
sub usage() {
print STDOUT "Usage: inuse [-a | -t type] [-p pid [-e eid]] [-s|-r] " .
"[-f|-F] [-h] [-R]\n";
print STDOUT " -h This message\n";
print STDOUT " -a Print all nodes (default: only PCs\n";
print STDOUT " -t type Limit to nodes of type (or class)\n";
print STDOUT " -p pid Limit to project\n";
print STDOUT " -e eid Limit to experiment\n";
print STDOUT " -s Sort by pid,eid, rather than node id\n";
print STDOUT " -r Sort by reserve time rather than node id\n";
print STDOUT " -f Include free nodes\n";
print STDOUT " -F Include ONLY free nodes\n";
print STDOUT " -R Only include pre-reserved nodes\n";
exit (-1);
}
my $optlist = "t:p:e:srafFhR";
my @columns = ("n.node_id","pid","eid","rsrv_time","reserved_pid");
my %opt = ();
if (! getopts($optlist, \%opt)) {
usage();
}
if (@ARGV != 0 || $opt{h}) {
usage();
}
# Check for mutually exclusive options or ones that must go together
if (($opt{s} && $opt{r}) || ($opt{e} && !$opt{p}) ||
($opt{a} && $opt{t}) || ($opt{f} && $opt{F})) {
usage();
}
if (($UID != 0) && (!TBAdmin())) {
die "Sorry, only testbed administrators can use this script\n";
}
my $result = DBQueryFatal("select r.* from reserved as r left join nodes " .
" as n on r.node_id=n.node_id order by priority");
my @whereclauses = ();
# Require that the node be reserved (unless otherwise specified)
if ($opt{F}) {
# include only free nodes
push @whereclauses, "r.pid is null";
} elsif ($opt{f}) {
# Nothing to insert - include all nodes
} elsif ($opt{R}) {
# include only pre-reserved nodes
push @whereclauses, "reserved_pid is not null";
} else {
# include only reserved nodes (default)
push @whereclauses, "r.pid is not null or reserved_pid is not null";
}
# Figure out type limits
if ($opt{t}) {
push @whereclauses, "t.type='$opt{t}' or t.class='$opt{t}'";
} elsif ($opt{a}) {
# Push no type-related clauses
} else {
# Default to only showing nodes with class 'pc'
push @whereclauses, "t.class='pc'";
}
if ($opt{p}) {
if ($opt{e}) {
push @whereclauses, "pid='$opt{p}' and eid='$opt{e}'";
} else {
push @whereclauses, "pid='$opt{p}'";
}
}
my $whereclause = "";
if (@whereclauses) {
$whereclause = "where " . join(" and ",map {"($_)"} @whereclauses);
}
my $sortclause = "order by priority";
if ($opt{s}) {
$sortclause = "order by pid,eid,priority";
} elsif ($opt{r}) {
$sortclause = "order by rsrv_time,priority";
}
my $columns = join(",",@columns);
my $result = DBQueryFatal("select $columns from nodes as n " .
"left join reserved as r on r.node_id=n.node_id " .
"left join node_types as t on n.type=t.type " .
"$whereclause " .
"$sortclause");
print $result->as_string();
This diff is collapsed.
<descriptors>
<osid>
<attribute name="magic">
<value></value>
</attribute>
<attribute name="features">
<value>ping,ssh,isup,veths,veth-ne,veth-en,mlinks,vlans</value>
</attribute>
<attribute name="version">
<value>0.1</value>
</attribute>
<attribute name="reboot_waittime">
<value>600</value>
</attribute>
<attribute name="description">
<value>Phoney OSID for GENI nodes</value>
</attribute>
<attribute name="mustclean">
<value>1</value>
</attribute>
<attribute name="shared">
<value>1</value>
</attribute>
<attribute name="op_mode">
<value>MINIMAL</value>
</attribute>
<attribute name="pid">
<value>emulab-ops</value>
</attribute>
<attribute name="osname">
<value>GENI</value>
</attribute>
<attribute name="OS">
<value>Other</value>
</attribute>
</osid>
<osid>
<attribute name="magic">
<value></value>
</attribute>
<attribute name="features">
<value>ping,ssh,isup,veths,veth-ne,veth-en,mlinks,vlans</value>
</attribute>
<attribute name="version">
<value>0.1</value>
</attribute>
<attribute name="reboot_waittime">
<value>600</value>
</attribute>
<attribute name="description">
<value>Phony OSID for Geni vnodes</value>
</attribute>
<attribute name="mustclean">
<value>1</value>
</attribute>
<attribute name="shared">
<value>1</value>
</attribute>
<attribute name="op_mode">
<value>MINIMAL</value>
</attribute>
<attribute name="pid">
<value>emulab-ops</value>
</attribute>
<attribute name="osname">
<value>GENIVM</value>
</attribute>
<attribute name="OS">
<value>Other</value>
</attribute>
<attribute name="nextosid">
<value>emulab-ops,GENI</value>
</attribute>
</osid>
</descriptors>
......@@ -206,10 +206,19 @@ CREATE TABLE `geni_resources` (
`manifest_idx` mediumint(8) unsigned NOT NULL default '0',
`ticket_idx` mediumint(8) unsigned NOT NULL default '0',
`newticket_idx` mediumint(8) unsigned NOT NULL default '0',
`rspec_idx` mediumint(8) unsigned default NULL,
PRIMARY KEY (`idx`),
UNIQUE KEY `manager` (`exptidx`,`manager_urn`(255))
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
DROP TABLE IF EXISTS `geni_rspecs`;
CREATE TABLE `geni_rspecs` (
`idx` int(10) unsigned NOT NULL auto_increment,
`created` datetime default NULL,
`rspec` text,
PRIMARY KEY (`idx`),
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
DROP TABLE IF EXISTS `geni_bindings`;
CREATE TABLE `geni_bindings` (
`slice_uuid` varchar(40) NOT NULL default '',
......
......@@ -239,6 +239,17 @@ sub GetCertificate($) { return $_[0]->{'CERTIFICATE'}; }
# An alias so that slivers look like aggregates.
sub resource_type($) { return field($_[0], "type"); }
# A place to stash a temporary rspec.
sub rspec($;$)
{
my ($self, $rspec) = @_;
if (defined($rspec)) {
$self->{'RSPEC'} = $rspec;
}
return $self->{'RSPEC'};
}
# Return the URN.
sub urn($)
{
......@@ -770,6 +781,8 @@ sub Start($$$)
return -1;
}
if ($reservation->SameExperiment($experiment)) {
my $vnode;
#
# Since this is an aggregate, some slivers may already be
# in the started state. Skip those, unless doing a restart.
......@@ -778,14 +791,28 @@ sub Start($$$)
if ($sliver->state() eq "started" && !$restart);
if ($node->isvirtnode()) {
$vnodes{$node->node_id} = $node;
# A virtnode on a shared physical node needs nothing else.
next
if ($node->sharing_mode());
# But if non-shared, have to make sure that the phys node
# gets loaded.
# A virtnode on a shared physical node needs reboot or setup
if ($node->sharing_mode()) {
if ($restart && $sliver->state() eq "started") {
$reboots{$node->node_id} = $node;
}
else {
$vnodes{$node->node_id} = $node;
}
next;
}
# See below.
$vnode = $node;
#
# Now it gets messy. Do not want to mess with the physnode
# if its running other vnodes, and we just need to fire up
# a new one. But if the physnode is going to get rebooted,
# then there is no need to do anything with the vnodes; they
# will boot up with the physnode.
#
# But, have to make sure that the phys node gets setup.
#
my $physnodeid = $node->phys_nodeid();
next
if (exists($poweron{$physnodeid}) ||
......@@ -798,21 +825,22 @@ sub Start($$$)
}
}
#
# Look to see if local physical node was stopped (powered off).
# If the node is not imageable, then there is not much to
# do except turn it on or reboot it. I am assuming that a
# a non imageable node is always in raw mode.
#
if (!$node->isremotenode() &&
($sliver->state() eq "stopped")) {
$poweron{$node->node_id} = $node;
}
else {
# node_reboot is smart enough to know that if a pnode
# is rebooted it can ignore the vnodes on it, so do
# not optimize this here.
$reboots{$node->node_id} = $node;
if (!$node->imageable()) {
if ($sliver->state() eq "stopped") {
$poweron{$node->node_id} = $node;
}
else {
$reboots{$node->node_id} = $node;
}
next;
}
next
if (!$node->imageable());
#
# See if the node is running the requested OS.
#
my $osinfo = OSinfo->Lookup($node->def_boot_osid());
if (!defined($osinfo)) {
print STDERR "Could not get osinfo for $node\n";
......@@ -852,6 +880,14 @@ sub Start($$$)
$reloads{$image->imageid()} = [ ];
}
push(@{ $reloads{$image->imageid()} }, $node);
# Reload means reboot or power on.
if (!defined($vnode) && $sliver->state() eq "stopped") {
$poweron{$node->node_id} = $node;
}
else {
$reboots{$node->node_id} = $node;
}
}
else {
#
......@@ -861,6 +897,33 @@ sub Start($$$)
print STDERR " Could not os_select $node to $osinfo\n";
return -1;
}
#
# If the node is going to get rebooted, then do not need
# to worry about the vnodes on it. But if the node is ready
# to go, then we have to do the vnodes. Remember, we do not
# reboot the physnode since we might only be adding a new node
# in which case, a full reboot is wrong.
#
if (! $node->IsUp()) {
if ($sliver->state() eq "stopped" && !defined($vnode)) {
$poweron{$node->node_id} = $node;
}
else {
$reboots{$node->node_id} = $node;
}
}
elsif ($restart && !defined($vnode)) {
# Just a physnode that needs restarting.
$reboots{$node->node_id} = $node;
}
elsif (defined($vnode)) {
if ($sliver->state() eq "started") {
$reboots{$vnode->node_id} = $vnode;
}
else {
$vnodes{$vnode->node_id} = $vnode;
}
}
}
}
else {
......
......@@ -150,7 +150,7 @@ sub Resolve($)
undef, "Nothing here by that name");
}
my $rspec = GetAdvertisement(0, $node->node_id(), "0.1");
my $rspec = GetAdvertisement(0, $node->node_id(), "0.1", undef);
if (! defined($rspec)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not start avail");
......@@ -237,10 +237,29 @@ sub DiscoverResourcesAux($$$)
}
}
#
# See if one of the credentials is a slice credential. If it is, and
# that slice is active, pass it to ptopgen so that it includes the current
# resources as available.
#
my $experiment = undef;
foreach my $credential (@$credentials) {
my ($auth, $type, $id) = GeniHRN::Parse($credential->target_urn());
if ($type eq "slice") {
# Might not exist here yet.
my $slice = GeniSlice->Lookup($credential->target_urn());
if (defined($slice)) {
# See if the local experiment exists yet.
$experiment = Experiment->Lookup($slice->uuid());
}
last;
}
}
#
# Acquire the advertisement from ptopgen and compress it if requested.
#
my $xml = GetAdvertisement($available, undef, "0.2");
my $xml = GetAdvertisement($available, undef, "0.2", $experiment);
if (! defined($xml)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not start avail");
......@@ -258,12 +277,16 @@ sub DiscoverResourcesAux($$$)
#
# Use ptopgen in xml mode to spit back an xml file.
#
sub GetAdvertisement($$$)
sub GetAdvertisement($$$$)
{
my ($available, $pc, $version) = @_;
my ($available, $pc, $version, $experiment) = @_;
my $xml = undef;
my $invocation = "$PTOPGEN -x -g $version -r -p GeniSlices";
if (defined($experiment)) {
my $eid = $experiment->eid();
$invocation .= " -e $eid";
}
$invocation .= " -a" unless $available;
if (defined($pc)) {
$invocation .= " -1 $pc";
......@@ -1535,6 +1558,7 @@ sub SliverWorkAux($$$$$$$)
my $response;
my $ticket;
my $rspec;
my $oldmanifest;
require Interface;
# V2 API support.
......@@ -1665,10 +1689,18 @@ sub SliverWorkAux($$$$$$$)
print GeniXML::Serialize($rspec);
# The Manifest starts out as a copy of the rspec.
my $manifest = $rspec->cloneNode(1);
#
# Find current slivers and save.
#
if (defined($aggregate)) {
$oldmanifest = $aggregate->GetManifest(0);
if (!defined($oldmanifest)) {
$message = "Internal error getting manifest";
goto bad;
}
my @slivers;
if ($aggregate->SliverList(\@slivers) != 0) {
$message = "Could not get sliverlist for $aggregate";
......@@ -2040,8 +2072,22 @@ sub SliverWorkAux($$$$$$$)
}
# Already in the aggregate?
next
if (grep {$_ eq $virtual_id} keys(%nodemap));
if (grep {$_ eq $virtual_id} keys(%nodemap)) {