Commit c3339c9d authored by Leigh B Stoller's avatar Leigh B Stoller

Add AddNodes and DeleteNodes, which are convenience functions for the HPC

folks.

AddNodes($slice_urn, $credentials, $nodes):

The "nodes" argument is a hash that looks like:

  {"node45" : {"diskimage" : "urn...",
               "startup"   : "/bin/echo",
               "tarballs"  : ["tarball1", "tarball2", ...],
               "lans"      : ["lan1", "lan2", ...]
               "node"      : "pc189"},
   "nodeXX" : {...}}

DeleteNodes($slice_urn, $credentials, $nodes):

The "nodes" argument is a list like:

  ["node45", ...]

Any node can be deleted, but it is not yet clear what happens if all the
nodes of a lan are removed. I probably need to do some work there, but
David can start with this.
parent 0a63deac
......@@ -34,7 +34,7 @@ package GeniAggregate;
#
use strict;
use Exporter;
use vars qw(@ISA @EXPORT);
use vars qw(@ISA @EXPORT @EXPORT_OK $ACTION_FLAGS_SYNCVLANS);
@ISA = qw(Exporter);
@EXPORT = qw();
......@@ -95,6 +95,11 @@ my $ELAB_SETUP = "$TB/sbin/elabinelab";
my %aggregates = ();
BEGIN { use GeniUtil; GeniUtil::AddCache(\%aggregates); }
# Action() flags.
$ACTION_FLAGS_SYNCVLANS = 0x01;
@EXPORT_OK = qw($ACTION_FLAGS_SYNCVLANS);
#
# Lookup by URN, idx, or uuid.
#
......@@ -926,25 +931,25 @@ sub ProcessManifest($$)
return 0;
}
sub Start($$)
sub Start($$;$)
{
my ($self, $version) = @_;
my ($self, $version, $flags) = @_;
return $self->Action($version, "start");
return $self->Action($version, "start", $flags);
}
sub Restart($$)
sub Restart($$;$)
{
my ($self, $version) = @_;
my ($self, $version, $flags) = @_;
return $self->Action($version, "restart");
return $self->Action($version, "restart", $flags);
}
sub Reload($$)
sub Reload($$;$)
{
my ($self, $version) = @_;
my ($self, $version, $flags) = @_;
return $self->Action($version, "reload");
return $self->Action($version, "reload", $flags);
}
#
......@@ -956,13 +961,14 @@ sub Reload($$)
# XXX Is is assumed that there is a single toplevel aggregate for the
# slice, so we can get all the nodes.
#
sub Action($$$)
sub Action($$$;$)
{
my ($self, $version, $action) = @_;
my ($self, $version, $action, $flags) = @_;
$self->ClearBootFailure();
my $msg = "Internal Error: ";
my $restart = ($action eq "restart" ? 1 : 0);
my $reload = ($action eq "reload" ? 1 : 0);
$flags = 0 if (!defined($flags));
require Lan;
require OSinfo;
require Image;
......@@ -1389,24 +1395,37 @@ sub Action($$$)
$msg .= "$NAMEDSETUP failed\n";
goto bad;
}
my @diff = ();
my @same = ();
if (Lan->CompareVlansWithSwitches($experiment, \@diff, \@same)) {
print STDERR "CompareVlansWithSwitches failed!\n";
goto bad;
}
if (@diff) {
system("$SNMPIT -f ". join(" ", map("-o $_", @diff)));
if ($flags & $ACTION_FLAGS_SYNCVLANS) {
if (Lan->CompareVlansWithSwitches2($experiment)) {
$msg .= "CompareVlansWithSwitches2 failed!\n";
goto bad;
}
system("$SNMPIT -X $pid $eid");
if ($?) {
$msg .= "Failed to remove obsolete VLANs.";
$msg .= "Failed to synchronize vlans";
goto bad;
}
}
system("$SNMPIT -t $pid $eid");
if ($?) {
$msg .= "Failed to setup vlans";
goto bad;
else {
my @diff = ();
my @same = ();
if (Lan->CompareVlansWithSwitches($experiment, \@diff, \@same)) {
print STDERR "CompareVlansWithSwitches failed!\n";
goto bad;
}
if (@diff) {
system("$SNMPIT -f ". join(" ", map("-o $_", @diff)));
if ($?) {
$msg .= "Failed to remove obsolete VLANs.";
goto bad;
}
}
system("$SNMPIT -t $pid $eid");
if ($?) {
$msg .= "Failed to setup vlans";
goto bad;
}
}
if ($experiment->SetupPortLans()) {
$msg .= "Failed to setup shared vlan ports";
......@@ -1953,9 +1972,9 @@ sub WaitForNodes($$@)
# Stop all the slivers in the aggregate. Stop is brutal, better to
# use restart!
#
sub Stop($$)
sub Stop($$;$)
{
my ($self, $version) = @_;
my ($self, $version, $flags) = @_;
$self->ClearBootFailure();
my $msg = "Internal Error: ";
......
......@@ -693,7 +693,7 @@ sub GetTicketAuxAux($$$$$$$$$$$)
goto bad;
}
}
elsif ($v2 && $level && !defined($ticket) && !defined($aggregate)) {
elsif ($v2 && $level > 0 && !defined($ticket) && !defined($aggregate)) {
print STDERR "No aggregate for $slice in version two API\n";
$response = GeniResponse->Create(GENIRESPONSE_ERROR);
goto bad;
......@@ -3031,7 +3031,7 @@ sub GetTicketAuxAux($$$$$$$$$$$)
#
# For the version 2 minimal API, just return the annotated rspec.
#
if ($v2 && $level == 0) {
if ($v2 && $level <= 0) {
# Bad, should leave it locked, but Redeem below would fail, and
# this whole arrangement is temporary, so lets not worry about it.
$slice->UnLock();
......@@ -3203,7 +3203,7 @@ sub SliverWorkAux($$$$$$$$)
require User;
# V2 API support.
if ($v2 && $level == 0) {
if (($v2 && $level == 0) || ref($object) ne "GeniTicket") {
$rspec = $object;
}
else {
......@@ -4106,14 +4106,8 @@ sub SliverWorkAux($$$$$$$$)
if ($inaggregate) {
my $nickname = "$linkname." . $node->node_id() . ".$iface_name";
$sliver = $linkaggregate->FindSliverByNickname($nickname);
if (!defined($sliver)) {
$message = "Could not find existing sliver for ".
"$nickname in $linkname";
goto bad;
}
}
else {
if (!defined($sliver)) {
$sliver = GeniSliver::Interface->Create($slice,
$owner,
$node->node_id(),
......
This diff is collapsed.
#! /usr/bin/env python
#
# Copyright (c) 2008-2015 University of Utah and the Flux Group.
#
# {{{GENIPUBLIC-LICENSE
#
# GENI Public License
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and/or hardware specification (the "Work") to
# deal in the Work without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Work, and to permit persons to whom the Work
# is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Work.
#
# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS
# IN THE WORK.
#
# }}}
#
#
#
import sys
import pwd
import getopt
import os
import re
ACCEPTSLICENAME=1
execfile( "test-common.py" )
#
# Get a credential for myself, that allows me to do things at the SA.
#
mycredential = get_self_credential()
print "Got my SA credential. Looking for slice ..."
#
# Lookup slice.
#
myslice = resolve_slice( SLICENAME, mycredential )
print "Found the slice, asking for a credential ..."
#
# Get the slice credential.
#
slicecred = get_slice_credential( myslice, mycredential )
print "Got the slice credential, asking for a sliver credential ..."
#
# Add a node.
#
params = {}
params["slice_urn"] = myslice["urn"]
params["credentials"] = (slicecred,)
params["nodes"] = {"node45" : {"startup" : "/bin/ls > /tmp/foo.txt"}}
rval,response = do_method("cm", "AddNodes", params, version="2.0")
if rval:
Fatal("Could not add nodes")
pass
#! /usr/bin/env python
#
# Copyright (c) 2008-2015 University of Utah and the Flux Group.
#
# {{{GENIPUBLIC-LICENSE
#
# GENI Public License
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and/or hardware specification (the "Work") to
# deal in the Work without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Work, and to permit persons to whom the Work
# is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Work.
#
# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS
# IN THE WORK.
#
# }}}
#
#
#
import sys
import pwd
import getopt
import os
import re
ACCEPTSLICENAME=1
execfile( "test-common.py" )
#
# Get a credential for myself, that allows me to do things at the SA.
#
mycredential = get_self_credential()
print "Got my SA credential. Looking for slice ..."
#
# Lookup slice.
#
myslice = resolve_slice( SLICENAME, mycredential )
print "Found the slice, asking for a credential ..."
#
# Get the slice credential.
#
slicecred = get_slice_credential( myslice, mycredential )
print "Got the slice credential, asking for a sliver credential ..."
#
# Add a node.
#
params = {}
params["slice_urn"] = myslice["urn"]
params["credentials"] = (slicecred,)
params["nodes"] = ("node45",)
rval,response = do_method("cm", "DeleteNodes", params, version="2.0")
if rval:
Fatal("Could not add nodes")
pass
......@@ -115,6 +115,8 @@ elsif ($GENI_VERSION eq "2.0") {
"ModifyDataset" => \&GeniCMV2::ModifyDataset,
"Lockdown" => \&GeniCMV2::Lockdown,
"TriggerImageUpdate"=> \&GeniCMV2::TriggerImageUpdate,
"AddNodes" => \&GeniCMV2::AddNodes,
"DeleteNodes" => \&GeniCMV2::DeleteNodes,
};
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment