mirror of
https://github.com/retspen/webvirtcloud
synced 2024-12-24 23:25:24 +00:00
Added graph scale for instance
This commit is contained in:
parent
02570cd826
commit
4a17f08740
5 changed files with 302 additions and 16 deletions
|
@ -1,7 +1,9 @@
|
||||||
|
import time
|
||||||
|
import json
|
||||||
from string import letters, digits
|
from string import letters, digits
|
||||||
from random import choice
|
from random import choice
|
||||||
from bisect import insort
|
from bisect import insort
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponse, HttpResponseRedirect
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
@ -408,3 +410,122 @@ def instance(request, compute_id, vname):
|
||||||
addlogmsg(request.user.id, instance.id, lib_err.message)
|
addlogmsg(request.user.id, instance.id, lib_err.message)
|
||||||
|
|
||||||
return render(request, 'instance.html', locals())
|
return render(request, 'instance.html', locals())
|
||||||
|
|
||||||
|
|
||||||
|
def inst_graph(request, compute_id, vname):
|
||||||
|
"""
|
||||||
|
Return instance usage
|
||||||
|
"""
|
||||||
|
if not request.user.is_authenticated():
|
||||||
|
return HttpResponseRedirect(reverse('login'))
|
||||||
|
|
||||||
|
datasets = {}
|
||||||
|
datasets_rd = []
|
||||||
|
datasets_wr = []
|
||||||
|
json_blk = []
|
||||||
|
cookie_blk = {}
|
||||||
|
blk_error = False
|
||||||
|
datasets_rx = []
|
||||||
|
datasets_tx = []
|
||||||
|
json_net = []
|
||||||
|
cookie_net = {}
|
||||||
|
net_error = False
|
||||||
|
networks = None
|
||||||
|
disks = None
|
||||||
|
points = 5
|
||||||
|
curent_time = time.strftime("%H:%M:%S")
|
||||||
|
compute = Compute.objects.get(id=compute_id)
|
||||||
|
|
||||||
|
try:
|
||||||
|
conn = wvmInstance(compute.hostname,
|
||||||
|
compute.login,
|
||||||
|
compute.password,
|
||||||
|
compute.type,
|
||||||
|
vname)
|
||||||
|
status = conn.get_status()
|
||||||
|
cpu_usage = conn.cpu_usage()
|
||||||
|
blk_usage = conn.disk_usage()
|
||||||
|
net_usage = conn.net_usage()
|
||||||
|
conn.close()
|
||||||
|
except libvirtError:
|
||||||
|
status = None
|
||||||
|
blk_usage = None
|
||||||
|
cpu_usage = None
|
||||||
|
net_usage = None
|
||||||
|
|
||||||
|
if status == 1:
|
||||||
|
cookies = request.COOKIES
|
||||||
|
if cookies.get('cpu') == '{}' or not cookies.get('cpu') or not cpu_usage:
|
||||||
|
datasets['cpu'] = [0]
|
||||||
|
datasets['timer'] = [curent_time]
|
||||||
|
else:
|
||||||
|
datasets['cpu'] = eval(cookies.get('cpu'))
|
||||||
|
datasets['timer'] = eval(cookies.get('timer'))
|
||||||
|
|
||||||
|
datasets['timer'].append(curent_time)
|
||||||
|
datasets['cpu'].append(int(cpu_usage['cpu']))
|
||||||
|
|
||||||
|
if len(datasets['timer']) > points:
|
||||||
|
datasets['timer'].pop(0)
|
||||||
|
if len(datasets['cpu']) > points:
|
||||||
|
datasets['cpu'].pop(0)
|
||||||
|
|
||||||
|
for blk in blk_usage:
|
||||||
|
if cookies.get('hdd') == '{}' or not cookies.get('hdd') or not blk_usage:
|
||||||
|
datasets_wr.append(0)
|
||||||
|
datasets_rd.append(0)
|
||||||
|
else:
|
||||||
|
datasets['hdd'] = eval(cookies.get('hdd'))
|
||||||
|
try:
|
||||||
|
datasets_rd = datasets['hdd'][blk['dev']][0]
|
||||||
|
datasets_wr = datasets['hdd'][blk['dev']][1]
|
||||||
|
except:
|
||||||
|
blk_error = True
|
||||||
|
|
||||||
|
if not blk_error:
|
||||||
|
datasets_rd.append(int(blk['rd']) / 1048576)
|
||||||
|
datasets_wr.append(int(blk['wr']) / 1048576)
|
||||||
|
|
||||||
|
if len(datasets_rd) > points:
|
||||||
|
datasets_rd.pop(0)
|
||||||
|
if len(datasets_wr) >= points + 1:
|
||||||
|
datasets_wr.pop(0)
|
||||||
|
|
||||||
|
json_blk.append({'dev': blk['dev'], 'data': [datasets_rd, datasets_wr]})
|
||||||
|
cookie_blk[blk['dev']] = [datasets_rd, datasets_wr]
|
||||||
|
|
||||||
|
for net in net_usage:
|
||||||
|
if cookies.get('net') == '{}' or not cookies.get('net') or not net_usage:
|
||||||
|
datasets_rx.append(0)
|
||||||
|
datasets_tx.append(0)
|
||||||
|
else:
|
||||||
|
datasets['net'] = eval(cookies.get('net'))
|
||||||
|
try:
|
||||||
|
datasets_rx = datasets['net'][net['dev']][0]
|
||||||
|
datasets_tx = datasets['net'][net['dev']][1]
|
||||||
|
except:
|
||||||
|
net_error = True
|
||||||
|
|
||||||
|
if not net_error:
|
||||||
|
datasets_rx.append(int(net['rx']) / 1048576)
|
||||||
|
datasets_tx.append(int(net['tx']) / 1048576)
|
||||||
|
|
||||||
|
if len(datasets_rx) > points:
|
||||||
|
datasets_rx.pop(0)
|
||||||
|
if len(datasets_tx) > points:
|
||||||
|
datasets_tx.pop(0)
|
||||||
|
|
||||||
|
json_net.append({'dev': net['dev'], 'data': [datasets_rx, datasets_tx]})
|
||||||
|
cookie_net[net['dev']] = [datasets_rx, datasets_tx]
|
||||||
|
|
||||||
|
data = json.dumps({'status': status, 'cpudata': datasets['cpu'], 'hdddata': json_blk, 'netdata': json_net, 'timeline': datasets['timer']})
|
||||||
|
|
||||||
|
response = HttpResponse()
|
||||||
|
response['Content-Type'] = "text/javascript"
|
||||||
|
if status == 1:
|
||||||
|
response.cookies['cpu'] = datasets['cpu']
|
||||||
|
response.cookies['timer'] = datasets['timer']
|
||||||
|
response.cookies['hdd'] = cookie_blk
|
||||||
|
response.cookies['net'] = cookie_net
|
||||||
|
response.write(data)
|
||||||
|
return response
|
|
@ -100,7 +100,7 @@ body {
|
||||||
width: 65px;
|
width: 65px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#action-button {
|
.action-button {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,43 +38,43 @@
|
||||||
<!-- Nav tabs -->
|
<!-- Nav tabs -->
|
||||||
<ul class="nav nav-pills" role="tablist">
|
<ul class="nav nav-pills" role="tablist">
|
||||||
<li role="presentation" class="active">
|
<li role="presentation" class="active">
|
||||||
<a href="#power" id="action-button" aria-controls="power" role="tab" data-toggle="tab">
|
<a href="#power" class="action-button" aria-controls="power" role="tab" data-toggle="tab">
|
||||||
<span id="action-block" class="glyphicon glyphicon-off" aria-hidden="true"></span>
|
<span id="action-block" class="glyphicon glyphicon-off" aria-hidden="true"></span>
|
||||||
{% trans "Power" %}
|
{% trans "Power" %}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li role="presentation">
|
<li role="presentation">
|
||||||
<a href="#access" id="action-button" aria-controls="access" role="tab" data-toggle="tab">
|
<a href="#access" class="action-button" aria-controls="access" role="tab" data-toggle="tab">
|
||||||
<span id="action-block" class="glyphicon glyphicon-lock" aria-hidden="true"></span>
|
<span id="action-block" class="glyphicon glyphicon-lock" aria-hidden="true"></span>
|
||||||
{% trans "Access" %}
|
{% trans "Access" %}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li role="presentation">
|
<li role="presentation">
|
||||||
<a href="#resize" id="action-button" aria-controls="resize" role="tab" data-toggle="tab">
|
<a href="#resize" class="action-button" aria-controls="resize" role="tab" data-toggle="tab">
|
||||||
<span id="action-block" class="glyphicon glyphicon-resize-full" aria-hidden="true"></span>
|
<span id="action-block" class="glyphicon glyphicon-resize-full" aria-hidden="true"></span>
|
||||||
{% trans "Resize" %}
|
{% trans "Resize" %}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li role="presentation">
|
<li role="presentation">
|
||||||
<a href="#snapshots" id="action-button" aria-controls="snapshots" role="tab" data-toggle="tab">
|
<a href="#snapshots" class="action-button" aria-controls="snapshots" role="tab" data-toggle="tab">
|
||||||
<span id="action-block" class="glyphicon glyphicon-camera" aria-hidden="true"></span>
|
<span id="action-block" class="glyphicon glyphicon-camera" aria-hidden="true"></span>
|
||||||
{% trans "Snapshots" %}
|
{% trans "Snapshots" %}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li role="presentation">
|
<li role="presentation">
|
||||||
<a href="#settings" id="action-button" aria-controls="settings" role="tab" data-toggle="tab">
|
<a href="#settings" class="action-button" aria-controls="settings" role="tab" data-toggle="tab">
|
||||||
<span id="action-block" class="glyphicon glyphicon-cog" aria-hidden="true"></span>
|
<span id="action-block" class="glyphicon glyphicon-cog" aria-hidden="true"></span>
|
||||||
{% trans "Settings" %}
|
{% trans "Settings" %}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li role="presentation">
|
<li role="presentation">
|
||||||
<a href="#graphics" id="action-button" aria-controls="graphics" role="tab" data-toggle="tab">
|
<a href="#graphics" id="chartgraphs" class="action-button" aria-controls="graphics" role="tab" data-toggle="tab">
|
||||||
<span id="action-block" class="glyphicon glyphicon-signal" aria-hidden="true"></span>
|
<span id="action-block" class="glyphicon glyphicon-signal" aria-hidden="true"></span>
|
||||||
{% trans "Graphs" %}
|
{% trans "Graphs" %}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li role="presentation">
|
<li role="presentation">
|
||||||
<a href="#undefine" id="action-button" aria-controls="undefine" role="tab" data-toggle="tab">
|
<a href="#undefine" class="action-button" aria-controls="undefine" role="tab" data-toggle="tab">
|
||||||
<span id="action-block" class="glyphicon glyphicon-trash" aria-hidden="true"></span>
|
<span id="action-block" class="glyphicon glyphicon-trash" aria-hidden="true"></span>
|
||||||
{% trans "Destroy" %}
|
{% trans "Destroy" %}
|
||||||
</a>
|
</a>
|
||||||
|
@ -689,15 +689,55 @@
|
||||||
<!-- Nav tabs -->
|
<!-- Nav tabs -->
|
||||||
<ul class="nav nav-tabs" role="tablist">
|
<ul class="nav nav-tabs" role="tablist">
|
||||||
<li role="presentation" class="active">
|
<li role="presentation" class="active">
|
||||||
<a href="#graps" aria-controls="graps" role="tab" data-toggle="tab">
|
<a href="#graphs" aria-controls="graphs" role="tab" data-toggle="tab">
|
||||||
{% trans "Real Time" %}
|
{% trans "Real Time" %}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<!-- Tab panes -->
|
<!-- Tab panes -->
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
<div role="tabpanel" class="tab-pane tab-pane-bordered active" id="graps">
|
<div role="tabpanel" class="tab-pane tab-pane-bordered active" id="graphs">
|
||||||
<p>Graphics</p>
|
<div class="panel panel-success">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h3 class="panel-title"><i class="fa fa-long-arrow-right"></i> {% trans "CPU usage" %}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="flot-chart">
|
||||||
|
<div class="flot-chart-content" id="flot-moving-line-chart" style="padding: 0px; position: relative;">
|
||||||
|
<canvas id="cpuChart" width="735" height="250"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% for net in networks %}
|
||||||
|
<div class="panel panel-info">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h3 class="panel-title"><i class="fa fa-long-arrow-right"></i> {% trans "Bandwidth device:" %} eth{{ forloop.counter0 }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="flot-chart">
|
||||||
|
<div class="flot-chart-content" id="flot-moving-line-chart" style="padding: 0px; position: relative;">
|
||||||
|
<canvas id="netEth{{ forloop.counter0 }}Chart" width="735" height="250"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% for disk in disks %}
|
||||||
|
<div class="panel panel-warning">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h3 class="panel-title"><i class="fa fa-long-arrow-right"></i> {% trans "Disk I/O device:" %} {{ disk.dev }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="flot-chart">
|
||||||
|
<div class="flot-chart-content" id="flot-moving-line-chart" style="padding: 0px; position: relative;">
|
||||||
|
<canvas id="blk{{ disk.dev }}Chart" width="735" height="250"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
<div class="clearfix"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -827,5 +867,127 @@
|
||||||
toggles.toggle();
|
toggles.toggle();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
</script>
|
||||||
|
<script src="{{ STATIC_URL }}js/Chart.min.js"></script>
|
||||||
|
<script>
|
||||||
|
$( "#graphics" ).click();
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
$('#chartgraphs').on('shown.bs.tab', function (e) {
|
||||||
|
var cpuLineData = {
|
||||||
|
labels : [0, 0, 0, 0, 0],
|
||||||
|
datasets : [
|
||||||
|
{
|
||||||
|
fillColor: "rgba(241,72,70,0.5)",
|
||||||
|
strokeColor: "rgba(241,72,70,1)",
|
||||||
|
pointColor : "rgba(241,72,70,1)",
|
||||||
|
pointStrokeColor : "#fff",
|
||||||
|
pointHighlightFill : "#fff",
|
||||||
|
pointHighlightStroke : "rgba(220,220,220,1)",
|
||||||
|
data : [0, 0, 0, 0, 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
var diskLineData = {
|
||||||
|
labels : [0, 0, 0, 0, 0],
|
||||||
|
datasets : [
|
||||||
|
{
|
||||||
|
"fillColor": "rgba(83,191,189,0.5)",
|
||||||
|
"strokeColor": "rgba(83,191,189,1)",
|
||||||
|
"pointColor": "rgba(83,191,189,1)",
|
||||||
|
"pointStrokeColor": "#fff",
|
||||||
|
"data": [0, 0, 0, 0, 0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fillColor": "rgba(249,134,33,0.5)",
|
||||||
|
"strokeColor": "rgba(249,134,33,1)",
|
||||||
|
"pointColor": "rgba(249,134,33,1)",
|
||||||
|
"pointStrokeColor": "#fff",
|
||||||
|
"data": [0, 0, 0, 0, 0]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
var netLineData = {
|
||||||
|
labels : [0, 0, 0, 0, 0],
|
||||||
|
datasets : [
|
||||||
|
{
|
||||||
|
"fillColor": "rgba(83,191,189,0.5)",
|
||||||
|
"strokeColor": "rgba(83,191,189,1)",
|
||||||
|
"pointColor": "rgba(83,191,189,1)",
|
||||||
|
"pointStrokeColor": "#fff",
|
||||||
|
"data": [0, 0, 0, 0, 0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fillColor": "rgba(151,187,205,0.5)",
|
||||||
|
"strokeColor": "rgba(151,187,205,1)",
|
||||||
|
"pointColor": "rgba(151,187,205,1)",
|
||||||
|
"pointStrokeColor": "#fff",
|
||||||
|
"data": [0, 0, 0, 0, 0]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
var cpuOpt = {
|
||||||
|
animation: false,
|
||||||
|
pointDotRadius: 2,
|
||||||
|
scaleLabel: "<%=value%> %",
|
||||||
|
scaleOverride: true,
|
||||||
|
scaleSteps: 10,
|
||||||
|
scaleStepWidth: 10,
|
||||||
|
scaleStartValue: 0,
|
||||||
|
responsive: true
|
||||||
|
};
|
||||||
|
|
||||||
|
var diskOpt = {
|
||||||
|
animation: false,
|
||||||
|
pointDotRadius: 2,
|
||||||
|
scaleLabel: "<%=value%> Mb/s",
|
||||||
|
responsive: true
|
||||||
|
};
|
||||||
|
|
||||||
|
var netOpt = {
|
||||||
|
animation: false,
|
||||||
|
pointDotRadius: 2,
|
||||||
|
scaleLabel: "<%=value%> Mbps",
|
||||||
|
responsive: true
|
||||||
|
};
|
||||||
|
|
||||||
|
var cpu_ctx = $("#cpuChart").get(0).getContext("2d");
|
||||||
|
var cpuChart = new Chart(cpu_ctx).Line(cpuLineData, cpuOpt);
|
||||||
|
|
||||||
|
var diskChart = {};
|
||||||
|
{% for disk in disks %}
|
||||||
|
var disk_ctx_{{ disk.dev }} = $("#blk{{ disk.dev }}Chart").get(0).getContext("2d");
|
||||||
|
diskChart['{{ disk.dev }}'] = new Chart(disk_ctx_{{ disk.dev }}).Line(diskLineData, diskOpt);
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
var netChart = {};
|
||||||
|
{% for net in networks %}
|
||||||
|
var net_ctx_{{ forloop.counter0 }} = $("#netEth{{ forloop.counter0 }}Chart").get(0).getContext("2d");
|
||||||
|
netChart['{{ forloop.counter0 }}'] = new Chart(net_ctx_{{ forloop.counter0 }}).Line(netLineData, netOpt);
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
function graph_usage() {
|
||||||
|
$.getJSON('{% url 'inst_graph' compute_id vname %}', function (data) {
|
||||||
|
cpuChart.scale.xLabels = data.timeline;
|
||||||
|
for (var i = 0; i < 5; i++) {
|
||||||
|
cpuChart.datasets[0].points[i].value = data.cpudata[i];
|
||||||
|
}
|
||||||
|
cpuChart.update();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
{##}
|
||||||
|
{# $(function(f) {#}
|
||||||
|
{# window.setInterval('graph_usage()', 2000);#}
|
||||||
|
{# });#}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -81,7 +81,7 @@
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block script %}
|
{% block script %}
|
||||||
<script src="{{ STATIC_URL }}/js/Chart.min.js"></script>
|
<script src="{{ STATIC_URL }}js/Chart.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
var cpuLineData = {
|
var cpuLineData = {
|
||||||
labels : [0, 0, 0, 0, 0],
|
labels : [0, 0, 0, 0, 0],
|
||||||
|
@ -133,7 +133,7 @@
|
||||||
responsive: true
|
responsive: true
|
||||||
});
|
});
|
||||||
|
|
||||||
function hostusage() {
|
function graph_usage() {
|
||||||
$.getJSON('{% url 'compute_graph' compute_id %}', function (data) {
|
$.getJSON('{% url 'compute_graph' compute_id %}', function (data) {
|
||||||
cpuChart.scale.xLabels = data.timeline;
|
cpuChart.scale.xLabels = data.timeline;
|
||||||
memChart.scale.xLabels = data.timeline;
|
memChart.scale.xLabels = data.timeline;
|
||||||
|
@ -145,8 +145,9 @@
|
||||||
memChart.update();
|
memChart.update();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
window.setInterval('hostusage()', 4000);
|
window.setInterval(graph_usage(), 4000);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -12,6 +12,8 @@ urlpatterns = patterns('',
|
||||||
url(r'^instances$', 'instances.views.instances', name='instances'),
|
url(r'^instances$', 'instances.views.instances', name='instances'),
|
||||||
url(r'^instance/(\d+)/([\w\-\.]+)/$', 'instances.views.instance', name='instance'),
|
url(r'^instance/(\d+)/([\w\-\.]+)/$', 'instances.views.instance', name='instance'),
|
||||||
|
|
||||||
|
url(r'^instance/statistics/(\d+)/([\w\-\.]+)/$', 'instances.views.inst_graph', name='inst_graph'),
|
||||||
|
|
||||||
url(r'^computes/$', 'computes.views.computes', name='computes'),
|
url(r'^computes/$', 'computes.views.computes', name='computes'),
|
||||||
url(r'^compute/overview/(\d+)/$', 'computes.views.overview', name='overview'),
|
url(r'^compute/overview/(\d+)/$', 'computes.views.overview', name='overview'),
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue