#!/usr/bin/perl -w # # Copyright (c) 2009, 2010 University of Utah and the Flux Group. # # {{{EMULAB-LICENSE # # This file is part of the Emulab network testbed software. # # This file is free software: you can redistribute it and/or modify it # under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or (at # your option) any later version. # # This file is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public # License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this file. If not, see . # # }}} # use strict; use English; use Getopt::Std; use Data::Dumper; # # Exit status is important. Exit with -1 if an error, else the number # of nodes that could not be allocated. Otherwise zero. # sub usage() { print("Usage: geni_control [-d] [-p] ...\n". " -p enables partial allocation mode\n". " -d enables debugging output\n"); exit(-1); } my $optlist = "dp"; my $debug = 0; my $partial = 0; my $exitval = 0; # # Configure variables # my $TB = "@prefix@"; # # Testbed Support libraries # use lib '@prefix@/lib'; use libdb; use libtestbed; use Experiment; use Project; use User; use Node; use libGeni; use GeniResource; use GeniHRN; use GeniXML; sub fatal($); sub AllocNodes(); sub FreeNodes(); sub Register(); sub UnRegister(); sub ClearAll(); sub StartAll(); sub StopAll(); sub WaitAll(); sub PurgeAll(); sub RenewAll(); sub GetManifests(); sub GetStatus(); sub MapNodes(); # # Turn off line buffering on output # $| = 1; # For perf analysis. #TBDebugTimeStampsOn(); # # Parse command arguments. Once we return from getopts, all that should be # left are the required arguments. # my %options = (); if (! getopts($optlist, \%options)) { usage(); } if (defined($options{"d"})) { $debug = 1; } if (defined($options{"p"})) { $partial = 1; } if (@ARGV < 3) { usage(); } my $pid = shift; my $eid = shift; my $action = shift; if ($action =~ /^(alloc|free|clear|wait|purge|start|mapnodes|status|stop|register|unregister||manifests|renew)$/) { $action = $1; } else { usage(); } # # Locals # my $error = 0; my $noalloc = 0; my @oldnodes = (); my @nodes = (); # # Experiment must exist. # my $experiment = Experiment->Lookup($pid, $eid); if (! $experiment) { die("*** $0:\n". " No such experiment $pid/$eid in the Emulab Database.\n"); } my $exptidx = $experiment->idx(); my $project = $experiment->GetProject(); if (!defined($project)) { die("*** $0:\n". " Could not get project for experiment $experiment!\n"); } # # User must have permission to modify the experiment. # my $this_user = User->ThisUser(); if (! defined($this_user)) { die("*** $0:\n". " You ($UID) do not exist in the Emulab DB!\n"); } if (!$experiment->AccessCheck($this_user, TB_EXPT_MODIFY)) { die("*** $0:\n". " You do not have permission to allocate nodes in $pid/$eid\n"); } # # Need an RPC context for this to work. # my $certificate = GeniCertificate->LoadFromFile("$TB/etc/genisa.pem"); fatal("Could not load SA certificate") if (!defined($certificate)); Genixmlrpc->SetContext(Genixmlrpc->Context($certificate)); $ENV{'MYUUID'} = $certificate->uuid(); $ENV{'MYURN'} = $certificate->urn(); my $foo = "urn:publicid:IDN+emulab.net+authority+cm"; my $fee = "urn:publicid:IDN+emulab.net+node+pc172"; @ARGV = ($fee); # # Now dispatch operation. # SWITCH: for ($action) { /^register$/ && do { Register(); last SWITCH; }; /^unregister$/ && do { UnRegister(); last SWITCH; }; /^alloc$/ && do { AllocNodes(); last SWITCH; }; /^free$/ && do { FreeNodes(); last SWITCH; }; /^clear$/ && do { ClearAll(); last SWITCH; }; /^start$/ && do { StartAll(); last SWITCH; }; /^stop$/ && do { StopAll(); last SWITCH; }; /^wait$/ && do { WaitAll(); last SWITCH; }; /^purge$/ && do { PurgeAll(); last SWITCH; }; /^renew$/ && do { RenewAll(); last SWITCH; }; /^manifests$/ && do { GetManifests(); last SWITCH; }; /^status$/ && do { GetStatus(); last SWITCH; }; /^mapnodes$/ && do { MapNodes(); last SWITCH; }; fatal("Unknown action $action"); } exit($exitval); # # Allocate # sub AllocNodes() { my $node_urn = $ARGV[0]; my ($auth,$type,$node_id) = GeniHRN::Parse($node_urn); my $cm = GeniHRN::Generate($auth, "authority", "cm"); my $resource = GeniResource->Lookup($experiment->idx(), $cm); if (!defined($resource)) { $resource = GeniResource->Create($experiment, $cm); if (!defined($resource)) { fatal("Cannot create new geni resource object for $cm"); } } print "$resource\n"; my $rspec = " ". " ". " " . ""; $resource->ModifyResources($this_user, $rspec) == 0 or fatal("Could not add new resources to $resource"); return 0; } # # Dealloc # sub FreeNodes() { } sub ClearAll() { my @resources = GeniResource->LookupAll($experiment); foreach my $resource (@resources) { $resource->Clear($this_user) == 0 or fatal("Could not clear resources from $resource"); } return 0; } sub PurgeAll() { my @resources = GeniResource->LookupAll($experiment); foreach my $resource (@resources) { $resource->Purge($this_user) == 0 or fatal("Could not purge resources from $resource"); $resource->Delete() == 0 or fatal("Could not delete $resource"); } UnRegister(); return 0; } sub StartAll() { libGeni::StartSlivers($experiment, $this_user, $debug) == 0 or fatal("Cannot start slivers!\n"); } 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, $debug) == 0 or fatal("Cannot wait on slivers!\n"); } sub RenewAll() { libGeni::RenewSlivers($experiment, $debug) == 0 or fatal("Cannot renew resources"); } sub MapNodes() { libGeni::MapNodes($experiment, $debug) == 0 or fatal("Cannot Mapnodes"); } sub Register() { libGeni::Register($experiment, $this_user) == 0 or fatal("Cannot register with Protgeni!\n"); return 0; } # # Unregister. # sub UnRegister() { libGeni::UnRegister($experiment) == 0 or fatal("Cannot unregister with Protgeni!"); return 0; } sub GetManifests() { my @resources = GeniResource->LookupAll($experiment); foreach my $resource (@resources) { $resource->GetManifest($this_user) == 0 or fatal("Could not get manifest for $resource"); my $manifest = $resource->Manifest(); if (!defined($manifest)) { print STDERR "No manifest for $resource\n"; next; } print STDERR Dumper(GeniXML::Serialize($manifest, 1)); } 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 get status for $resource"); print STDERR Dumper($ref); } return 0; } sub fatal($) { my ($msg) = @_; print STDERR "*** $0:\n$msg\n"; exit(-1); }