Commit 135e92b8 authored by Jonathon Duerig's avatar Jonathon Duerig
Browse files

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

parents 9d161d2f 46d9e236
......@@ -7,6 +7,7 @@
use strict;
use English;
use Getopt::Std;
use Data::Dumper;
#
# Exit status is important. Exit with -1 if an error, else the number
......@@ -50,9 +51,14 @@ sub Register();
sub UnRegister();
sub ClearAll();
sub StartAll();
sub RestartAll();
sub StopAll();
sub WaitAll();
sub PurgeAll();
sub RenewAll();
sub GetManifests();
sub GetStatus();
sub MapNodes();
#
# Turn off line buffering on output
......@@ -84,7 +90,7 @@ my $eid = shift;
my $action = shift;
if ($action =~
/^(alloc|free|clear|wait|purge|start|register|unregister|renew)$/) {
/^(alloc|free|clear|wait|purge|start|restart|mapnodes|status|stop|register|unregister||manifests|renew)$/) {
$action = $1;
}
else {
......@@ -160,6 +166,14 @@ SWITCH: for ($action) {
StartAll();
last SWITCH;
};
/^restart$/ && do {
RestartAll();
last SWITCH;
};
/^stop$/ && do {
StopAll();
last SWITCH;
};
/^wait$/ && do {
WaitAll();
last SWITCH;
......@@ -172,6 +186,18 @@ SWITCH: for ($action) {
RenewAll();
last SWITCH;
};
/^manifests$/ && do {
GetManifests();
last SWITCH;
};
/^status$/ && do {
GetStatus();
last SWITCH;
};
/^mapnodes$/ && do {
MapNodes();
last SWITCH;
};
fatal("Unknown action $action");
}
exit($exitval);
......@@ -244,25 +270,47 @@ sub PurgeAll()
sub StartAll()
{
libGeni::StartSlivers($experiment, $this_user) == 0 or
libGeni::StartSlivers($experiment, $this_user, 0, $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);
foreach my $resource (@resources) {
$resource->StopSliver($this_user) == 0
or fatal("Could not stop $resource");
}
return 0;
}
sub WaitAll()
{
libGeni::WaitForSlivers($experiment, $this_user) == 0 or
libGeni::WaitForSlivers($experiment, $this_user, $debug) == 0 or
fatal("Cannot wait on slivers!\n");
}
sub RenewAll()
{
libGeni::RenewSlivers($experiment, 1) == 0 or
libGeni::RenewSlivers($experiment, $debug) == 0 or
fatal("Cannot renew resources");
}
#
# Register.
#
sub MapNodes()
{
libGeni::MapNodes($experiment, $debug) == 0 or
fatal("Cannot Mapnodes");
}
sub Register()
{
libGeni::Register($experiment, $this_user) == 0 or
......@@ -282,6 +330,40 @@ sub UnRegister()
return 0;
}
sub GetManifests()
{
my @resources = GeniResource->LookupAll($experiment);
foreach my $resource (@resources) {
$resource->GetManifest($this_user) == 0
or fatal("Could not clear resources from $resource");
my $manifest = $resource->Manifest();
return -1
if (!defined($manifest));
print STDERR Dumper($manifest);
}
return 0;
}
sub GetStatus()
{
my @resources = GeniResource->LookupAll($experiment);
foreach my $resource (@resources) {
my $ref;
$resource->SliverStatus($this_user, \$ref) == 0
or fatal("Could not clear resources from $resource");
print STDERR Dumper($ref);
}
return 0;
}
sub fatal($)
{
my ($msg) = @_;
......
......@@ -27,6 +27,7 @@ use NodeType;
use Interface;
use Experiment;
use OSinfo;
use Lan;
use GeniEmulab;
use GeniResource;
use GeniResponse;
......@@ -483,7 +484,8 @@ sub MapNodes($$)
return -1
if (!defined($manifest));
print STDERR Dumper($manifest);
print STDERR Dumper($manifest)
if ($verbose);
foreach my $ref (@{ $manifest->{'node'} }) {
my $sliver_urn = $ref->{'sliver_urn'};
......@@ -552,12 +554,44 @@ sub MapNodes($$)
next
if (!exists($managers{$resource->manager_urn()}));
if (exists($ref->{'vlantag'})) {
my $TAG = $ref->{'vlantag'};
if (defined($TAG)) {
if (!($TAG =~ /^[\w]*$/)) {
print STDERR "Bad vlantag '$TAG' for $linkname\n";
print STDERR Dumper($manifest);
return -1;
}
my $lan = Lan->Lookup($experiment, $linkname, 1);
if (!defined($lan)) {
print STDERR "Could not find vlan for $linkname\n";
return -1;
}
#
# XXX This seems backwards. If the lan is pointing
# to another lan, then we really want to change that
# one.
#
if ($lan->type() eq "emulated" && defined($lan->link())) {
$lan = Lan->Lookup($lan->link());
if (!defined($lan)) {
print STDERR
"Could not find linked vlan for $linkname\n";
return -1;
}
}
return -1
if ($lan->SetAttribute("vlantag", $TAG));
}
}
foreach my $ifaceref (@{ $interfaces }) {
my $vname = $ifaceref->{'virtual_node_id'};
my $iface_id = $ifaceref->{'virtual_interface_id'};
my $MAC = $ifaceref->{'MAC'};
my ($node, $compid) = @{ $ifacemap{$iface_id} };
my ($iface,$interface);
my $iface;
if (GeniHRN::IsValid($compid)) {
(undef,undef,$iface) = GeniHRN::ParseInterface($compid);
......@@ -571,14 +605,16 @@ sub MapNodes($$)
print STDERR Dumper($manifest);
return -1;
}
#
# We do not need to do this for virtual nodes.
# XXX At this point, not sure if the interface is a
# vinterface or a real interface.
#
if ($node->isvirtnode()) {
$interface =
Interface::VInterface->LookupByVirtLan($experiment,
$linkname,
$vname);
my $interface =
Interface::VInterface->LookupByVirtLan($experiment,
$linkname,
$vname);
if (defined($interface)) {
$MAC = $ifaceref->{'VMAC'};
}
else {
......@@ -600,7 +636,7 @@ sub MapNodes($$)
return -1;
}
if ($interface->Update({"mac" => "$MAC"})) {
print STDERR "Could not update mac for $node,$iface\n";
print STDERR "Could not update $node,$iface\n";
print Dumper($manifest);
return -1;
}
......@@ -619,9 +655,9 @@ sub MapNodes($$)
# Boot (Start) all of the slivers. This does the entire set, and blocks
# till done.
#
sub StartSlivers($$)
sub StartSlivers($$$$)
{
my ($experiment, $user) = @_;
my ($experiment, $user, $restart, $verbose) = @_;
#
# Get the resource objects.
......@@ -638,10 +674,11 @@ sub StartSlivers($$)
my $coderef = sub {
my ($resource) = @_;
print STDERR "Starting ($$) sliver $resource\n";
while (1) {
my $retval = $resource->StartSliver($user);
print STDERR "Starting ($$) sliver $resource\n";
my $retval = ($restart ?
$resource->RestartSliver($user) :
$resource->StartSliver($user));
last
if (!$retval);
return -1
......@@ -650,6 +687,23 @@ sub StartSlivers($$)
sleep(10);
}
#
# Grab a new manifest;
#
if ($resource->ManagerVersion() == 2.0) {
while (1) {
print STDERR "Getting ($$) new manifest for $resource\n";
my $retval = $resource->GetManifest($user);
last
if (!$retval);
return -1
if (!$resource->last_rpc_error() ||
$resource->last_rpc_error() != GENIRESPONSE_BUSY());
sleep(10);
}
}
return 0;
};
if (ParRun(undef, \@results, $coderef, @resources)) {
......@@ -670,16 +724,27 @@ sub StartSlivers($$)
$errors++;
}
else {
#
# ParRun does a fork; so need to refresh the resource object
# to sync it to the DB.
#
if ($resource->Refresh()) {
print STDERR
"*** StartSlivers: Error synchronizing $resource\n";
$errors++;
}
push(@tmp, $resource);
}
$count++;
}
return WaitForSlivers($experiment, $user, @tmp);
MapNodes($experiment, $verbose);
return WaitForSlivers($experiment, $user, $verbose, @tmp);
}
sub WaitForSlivers($$@)
sub WaitForSlivers($$$@)
{
my ($experiment, $user, @resources) = @_;
my ($experiment, $user, $verbose, @resources) = @_;
my %nodemap = ();
#
......@@ -692,6 +757,8 @@ sub WaitForSlivers($$@)
return 0;
}
print STDERR "Waiting for slivers ...\n";
#
# Build a map of the nodes. I made a real mess of this in Version 1.
#
......@@ -743,7 +810,7 @@ sub WaitForSlivers($$@)
my $ref;
my $notready = 0;
print STDERR "Waiting ($$) for sliver $resource\n";
print STDERR "Getting ($$) sliver status for $resource\n";
if ($resource->SliverStatus($user, \$ref) != 0) {
# Tell the parent to keep trying.
......@@ -755,7 +822,8 @@ sub WaitForSlivers($$@)
# Tell the parent error.
return -1;
}
print STDERR Dumper($ref);
print STDERR Dumper($ref)
if ($verbose);
foreach my $key (keys(%{ $ref->{'details'} })) {
my $val = $ref->{'details'}->{$key};
......@@ -782,17 +850,11 @@ sub WaitForSlivers($$@)
# State was changed in a another process.
$node->Refresh();
#
# Only send on state change to avoid multiple events.
#
if ($status eq "ready" && !$node->IsUp()) {
# print STDERR " Sending ISUP event.\n";
# $node->SetEventState(TBDB_NODESTATE_ISUP());
if ($status eq "ready") {
# print statement would be repeated.
}
elsif ($status eq "failed" &&
$node->eventstate() ne TBDB_NODESTATE_TBFAILED) {
# print STDERR " Sending TBFAILED event.\n";
# $node->SetEventState(TBDB_NODESTATE_TBFAILED());
elsif ($status eq "failed") {
# print statement would be repeated.
}
else {
$notready++;
......@@ -839,7 +901,7 @@ sub WaitForSlivers($$@)
last
if ($experiment->canceled());
sleep(10)
sleep(15)
if (@resources);
}
#
......
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2009 University of Utah and the Flux Group.
# Copyright (c) 2000-2010 University of Utah and the Flux Group.
# All rights reserved.
#
use strict;
......@@ -377,6 +377,7 @@ foreach my $node (@freed_nodes) {
my $mustclean = 1;
my $estate = $node->eventstate();
my $isvirt = $node->isvirtnode();
my $isgeni = $node->isfednode();
my $isdynamic = $node->isdynamic();
my $def_boot_osid = $node->def_boot_osid();
my $imageable = $node->imageable();
......@@ -453,10 +454,11 @@ foreach my $node (@freed_nodes) {
#
# If the node is a virtnode, force its state to SHUTDOWN. This is mostly
# to avoid silly stated warnings for nodes that do not have a physical
# representation most of the time!
# representation most of the time! Ditto for geninodes which are really
# just proxies for a remote physical nodes.
#
$node->SetEventState(TBDB_NODESTATE_SHUTDOWN)
if ($isvirt && $estate ne TBDB_NODESTATE_SHUTDOWN());
if (($isvirt || $isgeni) && $estate ne TBDB_NODESTATE_SHUTDOWN());
# Clean out the SFS hostid. What about the other keys?
DBQueryWarn("update node_hostkeys set ".
......
......@@ -2127,10 +2127,10 @@ sub SliverWorkAux($$$$$$$)
goto bad;
}
#
# Not quite sure how to deal with links into virtual containers
# yet. For now, the link section will hold the physical info,
# Not quite sure how to deal with virtual interfaces yet.
# For now, the link section will hold the physical info,
# but we have to return the VMAC so the caller knows which
# virtual interface inside the container.
# virtual interface.
#
if ($node->isvirtnode()) {
$vnode = $node;
......@@ -2143,7 +2143,11 @@ sub SliverWorkAux($$$$$$$)
Interface::VInterface->LookupByVirtLan($experiment,
$linkname, $node_id);
}
else {
$vinterface =
Interface::VInterface->LookupByVirtLan($experiment,
$linkname, $node_id);
}
#
# The interface was set above.
#
......@@ -4086,6 +4090,16 @@ sub UpdateManifest($)
print STDERR "UpdateManifest: No tag for $vlan\n";
}
$vlantags{$vlan->vname()} = $tag;
#
# Encapsulation vlan, so need to find the actual link name.
#
my $linklan;
if ($vlan->GetAttribute("link/lan", \$linklan) == 0 &&
defined($linklan)) {
$vlantags{$linklan} = $tag;
}
}
foreach my $linkref (GeniXML::FindNodes("n:link", $rspec)->get_nodelist()){
my $vname = GeniXML::GetVirtualId($linkref);
......
......@@ -588,6 +588,29 @@ sub SliverAction($$$$$)
# For now, only allow top level aggregate or the slice
#
my ($slice, $aggregate) = Credential2SliceAggregate($credential);
if ( (!defined($slice)) &&
($credential->target_urn() =~ /\+authority\+cm$/)) {
# administrative credentials are presented.
my $cm_urn = GeniHRN::Generate($OURDOMAIN, "authority", "cm");
if ($cm_urn != $credential->target_urn()) {
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN(), undef,
"Credential target does not match CM URN");
}
if (!defined($slice_urn)) {
return GeniResponse->MalformedArgsResponse("Missing arguments");
}
$slice = GeniSlice->Lookup($slice_urn);
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"No Slice with urn $slice_urn here")
if (!defined($slice));
$aggregate = GeniAggregate->SliceAggregate($slice);
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"No Aggregate here")
if (!defined($aggregate));
}
if (! (defined($slice) && defined($aggregate))) {
return GeniResponse->Create(GENIRESPONSE_BADARGS, undef,
"No slice or aggregate here");
......@@ -681,7 +704,7 @@ sub SliverAction($$$$$)
goto bad
if (GeniResponse::IsResponse($response));
if ($action eq "start") {
if ($action eq "start" || $action eq "restart") {
GeniCM::UpdateManifest($slice);
}
$slice->UnLock();
......
......@@ -270,6 +270,7 @@ sub Refresh($)
$self->{'DBROW'} = $query_result->fetchrow_hashref();
$self->{'NEWTICKET'} = undef;
$self->{'MANIFEST'} = undef;
return 0;
}
......@@ -843,6 +844,112 @@ sub RedeemTicket($$)
return 0;
}
#
# Update the manifest.
#
sub GetManifest($$)
{
my ($self, $user) = @_;
my $response;
# Always clear for caller.
$self->{'last_rpc_error'} = 0;
$self->{'last_rpc_output'} = undef;
$self->{'last_rpc_value'} = undef;
my $slice = GeniSlice->Lookup($self->slice_idx());
if (!defined($slice)) {
print STDERR "*** GetManifest: No slice for $self\n";
return -1;
}
my $manager_urn = $self->manager_urn();
my $authority = GeniAuthority->CreateFromRegistry("cm", $manager_urn);
if (!defined($authority)) {
print STDERR "*** Could not find $manager_urn at ClearingHouse\n";
return -1;
}
my $manager_version = $self->ManagerVersion();
#
# Create a Geni user from current user doing the operation.
#
my $geniuser = GeniUser->CreateFromLocal($user);
if (!defined($geniuser)) {
print STDERR "*** Could not create a geni user from $user\n";
return -1;
}
my $usercontext = Genixmlrpc->UserContext($geniuser);
if (!defined($usercontext)) {
print STDERR "*** Could not create user context from $geniuser\n";
return -1;
}
#
# Load sliver credential.
#
if (!$self->credential_idx()) {
print STDERR "*** No credential defined for $self.\n";
return -1;
}
my $sliver_credential = GeniCredential->Lookup($self->credential_idx());
if (!defined($sliver_credential)) {
print STDERR "*** Could not get sliver credential for $self.\n";
return -1;
}
#
# Doit it.
#
my $method_name = "Resolve";
my $method_args = { 'credentials' => [$sliver_credential->asString()],
'urn' => $sliver_credential->target_urn(),
};
$response =
Genixmlrpc::CallMethod($authority->url(), $usercontext,
$method_name, $method_args);
if (!defined($response)) {
$self->{'last_rpc_error'} = GENIRESPONSE_RPCERROR();
print STDERR
"*** Internal error getting manifest for $self\n";
return -1;
}
$self->{'last_rpc_error'} = $response->code();
$self->{'last_rpc_output'} = $response->output();
$self->{'last_rpc_value'} = $response->value();
if ($response->code() != GENIRESPONSE_SUCCESS) {
print STDERR "Could not get manifest for $self. Error: ";
print STDERR " " . $response->output() . "\n";
return -1;
}
#
# Okay, so that worked. Store the new manifest.
#
my $manifest = $response->value()->{'manifest'};
#
# Move this elsewhere.
#
my $manifest_idx = ($self->manifest_idx() ?
$self->manifest_idx() : "NULL");
my $sliver_uuid = $sliver_credential->uuid();
my $query_result =
DBQueryWarn("replace into geni_manifests set ".
" manifest=". DBQuoteSpecial($manifest) . ", " .
" idx=$manifest_idx, slice_uuid='$sliver_uuid', ".
" created=now()");
return -1
if (!defined($query_result));
if (!$self->manifest_idx()) {
$manifest_idx = $query_result->insertid;
$self->Update({"manifest_idx" => $manifest_idx});
}
return 0;
}
#
# Clear all resources.
#
......@@ -1181,11 +1288,11 @@ sub Purge($$)
}
#
# Start a sliver. Optionally one part of it, but ignoring that for now.