Commit 5419a717 authored by Leigh B Stoller's avatar Leigh B Stoller

Two changes:

1. Add a Reload icon on the Graphs tab, to reload the cluster data and
   redraw the graphs.

2. Implement a Reload Topology function, with button on status page, to
   sync the portal topology with the clusters current manifests. Currently
   available to studly users only. This closes ticket #92.
parent 4acebde8
......@@ -58,6 +58,7 @@ sub usage()
print("Usage: manage_instance schedterminate instance [-m message] days [filename]\n");
print("Usage: manage_instance idledata instance\n");
print("Usage: manage_instance openstackstats instance\n");
print("Usage: manage_instance getmanifests instance\n");
exit(-1);
}
my $optlist = "dt:s";
......@@ -2191,16 +2192,53 @@ sub DoManifests()
goto killit;
}
#
# Lock the slice in case it is doing something else, like taking
# a disk image.
#
if ($slice->Lock()) {
$errmsg = "Experiment is busy, cannot lock it. Please try again later";
goto bad;
}
#
# Create the webtask object, but AFTER locking the slice so we do
# not destroy one in use.
#
if (defined($webtask_id)) {
$webtask = WebTask->LookupOrCreate($instance->uuid(), $webtask_id);
# Convenient.
$webtask->AutoStore(1);
}
my $coderef = sub {
my ($sliver) = @_;
my $webtask = $sliver->webtask();
my $errmsg;
my $response = $sliver->GetManifest();
if (!defined($response)) {
my $manifest = $sliver->GetManifest();
if (!defined($manifest)) {
$errmsg = "RPC Error calling GetManifest";
goto bad;
}
my $response = $sliver->SliceStatus();
if (!defined($response)) {
$errmsg = "RPC Error calling SliceStatus";
goto bad;
}
if ($response->code() != GENIRESPONSE_SUCCESS) {
if ($response->code() == GENIRESPONSE_SEARCHFAILED) {
$errmsg = "Slice is gone";
goto bad;
}
if ($response->code() == GENIRESPONSE_BUSY) {
$errmsg = "Slice is busy; try again later";
goto bad;
}
$errmsg = "Could not get slice status: ". $response->output();
goto bad;
}
$sliver->SetManifest($manifest);
$sliver->UpdateWebStatus($response->value()->{'details'});
return 0;
bad:
return 1;
......@@ -2227,9 +2265,16 @@ sub DoManifests()
goto bad;
}
}
$instance->ComputeNodeCounts();
$slice->UnLock();
exit(0);
bad:
$slice->UnLock();
print STDERR $errmsg . "\n";
if (defined($webtask)) {
$webtask->output($errmsg);
$webtask->Exited(1);
}
exit(1);
}
......
......@@ -258,6 +258,7 @@ function (_, sup, moment, ShowIdleGraphs,
function LoadIdleData()
{
ShowIdleGraphs({"uuid" : window.UUID,
"showwait" : false,
"loadID" : "#loadavg-panel-div",
"ctrlID" : "#ctrl-traffic-panel-div",
"exptID" : "#expt-traffic-panel-div"});
......
......@@ -10,7 +10,9 @@ define(['underscore', 'js/quickvm_sup', 'moment'],
var loadID = null;
var ctrlID = null;
var exptID = null;
var refreshID = null;
var C_callback = null;
var showWait = false;
/*
* Process data for one type (loadav, ctrl, expt) and return it.
......@@ -262,6 +264,9 @@ define(['underscore', 'js/quickvm_sup', 'moment'],
if (C_callback) {
C_callback(load.length + ctrl.length + expt.length);
}
if (showWait) {
sup.HideWaitWait();
}
if (load.length) {
CreateOneGraph(loadID, load,
......@@ -323,6 +328,9 @@ define(['underscore', 'js/quickvm_sup', 'moment'],
});
}
};
if (showWait) {
sup.ShowWaitWait("We are gathering data from the cluster(s)");
}
var xmlthing = sup.CallServerMethod(null, "status", "IdleData",
{"uuid" : uuid});
xmlthing.done(callback);
......@@ -432,6 +440,17 @@ define(['underscore', 'js/quickvm_sup', 'moment'],
ctrlID = args.ctrlID;
exptID = args.exptID;
C_callback = args.callback;
showWait = args.showwait;
if (_.has(args, "refreshID")) {
refreshID = args.refreshID;
$(refreshID).removeClass("hidden");
$(refreshID).click(function () {
d3.selectAll("svg > *").remove();
$('.toggles').addClass("hidden");
LoadIdleData();
});
}
LoadIdleData();
}
}
......
......@@ -28,6 +28,7 @@ function (_, sup, moment, marked, UriTemplate, ShowImagingModal,
var isadmin = 0;
var isfadmin = 0;
var isguest = 0;
var isstud = 0;
var ispprofile = 0;
var dossh = 1;
var profile_uuid= null;
......@@ -59,6 +60,7 @@ function (_, sup, moment, marked, UriTemplate, ShowImagingModal,
oneonly = window.APT_OPTIONS.oneonly;
isadmin = window.APT_OPTIONS.isadmin;
isfadmin= window.APT_OPTIONS.isfadmin;
isstud = window.APT_OPTIONS.isstud;
isguest = (window.APT_OPTIONS.registered ? false : true);
dossh = window.APT_OPTIONS.dossh;
extend = window.APT_OPTIONS.extend || null;
......@@ -92,6 +94,7 @@ function (_, sup, moment, marked, UriTemplate, ShowImagingModal,
registered: window.APT_OPTIONS.registered,
isadmin: window.APT_OPTIONS.isadmin,
isfadmin: window.APT_OPTIONS.isfadmin,
isstud: window.APT_OPTIONS.isstud,
extensions: extensions,
errorURL: errorURL,
paniced: paniced,
......@@ -187,6 +190,11 @@ function (_, sup, moment, marked, UriTemplate, ShowImagingModal,
window.location.replace('manage_profile.php?action=clone' +
'&snapuuid=' + uuid);
});
// Handler for the reload topology button
$('button#reload-topology-button').click(function (event) {
event.preventDefault();
DoReloadTopology();
});
//
// Attach a hover popover to explain what Clone means. We need
......@@ -490,6 +498,7 @@ function (_, sup, moment, marked, UriTemplate, ShowImagingModal,
DisableButtons();
EnableButton("terminate");
EnableButton("refresh");
EnableButton("reloadtopo");
}
else if (instanceStatus == 'imaging') {
bgtype = "panel-warning";
......@@ -512,6 +521,7 @@ function (_, sup, moment, marked, UriTemplate, ShowImagingModal,
DisableButtons();
EnableButton("terminate");
EnableButton("refresh");
EnableButton("reloadtopo");
}
else if (instanceStatus == 'terminating' ||
instanceStatus == 'terminated') {
......@@ -563,6 +573,7 @@ function (_, sup, moment, marked, UriTemplate, ShowImagingModal,
{
EnableButton("terminate");
EnableButton("refresh");
EnableButton("reloadtopo");
EnableButton("extend");
EnableButton("clone");
EnableButton("snapshot");
......@@ -572,6 +583,7 @@ function (_, sup, moment, marked, UriTemplate, ShowImagingModal,
{
DisableButton("terminate");
DisableButton("refresh");
DisableButton("reloadtopo");
DisableButton("extend");
DisableButton("clone");
DisableButton("snapshot");
......@@ -593,6 +605,8 @@ function (_, sup, moment, marked, UriTemplate, ShowImagingModal,
button = "#extend_button";
else if (button == "refresh")
button = "#refresh_button";
else if (button == "reloadtopo")
button = "#reload-topology-button";
else if (button == "clone" && nodecount == 1)
button = "#clone_button";
else if (button == "snapshot" && nodecount == 1)
......@@ -830,6 +844,38 @@ function (_, sup, moment, marked, UriTemplate, ShowImagingModal,
xmlthing.done(callback);
}
//
// Request a reload of the manifests (and thus the topology) from the
// backend clusters.
//
function DoReloadTopology()
{
var callback = function(json) {
//console.info(json);
EnableButtons();
if (json.code) {
statusHold = 0;
sup.HideModal('#waitwait-modal');
sup.SpitOops("oops", "Failed to reload topo: " + json.value);
return;
}
changingtopo = true;
statusHold = 0;
// Trigger status update.
GetStatus();
sup.HideModal('#waitwait-modal');
}
statusHold = 1;
DisableButtons();
sup.ShowModal('#waitwait-modal');
var xmlthing = sup.CallServerMethod(ajaxurl,
"status",
"ReloadTopology",
{"uuid" : uuid});
xmlthing.done(callback);
}
var svgimg = document.createElementNS('http://www.w3.org/2000/svg','image');
svgimg.setAttributeNS(null,'class','node-status-icon');
svgimg.setAttributeNS(null,'height','15');
......@@ -2611,16 +2657,16 @@ function (_, sup, moment, marked, UriTemplate, ShowImagingModal,
* and to hide the waiting modal.
*/
var callback = function (gotdata) {
sup.HideWaitWait();
if (!gotdata) {
$('#Idlegraphs #nodata').removeClass("hidden");
}
};
sup.ShowWaitWait("We are gathering data from the cluster(s)");
ShowIdleGraphs({"uuid" : uuid,
"showwait" : true,
"loadID" : "#loadavg-panel-div",
"ctrlID" : "#ctrl-traffic-panel-div",
"exptID" : "#expt-traffic-panel-div",
"refreshID": "#graphs-refresh-button",
"callback" : callback});
}
......
......@@ -146,6 +146,8 @@ $routing = array("myprofiles" =>
"Do_Reload",
"Refresh" =>
"Do_Refresh",
"ReloadTopology" =>
"Do_ReloadTopology",
"DecryptBlocks" =>
"Do_DecryptBlocks",
"Lockout" =>
......
......@@ -1095,6 +1095,51 @@ function Do_Refresh()
SPITAJAX_RESPONSE("Success");
}
#
# Reload rhe manifests.
#
function Do_ReloadTopology()
{
global $this_user, $instance, $suexec_output;
global $ajax_args;
if (StatusSetupAjax(1)) {
return;
}
$this_idx = $this_user->uid_idx();
$uuid = $ajax_args["uuid"];
#
# Call out to the backend.
#
$webtask_id = WebTask::GenerateID();
$retval = SUEXEC("nobody", "nobody",
"webmanage_instance -t $webtask_id -- getmanifests $uuid",
SUEXEC_ACTION_IGNORE);
$webtask = WebTask::Lookup($webtask_id);
if ($retval != 0) {
if ($retval < 0) {
SPITAJAX_ERROR(-11, "Internal error, cannot proceed.");
# Notify tbops.
SUEXECERROR(SUEXEC_ACTION_CONTINUE);
}
elseif ($webtask) {
SPITAJAX_ERROR(1, $webtask->TaskValue("output"));
}
elseif ($suexec_output != "") {
SPITAJAX_ERROR(1, $suexec_output);
}
else {
SPITAJAX_ERROR(-1, "Internal Error. Please try again later");
}
if ($webtask) {
$webtask->Delete();
}
return;
}
SPITAJAX_RESPONSE("Success");
}
#
# Ask the backend to reboot or reload a node.
#
......
......@@ -184,6 +184,7 @@ $isopenstack = $instance->isopenstack();
$paniced = $instance->paniced();
$project = $instance->pid();
$extensions = ExtensionInfo::LookupForInstance($instance);
$isstud = (isset($this_user) && $this_user->stud() ? 1 : 0);
#
# We give ssh to the creator (real user or guest user).
......@@ -240,6 +241,7 @@ else {
echo " window.APT_OPTIONS.registered = $registered;\n";
echo " window.APT_OPTIONS.isadmin = $isadmin;\n";
echo " window.APT_OPTIONS.isfadmin = $isfadmin;\n";
echo " window.APT_OPTIONS.isstud = $isstud;\n";
echo " window.APT_OPTIONS.cansnap = $cansnap;\n";
echo " window.APT_OPTIONS.canclone = $canclone;\n";
echo " window.APT_OPTIONS.snapping = $snapping;\n";
......
......@@ -196,7 +196,7 @@ pre {
href='manage_profile.php?action=copy&uuid=<%= profileUUID %>'
id='copy_button' type=button
data-toggle='popover'
data-delay='{"hide":1500, "show":500}'
data-delay='{"hide":1500, "show":500}'
data-html='true'
data-content="When you <em>copy</em> (instead of
clone), you are creating a new profile that
......@@ -293,7 +293,12 @@ pre {
</li>
<li class="hidden" id="show_idlegraphs_li">
<a href='#Idlegraphs' id='show_idlegraphs_tab'
data-toggle='tab'>Graphs</a>
data-toggle='tab'>Graphs
<button class='close hidden'
style="margin-top:0px;"
type='button' id="graphs-refresh-button">
<span class='glyphicon glyphicon-repeat'></span></button>
</a>
</li>
</ul>
<div id='quicktabs_content' class='tab-content'>
......@@ -305,17 +310,33 @@ pre {
<button class='btn btn-xs btn-success pull-right' disabled
id='refresh_button' type=button
data-toggle='popover'
data-delay='{"hide":1000, "show":500}'
data-content='Ask cluster for updated node status'>
Refresh Status</button>
<span>
<button class='btn btn-xs btn-success pull-right hidden' disabled
<button class='btn btn-xs btn-success pull-right hidden'
disabled
data-toggle='popover'
data-delay='{"hide":1000, "show":500}'
data-content='Run linktest on the topology'
style='margin-right: 10px;'
id='linktest-modal-button' type=button>
Run Linktest</button>
</span>
<% } %>
<% if (isadmin || isstud || isfadmin) { %>
<span>
<button class='btn btn-xs btn-success pull-right'
disabled
data-toggle='popover'
data-delay='{"hide":1000, "show":500}'
data-content='Reload the topology in case it has
changed at the cluster'
style='margin-right: 10px;'
id='reload-topology-button' type=button>
Reload Topo</button>
</span>
<% } %>
<% } %>
</div>
<div class='tab-pane' id='listview'>
<div id='showtopo_listview'>
......
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