Commit 79439d1f authored by Leigh Stoller's avatar Leigh Stoller

Portal version of node admin log.

parent 33fa8086
$(function ()
{
'use strict';
var templates = APT_OPTIONS.fetchTemplateList(['show-nodelog',
'oops-modal',
'waitwait-modal']);
var mainTemplate = _.template(templates['show-nodelog']);
var formfields = null;
function initialize()
{
window.APT_OPTIONS.initialize(sup);
GeneratePageBody();
}
function GeneratePageBody()
{
sup.CallServerMethod(null, "node", "GetLog",
{"node_id" : window.NODE_ID},
function(json) {
console.info("info", json);
if (json.code) {
alert("Could not get node log info " +
"from server: " + json.value);
return;
}
GeneratePageBodyAux(json.value);
});
}
function GeneratePageBodyAux(entries)
{
// Generate the template.
var html = mainTemplate({
entries: entries,
node_id: window.NODE_ID,
isadmin: window.ISADMIN,
});
$('#main-body').html(html);
// All the way to the bottom.
$('body, html').animate({
scrollTop: $('#log-table').height(),
}, 1000);
// Now we can do this.
$('#oops_div').html(templates['oops-modal']);
$('#waitwait_div').html(templates['waitwait-modal']);
// Format dates with moment before display.
$('.format-date').each(function() {
var date = $.trim($(this).html());
if (date != "") {
$(this).html(moment($(this).html()).format("lll"));
}
});
// Bind the new entry button.
$('#new-entry-button').click(function (event) {
event.preventDefault();
NewLogEntry();
});
// This activates the popover subsystem.
$('[data-toggle="popover"]').popover({
trigger: 'hover',
});
// This activates the tooltip subsystem.
$('[data-toggle="tooltip"]').tooltip({
trigger: 'hover',
});
}
// Throw up modal to create a new log entry.
function NewLogEntry()
{
// Bind the confirm button.
$('#save-log-confirm').click(function (event) {
SaveLogEntry();
});
sup.ShowModal('#save-log-modal', function () {
$('#save-log-confirm').off("click");
});
}
function SaveLogEntry()
{
var entry = $.trim($('#log-entry').val());
console.info("SaveLogEntry", entry);
var showError = function (which, error) {
var id = "#save-log-modal ." + which + "-error";
$(id).html(error);
$(id).removeClass("hidden");
};
// Hide errors.
$('#save-log-modal .log-error').addClass("hidden");
// No blank fields please
if (entry == "") {
showError("entry", "Please provide a log entry");
return;
}
var args = {
"node_id" : window.NODE_ID,
"log_entry" : entry,
};
var callback = function (json) {
console.info(json);
if (json.code) {
showError("general", json.value);
return;
}
sup.HideModal('#save-log-modal');
window.location.reload();
};
sup.CallServerMethod(null, "node", "SaveLogEntry", args, callback);
}
$(document).ready(initialize);
});
......@@ -269,6 +269,96 @@ function GetExpInfo($node)
return $blob;
}
#
# Get the log entries for a node.
#
function Do_GetLog()
{
global $this_user, $ajax_args;
if (! (ISADMIN() || OPSGUY())) {
SPITAJAX_ERROR(-1, "Not enough permission");
return -1;
}
if (!isset($ajax_args["node_id"])) {
SPITAJAX_ERROR(-1, "Missing node ID");
return -1;
}
$node_id = $ajax_args["node_id"];
if (!TBvalid_node_id($node_id)) {
SPITAJAX_ERROR(-1, "Invalid node ID");
return -1;
}
$node = Node::Lookup($node_id);
if (!$node) {
SPITAJAX_ERROR(-1, "No such node");
return -1;
}
$results = array();
$query_result =
DBQueryFatal("select * from nodelog where node_id='$node_id'".
"order by reported");
while ($row = mysql_fetch_array($query_result)) {
$blob = array(
"log_id" => $row["log_id"],
"reporter" => $row["reporting_uid"],
"reported" => DateStringGMT($row["reported"]),
"entry" => $row["entry"],
);
$results[] = $blob;
}
SPITAJAX_RESPONSE($results);
}
#
# Save log entry for a node.
#
function Do_SaveLogEntry()
{
global $this_user, $ajax_args, $TBADMINGROUP;
if (! (ISADMIN() || OPSGUY())) {
SPITAJAX_ERROR(-1, "Not enough permission");
return -1;
}
if (!isset($ajax_args["node_id"])) {
SPITAJAX_ERROR(-1, "Missing node ID");
return -1;
}
$node_id = $ajax_args["node_id"];
if (!TBvalid_node_id($node_id)) {
SPITAJAX_ERROR(-1, "Invalid node ID");
return -1;
}
$node = Node::Lookup($node_id);
if (!$node) {
SPITAJAX_ERROR(-1, "No such node");
return -1;
}
if (!isset($ajax_args["log_entry"])) {
SPITAJAX_ERROR(-1, "Missing log entry text");
return -1;
}
$log_entry = $ajax_args["log_entry"];
# Anything allowed, but not too long.
if (! TBvalid_description($log_entry)) {
SPITAJAX_ERROR(-1, "Invalid log entry: " . TBFieldErrorString());
return -1;
}
$log_entry = escapeshellarg($log_entry);
$retval = SUEXEC($this_user->uid(), $TBADMINGROUP,
"webnodelog -m $log_entry $node_id",
SUEXEC_ACTION_CONTINUE);
if ($retval) {
SPITAJAX_ERROR(-1, "Internal error saving new entry");
return;
}
SPITAJAX_RESPONSE(true);
}
# Local Variables:
# mode:php
# End:
......
......@@ -423,7 +423,11 @@ $routing = array("geni-login" =>
"methods" => array("GetInfo" =>
"Do_GetInfo",
"Modify" =>
"Do_Modify")),
"Do_Modify",
"GetLog" =>
"Do_GetLog",
"SaveLogEntry" =>
"Do_SaveLogEntry")),
"vlan" =>
array("file" => "vlan.ajax",
"guest" => false,
......
<?php
#
# Copyright (c) 2000-2019 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 <http://www.gnu.org/licenses/>.
#
# }}}
#
chdir("..");
include("defs.php3");
include("node_defs.php");
chdir("apt");
include("quickvm_sup.php");
# Must be after quickvm_sup.php since it changes the auth domain.
$page_title = "Show Node Log";
#
# Get current user.
#
RedirectSecure();
$this_user = CheckLoginOrRedirect();
$this_idx = $this_user->uid_idx();
$isadmin = (ISADMIN() ? "true" : "false");
#
# Verify page arguments.
#
$reqargs = RequiredPageArguments("node", PAGEARG_NODE);
if (!$node) {
SPITUSERERROR("No such node!");
}
$node_id = $node->node_id();
if (! ($isadmin || OPSGUY())) {
SPITUSERERROR("Not enough permission!");
}
SPITHEADER(1);
# Place to hang the toplevel template.
echo "<div id='main-body'></div>\n";
echo "<script type='text/javascript'>\n";
echo " window.NODE_ID = '$node_id';\n";
echo " window.ISADMIN = $isadmin;\n";
echo "</script>\n";
REQUIRE_UNDERSCORE();
REQUIRE_SUP();
REQUIRE_MOMENT();
SPITREQUIRE("js/show-nodelog.js");
AddTemplateList(array("show-nodelog", "oops-modal", "waitwait-modal"));
SPITFOOTER();
?>
......@@ -77,6 +77,14 @@
title="Console log tail"
type='button'>Console Log</a>
<% } %>
<% if (isadmin && window.ISEMULAB) { %>
<a href="show-nodelog.php?node=<%= fields.node_id %>"
class='btn btn-primary btn-xs pull-right'
style='margin-right: 10px; margin-top: -4px;'
data-toggle='tooltip'
title="Node message log"
type='button'>Admin Log</a>
<% } %>
<h3 class='panel-title'>Node <%- fields.node_id %></h3>
</div>
<div class='panel-body'>
......
<style>
.table-condensed > thead > tr > th,
.table-condensed > tbody > tr > th,
.table-condensed > tfoot > tr > th,
.table-condensed > thead > tr > td,
.table-condensed > tbody > tr > td,
.table-condensed > tfoot > tr > td {
font-size: small;
}
.panel-body > table {
margin-bottom: 0px;
}
</style>
<div class='col-xs-12'>
<div>
<div class='panel panel-default'>
<div class='panel-heading text-center'>
<h3 class='panel-title'>Node Log for <%- node_id %></h3>
</div>
<div class='panel-body'>
<table id="log-table"
class='table table-condensed table-bordered table-striped'>
<thead>
<th>ID</th>
<th>Reported</th>
<th>Reporter</th>
<th>Entry</th>
</thead>
<tbody>
<% _.each(entries, function (entry) { %>
<tr>
<td><%- entry.log_id %></td>
<td style='white-space: nowrap;'
class="format-date"><%- entry.reported %></td>
<td><%- entry.reporter %></td>
<td><%= entry.entry%>
</tr>
<% }); %>
</tbody>
</table>
<% if (isadmin) { %>
<center style="margin-top: 10px;">
<button class='btn btn-primary btn-xs'
id="new-entry-button"
type='button'>New Log Entry</button>
</center>
<% } %>
</div>
</div>
</div>
</div>
<div id='oops_div'></div>
<div id='waitwait_div'></div>
<div id='save-log-modal' class='modal fade'>
<div class='modal-dialog'>
<div class='modal-content'>
<div class="modal-header">
<center><h4>Create a log entry</h4></center>
</div>
<div class='modal-body'>
<center>
<div>
Please provide a brief log message.
<div>
<textarea id="log-entry" style="width: 80%;"
rows=2 type='textarea'></textarea>
<div class="text-danger hidden log-error entry-error"
style="text-align: center;"></div>
</div>
</div>
<div style="margin-top: 15px;">
<button type='button' style='margin-right: 20px;'
class='btn btn-primary btn-sm'
data-dismiss='modal' aria-hidden='true'>
Cancel</button>
<button type='button' class='btn btn-success btn-sm'
id='save-log-confirm'>
Save</button>
<div class="text-danger hidden log-error general-error"
style="text-align: center;"></div>
</div>
</center>
</div>
</div>
</div>
</div>
<?php
#
# Copyright (c) 2000-2007 University of Utah and the Flux Group.
# Copyright (c) 2000-2019 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
......@@ -35,6 +35,13 @@ $isadmin = ISADMIN();
# Verify page arguments.
#
$reqargs = RequiredPageArguments("node", PAGEARG_NODE);
$optargs = OptionalPageArguments("classic", PAGEARG_BOOLEAN);
$node_id = $node->node_id();
if (!$classic) {
header("Location: apt/show-nodelog.php?node_id=$node_id");
return;
}
#
# Standard Testbed Header
......
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