Commit fcfdd7fa authored by Leigh B Stoller's avatar Leigh B Stoller Committed by Gary Wong

Checkpoint

parent eca91b95
......@@ -30,3 +30,37 @@ body > #bodycontainer { height: auto; min-height: 100%; }
margin-left: -200px;
/* 4 */
}
/* Styles for svg diagrams */
.topomap {
display: block;
margin: 0 auto;
}
.linktext {
fill: blue;
font: Helvetica;
font-size: 12;
font-weight: bold;
}
.nodetext {
fill: black;
font: Helvetica;
font-size: 12;
font-weight: bold;
}
.linkline {
fill: black;
fill-opacity: 1.0;
stroke: black;
stroke-opacity: 1.0;
stroke-width: 1;
stroke-linecap: square;
}
.nodebox {
fill: palegreen;
fill-opacity: 1.0;
stroke: black;
stroke-opacity: 1.0;
stroke-width: 2;
}
......@@ -400,7 +400,7 @@ if (count($errors)) {
#
#
$retval = SUEXEC("nobody", "nobody", "webquickvm $xmlname",
SUEXEC_ACTION_IGNORE);
SUEXEC_ACTION_CONTINUE);
if ($retval != 0) {
if ($retval < 0) {
......
......@@ -161,7 +161,7 @@ if (isset($ajax_request)) {
"APT Extension: $uuid",
"A request to extend your APT experiment was made and ".
"granted.\n".
"Your reason was:\n\n". $ajax_argument . "\n".
"Your reason was:\n\n". $ajax_argument . "\n\n".
"Your experiment will now expire at $new_expires\n",
"CC: $TBMAIL_OPS");
}
......@@ -262,7 +262,12 @@ echo "</div>\n";
#
# The topo diagram goes inside this div, when it becomes available.
#
echo "<div id='showtopo_container' class='uk-panel uk-panel-box
uk-container-center uk-width-2-3 uk-hidden'>\n";
echo "<div id='showtopo_div'></div>\n";
SpitToolTip("Click on a node to SSH to that node.<br>".
"Click and drag on a node to move things around.");
echo "</div>\n";
#
# A modal to tell people how to register
......
......@@ -26,7 +26,7 @@ function CallMethod(method, callback, uuid, arg)
},
// whether this is a POST or GET request
type: (arg ? "POST" : "GET"),
type: (arg ? "GET" : "GET"),
// the type of data we expect back
dataType : "json",
......@@ -78,7 +78,8 @@ function StatusWatchCallBack(uuid, json)
}
$("#terminate_button").prop("disabled", false);
$("#extend_button").prop("disabled", false);
ShowTopo(uuid);
// ShowTopo(uuid);
ShowTopoNew(uuid);
}
else if (status == 'failed') {
status_html = "<font color=red>failed</font>";
......@@ -132,6 +133,24 @@ function ShowTopo(uuid)
$xmlthing.done(callback);
}
function ShowTopoNew(uuid)
{
var callback = function(json) {
console.log(json.value);
var xmlDoc = $.parseXML(json.value);
var xml = $(xmlDoc);
var topo = ConvertManifestToJSON(xml);
console.log(topo);
$("#showtopo_container").removeClass("uk-hidden");
maketopmap("#showtopo_div", 800, 500, topo);
}
console.log(uuid);
var $xmlthing = CallMethod("manifest", null, uuid, null);
$xmlthing.done(callback);
}
function Setsshurl(uuid)
{
var callback = function(json) {
......@@ -315,3 +334,203 @@ function StartCountdownClock(when)
$("#quickvm_countdown").html(countdown);
}, 1000);
}
var foo = {"nodes": [{"name" : "node1"},
{"name" : "node2"}],
"links": [{"source" : 0, "target" : 1, "value" : "foo"}]};
function maketopmap(divname, width, height, json)
{
var vis = d3.select(divname).append("svg:svg")
.attr("class", "topomap")
.attr("width", width)
.attr("height", height);
vis.append("svg:rect")
.attr("width", width)
.attr("height", height)
.style("fill-opacity", 0.0)
.style("stroke", "#000");
var topo = function(json) {
var force = self.force = d3.layout.force()
.nodes(json.nodes)
.links(json.links)
.distance(150)
.charge(-400)
.size([width, height])
.start();
var linkg = vis.selectAll("g.link")
.data(json.links)
.enter().append("svg:g");
var link = linkg.append("svg:line")
.attr("class", "linkline")
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
var linklabel = linkg.append("svg:text")
.attr("class", "linktext")
.attr("x", function(d) { return (d.source.x + d.target.x) / 2 })
.attr("y", function(d) { return (d.source.y + d.target.y) / 2 })
.text(function(d) { return d.name });
var node_drag = d3.behavior.drag()
.on("dragstart", dragstart)
.on("drag", dragmove)
.on("dragend", dragend);
function dragstart(d, i) {
// stops the force auto positioning before you start dragging
force.stop()
}
function dragmove(d, i) {
d.px += d3.event.dx;
d.py += d3.event.dy;
d.x += d3.event.dx;
d.y += d3.event.dy;
// this is the key to make it work together with updating
// both px,py,x,y on d !
tick();
}
function dragend(d, i) {
// of course set the node to fixed so the force doesn't
// include the node in its auto positioning stuff
d.fixed = true;
force.resume();
}
var nodeg = vis.selectAll("g.node")
.data(json.nodes)
.enter().append("svg:g")
.call(node_drag);
var nodea = nodeg.append("svg:a")
.attr("xlink:href", function(d) { return d.sshurl });
var node = nodea.append("svg:rect")
.attr("class", "nodebox")
.attr("x", "-8px")
.attr("y", "-8px")
.attr("width", "20px")
.attr("height", "20px");
nodeg.append("svg:text")
.attr("class", "nodetext")
.attr("dx", 16)
.attr("dy", ".35em")
.text(function(d) { return d.name });
function tick() {
if (0) {
node.attr("x",
function(d) {
return d.x =
Math.max(10,
Math.min(width - 10, d.x));
})
.attr("y",
function(d) {
return d.y =
Math.max(10,
Math.min(height - 10, d.y));
});
}
else {
nodeg.attr("transform", function(d) {
d.x = Math.max(10, Math.min(width - 10, d.x));
d.y = Math.max(10, Math.min(height - 10, d.y));
return "translate(" + d.x + "," + d.y + ")"; });
}
link.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
linklabel.attr("x", function(d) { return (d.source.x + d.target.x)
/ 2 })
.attr("y", function(d) { return (d.source.y + d.target.y)
/ 2 });
};
force.on("tick", tick);
}(json);
return topo;
}
//
// Convert a manifest in XML to a JSON object of nodes and links.
//
function ConvertManifestToJSON(xml)
{
var json = {
"nodes": [],
"links": [],
};
$(xml).find("node").each(function(){
var client_id = $(this).attr("client_id");
var jobj = {"name" : client_id};
var login = $(this).find("login");
if (login) {
var user = login.attr("username");
var host = login.attr("hostname");
var port = login.attr("port");
var sshurl = "ssh://" + user + "@" + host + ":" + port + "/";
jobj.sshurl = sshurl;
}
json.nodes.push(jobj);
});
$(xml).find("link").each(function(){
var client_id = $(this).attr("client_id");
var link_type = $(this).find("link_type");
if (link_type && $(link_type).attr("name") == "lan") {
console.log("Oops, a lan");
}
else {
var ifacerefs = $(xml).find("interface_ref");
var source = ifacerefs[0];
var target = ifacerefs[1];
source = $(source);
target = $(target);
var source_ifname = source.attr("client_id");
var target_ifname = target.attr("client_id");
var source_ifpair = source_ifname.split(":");
var target_ifpair = target_ifname.split(":");
var source_name = source_ifpair[0];
var target_name = target_ifpair[0];
var source_index = null;
var target_index = null;
// Javascript does not do dictionaries. Too bad.
for (i = 0; i < json.nodes.length; i++) {
if (json.nodes[i].name == source_name) {
source_index = i;
}
if (json.nodes[i].name == target_name) {
target_index = i;
}
}
json.links.push({"name" : client_id,
"source" : source_index,
"target" : target_index,
"source_name" : source_name,
"target_name" : target_name,
});
}
});
return json;
}
......@@ -31,11 +31,11 @@ function SPITHEADER($thinheader = 0)
<!-- UIKit -->
<link rel='stylesheet' href='uikit/css/uikit.almost-flat.css'>
<link rel='stylesheet' href='quickvm.css'>
<script src='gateone.js'></script>
<script src='quickvm_sup.js'></script>
<script src='/emulab_sup.js'></script>
<script src='https://code.jquery.com/jquery.js'></script>
<script src='uikit/js/uikit.js'></script>
<script src='d3.v3.js'></script>
</head>
<body>
<!-- Container for body, needed for sticky footer -->
......@@ -84,6 +84,15 @@ function SPITAJAX_ERROR($code, $msg)
echo json_encode($results);
}
#
# Spit out an info tooltip.
#
function SpitToolTip($info)
{
echo "<span data-uk-tooltip class='uk-icon-info-sign' ".
"title='$info'></span>";
}
function GateOneAuthObject($uid)
{
#
......
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