Overhaul some of the dashboard hooks/functionality

Fix crash in lease parser
Make DHCP Log and Config editing views calculate window height relative to user's browser window height
This commit is contained in:
Akkadius 2017-09-06 01:05:34 -05:00
parent e4c8faaa57
commit 8a5c16ade2
12 changed files with 275 additions and 174 deletions

94
app.js
View File

@ -5,6 +5,8 @@ var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
const execSync = require('child_process').execSync;
var app = express();
/* Read Config */
@ -66,6 +68,7 @@ module.exports = app;
/**
* Global Variables
*/
leases_per_minute = 0;
cpu_utilization = 0;
total_leases = 0;
@ -140,7 +143,7 @@ var glass_config = json_file.readFileSync('config/glass_config.json');
var options = {};
options.interval = 1000;
dashboard_timer = setInterval(function(){
var dashboard_timer = setInterval(function(){
// console.log("Checking timers...");
unix_time = Math.floor(new Date() / 1000);
if((unix_time - 5) > leases_last_update_time){
@ -151,12 +154,50 @@ dashboard_timer = setInterval(function(){
}, 5000);
/**
* Calculate leases per minute
*/
var leases_per_minute_data = [];
var leases_per_minute_counter = 0;
leases_per_minute_counter_timer = setInterval(function(){
// console.log("leases per minute counter %i", leases_per_minute_counter);
leases_per_minute_data[leases_per_minute_counter] = current_leases_per_second;
leases_per_minute_counter++;
/* Count how many actual data sets we walked that have values */
leases_per_minute = 0;
for (i = 0; i < 59; i++){
if(leases_per_minute_data[i] > 0) {
leases_per_minute += leases_per_minute_data[i];
// console.log("iteration " + i + " val: " + leases_per_minute_data[i] + " lpm: " + leases_per_minute);
}
else {
// console.log("no data " + i);
}
}
if (leases_per_minute_counter == 60)
leases_per_minute_counter = 0;
}, 1000);
/**
* Poll: CPU Utilization
*/
cpu_utilization_poll = setInterval(function(){
cpu_utilization = parseFloat(execSync("top -bn 1 | awk 'NR>7{s+=$9} END {print s/4}'"))
}, (15 * 1000));
/**
* Clean Expired Leases
*/
lease_clean_timer = setInterval(function(){
lease_parser.clean();
}, (60 * 1000));
function get_socket_clients_connected_count() {
wss.clients.forEach(function each(client) {
if (client.readyState === WebSocket.OPEN) {
@ -173,7 +214,6 @@ function get_socket_clients_connected_count() {
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
options.interval = 100;
var tail_dhcp_log = new tail_module(
glass_config.log_file,
@ -276,4 +316,48 @@ const interval = setInterval(function ping() {
stale_connections_audit();
}, 30000);
var socket_clients = 0;
var socket_clients = 0;
/**
* Slack Hooks
*/
var Slack = require('slack-node');
webhookUri = glass_config.slack_webhook_url;
slack = new Slack();
slack.setWebhook(webhookUri);
function slack_message(message) {
slack.webhook({
channel: glass_config.slack_alert_channel,
username: "Glass",
icon_emoji: "https://i.imgur.com/VDzAuAq.png",
text: message
}, function (err, response) {
console.log(response);
});
}
/**
* Alert Checks
*/
alert_status = [];
alert_status['leases_per_second'] = 0;
alert_check_timer = setInterval(function(){
if(glass_config.lease_per_second_threshold > 0) {
if (current_leases_per_second <= glass_config.lease_per_second_threshold && alert_status['leases_per_second'] == 0) {
alert_status['leases_per_second'] = 1;
// slack_message(":warning: WARNING: DHCP leases per second have dropped below critical threshold (" + glass_config.lease_per_second_threshold + ") Current LP/s (" + current_leases_per_second + ")");
}
else if (current_leases_per_second >= glass_config.lease_per_second_threshold && alert_status['leases_per_second'] == 1) {
alert_status['leases_per_second'] = 0;
// slack_message(":white_check_mark: CLEAR: DHCP leases per second have returned to above the critical threshold (" + glass_config.lease_per_second_threshold + ") Current LP/s (" + current_leases_per_second + ")");
}
}
}, (5 * 1000));

View File

@ -61,10 +61,12 @@ module.exports = {
dhcp_lease_data[ip_address].end = end_unix_time;
}
if (/ethernet/i.test(lines[l])) {
dhcp_lease_data[ip_address].mac = line_data_arg[2].replace(/;/gi, '').trim();
if(typeof line_data_arg[2] !== "undefined")
dhcp_lease_data[ip_address].mac = line_data_arg[2].replace(/;/gi, '').trim();
}
if (/hostname/i.test(lines[l])) {
dhcp_lease_data[ip_address].host = line_data_arg[1].replace(/;/gi, '').replace(/"/gi, '').trim();
if(typeof line_data_arg[1] !== "undefined")
dhcp_lease_data[ip_address].host = line_data_arg[1].replace(/;/gi, '').replace(/"/gi, '').trim();
}
if (/set/i.test(lines[l])) {
set_data = lines[l].replace(/;/gi, '').replace(/"/gi, '').replace(/ = /gi, ' ').replace(/set/gi, '').trim();

View File

@ -3,14 +3,25 @@
*/
$( document ).ajaxComplete(function( event, request, settings ) {
check_dashboard_active();
/*
* Form input highlighting events
*/
* Properly check pjax requests to see if we are in the dashboard or not
*/
if(/v_ajax/.test(settings.url)){
request = settings.url;
request = request.replace("\?v_ajax", "").trim();
//On focus event
if(request == "/" && in_dashboard != 1) {
in_dashboard = 1;
}
else {
in_dashboard = 0;
}
}
/*
* Form input focus event
*/
$('.form-control').focus(function () {
$(this).parent().addClass('focused');
});
@ -45,15 +56,6 @@ $( document ).ready(function() {
$('.form-line').removeClass("focused");
});
function check_dashboard_active() {
if(window.location.pathname == "/" && in_dashboard != 1) {
in_dashboard = 1;
}
else {
in_dashboard = 0;
}
}
function modal (title, content, buttons) {
$('#modal-buttons').html('');
$('#modal-title').html(title);

View File

@ -1,3 +1,5 @@
$('#dhcp_config').height($(window).height() * 0.6);
var dhcp_config = ace.edit("dhcp_config");
dhcp_config.setTheme("ace/theme/terminal");
dhcp_config.$blockScrolling = Infinity;

View File

@ -76,12 +76,14 @@ if(typeof socket === "undefined") {
editor.setValue("");
}
var row = editor.session.getLength() - 1
var column = editor.session.getLine(row).length // or simply Infinity
var row = editor.session.getLength() - 1;
var column = editor.session.getLine(row).length; // or simply Infinity
editor.gotoLine(row + 1, column);
};
}
$('#dhcp_log').height($(window).height() * 0.6);
var editor = ace.edit("dhcp_log");
editor.setTheme("ace/theme/terminal");
editor.$blockScrolling = Infinity;

View File

@ -5,8 +5,8 @@
<i class="material-icons">new_releases</i>
</div>
<div class="content">
<div class="text">Leases Per Second</div>
<div class="number" id="leases-sec">[current_leases_per_second]</div>
<div class="text">Leases Per Second / Minute</div>
<div class="number" id="leases-sec">0 / 0</div>
</div>
</div>
@ -18,7 +18,7 @@
</div>
<div class="content">
<div class="text">Total Leases</div>
<div class="number" id="total-leases">[total_leases]</div>
<div class="number" id="total-leases">0</div>
</div>
</div>
</div>
@ -29,7 +29,7 @@
</div>
<div class="content">
<div class="text">CPU</div>
<div class="number" id="cpu-utilization">[cpu_utilization]</div>
<div class="number" id="cpu-utilization">0</div>
</div>
</div>
</div>
@ -40,7 +40,7 @@
</div>
<div class="content">
<div class="text">SERVER</div>
<div class="number" id="server-name">[hostname]</div>
<div class="number" id="server-name">0</div>
</div>
</div>
</div>

View File

@ -20,20 +20,10 @@
</tr>
</thead>
<tbody>
[table_data]
</tbody>
</table>
</div>
</div>
</div>
</div>
<script type="text/javascript">
$('#display-subnets').DataTable({
dom: 'tip',
responsive: true,
"pageLength": 100,
"aaSorting": []
});
</script>

View File

@ -171,6 +171,13 @@
</section>
<!-- Jquery Core Js -->
<script src="assets/plugins/jquery/jquery.min.js"></script>
<script src="assets/plugins/jquery-datatable/jquery.dataTables.js"></script>
<script src="assets/plugins/jquery-datatable/skin/bootstrap/js/dataTables.bootstrap.js"></script>
<script src="assets/plugins/jquery-datatable/extensions/export/dataTables.buttons.min.js"></script>
<section class="content">
<div class="container-fluid">
<div class="block-header">
@ -182,9 +189,6 @@
</div>
</section>
<!-- Jquery Core Js -->
<script src="assets/plugins/jquery/jquery.min.js"></script>
<!-- Bootstrap Core Js -->
<script src="assets/plugins/bootstrap/js/bootstrap.js"></script>
@ -210,9 +214,7 @@
<script src="assets/js/file-saver.js"></script>
<script src="assets/plugins/jquery-datatable/jquery.dataTables.js"></script>
<script src="assets/plugins/jquery-datatable/skin/bootstrap/js/dataTables.bootstrap.js"></script>
<script src="assets/plugins/jquery-datatable/extensions/export/dataTables.buttons.min.js"></script>
<script type="text/javascript">
@ -228,27 +230,52 @@
function get_stats() {
$.get( "/get_stats", function( data ) {
$('#cpu-utilization').html(data.cpu_utilization + "%");
$('#leases-sec').html(data.leases_per_second.toLocaleString('en'));
$('#leases-sec').html(data.leases_per_second.toLocaleString('en') + ' / ' + data.leases_per_minute.toLocaleString('en'));
$('#total-leases').html(data.leases_used.toLocaleString('en'));
$('#shared-networks > tbody').html(data.shared_network_table);
$('#display-subnets > tbody').html(data.display_subnets_table);
if(typeof shared_networks !== "undefined")
shared_networks.destroy();
if(typeof display_subnets !== "undefined")
display_subnets.destroy();
shared_networks = $('#shared-networks').DataTable({
dom: 'tip',
responsive: true,
"pageLength": 100,
"aaSorting": []
});
display_subnets = $('#display-subnets').DataTable({
dom: 'tip',
responsive: true,
"pageLength": 100,
"aaSorting": []
});
});
}
dashboard_timer = setInterval(function () {
if (window_focus && $('#shared-networks').length && in_dashboard == 1) {
get_dashboard();
}
}, 5000);
get_stats_timer = setInterval(function () {
if (window_focus && $('#cpu-utilization').length && in_dashboard == 1) {
console.log("get_stats_timer");
if (window_focus && $('#total-leases').length && in_dashboard == 1) {
console.log("get_stats_timer trigger");
get_stats();
}
}, 5000);
if(window.location.pathname == "/") {
get_stats();
get_dashboard();
in_dashboard = 1;
console.log("in dash");
}
else {
in_dashboard = 0;
console.log("out dash");
}
var window_focus = true;

View File

@ -19,20 +19,10 @@
</tr>
</thead>
<tbody>
[table_data]
</tbody>
</table>
</div>
</div>
</div>
</div>
<script type="text/javascript">
$('#shared-networks').DataTable({
dom: 'tip',
responsive: true,
"pageLength": 100,
"aaSorting": []
});
</script>

View File

@ -8,116 +8,22 @@ glass_config = json_file.readFileSync('config/glass_config.json');
router.get('/', function(req, res, next) {
const execSync = require('child_process').execSync;
output = execSync('./bin/dhcpd-pools -c ' + glass_config.config_file + ' -l ' + glass_config.leases_file + ' -f j -A -s e');
var dhcp_data = JSON.parse(output);
for ( var i = 0; i < dhcp_data['shared-networks'].length; i++) {
utilization = round(parseFloat(dhcp_data['shared-networks'][i].used / dhcp_data['shared-networks'][i].defined) * 100, 2);
if(isNaN(utilization))
utilization = 0;
dhcp_data['shared-networks'][i].utilization = utilization;
}
dhcp_data['shared-networks'].sort(function(a, b) {
return parseFloat(b.utilization) - parseFloat(a.utilization);
});
shared_networks = '';
for ( var i = 0; i < dhcp_data['shared-networks'].length; i++) {
table_row = '';
table_row = table_row + '<td><b>' + dhcp_data['shared-networks'][i].location + '</b></td>';
table_row = table_row + '<td>' + dhcp_data['shared-networks'][i].used.toLocaleString('en') + '</td>';
table_row = table_row + '<td>' + dhcp_data['shared-networks'][i].defined.toLocaleString('en') + '</td>';
table_row = table_row + '<td>' + dhcp_data['shared-networks'][i].free.toLocaleString('en') + '</td>';
utilization = dhcp_data['shared-networks'][i].utilization;
table_row = table_row + '<td>' + utilization + '</td>';
utilization_color = 'green';
if(utilization >= 80)
utilization_color = 'orange';
if(utilization >= 90)
utilization_color = 'red';
table_row = table_row + '<td><div class="progress">' +
'<div class="progress-bar bg-' + utilization_color + '" role="progressbar" aria-valuenow="62" aria-valuemin="0" aria-valuemax="100" style="width: ' + utilization + '%"></div>' +
'</div></td>';
shared_networks = shared_networks + '<tr>' + table_row + '</tr>';
}
/* Display All Subnets */
for ( var i = 0; i < dhcp_data.subnets.length; i++) {
utilization = round(parseFloat(dhcp_data.subnets[i].used / dhcp_data.subnets[i].defined) * 100, 2);
if(isNaN(utilization))
utilization = 0;
dhcp_data.subnets[i].utilization = utilization;
}
dhcp_data.subnets.sort(function(a, b) {
return parseFloat(b.utilization) - parseFloat(a.utilization);
});
display_subnets = '';
for ( var i = 0; i < dhcp_data.subnets.length; i++) {
table_row = '';
table_row = table_row + '<td><b>' + dhcp_data.subnets[i].location + '</b></td>';
table_row = table_row + '<td>' + dhcp_data.subnets[i].range + '</td>';
table_row = table_row + '<td>' + dhcp_data.subnets[i].used.toLocaleString('en') + '</td>';
table_row = table_row + '<td>' + dhcp_data.subnets[i].defined.toLocaleString('en') + '</td>';
table_row = table_row + '<td>' + dhcp_data.subnets[i].free.toLocaleString('en') + '</td>';
utilization = dhcp_data.subnets[i].utilization;
table_row = table_row + '<td>' + utilization + '</td>';
utilization_color = 'green';
if(utilization >= 80)
utilization_color = 'orange';
if(utilization >= 90)
utilization_color = 'red';
table_row = table_row + '<td><div class="progress">' +
'<div class="progress-bar bg-' + utilization_color + '" role="progressbar" aria-valuenow="62" aria-valuemin="0" aria-valuemax="100" style="width: ' + utilization + '%"></div>' +
'</div></td>';
display_subnets = display_subnets + '<tr>' + table_row + '</tr>';
}
/* Display Counters Row */
counters = template_render.get_template("counters");
hostname = execSync('hostname').toString().trim();
counters = template_render.set_template_variable(counters, "hostname", hostname);
counters = template_render.set_template_variable(counters, "current_leases_per_second", current_leases_per_second);
counters = template_render.set_template_variable(counters, "total_leases", total_leases);
counters = template_render.set_template_variable(counters, "cpu_utilization", cpu_utilization);
/* Display Shared Networks Row */
content_shared_networks = template_render.get_template("shared_networks");
content_shared_networks = template_render.set_template_variable(content_shared_networks, "table_data", shared_networks);
/* Display Subnets Row */
content_subnets = template_render.get_template("display_subnets");
content_subnets = template_render.set_template_variable(content_subnets, "table_data", display_subnets);
res.send(
counters +
'<div class="row clearfix">' +
content_shared_networks + content_subnets +
'</div>'
'</div>' + '<script type="text/javascript">get_stats();</script>'
);
});
module.exports = router;
function round(num, places) {
var multiplier = Math.pow(10, places);
return Math.round(num * multiplier) / multiplier;
}

View File

@ -6,24 +6,109 @@ var template_render = require('../lib/render_template.js');
/* GET home page. */
router.get('/', function(req, res, next) {
var json_file = require('jsonfile');
var glass_config = json_file.readFileSync('config/glass_config.json');
const execSync = require('child_process').execSync;
// dhcp_exec = execSync('/home/cmiles/dhcpd-pools -c /home/cmiles/dhcpd.conf -l /home/cmiles/dhcpd.leases -f j -A -s e');
dhcp_exec = execSync('/home/cmiles/dhcpd-pools -c /etc/dhcp/dhcpd.conf -l /var/lib/dhcp/dhcpd.leases -f j -A -s e');
cpu_utilization = parseFloat(execSync("top -bn 1 | awk 'NR>7{s+=$9} END {print s/4}'"));
output = execSync('./bin/dhcpd-pools -c ' + glass_config.config_file + ' -l ' + glass_config.leases_file + ' -f j -A -s e');
var dhcp_data = JSON.parse(output);
var dhcp_data = JSON.parse(dhcp_exec);
for ( var i = 0; i < dhcp_data['shared-networks'].length; i++) {
utilization = round(parseFloat(dhcp_data['shared-networks'][i].used / dhcp_data['shared-networks'][i].defined) * 100, 2);
if(isNaN(utilization))
utilization = 0;
total_leases = dhcp_data.summary.used;
dhcp_data['shared-networks'][i].utilization = utilization;
}
dhcp_data['shared-networks'].sort(function(a, b) {
return parseFloat(b.utilization) - parseFloat(a.utilization);
});
shared_networks = '';
for ( var i = 0; i < dhcp_data['shared-networks'].length; i++) {
table_row = '';
table_row = table_row + '<td><b>' + dhcp_data['shared-networks'][i].location + '</b></td>';
table_row = table_row + '<td>' + dhcp_data['shared-networks'][i].used.toLocaleString('en') + '</td>';
table_row = table_row + '<td>' + dhcp_data['shared-networks'][i].defined.toLocaleString('en') + '</td>';
table_row = table_row + '<td>' + dhcp_data['shared-networks'][i].free.toLocaleString('en') + '</td>';
utilization = dhcp_data['shared-networks'][i].utilization;
table_row = table_row + '<td>' + utilization + '</td>';
utilization_color = 'green';
if(utilization >= 80)
utilization_color = 'orange';
if(utilization >= 90)
utilization_color = 'red';
table_row = table_row + '<td><div class="progress">' +
'<div class="progress-bar bg-' + utilization_color + '" role="progressbar" aria-valuenow="62" aria-valuemin="0" aria-valuemax="100" style="width: ' + utilization + '%"></div>' +
'</div></td>';
shared_networks = shared_networks + '<tr>' + table_row + '</tr>';
}
/* Display All Subnets */
for ( var i = 0; i < dhcp_data.subnets.length; i++) {
utilization = round(parseFloat(dhcp_data.subnets[i].used / dhcp_data.subnets[i].defined) * 100, 2);
if(isNaN(utilization))
utilization = 0;
dhcp_data.subnets[i].utilization = utilization;
}
dhcp_data.subnets.sort(function(a, b) {
return parseFloat(b.utilization) - parseFloat(a.utilization);
});
display_subnets = '';
for ( var i = 0; i < dhcp_data.subnets.length; i++) {
table_row = '';
table_row = table_row + '<td><b>' + dhcp_data.subnets[i].location + '</b></td>';
table_row = table_row + '<td>' + dhcp_data.subnets[i].range + '</td>';
table_row = table_row + '<td>' + dhcp_data.subnets[i].used.toLocaleString('en') + '</td>';
table_row = table_row + '<td>' + dhcp_data.subnets[i].defined.toLocaleString('en') + '</td>';
table_row = table_row + '<td>' + dhcp_data.subnets[i].free.toLocaleString('en') + '</td>';
utilization = dhcp_data.subnets[i].utilization;
table_row = table_row + '<td>' + utilization + '</td>';
utilization_color = 'green';
if(utilization >= 80)
utilization_color = 'orange';
if(utilization >= 90)
utilization_color = 'red';
table_row = table_row + '<td><div class="progress">' +
'<div class="progress-bar bg-' + utilization_color + '" role="progressbar" aria-valuenow="62" aria-valuemin="0" aria-valuemax="100" style="width: ' + utilization + '%"></div>' +
'</div></td>';
display_subnets = display_subnets + '<tr>' + table_row + '</tr>';
}
total_leases = dhcp_data.summary.used.toLocaleString('en');
return_data = {
"cpu_utilization": cpu_utilization,
"leases_used": total_leases,
"leases_per_second": current_leases_per_second
"leases_per_second": current_leases_per_second,
"leases_per_minute": leases_per_minute,
"shared_network_table": shared_networks,
"display_subnets_table": display_subnets
};
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify(return_data));
});
module.exports = router;
module.exports = router;
function round(num, places) {
var multiplier = Math.pow(10, places);
return Math.round(num * multiplier) / multiplier;
}

View File

@ -7,14 +7,25 @@ var template_render = require('../lib/render_template.js');
router.get('/', function(req, res, next) {
console.log(req.url);
res.send(
template_render.get_index_template(
'<script type="text/javascript">' +
'get_dashboard(); get_stats();' +
'</script>',
counters = template_render.get_template("counters");
/* Display Shared Networks Row */
content_shared_networks = template_render.get_template("shared_networks");
/* Display Subnets Row */
content_subnets = template_render.get_template("display_subnets");
res.send(
template_render.get_index_template(
counters +
'<div class="row clearfix">' +
content_shared_networks + content_subnets +
'</div>',
req.url
)
);
) + '<script type="text/javascript">get_stats();</script>'
);
});
module.exports = router;