Commit e6c63392 authored by Leigh Stoller's avatar Leigh Stoller

Merge branch 'mymaster'

parents 3b2d3d69 8d546de8
......@@ -177,7 +177,7 @@ sub GetCredential($)
return GeniResponse->MalformedArgsResponse()
if (! (defined($urn) && GeniHRN::IsValid($urn)));
my $authority = GeniAuthority->Lookup($ENV{'MYURN'});
$authority = GeniAuthority->Lookup($ENV{'MYURN'});
if (!defined($authority)) {
print STDERR "Could not find local authority object\n";
return GeniResponse->Create(GENIRESPONSE_ERROR);
......
......@@ -839,9 +839,9 @@ sub AnnotateManifest($)
}
GeniXML::SetText("name", $host, $vhostname);
}
my $services = GeniXML::FindFirst("n:services", $rspec);
if ($experiment->HasNonLocalUsers()) {
my $services = GeniXML::FindFirst("n:services", $rspec);
if (! defined($services)) {
$services = GeniXML::AddElement("services", $rspec);
}
......@@ -861,6 +861,19 @@ sub AnnotateManifest($)
GeniXML::SetText("username", $login, $localuser->{"login"});
}
}
my $tipserver = undef;
if ($node->TipServer(\$tipserver) == 0 && defined($tipserver)) {
if (! defined($services)) {
$services = GeniXML::AddElement("services", $rspec);
}
my $console = GeniXML::FindNodesNS("n:console", $services,
$GeniXML::EMULAB_NS)->pop();
if (defined($console)) {
$services->removeChild($console);
}
$console = GeniXML::AddElement("console",$services,$GeniXML::EMULAB_NS);
GeniXML::SetText("server", $console, $tipserver);
}
if ($self->UpdateRspec($rspec)) {
print STDERR "Could not insert annotated manifest for node $self ".
......
......@@ -640,7 +640,7 @@ function (_, sup, moment, marked, UriTemplate, ShowImagingModal,
// Trigger the custom event.
$("#" + tabname).trigger("killssh");
// remove the li from the ul.
$(this).parent().remove();
$(this).parent().parent().remove();
// Remove the content div.
$("#" + tabname).remove();
// Activate the "profile" tab.
......@@ -733,8 +733,10 @@ function (_, sup, moment, marked, UriTemplate, ShowImagingModal,
$(xml).find("node").each(function() {
var node = $(this).attr("client_id");
var login = $(this).find("login");
var console= $(this).find("rs:console");
var href = "n/a";
var ssh = "n/a";
var cons = "n/a";
if (login.length) {
var user = login.attr("username");
......@@ -764,9 +766,28 @@ function (_, sup, moment, marked, UriTemplate, ShowImagingModal,
NewSSHTab(hostport, node);
});
}
//
// Now a button to the console.
//
if (console.length) {
var cons = "<button class='btn btn-primary btn-sm' " +
" id='" + "consbutton_" + node + "' " +
" type='button'>" +
" <span class='glyphicon glyphicon-cog'><span>" +
" </button>";
// Use this to attach handlers to things that do not
// exist in the dom yet.
$('#listview_table').off('click', '#consbutton_' + node);
$('#listview_table').on('click',
'#consbutton_' + node, function () {
NewConsoleTab(node);
});
}
// and the table row.
$('#listview_table > tbody:last').append(
'<tr><td>' + node + '</td><td>' + ssh + '</td><td>' +
href + '</td></tr>'
href + '</td><td>' + cons + '</td></tr>'
);
nodecount++;
});
......@@ -865,5 +886,104 @@ function (_, sup, moment, marked, UriTemplate, ShowImagingModal,
xmlthing.done(callback);
}
//
// User clicked on a node, so we want to create a tab to hold
// the ssh tab with a panel in it, and then call StartSSH above
// to get things going.
//
function NewConsoleTab(client_id)
{
sup.ShowModal('#waitwait-modal');
var callback = function(json) {
sup.HideModal('#waitwait-modal');
if (json.code) {
sup.SpitOops("oops", "Could not start console: " + json.value);
return;
}
var url = json.value + '&noclose=1';
//
// Need to create the tab before we can create the topo, since
// we need to know the dimensions of the tab.
//
var tabname = client_id + "console_tab";
if (! $("#" + tabname).length) {
// The tab.
var html = "<li><a href='#" + tabname + "' data-toggle='tab'>" +
client_id + "-Cons" +
"<button class='close' type='button' " +
" id='" + tabname + "_kill'>x</button>" +
"</a>" +
"</li>";
// Append to end of tabs
$("#quicktabs_div ul").append(html);
// Install a kill click handler for the X button.
$("#" + tabname + "_kill").click(function(e) {
e.preventDefault();
// remove the li from the ul. this=ul.li.a.button
$(this).parent().parent().remove();
// Activate the "profile" tab.
$('#quicktabs li a:first').tab('show');
// Trigger the custom event.
$("#" + tabname).trigger("killconsole");
// Remove the content div. Have to delay this though.
// See below.
setTimeout(function(){ $("#" + tabname).remove() }, 3000);
});
// The content div.
html = "<div class='tab-pane' id='" + tabname + "'></div>";
$("#quicktabs_content").append(html);
// And make it active
$('#quicktabs a:last').tab('show') // Select last tab
// Now create the console iframe inside the new tab
var iwidth = "100%";
var iheight = 400;
$('#' + tabname).html('<iframe id="' + tabname + '_iframe" ' +
'width=' + iwidth + ' ' +
'height=' + iheight + ' ' +
'src=\'' + url + '\'>');
//
// Setup a custom event handler so we can kill the connection.
// Called from the kill click handler above.
//
// Post a kill message to the iframe. See nodetipacl.php3.
// Since postmessage is async, we have to wait before we
// can actually kill the content div with the iframe, cause
// its gone before the message is delivered. Just delay a
// couple of seconds. Maybe add a reply message later. The
// delay is above.
//
var sendkillmessage = function (event) {
var iframe = $('#' + tabname + '_iframe')[0];
iframe.contentWindow.postMessage("kill!", "*");
};
// This is the handler for the button, which invokes
// the function above.
$('#' + tabname).on("killconsole", sendkillmessage);
}
else {
// Switch back to it.
$('#quicktabs a[href="#' + tabname + '"]').tab('show');
return;
}
}
var xmlthing = sup.CallServerMethod(ajaxurl,
"status",
"ConsoleURL",
{"uuid" : uuid,
"node" : client_id});
xmlthing.done(callback);
}
$(document).ready(initialize);
});
......@@ -206,6 +206,49 @@ function Do_RequestExtension()
}
}
#
# Request a console URL and pass back to the status page.
#
function Do_ConsoleURL()
{
global $instance, $creator;
global $suexec_output_array;
global $ajax_args;
if (!isset($ajax_args["node"])) {
SPITAJAX_ERROR(1, "Missing node");
return 1;
}
$node = $ajax_args["node"];
if (StatusSetupAjax()) {
return;
}
$uuid = $instance->uuid();
$slice = GeniSlice::Lookup("sa", $instance->slice_uuid());
if (!slice) {
SPITAJAX_ERROR(1, "no slice for instance");
return 1;
}
$retval = SUEXEC("nobody", "nobody",
"webmanage_instance -c $uuid " . escapeshellarg($node),
SUEXEC_ACTION_CONTINUE);
if ($retval == 0) {
$url = $suexec_output_array[0];
if (preg_match("/^(https:.*)$/", $url, $matches)) {
$url = $matches[1];
}
SPITAJAX_RESPONSE($url);
}
elseif ($retval > 0) {
SPITAJAX_ERROR(1, $suexec_output);
}
else {
SPITAJAX_ERROR(-1, "Internal Error. Please try again later");
}
}
#
# Fire off a snapshot.
#
......
......@@ -146,6 +146,7 @@
<th>SSH command <small>
(if you provided your own key)</small>
</th>
<th>Console</th>
</tr>
</thead>
<tbody>
......
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