Skip to content

Commit

Permalink
Merge pull request #852 from jcrussell/miniweb
Browse files Browse the repository at this point in the history
miniweb: is born
  • Loading branch information
djfritz authored Feb 27, 2017
2 parents ccf308e + 0c2616a commit b4ceff7
Show file tree
Hide file tree
Showing 11 changed files with 536 additions and 618 deletions.
97 changes: 25 additions & 72 deletions misc/web/js/glue.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,34 +35,19 @@ function initVMDataTable() {
var vmDataTable = $('#vms-dataTable').DataTable({
"ajax": function( data, callback, settings) {
updateJSON('/vms.json', function(vmsData) {
updateJSON('/vlans.json', function(vlansData) {
// create mapping of vlans to aliases for easier lookup
var aliases = {};
vlansData.forEach(function(vlan) {
aliases[vlan[2]] = vlan[1];
});

// insert VLAN aliases into VMs network data
vmsData.forEach(function(vm) {
vm["network"].forEach(function(network) {
network["Alias"] = aliases[network["VLAN"]];
});
});

// disable auto-refresh there are too many VMs
VM_REFRESH_ENABLE = Object.keys(vmsData).length <= VM_REFRESH_THESHOLD;

// put into a structure that DataTables expects
var dataTablesData = {"data": vmsData};

callback(dataTablesData);
});
// disable auto-refresh there are too many VMs
VM_REFRESH_ENABLE = Object.keys(vmsData).length <= VM_REFRESH_THESHOLD;

// put into a structure that DataTables expects
var dataTablesData = {"data": vmsData};

callback(dataTablesData);
});
},
// custom DOM with Boostrap integration
// http://stackoverflow.com/a/32253335
"dom":
"<'row'<'col-sm-5'i><'col-sm-7'p>>" +
"dom":
"<'row'<'col-sm-5'i><'col-sm-7'p>>" +
//"<'row'<'col-sm-3'l><'col-sm-6 text-center'B><'col-sm-3'f>>" +
"<'row'<'col-sm-6'l><'col-sm-6'f>>" +
"<'row'<'col-sm-12 text-center'B>>" +
Expand All @@ -89,20 +74,14 @@ function initVMDataTable() {
{ "title": "VCPUs", "data": "vcpus" },
{ "title": "Memory", "data": "memory" },
{ "title": "Disk", "data": null, "visible": false, render: renderDisksColumn },
{ "title": "VLAN", "data": "network", render: function(data, type, full, meta) {
// create array with VLAN ID and alias zipped together
var vlansWithAliases = data.map(function(e, i) {
return e["VLAN"] + " (" + e["Alias"] + ")";
});
return renderArray(vlansWithAliases, type, full, meta);
} },
{ "title": "IPv4", "data": "network", render: renderArrayOfObjectsUsingKey("IP4") },
{ "title": "IPv6", "data": "network", "visible": false, render: renderArrayOfObjectsUsingKey("IP6") },
{ "title": "Taps", "data": "network", "visible": false, render: renderArrayOfObjectsUsingKey("Tap") },
{ "title": "VLAN", "data": "vlan" },
{ "title": "IPv4", "data": "ip" },
{ "title": "IPv6", "data": "ip6", "visible": false },
{ "title": "Taps", "data": "tap", "visible": false },
{ "title": "Tags", "data": "tags", "visible": false, render: renderFilteredObject(function(key) {
return key != 'minirouter_log';
}) },
{ "title": "Active CC", "data": "activecc", "visible": false },
{ "title": "Active CC", "data": "cc_active", "visible": false },
{
"title": "VNC",
"data": "name",
Expand All @@ -116,11 +95,11 @@ function initVMDataTable() {
"stateDuration": 0
/*initComplete: function(){
var api = this.api();
api.buttons().container().appendTo( '#' + api.table().container().id + ' .col-sm-6:eq(0)' );
api.buttons().container().appendTo( '#' + api.table().container().id + ' .col-sm-6:eq(0)' );
}*/
});


// Create second button group for other functionality
/*
new $.fn.dataTable.Buttons( vmDataTable, {
Expand Down Expand Up @@ -156,8 +135,8 @@ function initHostDataTable() {
"url": "hosts.json",
"dataSrc": ""
},
"dom":
"<'row'<'col-sm-5'i><'col-sm-7'p>>" +
"dom":
"<'row'<'col-sm-5'i><'col-sm-7'p>>" +
//"<'row'<'col-sm-3'l><'col-sm-6 text-center'B><'col-sm-3'f>>" +
"<'row'<'col-sm-6'l><'col-sm-6'f>>" +
"<'row'<'col-sm-12 text-center'B>>" +
Expand Down Expand Up @@ -351,7 +330,7 @@ function colorSpanWithThresholds(text, value, thresholdRed, thresholdYellow) {

// Generate the appropriate URL for requesting a screenshot
function screenshotURL (vm, size) {
return "screenshot/" + vm.host + "/" + vm.id + ".png?size=" + size;
return "screenshot/" + vm.name + ".png?size=" + size;
}


Expand Down Expand Up @@ -410,9 +389,9 @@ function renderDisksColumn(data, type, full, meta) {
var html = [];
var keys = [];
if (data.type === "container") {
var keys = ['container_fspath', 'container_preinit', 'container_init'];
var keys = ['filesystem', 'preinit', 'init'];
} else if (data.type === "kvm") {
var keys = ['kvm_initrdpath', 'kvm_kernelpath', 'kvm_diskpaths'];
var keys = ['initrd', 'kernel', 'disk'];
}

for (var i = 0; i < keys.length; i++) {
Expand All @@ -422,44 +401,18 @@ function renderDisksColumn(data, type, full, meta) {
return html.join("<br />");
}

function renderArray(data, type, full, meta) {
var html = [];
for (var i = 0; i < data.length; i++) {
html.push(data[i]);
}
return handleEmptyString(html.join(", "));
}

function renderArrayOfObjectsUsingKey(key) {
return function(data, type, full, meta) {
return handleEmptyString(data.reduce(
function (previous, current) {
return previous.concat([handleEmptyString(current[key])]);
}, []).join(", ")
);
};
}

function renderFilteredObject(filterFn) {
return function(data, type, full, meta) {
var jsonified = JSON.parse(data);
var html = [];
var keys = Object.keys(data).filter(filterFn);
var keys = Object.keys(jsonified).filter(filterFn);
for (var i = 0; i < keys.length; i++) {
html.push("<em>" + keys[i] + ":</em> " + data[keys[i]]);
html.push("<em>" + keys[i] + ":</em> " + jsonified[keys[i]]);
}
return handleEmptyString(html.join(", "));
}
}

function renderObject(data, type, full, meta) {
var html = [];
var keys = Object.keys(data);
for (var i = 0; i < keys.length; i++) {
html.push("<em>" + keys[i] + ":</em> " + data[keys[i]]);
}
return handleEmptyString(html.join(", "));
}

// Put an italic "null" in the table where there are fields that aren't set
function handleEmptyString (value, type) {
if (
Expand All @@ -478,4 +431,4 @@ function handleEmptyString (value, type) {
}
}
return value;
}
}
47 changes: 24 additions & 23 deletions misc/web/js/graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ function setSidebarNode (id) {
var nonRouterMachines = [];
for (var i = 0; i < vlanMachines.length; i++) {
var current = vlanMachines[i];
if (current.network.length == 1) {
if (current.vlan.length == 1) {
nonRouterMachines.push(current.uuid);
}
}
Expand Down Expand Up @@ -690,37 +690,39 @@ function makeGraph (response, ethers) {
min: Infinity
};

// The response is broken down by hosts. Loop through the machines in each host and populate
// the lists of machines accordingly.
// The response is broken down by hosts. Loop through the machines in each
// host and populate the lists of machines accordingly.
for (var i = 0; i < response.length; i++) {
var vm = response[i];

vm["node_type"] = null;
vm["uuid"] = vm["host"] + " " + vm["id"]; // Space suffices as a separator

// Unconnected machine (no VLANs)
if (vm.network.length < 1) {
// parse the VLAN string into a list of VLANs
vm.vlan = vm.vlan.substring(1, vm.vlan.length - 1).split(", ");

if (vm.vlan.length == 0) {
// Unconnected machine (no VLANs)
vm["node_type"] = "unconnected";
unconnected.push(vm);
network.machines.unconnected.push(vm);

// Router (multiple VLANs)
} else if (vm.network.length > 1) {
} else if (vm.vlan.length > 1) {
// Router (multiple VLANs)
vm["node_type"] = "router";
routers.push(vm);

for (var j = 0; j < vm.network.length; j++)
pushOrCreate(network.machines.vlans, vm.network[j].VLAN, vm);

// Normal machine (one VLAN)
for (var j = 0; j < vm.vlan.length; j++) {
pushOrCreate(network.machines.vlans, vm.vlan[j], vm);
}
} else {
// Normal machine (one VLAN)
vm["node_type"] = "normal";
pushOrCreate(vlans, vm.network[0].VLAN, vm);
pushOrCreate(network.machines.vlans, vm.network[0].VLAN, vm);
pushOrCreate(vlans, vm.vlan[0], vm);
pushOrCreate(network.machines.vlans, vm.vlan[0], vm);
}
}

// The first node is drawn under all the rest. This node is for providing a visual cue that a node is selected.
// The first node is drawn under all the rest. This node is for providing a
// visual cue that a node is selected.
for (var i = 0; i < ethers; i++) {
network.nodes.push({
"vlans": [],
Expand All @@ -733,10 +735,9 @@ function makeGraph (response, ethers) {
});
}

// VLANs need to be processed first, as the routers depend on them to be there to properly
// configure linkages.
// Add a node for each VLAN
for (var vlan in vlans) { // for vlan in vlans
// VLANs need to be processed first, as the routers depend on them to be
// there to properly configure linkages.
for (var vlan in vlans) {
var index = network.nodes.push({
"vlans": [vlan],
"group": config.types.normal,
Expand Down Expand Up @@ -767,8 +768,8 @@ function makeGraph (response, ethers) {
"r": null
}) - 1;

for (var j = 0; j < router.network.length; j++) { // for vlan in router.vlan
var vlan = router.network[j].VLAN;
for (var j = 0; j < router.vlan.length; j++) { // for vlan in router.vlan
var vlan = router.vlan[j];
network.nodes[index].vlans.push(vlan);

var from = index;
Expand Down Expand Up @@ -864,7 +865,7 @@ function initializeGraph() {
return Number(b).toString(16) }) // ["FF", "FF", "FF"]
.join(""); // "FFFFFF"

grapher.instance = new Grapher()
grapher.instance = new Grapher()
.palette(null)
.data(grapher.graph);

Expand Down
2 changes: 1 addition & 1 deletion src/minicli/minicli.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ type Response struct {
Header []string // Optional header. If set, will be used for both Response and Tabular data.
Tabular [][]string // Optional tabular data. If set, Response will be ignored
Error string // Because you can't gob/json encode an error type
Data interface{} `json:"-"` // Optional user data
Data interface{} //`json:"-"` // Optional user data

// Embedded output flags, overrides defaults if set for first response
*Flags `json:"-"`
Expand Down
7 changes: 7 additions & 0 deletions src/miniclient/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"os/signal"
"path"
"strings"
"sync"
"syscall"
)

Expand All @@ -42,6 +43,9 @@ type Conn struct {

conn net.Conn

// lock so we don't try to use enc/dec for concurrent Runs
lock sync.Mutex

enc *json.Encoder
dec *json.Decoder

Expand Down Expand Up @@ -83,6 +87,8 @@ func (mm *Conn) Run(cmd string) chan *Response {
return out
}

mm.lock.Lock()

err := mm.enc.Encode(Request{Command: cmd})
if err != nil {
log.Fatal("local command gob encode: %v", err)
Expand All @@ -92,6 +98,7 @@ func (mm *Conn) Run(cmd string) chan *Response {
respChan := make(chan *Response)

go func() {
defer mm.lock.Unlock()
defer close(respChan)

for {
Expand Down
1 change: 0 additions & 1 deletion src/minimega/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ func cliSetup() {
registerHandlers("vmconfig", vmconfigCLIHandlers)
registerHandlers("vmconfiger", vmconfigerCLIHandlers)
registerHandlers("vnc", vncCLIHandlers)
registerHandlers("web", webCLIHandlers)
}

// registerHandlers registers all the provided handlers with minicli, panicking
Expand Down
75 changes: 0 additions & 75 deletions src/minimega/tunnel.go

This file was deleted.

Loading

0 comments on commit b4ceff7

Please sign in to comment.