mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-23 22:50:09 +03:00
Feature #650: Full graph integration, OneMonitor tool and client with CSV support.
This commit is contained in:
parent
3a54ee1ba5
commit
2df1d7bcb2
@ -23,12 +23,18 @@ if [ -z "$ONE_LOCATION" ]; then
|
||||
SUNSTONE_LOCK_FILE=/var/lock/one/.sunstone.lock
|
||||
SUNSTONE_LOG=/var/log/one/sunstone.log
|
||||
SUNSTONE_CONF=/etc/one/sunstone-server.conf
|
||||
ONEMONITOR_CMD=/usr/lib/one/sunstone/share/OneMonitor/runOneMonitor.sh
|
||||
HOST_LOG_FOLDER=/var/log/one/OneMonitor/host
|
||||
VM_LOG_FOLDER=/var/log/one/OneMonitor/vm
|
||||
else
|
||||
SUNSTONE_PID=$ONE_LOCATION/var/sunstone.pid
|
||||
SUNSTONE_SERVER=$ONE_LOCATION/lib/sunstone/config.ru
|
||||
SUNSTONE_LOCK_FILE=$ONE_LOCATION/var/.sunstone.lock
|
||||
SUNSTONE_LOG=$ONE_LOCATION/var/sunstone.log
|
||||
SUNSTONE_CONF=$ONE_LOCATION/etc/sunstone-server.conf
|
||||
ONEMONITOR_CMD=$ONE_LOCATION/lib/sunstone/share/OneMonitor/runOneMonitor.sh
|
||||
HOST_LOG_FOLDER=$ONE_LOCATION/var/OneMonitor/host
|
||||
VM_LOG_FOLDER=$ONE_LOCATION/var/OneMonitor/vm
|
||||
fi
|
||||
|
||||
setup()
|
||||
@ -84,6 +90,24 @@ start()
|
||||
fi
|
||||
|
||||
echo "sunstone-server listening on $HOST:$PORT"
|
||||
|
||||
# Start the monitoring app
|
||||
if [ ! -d $HOST_LOG_FOLDER ]
|
||||
then
|
||||
mkdir -p $HOST_LOG_FOLDER
|
||||
[[ $? -ne 0 ]] && ( echo "Error creating host log directory"; exit 1 )
|
||||
fi
|
||||
|
||||
if [ ! -d $VM_LOG_FOLDER ]
|
||||
then
|
||||
mkdir -p $VM_LOG_FOLDER
|
||||
[[ $? -ne 0 ]] && ( echo "Error creating vm log directory"; exit 1 )
|
||||
fi
|
||||
|
||||
$ONEMONITOR_CMD $MONITORING_INTERVAL $HOST_LOG_FOLDER $VM_LOG_FOLDER &>/dev/null &
|
||||
|
||||
[[ $? -ne 0 ]] && ( echo "Error launching monitoring daemon"; exit 1 )
|
||||
|
||||
}
|
||||
|
||||
#
|
||||
@ -102,6 +126,8 @@ stop()
|
||||
# Remove pid files
|
||||
rm -f $SUNSTONE_LOCK_FILE &> /dev/null
|
||||
|
||||
killall $ONEMONITOR_CMD
|
||||
|
||||
echo "sunstone-server stopped"
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,8 @@
|
||||
require 'OpenNebulaJSON'
|
||||
include OpenNebulaJSON
|
||||
|
||||
require 'OneMonitorClient'
|
||||
|
||||
class SunstoneServer
|
||||
def initialize(username, password)
|
||||
# TBD one_client_user(name) from CloudServer
|
||||
@ -265,60 +267,22 @@ class SunstoneServer
|
||||
#
|
||||
############################################################################
|
||||
|
||||
def get_log(resource,id,config,monitor_resources,history_length)
|
||||
log_file_prefix = case resource
|
||||
when "vm","VM"
|
||||
config[:host_log_file]
|
||||
when "host","HOST"
|
||||
config[:vm_log_file]
|
||||
end
|
||||
def get_log(params)
|
||||
resource = params[:resource]
|
||||
id = params[:id]
|
||||
id = "global" unless id
|
||||
columns = params['monitor_resources'].split(',')
|
||||
history_length = params['history_length']
|
||||
|
||||
if !log_file_prefix or log_file_prefix.empty?
|
||||
log_file_prefix = "/srv/cloud/one-dummy/logs/"+resource
|
||||
end
|
||||
log_file_folder = case resource
|
||||
when "vm","VM"
|
||||
VM_LOG_FOLDER
|
||||
when "host","HOST"
|
||||
HOST_LOG_FOLDER
|
||||
end
|
||||
|
||||
log_file = "#{log_file_prefix}_#{id}.csv"
|
||||
|
||||
first_line = `head -1 #{log_file}`.chomp
|
||||
|
||||
if $?.exitstatus != 0
|
||||
error = Error.new("Cannot open log file")
|
||||
return [500, error.to_json]
|
||||
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
|
||||
|
||||
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
|
||||
monitor_client = OneMonitorClient.new(id,log_file_folder)
|
||||
return monitor_client.get_data_for_id(id,columns,history_length).to_json
|
||||
end
|
||||
|
||||
############################################################################
|
||||
|
@ -55,17 +55,16 @@ table#dashboard_table tr {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
table#dashboard_table td{
|
||||
table#dashboard_table > tbody > tr > td{
|
||||
width:50%;
|
||||
}
|
||||
|
||||
div.panel {
|
||||
background-color: #ffffff;
|
||||
padding:0;
|
||||
width:80%;
|
||||
margin: 10px;
|
||||
border: 1px #ddd solid;
|
||||
min-height: 110px;
|
||||
min-height: 50px;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
-moz-box-shadow: 5px 5px 5px #888;
|
||||
@ -77,6 +76,8 @@ div.panel h3 {
|
||||
border: 0;
|
||||
padding:5px 10px 5px 10px;
|
||||
margin: 0;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
background-color: #353735;
|
||||
-webkit-border-radius: 3px 3px 0 0;
|
||||
-moz-border-radius: 3px 3px 0 0;
|
||||
@ -105,7 +106,7 @@ div.panel_info table.info_table tr {
|
||||
border: 0;
|
||||
border-bottom: 1px dotted #ccc;
|
||||
}
|
||||
div.panel_info table.info_table td {
|
||||
div.panel_info table.info_table > tbody > tr > td {
|
||||
border: 0;
|
||||
width: 100%!important;
|
||||
}
|
||||
@ -114,11 +115,11 @@ div.panel_info table.info_table td.value_td {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.key_td_green {
|
||||
.green {
|
||||
color: green!important;
|
||||
}
|
||||
|
||||
.key_td_red {
|
||||
.red {
|
||||
color: #B81515!important;
|
||||
}
|
||||
|
||||
@ -387,6 +388,12 @@ tr.even:hover{
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
.info_table td.graph_td{
|
||||
padding-top:0px!important;
|
||||
padding-bottom:0px!important;
|
||||
vertical-align:middle!important;
|
||||
}
|
||||
|
||||
.info_table td.value_td{
|
||||
text-align:left;
|
||||
}
|
||||
|
@ -504,6 +504,37 @@ var OpenNebula = {
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
"monitor_all" : function(params){
|
||||
var callback = params.success;
|
||||
var callback_error = params.error;
|
||||
var resource = OpenNebula.Host.resource;
|
||||
var data = params.data;
|
||||
|
||||
var method = "monitor";
|
||||
var action = OpenNebula.Helper.action(method);
|
||||
var request = OpenNebula.Helper.request(resource,method, data);
|
||||
|
||||
$.ajax({
|
||||
url: "host/monitor",
|
||||
type: "GET",
|
||||
data: data['monitor'],
|
||||
dataType: "json",
|
||||
success: function(response)
|
||||
{
|
||||
if (callback)
|
||||
{
|
||||
callback(request,response);
|
||||
}
|
||||
},
|
||||
error: function(response)
|
||||
{
|
||||
if (callback_error)
|
||||
{
|
||||
callback_error(request, OpenNebula.Error(response));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@ -1369,6 +1400,37 @@ var OpenNebula = {
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
"monitor_all" : function(params){
|
||||
var callback = params.success;
|
||||
var callback_error = params.error;
|
||||
var resource = OpenNebula.VM.resource;
|
||||
var data = params.data;
|
||||
|
||||
var method = "monitor";
|
||||
var action = OpenNebula.Helper.action(method);
|
||||
var request = OpenNebula.Helper.request(resource,method, data);
|
||||
|
||||
$.ajax({
|
||||
url: "vm/monitor",
|
||||
type: "GET",
|
||||
data: data['monitor'],
|
||||
dataType: "json",
|
||||
success: function(response)
|
||||
{
|
||||
if (callback)
|
||||
{
|
||||
callback(request,response);
|
||||
}
|
||||
},
|
||||
error: function(response)
|
||||
{
|
||||
if (callback_error)
|
||||
{
|
||||
callback_error(request, OpenNebula.Error(response));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
|
@ -14,44 +14,81 @@
|
||||
/* limitations under the License. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
var HISTORY_LENGTH=40;
|
||||
var GRAPH_AUTOREFRESH_INTERVAL=10000; //10 secs
|
||||
|
||||
var graph1 = {
|
||||
title : "graph1",
|
||||
monitor_resources : "total,active,error",
|
||||
history_length : HISTORY_LENGTH
|
||||
};
|
||||
|
||||
var graph2 = {
|
||||
title : "graph2",
|
||||
monitor_resources : "cpu_usage,used_cpu,max_cpu",
|
||||
history_length : HISTORY_LENGTH
|
||||
};
|
||||
|
||||
var graph3 = {
|
||||
title : "graph3",
|
||||
monitor_resources : "mem_usage,used_mem,max_mem",
|
||||
history_length : HISTORY_LENGTH
|
||||
};
|
||||
|
||||
var graph4 = {
|
||||
title : "graph4",
|
||||
monitor_resources : "total,active,error",
|
||||
history_length : HISTORY_LENGTH
|
||||
};
|
||||
|
||||
var graph5 = {
|
||||
title : "graph5",
|
||||
monitor_resources : "net_tx,net_rx",
|
||||
history_length : HISTORY_LENGTH
|
||||
};
|
||||
|
||||
var dashboard_tab_content =
|
||||
'<table id="dashboard_table">\
|
||||
<tr>\
|
||||
<td style="width:40%">\
|
||||
<table id="information_table">\
|
||||
<tr>\
|
||||
<td>\
|
||||
<div class="panel">\
|
||||
<h3><a href="#hosts_tab">Hosts</a>\
|
||||
<div class="new-resource">\
|
||||
<a class="action_button" href="#hosts_tab" value="Host.create_dialog">+</a>\
|
||||
</div>\
|
||||
</h3>\
|
||||
<div class="panel_info">\
|
||||
<table class="info_table">\
|
||||
<tr>\
|
||||
<td class="key_td">Total</td>\
|
||||
<td class="value_td"><span id="total_hosts"></span></td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td key_td_green">Active</td>\
|
||||
<td class="value_td"><span id="active_hosts"></span></td>\
|
||||
</tr>\
|
||||
</table>\
|
||||
</div>\
|
||||
</div>\
|
||||
</td>\
|
||||
<td>\
|
||||
<div class="panel">\
|
||||
<h3><a href="#hosts_tab">Clusters</a>\
|
||||
<div class="new-resource">\
|
||||
<a class="action_button" href="#hosts_tab" value="Cluster.create_dialog">+</a>\
|
||||
</div>\
|
||||
</h3>\
|
||||
<h3>Summary of resources</h3>\
|
||||
<div class="panel_info">\
|
||||
<table class="info_table">\
|
||||
<tr>\
|
||||
<td class="key_td">Total</td>\
|
||||
<td class="value_td"><span id="total_clusters"></span></td>\
|
||||
</tr>\
|
||||
</table>\
|
||||
\
|
||||
<table class="info_table">\
|
||||
<tr>\
|
||||
<td class="key_td">Hosts (total/active)</td>\
|
||||
<td class="value_td"><span id="total_hosts"></span><span id="active_hosts" class="green"></span></td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td">Clusters</td>\
|
||||
<td class="value_td"><span id="total_clusters"></span></td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td">VM Templates (total/public)</td>\
|
||||
<td class="value_td"><span id="total_templates"></span><span id="public_templates"></span></td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td">VM Instances (total/<span class="green">running</span>/<span class="red">failed</span>)</td>\
|
||||
<td class="value_td"><span id="total_vms"></span><span id="running_vms" class="green"></span><span id="failed_vms" class="red"></span></td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td">Virtual Networks (total/public)</td>\
|
||||
<td class="value_td"><span id="total_vnets"></span><span id="public_vnets"></span></td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td">Images (total/public)</td>\
|
||||
<td class="value_td"><span id="total_images"></span><span id="public_images"></span></td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td oneadmin">Users</td>\
|
||||
<td class="value_td oneadmin"><span id="total_users"></span></td>\
|
||||
</tr>\
|
||||
</table>\
|
||||
\
|
||||
</div>\
|
||||
</div>\
|
||||
</td>\
|
||||
@ -59,95 +96,67 @@ var dashboard_tab_content =
|
||||
<tr>\
|
||||
<td>\
|
||||
<div class="panel">\
|
||||
<h3><a href="#vms_tab">Virtual Machines</a>\
|
||||
<div class="new-resource">\
|
||||
<a class="action_button" href="#vms_tab" value="VM.create_dialog">+</a>\
|
||||
</div>\
|
||||
</h3>\
|
||||
<div class="panel_info">\
|
||||
<table class="info_table">\
|
||||
<tr>\
|
||||
<td class="key_td">Total</td>\
|
||||
<td class="value_td"><span id="total_vms"></span></td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td key_td_green">Running</td>\
|
||||
<td class="value_td"><span id="running_vms"></span></td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td key_td_red">Failed</td>\
|
||||
<td class="value_td"><span id="failed_vms"></span></td>\
|
||||
</tr>\
|
||||
</table>\
|
||||
</div>\
|
||||
</div>\
|
||||
</td>\
|
||||
<td>\
|
||||
<div class="panel">\
|
||||
<h3><a href="#vnets_tab">Virtual Networks</a>\
|
||||
<div class="new-resource">\
|
||||
<a class="action_button" href="#vnets_tab" value="Network.create_dialog">+</a>\
|
||||
</div>\
|
||||
</h3>\
|
||||
<div class="panel_info">\
|
||||
<table class="info_table">\
|
||||
<tr>\
|
||||
<td class="key_td">Total</td>\
|
||||
<td class="value_td"><span id="total_vnets"></span></td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td">Public</td>\
|
||||
<td class="value_td"><span id="public_vnets"></span></td>\
|
||||
</tr>\
|
||||
</table>\
|
||||
</div>\
|
||||
</div>\
|
||||
<h3>Quickstart</h3>\
|
||||
<form id="quickstart_form"><fieldset>\
|
||||
<table style="width:100%;"><tr style="vertical-align:middle;"><td style="width:70%">\
|
||||
<label style="font-weight:bold;width:40px;height:7em;">New:</label>\
|
||||
<input type="radio" name="quickstart" value="Host.create_dialog">Host</input><br />\
|
||||
<input type="radio" name="quickstart" value="Cluster.create_dialog">Cluster</input><br />\
|
||||
<input type="radio" name="quickstart" value="Template.create_dialog">VM Template</input><br />\
|
||||
<input type="radio" name="quickstart" value="VM.create_dialog">VM Instance</input><br />\
|
||||
<input type="radio" name="quickstart" value="Image.create_dialog">Image</input><br />\
|
||||
<input type="radio" name="quickstart" value="User.create_dialog">User</input><br />\
|
||||
</td><td>\
|
||||
<button id="quickstart">Go</button></fieldset></form>\
|
||||
</td></tr></table>\
|
||||
</div>\
|
||||
</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td>\
|
||||
<div class="panel">\
|
||||
<h3>\
|
||||
<a href="#images_tab">Images</a>\
|
||||
<div class="new-resource">\
|
||||
<a class="action_button" href="#images_tab" value="Image.create_dialog">+</a>\
|
||||
</div>\
|
||||
</h3>\
|
||||
<div class="panel_info">\
|
||||
<table class="info_table">\
|
||||
<tr>\
|
||||
<td class="key_td">Total</td>\
|
||||
<td class="value_td"><span id="total_images"></span></td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td">Public</td>\
|
||||
<td class="value_td"><span id="public_images"></span></td>\
|
||||
</tr>\
|
||||
</table>\
|
||||
</div>\
|
||||
<h3>Sunstone documentation</h3>\
|
||||
<ul style="list-style-type:none;">\
|
||||
<li>Sunstone installation and setup</li>\
|
||||
<li>Sunstone plugin guide</li>\
|
||||
<li>Sunstone plugin reference</li>\
|
||||
</ul>\
|
||||
</div>\
|
||||
</td>\
|
||||
<td class="oneadmin">\
|
||||
</tr>\
|
||||
</table>\
|
||||
</td>\
|
||||
<td style="width:60%">\
|
||||
<table id="historical_table" style="width:100%">\
|
||||
<tr>\
|
||||
<td>\
|
||||
<div class="panel">\
|
||||
<h3><a href="#users_tab">Users</a>\
|
||||
<div class="new-resource">\
|
||||
<a class="action_button" href="#users_tab" value="User.create_dialog">+</a>\
|
||||
</div>\
|
||||
</h3>\
|
||||
<h3>Historical monitoring information</h3>\
|
||||
<div class="panel_info">\
|
||||
<table class="info_table">\
|
||||
<tr>\
|
||||
<td class="key_td">Total</td>\
|
||||
<td class="value_td"><span id="total_users"></span></td>\
|
||||
</tr>\
|
||||
</table>\
|
||||
<table class="info_table">\
|
||||
<tr><td class="key_td graph_td">Total host count</td>\
|
||||
<td class="graph_td" id="graph1_legend"></td></tr>\
|
||||
<tr><td id="graph1" colspan="2">'+spinner+'</td></tr>\
|
||||
<tr><td class="key_td graph_td">Hosts CPU</td>\
|
||||
<td class="graph_td" id="graph2_legend"></td></tr>\
|
||||
<tr><td id="graph2" colspan="2">'+spinner+'</td></tr>\
|
||||
<tr><td class="key_td graph_td">Hosts memory</td>\
|
||||
<td class="graph_td" id="graph3_legend"></td></tr>\
|
||||
<tr><td id="graph3" colspan="2">'+spinner+'</td></tr>\
|
||||
<tr><td class="key_td graph_td">Total VM count</td>\
|
||||
<td class="graph_td" id="graph4_legend"></td></tr>\
|
||||
<tr><td id="graph4" colspan="2">'+spinner+'</td></tr>\
|
||||
<tr><td class="key_td graph_td">VM Network stats</td>\
|
||||
<td class="graph_td" id="graph5_legend"></td></tr>\
|
||||
<tr><td id="graph5" colspan="2">'+spinner+'</td></tr>\
|
||||
</table>\
|
||||
</div>\
|
||||
</div>\
|
||||
</td>\
|
||||
</tr>\
|
||||
</table>';
|
||||
|
||||
</table>\
|
||||
</td>\
|
||||
</tr></table>';
|
||||
|
||||
var dashboard_tab = {
|
||||
title: 'Dashboard',
|
||||
@ -157,6 +166,74 @@ var dashboard_tab = {
|
||||
|
||||
Sunstone.addMainTab('dashboard_tab',dashboard_tab);
|
||||
|
||||
function plot_global_graph(data,info){
|
||||
var id = info.title;
|
||||
var labels_arr = info.monitor_resources.split(',');
|
||||
var serie;
|
||||
var series = [];
|
||||
var width = ($(window).width()-129)*45/100;
|
||||
|
||||
$('#'+id).html('<div id="'+id+'_graph" style="height:70px;width:'+width+'px"><div>');
|
||||
|
||||
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,
|
||||
noColumns: labels_arr.length,
|
||||
container: $('#'+id+'_legend')},
|
||||
xaxis : { mode: "time",
|
||||
timeformat: "%h:%M"
|
||||
},
|
||||
yaxis : { labelWidth: 40 }
|
||||
}
|
||||
|
||||
switch (id){
|
||||
case "graph3":
|
||||
case "graph5":
|
||||
options["yaxis"]["tickFormatter"] = function(val,axis) { return humanize_size(val); }
|
||||
}
|
||||
|
||||
|
||||
|
||||
$.plot($('#'+id+'_graph'),series,options);
|
||||
}
|
||||
|
||||
function quickstart_setup(){
|
||||
|
||||
$('#quickstart').button("disable");
|
||||
|
||||
$('#quickstart_form input').click(function(){
|
||||
$('#quickstart').val($(this).val());
|
||||
$('#quickstart').button("enable");
|
||||
});
|
||||
|
||||
$('#quickstart').click(function(){
|
||||
Sunstone.runAction($(this).val());
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
function graph_autorefresh(){
|
||||
setInterval(function(){
|
||||
refresh_graphs();
|
||||
},GRAPH_AUTOREFRESH_INTERVAL);
|
||||
|
||||
}
|
||||
|
||||
function refresh_graphs(){
|
||||
Sunstone.runAction("Host.monitor_all", graph1);
|
||||
Sunstone.runAction("Host.monitor_all", graph2);
|
||||
Sunstone.runAction("Host.monitor_all", graph3);
|
||||
Sunstone.runAction("VM.monitor_all", graph4);
|
||||
Sunstone.runAction("VM.monitor_all", graph5);
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
//Dashboard link listener
|
||||
$("#dashboard_table h3 a").live("click", function (){
|
||||
@ -164,13 +241,17 @@ $(document).ready(function(){
|
||||
showTab(tab);
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
emptyDashboard();
|
||||
if (uid!=0) {
|
||||
$("td.oneadmin").hide();
|
||||
}
|
||||
|
||||
|
||||
|
||||
quickstart_setup();
|
||||
|
||||
refresh_graphs();
|
||||
graph_autorefresh();
|
||||
|
||||
});
|
||||
|
||||
//puts the dashboard values into "retrieving"
|
||||
@ -180,62 +261,73 @@ function emptyDashboard(){
|
||||
|
||||
|
||||
function updateDashboard(what,json_info){
|
||||
db = $('#dashboard_tab');
|
||||
switch (what){
|
||||
case "hosts":
|
||||
total_hosts=json_info.length;
|
||||
active_hosts=0;
|
||||
$.each(json_info,function(){
|
||||
if (parseInt(this.HOST.STATE) < 3){
|
||||
active_hosts++;}
|
||||
});
|
||||
$('#total_hosts',db).html(total_hosts);
|
||||
$('#active_hosts',db).html(active_hosts);
|
||||
break;
|
||||
case "clusters":
|
||||
total_clusters=json_info.length;
|
||||
$('#total_clusters',db).html(total_clusters);
|
||||
break;
|
||||
case "vms":
|
||||
total_vms=json_info.length;
|
||||
running_vms=0;
|
||||
var db = $('#dashboard_tab');
|
||||
switch (what){
|
||||
case "hosts":
|
||||
var total_hosts=json_info.length;
|
||||
var active_hosts=0;
|
||||
$.each(json_info,function(){
|
||||
if (parseInt(this.HOST.STATE) < 3){
|
||||
active_hosts++;}
|
||||
});
|
||||
$('#total_hosts',db).html(total_hosts+' / ');
|
||||
$('#active_hosts',db).html(active_hosts);
|
||||
break;
|
||||
case "clusters":
|
||||
var total_clusters=json_info.length;
|
||||
$('#total_clusters',db).html(total_clusters);
|
||||
break;
|
||||
case "vms":
|
||||
var total_vms=json_info.length;
|
||||
var running_vms=0;
|
||||
failed_vms=0;
|
||||
$.each(json_info,function(){
|
||||
vm_state = parseInt(this.VM.STATE);
|
||||
if (vm_state == 3){
|
||||
running_vms++;
|
||||
}
|
||||
else if (vm_state == 7) {
|
||||
failed_vms++;
|
||||
}
|
||||
});
|
||||
$('#total_vms',db).html(total_vms);
|
||||
$('#running_vms',db).html(running_vms);
|
||||
$('#failed_vms',db).html(failed_vms);
|
||||
break;
|
||||
case "vnets":
|
||||
public_vnets=0;
|
||||
total_vnets=json_info.length;
|
||||
$.each(json_info,function(){
|
||||
if (parseInt(this.VNET.PUBLIC)){
|
||||
public_vnets++;}
|
||||
});
|
||||
$('#total_vnets',db).html(total_vnets);
|
||||
$('#public_vnets',db).html(public_vnets);
|
||||
break;
|
||||
case "users":
|
||||
total_users=json_info.length;
|
||||
$('#total_users',db).html(total_users);
|
||||
break;
|
||||
case "images":
|
||||
total_images=json_info.length;
|
||||
public_images=0;
|
||||
$.each(json_info,function(){
|
||||
if (parseInt(this.IMAGE.PUBLIC)){
|
||||
public_images++;}
|
||||
});
|
||||
$('#total_images',db).html(total_images);
|
||||
$('#public_images',db).html(public_images);
|
||||
break;
|
||||
}
|
||||
}
|
||||
$.each(json_info,function(){
|
||||
vm_state = parseInt(this.VM.STATE);
|
||||
if (vm_state == 3){
|
||||
running_vms++;
|
||||
}
|
||||
else if (vm_state == 7) {
|
||||
failed_vms++;
|
||||
}
|
||||
});
|
||||
$('#total_vms',db).html(total_vms+' / ');
|
||||
$('#running_vms',db).html(running_vms+' / ');
|
||||
$('#failed_vms',db).html(failed_vms);
|
||||
break;
|
||||
case "vnets":
|
||||
var public_vnets=0;
|
||||
var total_vnets=json_info.length;
|
||||
$.each(json_info,function(){
|
||||
if (parseInt(this.VNET.PUBLIC)){
|
||||
public_vnets++;}
|
||||
});
|
||||
$('#total_vnets',db).html(total_vnets+' / ');
|
||||
$('#public_vnets',db).html(public_vnets);
|
||||
break;
|
||||
case "users":
|
||||
var total_users=json_info.length;
|
||||
$('#total_users',db).html(total_users);
|
||||
break;
|
||||
case "images":
|
||||
var total_images=json_info.length;
|
||||
var public_images=0;
|
||||
$.each(json_info,function(){
|
||||
if (parseInt(this.IMAGE.PUBLIC)){
|
||||
public_images++;}
|
||||
});
|
||||
$('#total_images',db).html(total_images+' / ');
|
||||
$('#public_images',db).html(public_images);
|
||||
break;
|
||||
case "templates":
|
||||
var total_templates=json_info.length;
|
||||
var public_templates=0;
|
||||
$.each(json_info,function(){
|
||||
if (parseInt(this.VMTEMPLATE.PUBLIC)){
|
||||
public_templates++;
|
||||
}
|
||||
});
|
||||
$('#total_templates',db).html(total_templates+' / ');
|
||||
$('#public_templates',db).html(public_templates);
|
||||
break;
|
||||
}
|
||||
}
|
@ -231,6 +231,10 @@ var host_actions = {
|
||||
"Host.monitor_all" : {
|
||||
type: "monitor_global",
|
||||
call: OpenNebula.Host.monitor_all,
|
||||
callback: function(req,response) {
|
||||
var info = req.request.data[0].monitor;
|
||||
plot_global_graph(response,info);
|
||||
},
|
||||
error: onError
|
||||
},
|
||||
|
||||
|
@ -663,13 +663,16 @@ function setupCreateImageDialog(){
|
||||
//Insert HTML in place
|
||||
$('#create_image_dialog').html(create_image_tmpl);
|
||||
|
||||
var height = Math.floor($(window).height()*0.8); //set height to a percentage of the window
|
||||
|
||||
//Prepare jquery dialog
|
||||
$('#create_image_dialog').dialog({
|
||||
autoOpen: false,
|
||||
modal:true,
|
||||
width: 520
|
||||
});
|
||||
|
||||
autoOpen: false,
|
||||
modal:true,
|
||||
width: 520,
|
||||
height: height
|
||||
});
|
||||
|
||||
$('#img_tabs').tabs();
|
||||
$('#create_image_dialog button').button();
|
||||
$('#img_type option').first().attr("selected","selected");
|
||||
|
@ -803,6 +803,7 @@ function updateTemplateSelect(){
|
||||
|
||||
//update static selectors:
|
||||
$('#create_vm_dialog #template_id').html(templates_select);
|
||||
$('#speed_virt').html(templates_select);
|
||||
}
|
||||
|
||||
// Callback to update an element in the dataTable
|
||||
|
@ -44,9 +44,8 @@ var vm_graphs = [
|
||||
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!\');">\
|
||||
@ -364,7 +363,16 @@ var vm_actions = {
|
||||
'vm_monitor_',info);
|
||||
},
|
||||
error: onError
|
||||
}
|
||||
},
|
||||
"VM.monitor_all" : {
|
||||
type: "monitor_global",
|
||||
call: OpenNebula.VM.monitor_all,
|
||||
callback: function(req,response) {
|
||||
var info = req.request.data[0].monitor;
|
||||
plot_global_graph(response,info);
|
||||
},
|
||||
error: onError
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
var cookie = {};
|
||||
var username = '';
|
||||
var uid = '';
|
||||
var spinner = '<img src="/images/ajax-loader.gif" alt="retrieving" class="loading_img"/>';
|
||||
var spinner = '<img src="/images/ajax-loader.gif" alt="retrieving" class="loading_img" />';
|
||||
|
||||
|
||||
//Sunstone configuration is formed by predifined "actions", main tabs
|
||||
@ -194,7 +194,7 @@ var Sunstone = {
|
||||
// * The default actions. Simple call the the pre-defined "call"
|
||||
// function with an extraparam if defined.
|
||||
switch (action_cfg.type){
|
||||
|
||||
|
||||
case "create":
|
||||
case "register":
|
||||
call({data:data_arg, success: callback, error:err});
|
||||
@ -206,11 +206,11 @@ var Sunstone = {
|
||||
call({success: callback, error:err});
|
||||
break;
|
||||
case "monitor_global":
|
||||
call({success: callback, error:err, data: {monitor: extra_param}});
|
||||
call({timeout: true, success: callback, error:err, data: {monitor: data_arg}});
|
||||
break;
|
||||
case "monitor":
|
||||
case "monitor_single":
|
||||
call({success: callback, error:err, data: {id:data_arg, monitor: extra_param}});
|
||||
call({timeout: true, success: callback, error:err, data: {id:data_arg, monitor: extra_param}});
|
||||
break;
|
||||
case "multiple":
|
||||
//run on the list of nodes that come on the data
|
||||
|
@ -1,3 +1,19 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
require 'OneMonitor'
|
||||
|
||||
class HostMonitor < OneMonitor
|
||||
@ -22,16 +38,12 @@ class HostMonitor < OneMonitor
|
||||
:used_cpu => "HOST_SHARE/USED_CPU"
|
||||
}
|
||||
|
||||
def initialize (log_file,monitoring_elems=HOST_MONITORING_ELEMS)
|
||||
super log_file,monitoring_elems
|
||||
def initialize (log_file_folder,monitoring_elems=HOST_MONITORING_ELEMS)
|
||||
super log_file_folder,monitoring_elems
|
||||
end
|
||||
|
||||
def monitor
|
||||
super HostPool
|
||||
end
|
||||
|
||||
def snapshot
|
||||
super HostPool
|
||||
def factory(client)
|
||||
HostPool.new(client)
|
||||
end
|
||||
|
||||
def active (host_hash)
|
||||
|
@ -1,3 +1,19 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
ONE_LOCATION = ENV["ONE_LOCATION"]
|
||||
|
||||
if !ONE_LOCATION
|
||||
@ -19,10 +35,10 @@ class OneMonitor
|
||||
when "CSV" then include OneMonitorCSV
|
||||
end
|
||||
|
||||
def initialize(log_file_prefix,monitoring_elems)
|
||||
def initialize(log_file_folder,monitoring_elems)
|
||||
# Authenticate in OpenNebula
|
||||
@client = Client.new
|
||||
@log_file_prefix = log_file_prefix
|
||||
@log_file_folder = log_file_folder
|
||||
@monitoring_elems = monitoring_elems
|
||||
@results = []
|
||||
reinit_global_results
|
||||
@ -32,7 +48,7 @@ class OneMonitor
|
||||
@results
|
||||
end
|
||||
|
||||
def snapshot(poolClass)
|
||||
def snapshot
|
||||
#init global results
|
||||
|
||||
rc = monitor #calling the extending class method
|
||||
@ -47,23 +63,31 @@ class OneMonitor
|
||||
return rc
|
||||
end
|
||||
|
||||
def monitor(poolClass)
|
||||
pool = poolClass.new(@client)
|
||||
def monitor
|
||||
pool = factory(@client)
|
||||
rc = pool.info
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
then
|
||||
puts "Error monitoring: #{rc}"
|
||||
puts "Error monitoring: #{rc.message}"
|
||||
return nil
|
||||
end
|
||||
|
||||
pool.each do | elem |
|
||||
time = elem[@monitoring_elems[:time]].to_i
|
||||
|
||||
hash = {}
|
||||
@monitoring_elems.each do | key,value |
|
||||
hash[key] = elem[value]
|
||||
end
|
||||
@results << hash
|
||||
add_to_global(hash)
|
||||
|
||||
#do not log time = 0, it causes
|
||||
#graphs being drawn from 1970
|
||||
|
||||
if time > 0
|
||||
@results << hash
|
||||
add_to_global(hash)
|
||||
end
|
||||
|
||||
@n_active += 1 if active(hash)
|
||||
@n_error += 1 if error(hash)
|
||||
@n_total += 1
|
||||
@ -83,7 +107,8 @@ class OneMonitor
|
||||
hash.each do | key,value |
|
||||
@global_results[key] += value.to_i
|
||||
end
|
||||
@global_results[:time] = hash[:time].to_i
|
||||
time = hash[:time].to_i
|
||||
@global_results[:time] = time
|
||||
end
|
||||
|
||||
end
|
||||
|
35
src/sunstone/share/OneMonitor/OneMonitorClient.rb
Normal file
35
src/sunstone/share/OneMonitor/OneMonitorClient.rb
Normal file
@ -0,0 +1,35 @@
|
||||
require 'OneMonitorClientUtils'
|
||||
|
||||
class OneMonitorClient
|
||||
|
||||
INPUT_METHOD="CSV"
|
||||
case INPUT_METHOD
|
||||
when "CSV" then include OneMonitorCSVClient
|
||||
end
|
||||
|
||||
def initialize(ids, log_file_folder)
|
||||
#create filenames to read
|
||||
ids = [ids] unless ids.class == Array
|
||||
@file_names = {}
|
||||
ids.each do | id |
|
||||
@file_names[id] = OneMonitorClient.full_path(log_file_folder,id)
|
||||
end
|
||||
return @file_names
|
||||
end
|
||||
|
||||
def get_multiple_data(columns,length)
|
||||
result = []
|
||||
@file_names.each do | id,file_name |
|
||||
result << get_data_for_id(id,columns,length)
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
def get_data_for_id(id, columns, length)
|
||||
readOneMonitorFile(@file_names[id],columns,length)
|
||||
end
|
||||
|
||||
def self.full_path(folder,id)
|
||||
"#{folder}/#{id}"
|
||||
end
|
||||
end
|
40
src/sunstone/share/OneMonitor/OneMonitorClientUtils.rb
Normal file
40
src/sunstone/share/OneMonitor/OneMonitorClientUtils.rb
Normal file
@ -0,0 +1,40 @@
|
||||
module OneMonitorCSVClient
|
||||
def readOneMonitorFile(file_name,columns,length)
|
||||
first_line = `head -1 #{file_name}`.chomp
|
||||
|
||||
if $?.exitstatus != 0
|
||||
return [] #silently fail, cannot find this file
|
||||
end
|
||||
|
||||
n_lines = `wc -l #{file_name} | cut -d' ' -f 1`.to_i
|
||||
if n_lines <= length.to_i
|
||||
length = n_lines-1
|
||||
end
|
||||
|
||||
fields = first_line.split(',')
|
||||
poll_time_pos = fields.index("time")
|
||||
|
||||
if !poll_time_pos
|
||||
return [] #silently fail, no timestamp
|
||||
end
|
||||
|
||||
tail = `tail -#{length} #{file_name}`
|
||||
series = [] #will hold several graphs
|
||||
|
||||
columns.each do | column_name |
|
||||
|
||||
graph = []
|
||||
column_pos = fields.index(column_name)
|
||||
next unless column_pos
|
||||
|
||||
tail.each_line do | line |
|
||||
line_arr = line.delete('"').split(',')
|
||||
graph << [ line_arr[poll_time_pos].to_i*1000, line_arr[column_pos].to_i ]
|
||||
end
|
||||
|
||||
series << graph
|
||||
end
|
||||
|
||||
return series
|
||||
end
|
||||
end
|
@ -1,3 +1,19 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
module OneMonitorCSV
|
||||
|
||||
def save
|
||||
@ -9,13 +25,12 @@ module OneMonitorCSV
|
||||
|
||||
@results.each do | mon_hash |
|
||||
id = mon_hash[:id]
|
||||
log_name = "#{@log_file_prefix}_#{id}.csv"
|
||||
log_name = "#{@log_file_folder}/#{id}"
|
||||
|
||||
begin
|
||||
log_file = File.new(log_name,'a')
|
||||
|
||||
if !File.size?(log_name)
|
||||
then
|
||||
header = csv_header
|
||||
log_file.puts(header)
|
||||
end
|
||||
@ -34,7 +49,7 @@ module OneMonitorCSV
|
||||
def save_global_csv
|
||||
begin
|
||||
|
||||
global_log_file = "#{@log_file_prefix}_global.csv"
|
||||
global_log_file = "#{@log_file_folder}/global"
|
||||
global_file = File.new(global_log_file,'a')
|
||||
|
||||
if !File.size?(global_log_file)
|
||||
|
@ -1,3 +1,19 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
require 'OneMonitor'
|
||||
|
||||
class VMMonitor < OneMonitor
|
||||
@ -14,16 +30,12 @@ class VMMonitor < OneMonitor
|
||||
:net_rx => "NET_RX"
|
||||
}
|
||||
|
||||
def initialize (log_file,monitoring_elems=VM_MONITORING_ELEMS)
|
||||
super log_file,monitoring_elems
|
||||
def initialize (log_file_folder,monitoring_elems=VM_MONITORING_ELEMS)
|
||||
super log_file_folder,monitoring_elems
|
||||
end
|
||||
|
||||
def monitor
|
||||
super VirtualMachinePool
|
||||
end
|
||||
|
||||
def snapshot
|
||||
super VirtualMachinePool
|
||||
def factory(client)
|
||||
VirtualMachinePool.new(client)
|
||||
end
|
||||
|
||||
def active (vm_hash)
|
||||
|
41
src/sunstone/share/OneMonitor/runOneMonitor.rb
Executable file
41
src/sunstone/share/OneMonitor/runOneMonitor.rb
Executable file
@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
$: << File.dirname(__FILE__)
|
||||
|
||||
require 'HostMonitor.rb'
|
||||
require 'VMMonitor.rb'
|
||||
|
||||
DEFAULT_INTERVAL= 600 #secs
|
||||
DEFAULT_HOST_LOG_FOLDER = "#{ENV['ONE_LOCATION']}/logs/host/"
|
||||
DEFAULT_VM_LOG_FOLDER = "#{ENV['ONE_LOCATION']}/logs/vm/"
|
||||
|
||||
|
||||
#ARG0=interval, ARG1=hostfolder, ARG2=vmfolder
|
||||
MONITOR_INTERVAL= ARGV[0]? ARGV[0].to_i : DEFAULT_INTERVAL #secs
|
||||
HOST_LOG_FOLDER= ARGV[1]? ARGV[1]: DEFAULT_HOST_LOG_FOLDER
|
||||
VM_LOG_FOLDER=ARGV[2] ? ARGV[2] : DEFAULT_VM_LOG_FOLDER
|
||||
|
||||
hostm = HostMonitor.new(HOST_LOG_FOLDER)
|
||||
vmm = VMMonitor.new(VM_LOG_FOLDER)
|
||||
|
||||
while true do
|
||||
hostm.snapshot
|
||||
vmm.snapshot
|
||||
sleep MONITOR_INTERVAL
|
||||
end
|
@ -1,20 +0,0 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
MONITOR_INTERVAL= ARGV[1]? ARGV[1].to_i : 10 #secs
|
||||
|
||||
$: << File.dirname(__FILE__)
|
||||
|
||||
require 'HostMonitor.rb'
|
||||
require 'VMMonitor.rb'
|
||||
|
||||
FILE= ARGV[0]? ARGV[0]: "#{ENV['ONE_LOCATION']}/logs/"
|
||||
|
||||
hostm = HostMonitor.new(FILE+"host")
|
||||
vmm = VMMonitor.new(FILE+"vm")
|
||||
|
||||
while true do
|
||||
hostm.snapshot
|
||||
vmm.snapshot
|
||||
sleep MONITOR_INTERVAL
|
||||
end
|
||||
|
@ -31,8 +31,12 @@ else
|
||||
CONFIGURATION_FILE = ONE_LOCATION+"/etc/sunstone-server.conf"
|
||||
end
|
||||
|
||||
HOST_LOG_FOLDER = LOG_LOCATION+"/OneMonitor/host"
|
||||
VM_LOG_FOLDER = LOG_LOCATION+"/OneMonitor/vm"
|
||||
|
||||
$: << RUBY_LIB_LOCATION
|
||||
$: << File.dirname(__FILE__)+'/models'
|
||||
$: << File.dirname(__FILE__)+'/share/OneMonitor'
|
||||
|
||||
##############################################################################
|
||||
# Required libraries
|
||||
@ -91,6 +95,7 @@ helpers do
|
||||
session.clear
|
||||
return [204, ""]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
before do
|
||||
@ -161,12 +166,11 @@ end
|
||||
##############################################################################
|
||||
|
||||
get '/:resource/monitor' do
|
||||
|
||||
|
||||
@SunstoneServer.get_log(params)
|
||||
end
|
||||
|
||||
get '/:resource/:id/monitor' do
|
||||
@SunstoneServer.get_log(params[:resource],params[:id],settings.config,params['monitor_resources'],params['history_length'])
|
||||
@SunstoneServer.get_log(params)
|
||||
end
|
||||
|
||||
|
||||
|
304
src/sunstone/sunstone-server.rb.startmonitor
Executable file
304
src/sunstone/sunstone-server.rb.startmonitor
Executable file
@ -0,0 +1,304 @@
|
||||
#!/usr/bin/env ruby
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
ONE_LOCATION = ENV["ONE_LOCATION"]
|
||||
|
||||
if !ONE_LOCATION
|
||||
LOG_LOCATION = "/var/log/one"
|
||||
VAR_LOCATION = "/var/lib/one"
|
||||
RUBY_LIB_LOCATION = "/usr/lib/one/ruby"
|
||||
CONFIGURATION_FILE = "/etc/one/sunstone-server.conf"
|
||||
else
|
||||
VAR_LOCATION = ONE_LOCATION+"/var"
|
||||
LOG_LOCATION = ONE_LOCATION+"/var"
|
||||
RUBY_LIB_LOCATION = ONE_LOCATION+"/lib/ruby"
|
||||
CONFIGURATION_FILE = ONE_LOCATION+"/etc/sunstone-server.conf"
|
||||
end
|
||||
|
||||
HOST_LOG_FOLDER = LOG_LOCATION+"/OneMonitor/host"
|
||||
VM_LOG_FOLDER = LOG_LOCATION+"/OneMonitor/vm"
|
||||
|
||||
#TODO put share
|
||||
MONITOR_CMD = File.dirname(__FILE__)+'/share/OneMonitor/runOneMonitor.rb'
|
||||
MONITORING_INTERVAL = 10 #seconds
|
||||
|
||||
$: << RUBY_LIB_LOCATION
|
||||
$: << File.dirname(__FILE__)+'/models'
|
||||
|
||||
##############################################################################
|
||||
# Required libraries
|
||||
##############################################################################
|
||||
require 'rubygems'
|
||||
require 'sinatra'
|
||||
|
||||
require 'cloud/Configuration'
|
||||
require 'SunstoneServer'
|
||||
|
||||
set :config, Configuration.new(CONFIGURATION_FILE)
|
||||
|
||||
##############################################################################
|
||||
# Sinatra Configuration
|
||||
##############################################################################
|
||||
use Rack::Session::Pool
|
||||
set :host, settings.config[:host]
|
||||
set :port, settings.config[:port]
|
||||
|
||||
##############################################################################
|
||||
# Helpers
|
||||
##############################################################################
|
||||
helpers do
|
||||
def authorized?
|
||||
session[:ip] && session[:ip]==request.ip ? true : false
|
||||
end
|
||||
|
||||
def build_session
|
||||
auth = Rack::Auth::Basic::Request.new(request.env)
|
||||
if auth.provided? && auth.basic? && auth.credentials
|
||||
user = auth.credentials[0]
|
||||
sha1_pass = Digest::SHA1.hexdigest(auth.credentials[1])
|
||||
|
||||
rc = SunstoneServer.authorize(user, sha1_pass)
|
||||
if rc[1]
|
||||
session[:user] = user
|
||||
session[:user_id] = rc[1]
|
||||
session[:password] = sha1_pass
|
||||
session[:ip] = request.ip
|
||||
session[:remember] = params[:remember]
|
||||
|
||||
if params[:remember]
|
||||
env['rack.session.options'][:expire_after] = 30*60*60*24
|
||||
end
|
||||
|
||||
return [204, ""]
|
||||
else
|
||||
return [rc.first, ""]
|
||||
end
|
||||
end
|
||||
|
||||
return [401, ""]
|
||||
end
|
||||
|
||||
def destroy_session
|
||||
session.clear
|
||||
return [204, ""]
|
||||
end
|
||||
|
||||
def start_monitor
|
||||
if !session['monitor']
|
||||
config = settings.config
|
||||
|
||||
begin
|
||||
Dir.mkdir(HOST_LOG_FOLDER) if !File.directory?(HOST_LOG_FOLDER)
|
||||
Dir.mkdir(VM_LOG_FOLDER) if !File.directory?(VM_LOG_FOLDER)
|
||||
rescue
|
||||
return [500,Error.new("Cannot create log folders")]
|
||||
end
|
||||
|
||||
monitoring_interval = config[:monitoring_interval]
|
||||
monitoring_interval = MONITORING_INTERVAL if !monitoring_interval
|
||||
|
||||
pipe = IO.popen("#{MONITOR_CMD} #{monitoring_interval} #{HOST_LOG_FOLDER} #{VM_LOG_FOLDER}")
|
||||
session['monitor'] = pipe
|
||||
puts "OneMonitor successfully started"
|
||||
return [200,""]
|
||||
end
|
||||
end
|
||||
|
||||
def stop_monitor
|
||||
pipe = session['monitor']
|
||||
if pipe
|
||||
Process.kill('KILL',pipe.pid)
|
||||
pipe.close
|
||||
end
|
||||
return [200,""]
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
unless request.path=='/login' || request.path=='/'
|
||||
halt 401 unless authorized?
|
||||
|
||||
@SunstoneServer = SunstoneServer.new(session[:user], session[:password])
|
||||
end
|
||||
end
|
||||
|
||||
after do
|
||||
unless request.path=='/login' || request.path=='/'
|
||||
unless session[:remember]
|
||||
if params[:timeout] == true
|
||||
env['rack.session.options'][:defer] = true
|
||||
else
|
||||
env['rack.session.options'][:expire_after] = 60*10
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
# HTML Requests
|
||||
##############################################################################
|
||||
get '/' do
|
||||
redirect '/login' unless authorized?
|
||||
|
||||
time = Time.now + 60
|
||||
response.set_cookie("one-user",
|
||||
:value=>"#{session[:user]}",
|
||||
:expires=>time)
|
||||
response.set_cookie("one-user_id",
|
||||
:value=>"#{session[:user_id]}",
|
||||
:expires=>time)
|
||||
|
||||
File.read(File.dirname(__FILE__)+'/templates/index.html')
|
||||
end
|
||||
|
||||
get '/login' do
|
||||
File.read(File.dirname(__FILE__)+'/templates/login.html')
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
# Login
|
||||
##############################################################################
|
||||
post '/login' do
|
||||
build_session
|
||||
end
|
||||
|
||||
post '/logout' do
|
||||
destroy_session
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
# Config and Logs
|
||||
##############################################################################
|
||||
get '/config' do
|
||||
@SunstoneServer.get_configuration(session[:user_id])
|
||||
end
|
||||
|
||||
get '/vm/:id/log' do
|
||||
@SunstoneServer.get_vm_log(params[:id])
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
# Logs
|
||||
##############################################################################
|
||||
|
||||
post '/startmonitor' do
|
||||
start_monitor
|
||||
end
|
||||
|
||||
get '/:resource/monitor' do
|
||||
@SunstoneServer.get_log(params[:resource],
|
||||
-1,
|
||||
settings.config,
|
||||
params['monitor_resources'],
|
||||
params['history_length'])
|
||||
end
|
||||
|
||||
get '/:resource/:id/monitor' do
|
||||
@SunstoneServer.get_log(params[:resource],
|
||||
params[:id],
|
||||
settings.config,
|
||||
params['monitor_resources'],
|
||||
params['history_length'])
|
||||
end
|
||||
|
||||
|
||||
##############################################################################
|
||||
# GET Pool information
|
||||
##############################################################################
|
||||
get '/:pool' do
|
||||
@SunstoneServer.get_pool(params[:pool])
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
# GET Resource information
|
||||
##############################################################################
|
||||
get '/:resource/:id' do
|
||||
@SunstoneServer.get_resource(params[:resource], params[:id])
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
# Delete Resource
|
||||
##############################################################################
|
||||
delete '/:resource/:id' do
|
||||
@SunstoneServer.delete_resource(params[:resource], params[:id])
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
# Create a new Resource
|
||||
##############################################################################
|
||||
post '/:pool' do
|
||||
@SunstoneServer.create_resource(params[:pool], request.body.read)
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
# Stop the VNC Session of a target VM
|
||||
##############################################################################
|
||||
post '/vm/:id/stopvnc' do
|
||||
vm_id = params[:id]
|
||||
vnc_hash = session['vnc']
|
||||
|
||||
if !vnc_hash || !vnc_hash[vm_id]
|
||||
msg = "It seems there is no VNC proxy running for this machine"
|
||||
return [403, OpenNebula::Error.new(msg).to_json]
|
||||
end
|
||||
|
||||
rc = @SunstoneServer.stopvnc(vm_id, vnc_hash[vm_id][:pipe])
|
||||
if rc[0] == 200
|
||||
session['vnc'].delete(vm_id)
|
||||
end
|
||||
|
||||
rc
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
# Start a VNC Session for a target VM
|
||||
##############################################################################
|
||||
post '/vm/:id/startvnc' do
|
||||
vm_id = params[:id]
|
||||
|
||||
vnc_hash = session['vnc']
|
||||
|
||||
if !vnc_hash
|
||||
session['vnc']= {}
|
||||
elsif vnc_hash[vm_id]
|
||||
#return existing information
|
||||
info = vnc_hash[vm_id].clone
|
||||
info.delete(:pipe)
|
||||
|
||||
return [200, info.to_json]
|
||||
end
|
||||
|
||||
rc = @SunstoneServer.startvnc(vm_id, settings.config)
|
||||
if rc[0] == 200
|
||||
info = rc[1]
|
||||
session['vnc'][vm_id] = info.clone
|
||||
info.delete(:pipe)
|
||||
|
||||
[200, info.to_json]
|
||||
else
|
||||
rc
|
||||
end
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
# Perform an action on a Resource
|
||||
##############################################################################
|
||||
post '/:resource/:id/action' do
|
||||
@SunstoneServer.perform_action(params[:resource], params[:id], request.body.read)
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user