Adds hypervisor statistics to admin dashboard
Uses the existing d3 visualizations along with the hypervisor stats API in Nova to display some useful at-a-glance information about the utilization of your cloud. Implements blueprint hypervisor-info Change-Id: If71c533529a1f51d565eafb0b9b84f6ce93427c8
This commit is contained in:
@@ -599,6 +599,10 @@ def hypervisor_list(request):
|
|||||||
return novaclient(request).hypervisors.list()
|
return novaclient(request).hypervisors.list()
|
||||||
|
|
||||||
|
|
||||||
|
def hypervisor_stats(request):
|
||||||
|
return novaclient(request).hypervisors.statistics()
|
||||||
|
|
||||||
|
|
||||||
def tenant_absolute_limits(request, reserved=False):
|
def tenant_absolute_limits(request, reserved=False):
|
||||||
limits = novaclient(request).limits.get(reserved=reserved).absolute
|
limits = novaclient(request).limits.get(reserved=reserved).absolute
|
||||||
limits_dict = {}
|
limits_dict = {}
|
||||||
|
@@ -17,25 +17,27 @@
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from horizon import tables
|
from horizon import tables
|
||||||
|
from horizon.templatetags import sizeformat
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def get_memory(hypervisor):
|
def get_memory(hypervisor):
|
||||||
return _("%s MB") % hypervisor.memory_mb
|
return sizeformat.mbformat(hypervisor.memory_mb)
|
||||||
|
|
||||||
|
|
||||||
def get_memory_used(hypervisor):
|
def get_memory_used(hypervisor):
|
||||||
return _("%s MB") % hypervisor.memory_mb_used
|
return sizeformat.mbformat(hypervisor.memory_mb_used)
|
||||||
|
|
||||||
|
|
||||||
def get_local(hypervisor):
|
def get_local(hypervisor):
|
||||||
return _("%s GB") % hypervisor.local_gb
|
return sizeformat.diskgbformat(hypervisor.local_gb)
|
||||||
|
|
||||||
|
|
||||||
def get_local_used(hypervisor):
|
def get_local_used(hypervisor):
|
||||||
return _("%s GB") % hypervisor.local_gb_used
|
return sizeformat.diskgbformat(hypervisor.local_gb_used)
|
||||||
|
|
||||||
|
|
||||||
class AdminHypervisorsTable(tables.DataTable):
|
class AdminHypervisorsTable(tables.DataTable):
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% load i18n %}
|
{% load i18n horizon humanize sizeformat %}
|
||||||
|
|
||||||
{% block title %}{% trans "Hypervisors" %}{% endblock %}
|
{% block title %}{% trans "Hypervisors" %}{% endblock %}
|
||||||
|
|
||||||
{% block page_header %}
|
{% block page_header %}
|
||||||
@@ -7,5 +8,28 @@
|
|||||||
{% endblock page_header %}
|
{% endblock page_header %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
<div class="quota-dynamic">
|
||||||
|
<h3>{% trans "Hypervisor Summary" %}</h3>
|
||||||
|
<div class="d3_quota_bar">
|
||||||
|
<div class="d3_pie_chart" data-used="{% widthratio stats.vcpus_used stats.vcpus 100 %}"></div>
|
||||||
|
<strong>{% trans "VCPU Usage" %} <br />
|
||||||
|
{% blocktrans with used=stats.vcpus_used|intcomma available=stats.vcpus|intcomma %}Used <span> {{ used }} </span> of <span> {{ available }} </span>{% endblocktrans %}
|
||||||
|
</strong>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d3_quota_bar">
|
||||||
|
<div class="d3_pie_chart" data-used="{% widthratio stats.memory_mb_used stats.memory_mb 100 %}"></div>
|
||||||
|
<strong>{% trans "Memory Usage" %} <br />
|
||||||
|
{% blocktrans with used=stats.memory_mb_used|mbformat available=stats.memory_mb|mbformat %}Used <span> {{ used }} </span> of <span> {{ available }} </span>{% endblocktrans %}
|
||||||
|
</strong>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d3_quota_bar">
|
||||||
|
<div class="d3_pie_chart" data-used="{% widthratio stats.local_gb_used stats.local_gb 100 %}"></div>
|
||||||
|
<strong>{% trans "Disk Usage" %} <br />
|
||||||
|
{% blocktrans with used=stats.local_gb_used|diskgbformat available=stats.local_gb|diskgbformat %}Used <span> {{ used }} </span> of <span> {{ available }} </span>{% endblocktrans %}
|
||||||
|
</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{{ table.render }}
|
{{ table.render }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@@ -23,10 +23,13 @@ from openstack_dashboard.test import helpers as test
|
|||||||
|
|
||||||
|
|
||||||
class HypervisorViewTest(test.BaseAdminViewTests):
|
class HypervisorViewTest(test.BaseAdminViewTests):
|
||||||
@test.create_stubs({api.nova: ('hypervisor_list',)})
|
@test.create_stubs({api.nova: ('hypervisor_list',
|
||||||
|
'hypervisor_stats')})
|
||||||
def test_index(self):
|
def test_index(self):
|
||||||
hypervisors = self.hypervisors.list()
|
hypervisors = self.hypervisors.list()
|
||||||
|
stats = self.hypervisors.stats
|
||||||
api.nova.hypervisor_list(IsA(http.HttpRequest)).AndReturn(hypervisors)
|
api.nova.hypervisor_list(IsA(http.HttpRequest)).AndReturn(hypervisors)
|
||||||
|
api.nova.hypervisor_stats(IsA(http.HttpRequest)).AndReturn(stats)
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
res = self.client.get(reverse('horizon:admin:hypervisors:index'))
|
res = self.client.get(reverse('horizon:admin:hypervisors:index'))
|
||||||
|
@@ -35,8 +35,18 @@ class AdminIndexView(tables.DataTableView):
|
|||||||
hypervisors = []
|
hypervisors = []
|
||||||
try:
|
try:
|
||||||
hypervisors = api.nova.hypervisor_list(self.request)
|
hypervisors = api.nova.hypervisor_list(self.request)
|
||||||
except:
|
except Exception:
|
||||||
exceptions.handle(self.request,
|
exceptions.handle(self.request,
|
||||||
_('Unable to retrieve hypervisor list.'))
|
_('Unable to retrieve hypervisor information.'))
|
||||||
|
|
||||||
return hypervisors
|
return hypervisors
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super(AdminIndexView, self).get_context_data(**kwargs)
|
||||||
|
try:
|
||||||
|
context["stats"] = api.nova.hypervisor_stats(self.request)
|
||||||
|
except Exception:
|
||||||
|
exceptions.handle(self.request,
|
||||||
|
_('Unable to retrieve hypervisor statistics.'))
|
||||||
|
|
||||||
|
return context
|
||||||
|
@@ -517,6 +517,23 @@ def data(TEST):
|
|||||||
)
|
)
|
||||||
TEST.hypervisors.add(hypervisor_1)
|
TEST.hypervisors.add(hypervisor_1)
|
||||||
|
|
||||||
|
TEST.hypervisors.stats = {
|
||||||
|
"hypervisor_statistics": {
|
||||||
|
"count": 5,
|
||||||
|
"vcpus_used": 3,
|
||||||
|
"local_gb_used": 15,
|
||||||
|
"memory_mb": 483310,
|
||||||
|
"current_workload": 0,
|
||||||
|
"vcpus": 160,
|
||||||
|
"running_vms": 3,
|
||||||
|
"free_disk_gb": 12548,
|
||||||
|
"disk_available_least": 12556,
|
||||||
|
"local_gb": 12563,
|
||||||
|
"free_ram_mb": 428014,
|
||||||
|
"memory_mb_used": 55296
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Services
|
# Services
|
||||||
service_1 = services.Service(services.ServiceManager(None),
|
service_1 = services.Service(services.ServiceManager(None),
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user