Commit 88e0ecb5 authored by Leigh Stoller's avatar Leigh Stoller

Checkpoint multisite support.

parent e11d79be
...@@ -46,6 +46,10 @@ my $MAINSITE = @TBMAINSITE@; ...@@ -46,6 +46,10 @@ my $MAINSITE = @TBMAINSITE@;
my $TBOPS = "@TBOPSEMAIL@"; my $TBOPS = "@TBOPSEMAIL@";
my $SACERT = "$TB/etc/genisa.pem"; my $SACERT = "$TB/etc/genisa.pem";
# Cache credentials so we do not keep regenerating down inside the
# libraries that make the XMLRPC calls.
my %credcache = ();
# #
# Generate the credentials we need. # Generate the credentials we need.
# #
...@@ -66,6 +70,15 @@ sub GenCredentials($$;$) ...@@ -66,6 +70,15 @@ sub GenCredentials($$;$)
$speaker_signer = "/usr/testbed/etc/utah-apt.sa"; $speaker_signer = "/usr/testbed/etc/utah-apt.sa";
} }
#
# Check cache.
#
my $cachetag = $target->urn() . "::" . $geniuser->urn();
if (exists($credcache{$cachetag})) {
($credential,$speaksfor) = @{ $credcache{$cachetag} };
goto cached;
}
# #
# If a local user account, but a nonlocal id, then we should # If a local user account, but a nonlocal id, then we should
# have a speaksfor credential stored, as well as a certificate # have a speaksfor credential stored, as well as a certificate
...@@ -139,6 +152,10 @@ sub GenCredentials($$;$) ...@@ -139,6 +152,10 @@ sub GenCredentials($$;$)
print STDERR "Could not sign $target credential\n"; print STDERR "Could not sign $target credential\n";
goto bad; goto bad;
} }
if ($wantspeaksfor) {
$credcache{$cachetag} = [$credential, $speaksfor];
}
cached:
if (wantarray) { if (wantarray) {
return ($credential, $speaksfor); return ($credential, $speaksfor);
} }
......
This diff is collapsed.
...@@ -947,9 +947,9 @@ sub CheckDatasets($$$) ...@@ -947,9 +947,9 @@ sub CheckDatasets($$$)
# #
# Set the component_manager_urn for the sites. # Set the component_manager_urn for the sites.
# #
sub SetSites($$$) sub SetSites($$$$)
{ {
my ($prspecstr, $sitemap, $perrmsg) = @_; my ($prspecstr, $sitemap, $pneedstitcher, $perrmsg) = @_;
my $rspec = GeniXML::Parse($$prspecstr); my $rspec = GeniXML::Parse($$prspecstr);
if (! defined($rspec)) { if (! defined($rspec)) {
...@@ -961,17 +961,60 @@ sub SetSites($$$) ...@@ -961,17 +961,60 @@ sub SetSites($$$)
my $site_id = GeniXML::GetJacksSiteId($ref); my $site_id = GeniXML::GetJacksSiteId($ref);
if (!defined($site_id)) { if (!defined($site_id)) {
$$perrmsg = "No site ID for $client_id"; $$perrmsg = "No site ID for node $client_id";
return -1; return -1;
} }
my $site_mid = "site:" . $site_id; my $site_mid = "site:" . $site_id;
if (!exists($sitemap->{$site_mid})) { if (!exists($sitemap->{$site_mid})) {
$$perrmsg = "No site mapping for $client_id ($site_id)"; $$perrmsg = "No site mapping for node $client_id ($site_id)";
return -1; return -1;
} }
GeniXML::SetManagerId($ref, $sitemap->{$site_mid}); GeniXML::SetManagerId($ref, $sitemap->{$site_mid});
GeniXML::SetJacksSiteManagerId($ref, $sitemap->{$site_mid}); GeniXML::SetJacksSiteManagerId($ref, $sitemap->{$site_mid});
} }
foreach my $ref (GeniXML::FindNodes("n:link", $rspec)->get_nodelist()) {
my %linksites = ();
my $client_id = GetVirtualId($ref);
foreach my $siteref (GeniXML::FindNodesNS("n:site", $ref,
$GeniXML::JACKS_NS)->get_nodelist()) {
my $site_id = GeniXML::GetText("id", $siteref);
if (!defined($site_id)) {
$$perrmsg = "No site ID for link $client_id";
return -1;
}
my $site_mid = "site:" . $site_id;
if (!exists($sitemap->{$site_mid})) {
$$perrmsg = "No site mapping for link $client_id ($site_id)";
return -1;
}
GeniXML::AddManagerToLink($ref, $sitemap->{$site_mid});
$linksites{$sitemap->{$site_mid}} = 1;
}
# if more then one site for a link, must use the stitcher.
$$pneedstitcher = 1
if (keys(%linksites) > 1);
}
$$prspecstr = GeniXML::Serialize($rspec);
return 0;
}
#
# Set the component_manager_urn for the rspec
#
sub BindRspec($$$)
{
my ($prspecstr, $aggregate_urn, $perrmsg) = @_;
my $rspec = GeniXML::Parse($$prspecstr);
if (! defined($rspec)) {
$$perrmsg = "Could not parse rspec\n";
return -1;
}
foreach my $ref (GeniXML::FindNodes("n:node", $rspec)->get_nodelist()) {
GeniXML::SetManagerId($ref, $aggregate_urn);
}
$$prspecstr = GeniXML::Serialize($rspec); $$prspecstr = GeniXML::Serialize($rspec);
return 0; return 0;
} }
......
This diff is collapsed.
...@@ -205,6 +205,7 @@ sub DoCreate() ...@@ -205,6 +205,7 @@ sub DoCreate()
if (!defined($aggregate)) { if (!defined($aggregate)) {
fatal("Could not find aggregate for $nodeid"); fatal("Could not find aggregate for $nodeid");
} }
$aggregate_urn = $aggregate->aggregate_urn();
} }
if (defined($options{"f"})) { if (defined($options{"f"})) {
$fstype = $options{"f"}; $fstype = $options{"f"};
...@@ -345,7 +346,7 @@ sub DoCreate() ...@@ -345,7 +346,7 @@ sub DoCreate()
# Handoff to snapshot if an imdataset. # Handoff to snapshot if an imdataset.
# #
if ($type eq "imdataset" && if ($type eq "imdataset" &&
DoSnapShotInternal($dataset, $instance, DoSnapShotInternal($dataset, $aggregate,
$bsname, $nodeid, \$errmsg)) { $bsname, $nodeid, \$errmsg)) {
$instance->Unlock(); $instance->Unlock();
goto failed; goto failed;
...@@ -624,6 +625,10 @@ sub DoSnapshot() ...@@ -624,6 +625,10 @@ sub DoSnapshot()
if (!defined($instance)) { if (!defined($instance)) {
fatal("No such instance"); fatal("No such instance");
} }
my $aggregate = $instance->FindAggregateByNodeId($nodeid);
if (!defined($aggregate)) {
fatal("Could not find aggregate for $nodeid");
}
if ($dataset->Lock()) { if ($dataset->Lock()) {
fatal("dataset is busy, cannot lock it"); fatal("dataset is busy, cannot lock it");
} }
...@@ -639,7 +644,7 @@ sub DoSnapshot() ...@@ -639,7 +644,7 @@ sub DoSnapshot()
# Convenient. # Convenient.
$webtask->AutoStore(1); $webtask->AutoStore(1);
} }
if (DoSnapShotInternal($dataset, $instance, $bsname, $nodeid, \$errmsg)) { if (DoSnapShotInternal($dataset, $aggregate, $bsname, $nodeid, \$errmsg)) {
goto failed; goto failed;
} }
if (PollDatasetStatus($dataset, \$errmsg)) { if (PollDatasetStatus($dataset, \$errmsg)) {
...@@ -659,10 +664,10 @@ sub DoSnapshot() ...@@ -659,10 +664,10 @@ sub DoSnapshot()
sub DoSnapShotInternal($$$$$) sub DoSnapShotInternal($$$$$)
{ {
my ($dataset, $instance, $bsname, $nodeid, $perrmsg) = @_; my ($dataset, $aggregate, $bsname, $nodeid, $perrmsg) = @_;
my $errmsg; my $errmsg;
my $manifest = GeniXML::Parse($instance->manifest()); my $manifest = GeniXML::Parse($aggregate->manifest());
if (! defined($manifest)) { if (! defined($manifest)) {
$errmsg = "Could not parse manifest"; $errmsg = "Could not parse manifest";
goto failed; goto failed;
...@@ -697,8 +702,8 @@ sub DoSnapShotInternal($$$$$) ...@@ -697,8 +702,8 @@ sub DoSnapShotInternal($$$$$)
$errmsg = "Could not find node '$nodeid' in manifest"; $errmsg = "Could not find node '$nodeid' in manifest";
goto failed; goto failed;
} }
my $response = $instance->CreateImage($sliver_urn, my $response = $aggregate->CreateImage($sliver_urn,
$dataset->dataset_id(), 0, $bsname); $dataset->dataset_id(), 0, $bsname);
if ($response->code() != GENIRESPONSE_SUCCESS) { if ($response->code() != GENIRESPONSE_SUCCESS) {
$errmsg = "SnapshotDataset failed: ". $response->output() . "\n"; $errmsg = "SnapshotDataset failed: ". $response->output() . "\n";
goto failed; goto failed;
......
...@@ -45,6 +45,7 @@ sub usage() ...@@ -45,6 +45,7 @@ sub usage()
print("Usage: manage_instance reload instance node_id [node_id ...]\n"); print("Usage: manage_instance reload instance node_id [node_id ...]\n");
print("Usage: manage_instance monitor instance\n"); print("Usage: manage_instance monitor instance\n");
print("Usage: manage_instance lockdown instance set|clear user|admin\n"); print("Usage: manage_instance lockdown instance set|clear user|admin\n");
print("Usage: manage_instance writecreds instance directory\n");
exit(-1); exit(-1);
} }
my $optlist = "dt:"; my $optlist = "dt:";
...@@ -104,6 +105,7 @@ sub DoRefresh(); ...@@ -104,6 +105,7 @@ sub DoRefresh();
sub DoReboot(); sub DoReboot();
sub DoReload(); sub DoReload();
sub DoLockdown(); sub DoLockdown();
sub WriteCredentials();
sub StartMonitor(); sub StartMonitor();
# #
...@@ -160,6 +162,9 @@ elsif ($action eq "monitor") { ...@@ -160,6 +162,9 @@ elsif ($action eq "monitor") {
elsif ($action eq "lockdown") { elsif ($action eq "lockdown") {
DoLockdown() DoLockdown()
} }
elsif ($action eq "writecreds") {
WriteCredentials()
}
else { else {
usage(); usage();
} }
...@@ -248,7 +253,7 @@ sub DoSnapshot() ...@@ -248,7 +253,7 @@ sub DoSnapshot()
# #
# Sanity checks. # Sanity checks.
# #
my @aggs = @{ $instance->AggregateList() }; my @aggs = $instance->AggregateList();
if (! @aggs) { if (! @aggs) {
fatal("No slivers for instance!"); fatal("No slivers for instance!");
} }
...@@ -279,12 +284,15 @@ sub DoSnapshot() ...@@ -279,12 +284,15 @@ sub DoSnapshot()
} }
foreach my $ref (GeniXML::FindNodes("n:node", foreach my $ref (GeniXML::FindNodes("n:node",
$manifest)->get_nodelist()) { $manifest)->get_nodelist()) {
my $client_id = GeniXML::GetVirtualId($ref); my $client_id = GeniXML::GetVirtualId($ref);
my $urn = GeniXML::GetSliverId($ref); my $manager_urn = GetManagerId($ref);
my $urn = GeniXML::GetSliverId($ref);
# No sliver urn or a different aggregate. # No sliver urn or a different aggregate.
next next
if (! (defined($urn) && $urn eq $agg->aggregate_urn())); if (! (defined($urn) &&
defined($manager_urn) &&
$manager_urn eq $agg->aggregate_urn()));
if ($node_id eq $client_id) { if ($node_id eq $client_id) {
$node = $ref; $node = $ref;
...@@ -414,7 +422,7 @@ sub DoSnapshot() ...@@ -414,7 +422,7 @@ sub DoSnapshot()
sleep($interval); sleep($interval);
$seconds -= $interval; $seconds -= $interval;
my $response = $aggregate->SliverStatus(); my $response = $aggregate->SliceStatus();
if ($response->code() != GENIRESPONSE_SUCCESS && if ($response->code() != GENIRESPONSE_SUCCESS &&
$response->code() != GENIRESPONSE_BUSY) { $response->code() != GENIRESPONSE_BUSY) {
$errmsg = "Sliverstatus failed: ". $response->output() . "\n"; $errmsg = "Sliverstatus failed: ". $response->output() . "\n";
...@@ -579,7 +587,7 @@ sub DoConsole() ...@@ -579,7 +587,7 @@ sub DoConsole()
# #
my $sliver_urn; my $sliver_urn;
my $sliver; my $sliver;
foreach my $obj (@{ $instance->AggregateList() }) { foreach my $obj ($instance->AggregateList()) {
my $manifest = GeniXML::Parse($obj->manifest()); my $manifest = GeniXML::Parse($obj->manifest());
if (! defined($manifest)) { if (! defined($manifest)) {
fatal("Could not parse manifest for $obj"); fatal("Could not parse manifest for $obj");
...@@ -725,7 +733,7 @@ sub DoTerminate() ...@@ -725,7 +733,7 @@ sub DoTerminate()
return -1; return -1;
}; };
my @return_codes = (); my @return_codes = ();
my @agglist = @{ $instance->AggregateList() }; my @agglist = $instance->AggregateList();
if (ParRun({"maxwaittime" => 99999, if (ParRun({"maxwaittime" => 99999,
"maxchildren" => scalar(@agglist)}, "maxchildren" => scalar(@agglist)},
\@return_codes, $coderef, @agglist)) { \@return_codes, $coderef, @agglist)) {
...@@ -851,7 +859,7 @@ sub DoExtend() ...@@ -851,7 +859,7 @@ sub DoExtend()
return -1; return -1;
}; };
my @return_codes = (); my @return_codes = ();
my @agglist = @{ $instance->AggregateList() }; my @agglist = $instance->AggregateList();
if (ParRun({"maxwaittime" => 99999, if (ParRun({"maxwaittime" => 99999,
"maxchildren" => scalar(@agglist)}, "maxchildren" => scalar(@agglist)},
\@return_codes, $coderef, @agglist)) { \@return_codes, $coderef, @agglist)) {
...@@ -976,7 +984,7 @@ sub DoRefresh() ...@@ -976,7 +984,7 @@ sub DoRefresh()
return 1; return 1;
}; };
my @return_codes = (); my @return_codes = ();
my @agglist = @{ $instance->AggregateList() }; my @agglist = $instance->AggregateList();
if (ParRun({"maxwaittime" => 99999, if (ParRun({"maxwaittime" => 99999,
"maxchildren" => scalar(@agglist)}, "maxchildren" => scalar(@agglist)},
\@return_codes, $coderef, @agglist)) { \@return_codes, $coderef, @agglist)) {
...@@ -1031,7 +1039,7 @@ sub DoRebootOrReload($) ...@@ -1031,7 +1039,7 @@ sub DoRebootOrReload($)
my %sliver_urns = (); my %sliver_urns = ();
my @slivers = (); my @slivers = ();
foreach my $obj (@{ $instance->AggregateList() }) { foreach my $obj ($instance->AggregateList()) {
my $manifest = GeniXML::Parse($obj->manifest()); my $manifest = GeniXML::Parse($obj->manifest());
if (! defined($manifest)) { if (! defined($manifest)) {
fatal("Could not parse manifest"); fatal("Could not parse manifest");
...@@ -1083,7 +1091,7 @@ sub DoRebootOrReload($) ...@@ -1083,7 +1091,7 @@ sub DoRebootOrReload($)
# Clear this so that web interface will not update it. # Clear this so that web interface will not update it.
$webtask->sliverstatus({}); $webtask->sliverstatus({});
my $response = $sliver->SliverAction($which, @urns); my $response = $sliver->SliverAction(\$errmsg, $which, @urns);
if (!defined($response)) { if (!defined($response)) {
$errmsg = "RPC Error calling SliverAction"; $errmsg = "RPC Error calling SliverAction";
goto bad; goto bad;
...@@ -1267,7 +1275,7 @@ sub StartMonitor() ...@@ -1267,7 +1275,7 @@ sub StartMonitor()
local $SIG{INT} = $handler; local $SIG{INT} = $handler;
} }
my @return_codes = (); my @return_codes = ();
my @agglist = @{ $instance->AggregateList() }; my @agglist = $instance->AggregateList();
if (ParRun({"maxwaittime" => 99999, if (ParRun({"maxwaittime" => 99999,
"maxchildren" => scalar(@agglist)}, "maxchildren" => scalar(@agglist)},
\@return_codes, $coderef, @agglist)) { \@return_codes, $coderef, @agglist)) {
...@@ -1351,7 +1359,7 @@ sub DoLockdownInternal($$) ...@@ -1351,7 +1359,7 @@ sub DoLockdownInternal($$)
return 0; return 0;
}; };
my @return_codes = (); my @return_codes = ();
my @agglist = @{ $instance->AggregateList() }; my @agglist = $instance->AggregateList();
if (ParRun({"maxwaittime" => 99999, if (ParRun({"maxwaittime" => 99999,
"maxchildren" => scalar(@agglist)}, "maxchildren" => scalar(@agglist)},
\@return_codes, $coderef, @agglist)) { \@return_codes, $coderef, @agglist)) {
...@@ -1398,6 +1406,22 @@ sub DoLockdown() ...@@ -1398,6 +1406,22 @@ sub DoLockdown()
exit(0); exit(0);
} }
#
# Write instance credentials to files.
#
sub WriteCredentials()
{
usage()
if (!@ARGV);
my $directory = shift(@ARGV);
fatal("$directory does not exist")
if (! -e $directory);
fatal("$directory is not a directory")
if (! -d $directory);
return $instance->WriteCredentials($directory);
}
sub fatal($) sub fatal($)
{ {
my ($mesg) = @_; my ($mesg) = @_;
......
...@@ -320,11 +320,11 @@ if ($snap) { ...@@ -320,11 +320,11 @@ if ($snap) {
if (!defined($instance)) { if (!defined($instance)) {
fatal("Could not look up instance $uuid"); fatal("Could not look up instance $uuid");
} }
if (@{ $instance->AggregateList() } != 1) { if ($instance->AggregateList() != 1) {
$errors{"error"} = "Must be only one aggregate to snapshot"; $errors{"error"} = "Must be only one aggregate to snapshot";
UserError(); UserError();
} }
($aggregate) = @{ $instance->AggregateList() }; ($aggregate) = $instance->AggregateList();
my $manifest = GeniXML::Parse($aggregate->manifest()); my $manifest = GeniXML::Parse($aggregate->manifest());
if (! defined($manifest)) { if (! defined($manifest)) {
fatal("Could not parse manifest"); fatal("Could not parse manifest");
......
...@@ -542,6 +542,18 @@ sub SetManagerId($$) ...@@ -542,6 +542,18 @@ sub SetManagerId($$)
return $node; return $node;
} }
sub AddManagerToLink($$)
{
my ($link, $urn) = @_;
my $ref = AddElement("component_manager", $link);
return undef
if (!defined($ref));
GeniXML::SetText("name", $ref, $urn);
return $link;
}
sub GetColocate($) sub GetColocate($)
{ {
my ($node) = @_; my ($node) = @_;
......
...@@ -180,7 +180,7 @@ function (_, Constraints, sup, ppstart, aboutaptString, aboutcloudString, waitwa ...@@ -180,7 +180,7 @@ function (_, Constraints, sup, ppstart, aboutaptString, aboutcloudString, waitwa
var continuation = function(rspec, description, name, amdefault, ispp) { var continuation = function(rspec, description, name, amdefault, ispp) {
$('#showtopo_title').html("<h3>" + name + "</h3>"); $('#showtopo_title').html("<h3>" + name + "</h3>");
$('#showtopo_description').html(description); $('#showtopo_description').html(description);
sup.maketopmap('#showtopo_div', rspec, null); sup.maketopmap('#showtopo_div', rspec, false);
}; };
GetProfile($(selectedElement).attr('value'), continuation); GetProfile($(selectedElement).attr('value'), continuation);
} }
......
...@@ -834,17 +834,6 @@ function (_, sup, filesize, JacksEditor, ShowImagingModal, moment, ppstart, ...@@ -834,17 +834,6 @@ function (_, sup, filesize, JacksEditor, ShowImagingModal, moment, ppstart,
} }
} }
//
// Show the rspec text in the modal.
//
function ShowRspecTopo(xml)
{
sup.ShowModal("#quickvm_topomodal");
$('#quickvm_topomodal').one('shown.bs.modal', function() {
sup.maketopmap("#showtopo_nopicker", xml, null);
});
}
// //
// Instantiate a profile as a guest User. // Instantiate a profile as a guest User.
// //
......
...@@ -70,7 +70,7 @@ function (sup, moment) ...@@ -70,7 +70,7 @@ function (sup, moment)
} }
sup.ShowModal("#quickvm_topomodal"); sup.ShowModal("#quickvm_topomodal");
$("#quickvm_topomodal").one("shown.bs.modal", function () { $("#quickvm_topomodal").one("shown.bs.modal", function () {
sup.maketopmap('#showtopo_nopicker', json.value.rspec, null); sup.maketopmap('#showtopo_nopicker', json.value.rspec, false);
}); });
}; };
var $xmlthing = sup.CallServerMethod(ajaxurl, var $xmlthing = sup.CallServerMethod(ajaxurl,
......
...@@ -45,11 +45,8 @@ var jacksInstance; ...@@ -45,11 +45,8 @@ var jacksInstance;
var jacksInput; var jacksInput;
var jacksOutput; var jacksOutput;
function maketopmap(divname, xml, sshcallback, writeable) function maketopmap(divname, xml, showinfo)
{ {
if (writeable === undefined) {
writeable = false;
}
if (! jacksInstance) if (! jacksInstance)
{ {
jacksInstance = new window.Jacks({ jacksInstance = new window.Jacks({
...@@ -57,27 +54,18 @@ function maketopmap(divname, xml, sshcallback, writeable) ...@@ -57,27 +54,18 @@ function maketopmap(divname, xml, sshcallback, writeable)
source: 'rspec', source: 'rspec',
multiSite: true, multiSite: true,
root: divname, root: divname,
nodeSelect: writeable, nodeSelect: showinfo,
readyCallback: function (input, output) { readyCallback: function (input, output) {
jacksInput = input; jacksInput = input;
jacksOutput = output; jacksOutput = output;
jacksInput.trigger('change-topology', jacksInput.trigger('change-topology',
[{ rspec: xml }]); [{ rspec: xml }]);
if (sshcallback)
{
jacksOutput.on('click-event', function (event) {
if (event.type === 'node')
{
sshcallback(event.ssh, event.client_id);
}
});
}
}, },
show: { show: {
rspec: false, rspec: false,
tour: false, tour: false,
version: false, version: false,
selectInfo: writeable, selectInfo: showinfo,
menu: false menu: false
}, },
canvasOptions: { canvasOptions: {
......
...@@ -90,7 +90,7 @@ function (_, sup, moment, ppstart, ...@@ -90,7 +90,7 @@ function (_, sup, moment, ppstart,
}); });
$('#quickvm_topomodal').on('shown.bs.modal', function() { $('#quickvm_topomodal').on('shown.bs.modal', function() {
sup.maketopmap("#showtopo_nopicker", sup.maketopmap("#showtopo_nopicker",
$('#profile_rspec_textarea').val(), null, true); $('#profile_rspec_textarea').val(), true);
}); });
// The Show Source button. // The Show Source button.
......
...@@ -1478,13 +1478,14 @@ function (_, sup, moment, marked, UriTemplate, ShowImagingModal, ...@@ -1478,13 +1478,14 @@ function (_, sup, moment, marked, UriTemplate, ShowImagingModal,
var manifests = _.values(manifest_object); var manifests = _.values(manifest_object);
var first_manifest = _.first(manifests); var first_manifest = _.first(manifests);
var rest = _.rest(manifests); var rest = _.rest(manifests);
var multisite = rest.length ? true : false;
if (! jacksInstance) if (! jacksInstance)
{ {
jacksInstance = new window.Jacks({ jacksInstance = new window.Jacks({
mode: 'viewer', mode: 'viewer',
source: 'rspec', source: 'rspec',
multiSite: true, multiSite: multisite,
root: divname, root: divname,
nodeSelect: false, nodeSelect: false,
readyCallback: function (input, output) { readyCallback: function (input, output) {
......
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