All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

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

Checkpoint multisite topology code. Work in progress.

parent 9f49096b
This diff is collapsed.
......@@ -781,85 +781,12 @@ sub UpdateDiskImage($$@)
return 0;
}
#
# We need to convert from using URNs to using URLs for disk images,
# since we want to support choosing the backend. This list is the
# list as of the conversion, at the APT. Before we instantiate, look
# at the rspec and update the URNs to URLs based on this list.
#
my %APTImages = (
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:demo-profile' => 'https://www.apt.emulab.net/image_metadata.php?uuid=39383c39-7b2f-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:docker' => 'https://www.apt.emulab.net/image_metadata.php?uuid=5ae53ff8-7b2f-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:docker-running-env' => 'https://www.apt.emulab.net/image_metadata.php?uuid=a1317423-7b2f-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:docker-running-env-02' => 'https://www.apt.emulab.net/image_metadata.php?uuid=f30e8657-7b2f-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:Docker1' => 'https://www.apt.emulab.net/image_metadata.php?uuid=31d9f5c1-7b30-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:ESA' => 'https://www.apt.emulab.net/image_metadata.php?uuid=72d94622-7b35-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:firstclone' => 'https://www.apt.emulab.net/image_metadata.php?uuid=d49e30a8-7b31-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:FPTaylorVM' => 'https://www.apt.emulab.net/image_metadata.php?uuid=f2e99dbe-7b31-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:FrequentDirection' => 'https://www.apt.emulab.net/image_metadata.php?uuid=1c6b4e98-7b32-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:geni-lib' => 'https://www.apt.emulab.net/image_metadata.php?uuid=441fc279-7b32-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:gimiovsomf6' => 'https://www.apt.emulab.net/image_metadata.php?uuid=626184be-7b32-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:hadoop' => 'https://www.apt.emulab.net/image_metadata.php?uuid=ffa8f859-3524-11e4-8944-81966d62745f',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:hg' => 'https://www.apt.emulab.net/image_metadata.php?uuid=91dcd7d5-7b32-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:imageusage' => 'https://www.apt.emulab.net/image_metadata.php?uuid=adc61bad-7b32-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:Iperf' => 'https://www.apt.emulab.net/image_metadata.php?uuid=d0c8aba4-7b32-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:labwikiXORP' => 'https://www.apt.emulab.net/image_metadata.php?uuid=eee5f68d-7b32-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:myapt' => 'https://www.apt.emulab.net/image_metadata.php?uuid=13baa069-7b33-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:myclone' => 'https://www.apt.emulab.net/image_metadata.php?uuid=301d4978-7b33-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:myimage' => 'https://www.apt.emulab.net/image_metadata.php?uuid=03a342be-7b2c-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:myvm' => 'https://www.apt.emulab.net/image_metadata.php?uuid=6334cf1c-7a59-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:myvm2' => 'https://www.apt.emulab.net/image_metadata.php?uuid=aa8b3638-7a79-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:ricci-cav-2014' => 'https://www.apt.emulab.net/image_metadata.php?uuid=b3d6f6f7-7b35-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:rob-profile' => 'https://www.apt.emulab.net/image_metadata.php?uuid=31278fc7-7b34-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:robtestimage' => 'https://www.apt.emulab.net/image_metadata.php?uuid=4d43d6bb-7b34-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:singlenodelime' => 'https://www.apt.emulab.net/image_metadata.php?uuid=60905cf9-7b34-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:singlenodelime-2' => 'https://www.apt.emulab.net/image_metadata.php?uuid=8db24268-7b34-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:singlevmlime' => 'https://www.apt.emulab.net/image_metadata.php?uuid=b192a572-7b34-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:smack-cav2014-test' => 'https://www.apt.emulab.net/image_metadata.php?uuid=a4594b69-7b36-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:ubuntu1204maas' => 'https://www.apt.emulab.net/image_metadata.php?uuid=e532f26d-7b36-11e4-9439-db9edc46fe2c',
'urn:publicid:IDN+utahddc.geniracks.net+image+emulab-net:Ubuntu1404' => 'https://www.apt.emulab.net/image_metadata.php?uuid=0838c611-7b37-11e4-9439-db9edc46fe2c'
);
sub ConvertDiskImages($)
{
my ($self) = @_;
my $modified = 0;
my $rspec = GeniXML::Parse($self->rspec());
if (! defined($rspec)) {
print STDERR "Could not parse rspec\n";
return -1;
}
foreach my $ref (GeniXML::FindNodes("n:node", $rspec)->get_nodelist()) {
my $diskref = GeniXML::GetDiskImage($ref);
next
if (!defined($diskref));
my $imageurn = GeniXML::GetText("name", $diskref);
next
if (!defined($imageurn));
if (exists($APTImages{$imageurn})) {
GeniXML::SetDiskImage($ref, $APTImages{$imageurn});
$modified = 1;
}
}
if ($modified) {
$self->{'DBROW'}->{'rspec'} = GeniXML::Serialize($rspec);
my $profileid = $self->profileid();
my $version = $self->version();
my $safe_rspec = DBQuoteSpecial($self->rspec());
DBQueryWarn("update apt_profile_versions set rspec=$safe_rspec ".
"where profileid='$profileid' and version='$version'")
if (1);
}
return 0;
}
# Total nonsense, to be thrown away.
sub CheckNodeConstraints($$$)
{
my ($self, $iscloudlab, $pmsg) = @_;
my ($self, $default_aggregate_urn, $pmsg) = @_;
my $cloudwww = "www.utah.cloudlab.us";
my $cloudurn = "urn:publicid:IDN+utah.cloudlab.us+authority+cm";
require URI;
my $rspec = GeniXML::Parse($self->rspec());
......@@ -870,6 +797,11 @@ sub CheckNodeConstraints($$$)
foreach my $ref (GeniXML::FindNodes("n:node", $rspec)->get_nodelist()) {
my $client_id = GetVirtualId($ref);
my $virtualization_type = GeniXML::GetVirtualizationSubtype($ref);
my $manager_urn = GetManagerId($ref);
if (! defined($manager_urn)) {
$manager_urn = $default_aggregate_urn;
}
my $iscloudlab = ($manager_urn eq $cloudurn ? 1 : 0);
if (defined($virtualization_type) && $iscloudlab &&
$virtualization_type eq "emulab-xen") {
......@@ -1012,6 +944,38 @@ sub CheckDatasets($$$)
return 0;
}
#
# Set the component_manager_urn for the sites.
#
sub SetSites($$$)
{
my ($prspecstr, $sitemap, $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()) {
my $client_id = GetVirtualId($ref);
my $site_id = GeniXML::GetJacksSiteId($ref);
if (!defined($site_id)) {
$$perrmsg = "No site ID for $client_id";
return -1;
}
my $site_mid = "site:" . $site_id;
if (!exists($sitemap->{$site_mid})) {
$$perrmsg = "No site mapping for $client_id ($site_id)";
return -1;
}
GeniXML::SetManagerId($ref, $sitemap->{$site_mid});
GeniXML::SetJacksSiteManagerId($ref, $sitemap->{$site_mid});
}
$$prspecstr = GeniXML::Serialize($rspec);
return 0;
}
sub IsHead($)
{
my ($self) = @_;
......
This diff is collapsed.
......@@ -167,7 +167,7 @@ sub DoCreate()
my $read_access;
my $write_access;
# imdataset snapshot info.
my ($instance,$nodeid,$bsname);
my ($instance,$aggregate,$nodeid,$bsname);
my $optlist = "ds:t:e:f:w:p:R:W:I:i:";
my %options = ();
......@@ -196,13 +196,15 @@ sub DoCreate()
if (!defined($instance)) {
fatal("Instance does not exist!");
}
$aggregate_urn = $instance->aggregate_urn();
($nodeid,$bsname) = split(",", $options{"I"});
if (! (defined($nodeid) && defined($bsname))) {
print STDERR "Improper -I opton for imdatasets\n";
&$usage();
}
$aggregate = $instance->FindAggregateByNodeId($nodeid);
if (!defined($aggregate)) {
fatal("Could not find aggregate for $nodeid");
}
}
if (defined($options{"f"})) {
$fstype = $options{"f"};
......@@ -696,7 +698,7 @@ sub DoSnapShotInternal($$$$$)
goto failed;
}
my $response = $instance->CreateImage($sliver_urn,
$dataset->dataset_id(), $bsname);
$dataset->dataset_id(), 0, $bsname);
if ($response->code() != GENIRESPONSE_SUCCESS) {
$errmsg = "SnapshotDataset failed: ". $response->output() . "\n";
goto failed;
......
This diff is collapsed.
......@@ -68,9 +68,15 @@ class Instance
$this->instance = null;
return;
}
$this->instance = mysql_fetch_array($query_result);
$this->instance = mysql_fetch_array($query_result);
$this->slivers = InstanceSliver::LookupForInstance($this);
if (!count($this->slivers) && $this->aggregate_urn()) {
$this->slivers =
array(InstanceSliver::Lookup($this, $this->aggregate_urn()));
}
}
# accessors
function slivers() { return $this->slivers; }
function field($name) {
return (is_null($this->instance) ? -1 : $this->instance[$name]);
}
......@@ -431,4 +437,85 @@ class Instance
}
}
}
class InstanceSliver
{
var $sliver;
#
# Constructor by lookup on unique index.
#
function InstanceSliver($instance, $urn) {
$uuid = $instance->uuid();
$query_result =
DBQueryWarn("select * from apt_instance_aggregates ".
"where uuid='$uuid' and aggregate_urn='$urn'");
if (!$query_result || !mysql_num_rows($query_result)) {
$this->sliver = null;
return;
}
$this->sliver = mysql_fetch_array($query_result);
}
# accessors
function field($name) {
return (is_null($this->sliver) ? -1 : $this->sliver[$name]);
}
function uuid() { return $this->field('uuid'); }
function name() { return $this->field('name'); }
function aggregate_urn(){ return $this->field('aggregate_urn'); }
function status() { return $this->field('status'); }
function public_url() { return $this->field('public_url'); }
function webtask_id() { return $this->field('webtask_id'); }
function manifest() { return $this->field('manifest'); }
# Hmm, how does one cause an error in a php constructor?
function IsValid() {
return !is_null($this->sliver);
}
function Lookup($instance, $urn) {
$foo = new InstanceSliver($instance, $urn);
if ($foo->IsValid()) {
return $foo;
}
#
# Backwards compat for a while, create a fake one.
#
$webtask = WebTask::LookupByObject($instance->uuid());
$foo->sliver = array(
"uuid" => $instance->uuid(),
"name" => $instance->name(),
"aggregate_urn" => $instance->aggregate_urn(),
"status" => $instance->status(),
"public_url" => $instance->public_url(),
"manifest" => $instance->manifest(),
"webtask_id" => $webtask->task_id(),
);
return $foo;
}
#
# Lookup all slivers for an instance
#
function LookupForInstance($instance) {
$result = array();
$uuid = $instance->uuid();
$query_result =
DBQueryFatal("select aggregate_urn from apt_instance_aggregates ".
"where uuid='$uuid'");
while ($row = mysql_fetch_array($query_result)) {
$sliver = InstanceSliver::Lookup($instance, $row['aggregate_urn']);
if ($sliver) {
$result[] = $sliver;
}
}
return $result;
}
}
?>
......@@ -561,8 +561,8 @@ function SPITFORM($formfields, $newuser, $errors)
$am_options .=
"<option $selected value='$am'>$am</option>\n";
}
$html =
"<div class='form-horizontal' id='aggregate_selector'>
$html = "<div id='aggregate_selector'>
<div class='form-horizontal' id='nosite_selector'>
<div class='form-group'>
<label class='col-sm-4 control-label'
style='text-align: right;'>
......@@ -572,8 +572,9 @@ function SPITFORM($formfields, $newuser, $errors)
id='profile_where' class='form-control'>
$am_options</select><br>
<div class='alert alert-warning' id='where-warning' style='display: none'>This profile only works on some clusters. Incompatible clusters are unselectable.</div>
</div></div><div>\n";
echo $html;
</div></div></div>";
$html = $html . "<div id='site_selector' class='hidden'></div></div>";
echo $html;
}
echo "</fieldset>
<div class='form-group row'>
......@@ -819,18 +820,29 @@ if ($profile && $profile->isParameterized() &&
# Allow admin users to select the Aggregate. Experimental.
#
$aggregate_urn = "";
$sitemap = array();
if ($this_user && ($ISCLOUD || ISADMIN() || STUDLY())) {
if (isset($formfields["where"]) && $formfields["where"] != "") {
if (array_key_exists($formfields["where"], $am_array)) {
if (isset($formfields["sites"]) && is_array($formfields["sites"])) {
while (list($siteid, $am) = each($formfields["sites"])) {
if (array_key_exists($am, $am_array)) {
$sitemap[$siteid] = $am_array[$am];
}
else {
$errors["sites"] = "Invalid Aggregate";
break;
}
}
}
elseif (isset($formfields["where"]) &&
$formfields["where"] != "" &&
array_key_exists($formfields["where"], $am_array)) {
$aggregate_urn = $am_array[$formfields["where"]];
}
else {
$errors["where"] = "Invalid Aggregate";
}
}
else {
$errors["where"] = "Invalid Aggregate";
}
}
if (count($errors)) {
SPITFORM($formfields, false, $errors);
SPITFOOTER();
......@@ -929,7 +941,16 @@ if (!$this_user &&
}
# Admins can change aggregate.
$options = ($aggregate_urn != "" ? " -a '$aggregate_urn'" : "");
$options = "";
if ($aggregate_urn != "") {
$options = " -a '$aggregate_urn'";
}
elseif (count($sitemap)) {
while (list($siteid, $urn) = each($sitemap)) {
$options .= "--site 'site:${siteid}=${urn}' ";
}
}
#
# Invoke the backend.
......
......@@ -101,6 +101,7 @@ function (_, editModalString)
mode: this.mode,
source: 'rspec',
root: '#edit_nopicker',
multiSite: true,
nodeSelect: true,
readyCallback: _.bind(this.jacksReady, this),
show: {
......
......@@ -17,6 +17,7 @@ function (_, Constraints, sup, ppstart, aboutaptString, aboutcloudString, waitwa
var webonly = 0;
var portal = null;
var registered = false;
var JACKS_NS = "http://www.protogeni.net/resources/rspec/ext/jacks/1";
var jacks = {
instance: null,
input: null,
......@@ -217,6 +218,8 @@ function (_, Constraints, sup, ppstart, aboutaptString, aboutcloudString, waitwa
$('#instantiate_submit').attr('disabled', false);
}
CreateAggregateSelectors(rspec);
// Hide the aggregate picker for a parameterized profile.
// Shown later.
if (ispprofile) {
......@@ -305,6 +308,73 @@ function (_, Constraints, sup, ppstart, aboutaptString, aboutcloudString, waitwa
}
}
/*
* Build up a list of Aggregate selectors. Normally just one, but for
* a multisite aggregate, need more then one.
*/
function CreateAggregateSelectors(rspec)
{
var xmlDoc = $.parseXML(rspec);
var xml = $(xmlDoc);
var sites = {};
var html = "";
/*
* Find the sites. Might not be any if not a multisite topology
*/
$(xml).find("node").each(function() {
var node_id = $(this).attr("client_id");
var site = this.getElementsByTagNameNS(JACKS_NS, 'site');
if (! site.length) {
return;
}
var siteid = $(site).attr("id");
if (siteid === undefined) {
console.log("No site ID in " + site);
return;
}
sites[siteid] = siteid;
});
if (Object.keys(sites) == 0) {
$("#site_selector").addClass("hidden");
$("#nosite_selector").removeClass("hidden");
// Clear the form data.
$("#site_selector").html("");
return;
}
// Create the dropdown selection list. First the options which
// are duplicated in each dropdown.
var options = "";
_.each(amlist, function(name) {
options = options +
"<option value='" + name + "'>" + name + "</option>";
});
for (var siteid in sites) {
html = html +
"<div class='form-horizontal'>" +
" <div class='form-group'>" +
" <label class='col-sm-4 control-label' " +
" style='text-align: right;'>"+
" <a href=cluster-status.php " +
" target=_blank>Site " + siteid + " Cluster:</a>" +
" </label> " +
" <div class='col-sm-6'>" +
" <select name=\"formfields[sites][" + siteid + "]\"" +
" class='form-control'>" + options +
" </select>" +
"</div></div><div>";
}
html = html + "<br>";
console.info(html);
$("#nosite_selector").addClass("hidden");
$("#site_selector").removeClass("hidden");
$("#site_selector").html(html);
}
var constraints;
function contextReady(data)
......
......@@ -55,6 +55,7 @@ function maketopmap(divname, xml, sshcallback, writeable)
jacksInstance = new window.Jacks({
mode: 'viewer',
source: 'rspec',
multiSite: true,
root: divname,
nodeSelect: writeable,
readyCallback: function (input, output) {
......
This diff is collapsed.
......@@ -94,30 +94,35 @@ function Do_GetInstanceStatus()
}
$blob = array();
$blob["status"] = $instance->status();
# Indicate that we have a manifest and so we can view it.
$blob["havemanifest"] = ($instance->manifest() ? 1 : 0);
# Provide PublicURL so that we can show the sliver info button
if ($instance->public_url()) {
$blob["publicURL"] = $instance->public_url();
}
$blob["sliverstatus"] = array();
$blob["sliverurls"] = array();
$webtask = WebTask::LookupByObject($instance->uuid());
if ($webtask) {
if ($webtask->exited()) {
# Reflect errors back to the user.
if ($webtask->exitcode() == 26) {
$blob["reason"] = "Not enough free nodes, ".
"please try again later.";
}
else {
$blob["reason"] = htmlentities($webtask->TaskValue("output"));
#
# If we have all of our manifests, the client can request them
# and show the topology.
#
$havemanifests = 1;
foreach ($instance->slivers() as $sliver) {
if (!$sliver->manifest()) {
$havemanifests = 0;
}
else {
$webtask = WebTask::Lookup($sliver->webtask_id());
if ($webtask) {
$sliverstatus = $webtask->TaskValue("sliverstatus");
if ($sliverstatus) {
$blob["sliverstatus"][$sliver->aggregate_urn()] =
$sliverstatus;
}
}
}
$sliverstatus = $webtask->TaskValue("sliverstatus");
if ($sliverstatus) {
$blob["sliverstatus"] = $sliverstatus;
if ($sliver->public_url()) {
$blob["sliverurls"][$sliver->aggregate_urn()] =
$sliver->public_url();
}
}
$blob["havemanifests"] = $havemanifests;
SPITAJAX_RESPONSE($blob);
}
......@@ -167,24 +172,14 @@ function Do_TerminateInstance()
}
# This needs work.
$retval = SUEXEC("nobody", "nobody",
"webmanage_instance -t $webtask_id -- terminate $uuid",
"webmanage_instance terminate $uuid",
SUEXEC_ACTION_CONTINUE);
$webtask = WebTask::Lookup($webtask_id);
if ($retval == 0) {
SPITAJAX_RESPONSE("");
if ($webtask) {
$webtask->Delete();
}
return;
}
if ($webtask && $webtask->exited()) {
SPITAJAX_ERROR(1, $webtask->TaskValue("output"));
$webtask->Delete();
}
else {
SPITAJAX_ERROR(-1, "Internal Error. Please try again later");
}
SPITAJAX_ERROR(-1, "Unable to Terminate; please try again later");
}
#
......@@ -198,7 +193,14 @@ function Do_GetInstanceManifest()
return;
}
SPITAJAX_RESPONSE($instance->manifest());
$blob = array();
foreach ($instance->slivers() as $sliver) {
if ($sliver->manifest()) {
$blob[$sliver->aggregate_urn()] = $sliver->manifest();
}
}
SPITAJAX_RESPONSE($blob);
}
#
......@@ -747,12 +749,7 @@ function Do_Refresh()
}
return;
}
$blob = array();
if ($webtask) {
$blob = $webtask->TaskValue("sliverstatus");
$webtask->Delete();
}
SPITAJAX_RESPONSE($blob);
SPITAJAX_RESPONSE("Success");
}
#
......
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