Merge "Add a detailed view of a Host"
This commit is contained in:
commit
640af94061
|
@ -42,12 +42,24 @@ class Lease(base.APIDictWrapper):
|
|||
class Host(base.APIDictWrapper):
|
||||
"""Represents one Blazar host."""
|
||||
|
||||
_attrs = ['id', 'hypervisor_hostname', 'hypervisor_type', 'vcpus',
|
||||
'cpu_info', 'memory_mb', 'local_gb']
|
||||
_attrs = ['id', 'hypervisor_hostname', 'hypervisor_type',
|
||||
'hypervisor_version', 'vcpus', 'cpu_info', 'memory_mb',
|
||||
'local_gb', 'status', 'created_at', 'updated_at',
|
||||
'service_name', 'trust_id']
|
||||
|
||||
def __init__(self, apiresource):
|
||||
super(Host, self).__init__(apiresource)
|
||||
|
||||
def cpu_info_dict(self):
|
||||
return eval(getattr(self, 'cpu_info', ""))
|
||||
|
||||
def extra_capabilities(self):
|
||||
excaps = {}
|
||||
for k, v in self._apidict.items():
|
||||
if k not in self._attrs:
|
||||
excaps[k] = v
|
||||
return excaps
|
||||
|
||||
|
||||
@memoized
|
||||
def blazarclient(request):
|
||||
|
@ -98,3 +110,9 @@ def host_list(request):
|
|||
"""List hosts."""
|
||||
hosts = blazarclient(request).host.list()
|
||||
return [Host(h) for h in hosts]
|
||||
|
||||
|
||||
def host_get(request, host_id):
|
||||
"""Get a host."""
|
||||
host = blazarclient(request).host.get(host_id)
|
||||
return Host(host)
|
||||
|
|
|
@ -16,7 +16,8 @@ from horizon.templatetags import sizeformat
|
|||
|
||||
|
||||
class HostsTable(tables.DataTable):
|
||||
name = tables.Column("hypervisor_hostname", verbose_name=_("Host name"))
|
||||
name = tables.Column("hypervisor_hostname", verbose_name=_("Host name"),
|
||||
link="horizon:admin:hosts:detail")
|
||||
vcpus = tables.Column("vcpus", verbose_name=_("VCPUs"))
|
||||
memory_mb = tables.Column("memory_mb", verbose_name=_("RAM"),
|
||||
filters=(sizeformat.mb_float_format,))
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
# Copyright 2014 Intel Corporation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from horizon import exceptions
|
||||
from horizon import tabs
|
||||
|
||||
from blazar_dashboard.api import client
|
||||
|
||||
|
||||
class OverviewTab(tabs.Tab):
|
||||
name = _("Overview")
|
||||
slug = "overview"
|
||||
template_name = "admin/hosts/_detail_overview.html"
|
||||
|
||||
def get_context_data(self, request):
|
||||
host_id = self.tab_group.kwargs['host_id']
|
||||
try:
|
||||
host = client.host_get(self.request, host_id)
|
||||
except Exception:
|
||||
redirect = reverse('horizon:admin:hosts:index')
|
||||
msg = _('Unable to retrieve host details.')
|
||||
exceptions.handle(request, msg, redirect=redirect)
|
||||
|
||||
return {'host': host}
|
||||
|
||||
|
||||
class HostDetailTabs(tabs.TabGroup):
|
||||
slug = "host_details"
|
||||
tabs = (OverviewTab,)
|
|
@ -0,0 +1,49 @@
|
|||
{% load i18n sizeformat %}
|
||||
|
||||
<div class="detail">
|
||||
<div class="info detail">
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "Host name" %}</dt>
|
||||
<dd>{{ host.hypervisor_hostname }}</dd>
|
||||
<dt>{% trans "Id" %}</dt>
|
||||
<dd>{{ host.id }}</dd>
|
||||
<dt>{% trans "Status" %}</dt>
|
||||
<dd>{{ host.status }}</dd> <dt>{% trans "Created at" %}</dt>
|
||||
<dd>{{ host.created_at|parse_isotime|date:"Y-m-d H:i T"|default:"-" }}</dd>
|
||||
<dt>{% trans "Updated at" %}</dt>
|
||||
<dd>{{ host.updated_at|parse_isotime|date:"Y-m-d H:i T"|default:"-" }}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4>{% trans "CPU Specs" %}</h4>
|
||||
<hr class="header_rule">
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "VCPUs" %}</dt>
|
||||
<dd>{{ host.vcpus|default:_("None") }}</dd>
|
||||
{% for key, value in host.cpu_info_dict.items %}
|
||||
<dt>{{ key }}</dt>
|
||||
<dd>{{ value }}</dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4>{% trans "Other Specs" %}</h4>
|
||||
<hr class="header_rule">
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "RAM" %}</dt>
|
||||
<dd>{{ host.memory_mb|mb_float_format }}</dd>
|
||||
<dt>{% trans "Local storage" %}</dt>
|
||||
<dd>{{ host.local_gb|diskgbformat }}</dd>
|
||||
<dt>{% trans "Hypervisor type" %}</dt>
|
||||
<dd>{{ host.hypervisor_type }}</dd>
|
||||
<dt>{% trans "Hypervisor version" %}</dt>
|
||||
<dd>{{ host.hypervisor_version }}</dd>
|
||||
{% for key, value in host.extra_capabilities.items %}
|
||||
<dt>{{ key }}</dt>
|
||||
<dd>{{ value }}</dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,15 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Host Details"%}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Host Details") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
{{ tab_group.render }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -22,6 +22,8 @@ LOG = logging.getLogger(__name__)
|
|||
|
||||
INDEX_TEMPLATE = 'admin/hosts/index.html'
|
||||
INDEX_URL = reverse('horizon:admin:hosts:index')
|
||||
DETAIL_TEMPLATE = 'admin/hosts/detail.html'
|
||||
DETAIL_URL_BASE = 'horizon:admin:hosts:detail'
|
||||
|
||||
|
||||
class HostsTests(test.BaseAdminViewTests):
|
||||
|
@ -57,3 +59,26 @@ class HostsTests(test.BaseAdminViewTests):
|
|||
res = self.client.get(INDEX_URL)
|
||||
self.assertTemplateUsed(res, INDEX_TEMPLATE)
|
||||
self.assertMessageCount(res, error=1)
|
||||
|
||||
@test.create_stubs({api.client: ('host_get',)})
|
||||
def test_host_detail(self):
|
||||
host = self.hosts.get(hypervisor_hostname='compute-1')
|
||||
api.client.host_get(IsA(http.HttpRequest),
|
||||
host['id']).AndReturn(host)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.get(reverse(DETAIL_URL_BASE, args=[host['id']]))
|
||||
self.assertTemplateUsed(res, DETAIL_TEMPLATE)
|
||||
self.assertContains(res, 'compute-1')
|
||||
self.assertContains(res, 'ex1')
|
||||
|
||||
@test.create_stubs({api.client: ('host_get',)})
|
||||
def test_host_detail_error(self):
|
||||
api.client.host_get(IsA(http.HttpRequest),
|
||||
'invalid').AndRaise(self.exceptions.blazar)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.get(reverse(DETAIL_URL_BASE, args=['invalid']))
|
||||
self.assertTemplateNotUsed(res, DETAIL_TEMPLATE)
|
||||
self.assertMessageCount(error=1)
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
|
|
|
@ -17,4 +17,5 @@ from blazar_dashboard.content.hosts import views
|
|||
|
||||
urlpatterns = [
|
||||
url(r'^$', views.IndexView.as_view(), name='index'),
|
||||
url(r'^(?P<host_id>[^/]+)/$', views.DetailView.as_view(), name='detail')
|
||||
]
|
||||
|
|
|
@ -13,9 +13,11 @@
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from horizon import exceptions
|
||||
from horizon import tables
|
||||
from horizon import tabs
|
||||
|
||||
from blazar_dashboard import api
|
||||
from blazar_dashboard.content.hosts import tables as project_tables
|
||||
from blazar_dashboard.content.hosts import tabs as project_tabs
|
||||
|
||||
|
||||
class IndexView(tables.DataTableView):
|
||||
|
@ -30,3 +32,8 @@ class IndexView(tables.DataTableView):
|
|||
msg = _('Unable to retrieve host information.')
|
||||
exceptions.handle(self.request, msg)
|
||||
return hosts
|
||||
|
||||
|
||||
class DetailView(tabs.TabView):
|
||||
tab_group_class = project_tabs.HostDetailTabs
|
||||
template_name = 'admin/hosts/detail.html'
|
||||
|
|
|
@ -146,7 +146,8 @@ host_sample1 = {
|
|||
"hypervisor_version": 2005000,
|
||||
"local_gb": 128,
|
||||
"id": "1",
|
||||
"trust_id": "dummy"
|
||||
"trust_id": "dummy",
|
||||
"ex1": "dummy"
|
||||
}
|
||||
|
||||
host_sample2 = {
|
||||
|
@ -162,7 +163,8 @@ host_sample2 = {
|
|||
"hypervisor_version": 2005000,
|
||||
"local_gb": 128,
|
||||
"id": "2",
|
||||
"trust_id": "dummy"
|
||||
"trust_id": "dummy",
|
||||
"ex2": "dummy"
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue