mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-23 22:50:09 +03:00
Feature #650: General completion and refactoring of single host and VMs monitoring:
*Fixed bugs on server. Enabled requesting several resources at once. *Correct css for .info_tables *Add graphs to hosts and VMs info tabs. Correct vm_log method so dialog is not regenerated (and graphs destroyed with it). Improved the common methods for creating the divs containing grahps and plotting the information. *Improved OneMonitor tool. Add total, active and error counts to the global logs.
This commit is contained in:
parent
728268d802
commit
3a54ee1ba5
@ -265,7 +265,7 @@ class SunstoneServer
|
||||
#
|
||||
############################################################################
|
||||
|
||||
def get_log(resource,id,config,monitor_res,history_length)
|
||||
def get_log(resource,id,config,monitor_resources,history_length)
|
||||
log_file_prefix = case resource
|
||||
when "vm","VM"
|
||||
config[:host_log_file]
|
||||
@ -279,32 +279,46 @@ class SunstoneServer
|
||||
|
||||
log_file = "#{log_file_prefix}_#{id}.csv"
|
||||
|
||||
first_line = `head -1 #{log_file}`
|
||||
first_line = `head -1 #{log_file}`.chomp
|
||||
|
||||
if $?.exitstatus != 0
|
||||
then
|
||||
error = Error.new("Cannot open log file")
|
||||
return [500, error.to_json]
|
||||
end
|
||||
|
||||
fields = first_line.split(',')
|
||||
|
||||
poll_time_pos = fields.index("time")
|
||||
resource_pos = fields.index(monitor_res)
|
||||
id_pos = fields.index("id")
|
||||
|
||||
graph = []
|
||||
tail = `tail -#{history_length} #{log_file}`
|
||||
|
||||
tail.each_line do | line |
|
||||
line_arr = line.delete('"').split(',')
|
||||
if (line_arr[id_pos].to_i == id.to_i)
|
||||
then
|
||||
graph << [ line_arr[poll_time_pos].to_i*1000, line_arr[resource_pos].to_i ]
|
||||
end
|
||||
n_lines = `wc -l #{log_file} | cut -d' ' -f 1`.to_i
|
||||
if n_lines <= history_length.to_i
|
||||
history_length = n_lines-1
|
||||
end
|
||||
|
||||
return graph.to_json
|
||||
fields = first_line.split(',')
|
||||
poll_time_pos = fields.index("time")
|
||||
id_pos = fields.index("id")
|
||||
|
||||
if !id_pos or !poll_time_pos
|
||||
error = Error.new("It seems poll_time or id information cannot be read from log file")
|
||||
return [500, error.to_json]
|
||||
end
|
||||
|
||||
series = [] #will hold several graphs
|
||||
tail = `tail -#{history_length} #{log_file}`
|
||||
|
||||
monitor_resources.split(',').each do | resource |
|
||||
|
||||
graph = []
|
||||
resource_pos = fields.index(resource)
|
||||
|
||||
tail.each_line do | line |
|
||||
line_arr = line.delete('"').split(',')
|
||||
if (line_arr[id_pos].to_i == id.to_i)
|
||||
graph << [ line_arr[poll_time_pos].to_i*1000, line_arr[resource_pos].to_i ]
|
||||
end
|
||||
end
|
||||
|
||||
series << graph
|
||||
end
|
||||
|
||||
return series.to_json
|
||||
end
|
||||
|
||||
############################################################################
|
||||
|
@ -362,7 +362,7 @@ tr.even:hover{
|
||||
vertical-align:top;
|
||||
}
|
||||
|
||||
.info_table th,h3 {
|
||||
.info_table > thead th,h3 {
|
||||
border-bottom: 2px solid #353735;
|
||||
color: #353735;
|
||||
font-size: 14px;
|
||||
@ -371,7 +371,7 @@ tr.even:hover{
|
||||
}
|
||||
|
||||
|
||||
.info_table td{
|
||||
.info_table > tbody > tr > td{
|
||||
border-bottom: 1px solid #CCCCCC;
|
||||
color: #353735;
|
||||
padding-top: 6px;
|
||||
|
@ -17,6 +17,22 @@
|
||||
/*Host tab plugin*/
|
||||
|
||||
var HOST_HISTORY_LENGTH = 40;
|
||||
var host_graphs = [
|
||||
{
|
||||
title : "CPU Monitoring information",
|
||||
monitor_resources : "cpu_usage,used_cpu,max_cpu",
|
||||
humanize_figures : false,
|
||||
history_length : HOST_HISTORY_LENGTH
|
||||
},
|
||||
{
|
||||
title: "Memory monitoring information",
|
||||
monitor_resources : "mem_usage,used_mem,max_mem",
|
||||
humanize_figures : true,
|
||||
history_length : HOST_HISTORY_LENGTH
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
|
||||
var hosts_tab_content =
|
||||
'<form id="form_hosts" action="javascript:alert(\'js errors?!\')">\
|
||||
@ -205,14 +221,9 @@ var host_actions = {
|
||||
type: "monitor",
|
||||
call : OpenNebula.Host.monitor,
|
||||
callback: function(req,response) {
|
||||
var info = req.request.data[0];
|
||||
var label = info.monitor.monitor_res;
|
||||
|
||||
//remove spinner
|
||||
$('#host_monitoring_tab .loading_img').parent().remove();
|
||||
|
||||
var info = req.request.data[0].monitor;
|
||||
plot_graph(response,'#host_monitoring_tab',
|
||||
'host_monitor_'+label,label);
|
||||
'host_monitor_',info);
|
||||
},
|
||||
error: onError
|
||||
},
|
||||
@ -583,7 +594,7 @@ function updateHostInfo(request,host){
|
||||
|
||||
var monitor_tab = {
|
||||
title: "Monitoring information",
|
||||
content : generateMonitoringDivs(["cpu_usage","mem_usage"],"host_monitor_")
|
||||
content : generateMonitoringDivs(host_graphs,"host_monitor_")
|
||||
}
|
||||
|
||||
//Sunstone.updateInfoPanelTab(info_panel_name,tab_name, new tab object);
|
||||
@ -593,8 +604,9 @@ function updateHostInfo(request,host){
|
||||
|
||||
Sunstone.popUpInfoPanel("host_info_panel");
|
||||
//pop up panel while we retrieve the graphs
|
||||
Sunstone.runAction("Host.monitor",host_info.ID,{history_length: HOST_HISTORY_LENGTH, monitor_res: "cpu_usage"});
|
||||
Sunstone.runAction("Host.monitor",host_info.ID,{history_length: HOST_HISTORY_LENGTH, monitor_res: "mem_usage"});
|
||||
for (var i=0; i<host_graphs.length; i++){
|
||||
Sunstone.runAction("Host.monitor",host_info.ID,host_graphs[i]);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
@ -16,12 +16,38 @@
|
||||
|
||||
/*Virtual Machines tab plugin*/
|
||||
var INCLUDE_URI = "vendor/noVNC/include/";
|
||||
var VM_HISTORY_LENGTH = 40;
|
||||
|
||||
function loadVNC(){
|
||||
var script = '<script src="vendor/noVNC/include/vnc.js"></script>';
|
||||
document.write(script);
|
||||
}
|
||||
loadVNC();
|
||||
|
||||
var vm_graphs = [
|
||||
{ title : "CPU",
|
||||
monitor_resources : "cpu",
|
||||
humanize_figures : false,
|
||||
history_length : VM_HISTORY_LENGTH
|
||||
},
|
||||
{ title : "Memory",
|
||||
monitor_resources : "memory",
|
||||
humanize_figures : true,
|
||||
history_length : VM_HISTORY_LENGTH
|
||||
},
|
||||
{ title : "Network transmission",
|
||||
monitor_resources : "net_tx",
|
||||
humanize_figures : true,
|
||||
history_length : VM_HISTORY_LENGTH
|
||||
},
|
||||
{ title : "Network reception",
|
||||
monitor_resources : "net_rx",
|
||||
humanize_figures : true,
|
||||
history_length : VM_HISTORY_LENGTH
|
||||
},
|
||||
|
||||
]
|
||||
|
||||
var vms_tab_content =
|
||||
'<form id="virtualMachine_list" action="javascript:alert(\'js error!\');">\
|
||||
<div class="action_blocks">\
|
||||
@ -305,13 +331,7 @@ var vm_actions = {
|
||||
colored_log += line + "\n";
|
||||
}
|
||||
|
||||
var log_tab = {
|
||||
title: "VM log",
|
||||
content: '<pre>'+colored_log+'</pre>'
|
||||
}
|
||||
Sunstone.updateInfoPanelTab("vm_info_panel","vm_log_tab",log_tab);
|
||||
Sunstone.popUpInfoPanel("vm_info_panel",0);
|
||||
|
||||
$('#vm_log_tab#').html('<pre>'+colored_log+'</pre>')
|
||||
},
|
||||
error: function(request,error_json){
|
||||
$("#vm_log pre").html('');
|
||||
@ -333,6 +353,17 @@ var vm_actions = {
|
||||
callback: null,
|
||||
error: onError,
|
||||
notify: true
|
||||
},
|
||||
|
||||
"VM.monitor" : {
|
||||
type: "monitor",
|
||||
call : OpenNebula.VM.monitor,
|
||||
callback: function(req,response) {
|
||||
var info = req.request.data[0].monitor;
|
||||
plot_graph(response,'#vm_monitoring_tab',
|
||||
'vm_monitor_',info);
|
||||
},
|
||||
error: onError
|
||||
}
|
||||
}
|
||||
|
||||
@ -624,30 +655,36 @@ function updateVMInfo(request,vm){
|
||||
</tr>\
|
||||
</table>'
|
||||
}
|
||||
|
||||
|
||||
var template_tab = {
|
||||
title: "VM Template",
|
||||
content: '<table id="vm_template_table" class="info_table">\
|
||||
<thead><tr><th colspan="2">VM template</th></tr></thead>'+
|
||||
prettyPrintJSON(vm_info.TEMPLATE)+
|
||||
'</table>'
|
||||
'</table>'
|
||||
}
|
||||
|
||||
|
||||
var log_tab = {
|
||||
title: "VM log",
|
||||
content: '<pre>'+spinner+'</pre>'
|
||||
content: '<div>'+spinner+'</div>'
|
||||
}
|
||||
|
||||
Sunstone.updateInfoPanelTab("vm_info_panel","vm_info_tab",info_tab);
|
||||
|
||||
var monitoring_tab = {
|
||||
title: "Monitoring information",
|
||||
content: generateMonitoringDivs(vm_graphs,"vm_monitor_")
|
||||
}
|
||||
|
||||
Sunstone.updateInfoPanelTab("vm_info_panel","vm_info_tab",info_tab);
|
||||
Sunstone.updateInfoPanelTab("vm_info_panel","vm_template_tab",template_tab);
|
||||
Sunstone.updateInfoPanelTab("vm_info_panel","vm_log_tab",log_tab);
|
||||
|
||||
|
||||
//Here it is special, as we will let the callback from the VM.log
|
||||
//action popUp the info panel again when the info is received.
|
||||
Sunstone.updateInfoPanelTab("vm_info_panel","vm_monitoring_tab",monitoring_tab);
|
||||
|
||||
//Pop up the info panel and asynchronously get vm_log and stats
|
||||
Sunstone.popUpInfoPanel("vm_info_panel");
|
||||
Sunstone.runAction("VM.log",vm_info.ID);
|
||||
|
||||
for (var i=0; i<vm_graphs.length; i++){
|
||||
Sunstone.runAction("VM.monitor",vm_info.ID,vm_graphs[i]);
|
||||
};
|
||||
}
|
||||
|
||||
// Sets up the create-template dialog and all the processing associated to it,
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
|
||||
/* Some useful functions for Sunstone default plugins */
|
||||
var INTERVAL=60000;
|
||||
var INTERVAL=60000; //milisecs
|
||||
|
||||
function someTime(){
|
||||
return Math.floor(Math.random()*30000);
|
||||
@ -478,30 +478,62 @@ function escapeDoubleQuotes(string){
|
||||
return string.replace(/"/g,'\\"');
|
||||
}
|
||||
|
||||
function generateMonitoringDivs(labels, id_prefix){
|
||||
str = '<pre>'+spinner+'</pre>';
|
||||
var width = ($(window).width()-129)*40/100;
|
||||
$.each(labels,function(){
|
||||
str+='<div class="monitoring_info" id="'+id_prefix+this+'" style="width:'+width+'px; height:150px; margin: 20px 15px; display: inline-block;"></div>';
|
||||
function generateMonitoringDivs(graphs, id_prefix){
|
||||
var str = "";
|
||||
//40% of the width of the screen minus
|
||||
//129px (left menu size)
|
||||
var width = ($(window).width()-129)*45/100;
|
||||
var id_suffix="";
|
||||
var label="";
|
||||
|
||||
$.each(graphs,function(){
|
||||
label = this.monitor_resources;
|
||||
id_suffix=label.replace(/,/g,'_');
|
||||
id = id_prefix+id_suffix;
|
||||
str+='<table class="info_table">\
|
||||
<thead><tr><th colspan="1">'+this.title+'</th></tr></thead>\
|
||||
<tr><td id="legend_'+id_suffix+'"></td></tr>\
|
||||
<tr><td style="border:0">\
|
||||
<div id="'+id+'" style="width:'+width+'px; height:150px;">'+spinner+'</div>\
|
||||
</td></tr></table>';
|
||||
});
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
function plot_graph(data,context,id,label){
|
||||
function plot_graph(data,context,id_prefix,info){
|
||||
var labels = info.monitor_resources;
|
||||
var humanize = info.humanize_figures ? humanize_size : function(val){return val};
|
||||
var labels_arr = labels.split(',');
|
||||
var id_suffix = labels.replace(/,/g,'_');
|
||||
var series = [];
|
||||
var serie = null;
|
||||
|
||||
var serie = {
|
||||
label : label,
|
||||
data : data
|
||||
for (var i = 0; i< labels_arr.length; i++) {
|
||||
serie = {
|
||||
label: labels_arr[i],
|
||||
data: data[i]
|
||||
};
|
||||
series.push(serie);
|
||||
};
|
||||
|
||||
var options = {
|
||||
legend : { show : true },
|
||||
xaxis : { mode: "time", timeformat: "%h:%M" },
|
||||
yaxis : { labelWidth: 30 }
|
||||
legend : { show : true,
|
||||
noColumns: labels_arr.length,
|
||||
container: $('#legend_'+id_suffix)
|
||||
},
|
||||
xaxis : { mode: "time",
|
||||
timeformat: "%h:%M"
|
||||
},
|
||||
yaxis : { labelWidth: 40,
|
||||
tickFormatter: function(val, axis) {
|
||||
return humanize(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$.plot($('#'+id, context),[serie],options);
|
||||
id = id_prefix + id_suffix;
|
||||
$.plot($('#'+id, context),series,options);
|
||||
}
|
||||
|
||||
//functions that used as true and false conditions for testing mainly
|
||||
|
@ -1,7 +1,7 @@
|
||||
require 'OneMonitor'
|
||||
|
||||
class HostMonitor < OneMonitor
|
||||
#:time label is mandatory and must be first
|
||||
#:time, :id labels
|
||||
HOST_MONITORING_ELEMS = {
|
||||
:time => "LAST_MON_TIME",
|
||||
:id => "ID",
|
||||
@ -33,4 +33,12 @@ class HostMonitor < OneMonitor
|
||||
def snapshot
|
||||
super HostPool
|
||||
end
|
||||
|
||||
def active (host_hash)
|
||||
host_hash[:state].to_i < 3
|
||||
end
|
||||
|
||||
def error (host_hash)
|
||||
host_hash[:state].to_i == 3
|
||||
end
|
||||
end
|
||||
|
@ -35,7 +35,7 @@ class OneMonitor
|
||||
def snapshot(poolClass)
|
||||
#init global results
|
||||
|
||||
rc = monitor
|
||||
rc = monitor #calling the extending class method
|
||||
rc = save if rc
|
||||
if rc
|
||||
@results = []
|
||||
@ -64,7 +64,11 @@ class OneMonitor
|
||||
end
|
||||
@results << hash
|
||||
add_to_global(hash)
|
||||
@n_active += 1 if active(hash)
|
||||
@n_error += 1 if error(hash)
|
||||
@n_total += 1
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def reinit_global_results
|
||||
@ -72,6 +76,7 @@ class OneMonitor
|
||||
@monitoring_elems.each do | key,value |
|
||||
@global_results[key] = 0
|
||||
end
|
||||
@n_active = @n_error = @n_total = 0
|
||||
end
|
||||
|
||||
def add_to_global(hash)
|
||||
|
@ -39,11 +39,11 @@ module OneMonitorCSV
|
||||
|
||||
if !File.size?(global_log_file)
|
||||
then
|
||||
header = csv_header
|
||||
header = csv_header+",active,error,total"
|
||||
global_file.puts(header)
|
||||
end
|
||||
|
||||
csv = hash_to_csv(@global_results)
|
||||
csv = hash_to_csv(@global_results)+%&,"#{@n_active}","#{@n_error}","#{@n_total}"&
|
||||
global_file.puts(csv)
|
||||
global_file.close
|
||||
return 0
|
||||
|
@ -7,6 +7,7 @@ class VMMonitor < OneMonitor
|
||||
:id => "ID",
|
||||
:name => "NAME",
|
||||
:lcm_state => "LCM_STATE",
|
||||
:state => "STATE",
|
||||
:memory => "MEMORY",
|
||||
:cpu => "CPU",
|
||||
:net_tx => "NET_TX",
|
||||
@ -24,4 +25,12 @@ class VMMonitor < OneMonitor
|
||||
def snapshot
|
||||
super VirtualMachinePool
|
||||
end
|
||||
|
||||
def active (vm_hash)
|
||||
vm_hash[:state].to_i == 3
|
||||
end
|
||||
|
||||
def error (vm_hash)
|
||||
vm_hash[:state].to_i == 7
|
||||
end
|
||||
end
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
MONITOR_INTERVAL= ARGV[1]? ARGV[1].to_i : 60 #secs
|
||||
MONITOR_INTERVAL= ARGV[1]? ARGV[1].to_i : 10 #secs
|
||||
|
||||
$: << File.dirname(__FILE__)
|
||||
|
||||
|
@ -166,7 +166,7 @@ get '/:resource/monitor' do
|
||||
end
|
||||
|
||||
get '/:resource/:id/monitor' do
|
||||
@SunstoneServer.get_log(params[:resource],params[:id],settings.config,params['monitor_res'],params['history_length'])
|
||||
@SunstoneServer.get_log(params[:resource],params[:id],settings.config,params['monitor_resources'],params['history_length'])
|
||||
end
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user