Ladislav Smola afbe1fb481 Styling Nodes Overview page
Styling overview page. Extracting performance charts to
separate template, so it is reusable elsewhere.

Change-Id: Iea55815f7680b8fb15b06670281f3a7105f00d8e
2014-10-22 18:24:35 +02:00

242 lines
8.5 KiB
Python

# Copyright 2012 Nebula, Inc.
#
# 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.
import itertools
from django.core import urlresolvers
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import tabs
from horizon.utils import functions
from openstack_dashboard.api import base as api_base
from tuskar_ui import api
from tuskar_ui.cached_property import cached_property # noqa
from tuskar_ui.infrastructure.nodes import tables
from tuskar_ui.utils import metering as metering_utils
from tuskar_ui.utils import utils
class OverviewTab(tabs.Tab):
name = _("Overview")
slug = "overview"
template_name = "infrastructure/nodes/_overview.html"
def get_context_data(self, request):
nodes = api.node.Node.list(request)
cpus = sum(int(node.cpus) for node in nodes if node.cpus)
memory_mb = sum(int(node.memory_mb) for node in nodes if
node.memory_mb)
local_gb = sum(int(node.local_gb) for node in nodes if node.local_gb)
nodes_provisioned = api.node.Node.list(request, associated=True)
nodes_free = api.node.Node.list(request, associated=False)
nodes_provisioned_down = utils.filter_items(
nodes_provisioned, power_state__not_in=api.node.POWER_ON_STATES)
nodes_free_down = utils.filter_items(
nodes_free, power_state__not_in=api.node.POWER_ON_STATES)
nodes_down = itertools.chain(nodes_provisioned_down, nodes_free_down)
nodes_up = utils.filter_items(
nodes, power_state__in=api.node.POWER_ON_STATES)
context = {
'cpus': cpus,
'memory_gb': memory_mb / 1024.0,
'local_gb': local_gb,
'nodes_up_count': utils.length(nodes_up),
'nodes_down_count': utils.length(nodes_down),
'nodes_provisioned_count': utils.length(nodes_provisioned),
'nodes_free_count': utils.length(nodes_free),
'nodes_all_count': (utils.length(nodes_provisioned) +
utils.length(nodes_free))
}
if api_base.is_service_enabled(self.request, 'metering'):
context['meter_conf'] = (
(_('System Load'),
metering_utils.url_part('hardware.cpu.load.1min', False),
None),
(_('CPU Utilization'),
metering_utils.url_part('hardware.system_stats.cpu.util',
True),
'100'),
(_('Swap Utilization'),
metering_utils.url_part('hardware.memory.swap.util',
True),
'100'),
)
return context
class RegisteredTab(tabs.TableTab):
table_classes = (tables.RegisteredNodesTable,)
name = _("Registered")
slug = "registered"
template_name = "horizon/common/_detail_table.html"
def __init__(self, tab_group, request):
super(RegisteredTab, self).__init__(tab_group, request)
def get_items_count(self):
return len(self._nodes)
@cached_property
def _nodes(self):
redirect = urlresolvers.reverse('horizon:infrastructure:nodes:index')
if 'provisioned' in self.request.GET:
associated = True
elif 'free' in self.request.GET:
associated = False
else:
associated = None
return api.node.Node.list(self.request, associated=associated,
maintenance=False, _error_redirect=redirect)
@cached_property
def _nodes_info(self):
page_size = functions.get_page_size(self.request)
prev_marker = self.request.GET.get(
tables.RegisteredNodesTable._meta.prev_pagination_param, None)
if prev_marker is not None:
sort_dir = 'asc'
marker = prev_marker
else:
sort_dir = 'desc'
marker = self.request.GET.get(
tables.RegisteredNodesTable._meta.pagination_param, None)
nodes = self._nodes
if marker:
node_ids = [node.uuid for node in self._nodes]
position = node_ids.index(marker)
if sort_dir == 'asc':
start = max(0, position - page_size)
end = position
else:
start = position + 1
end = start + page_size
else:
start = 0
end = page_size
prev = start != 0
more = len(nodes) > end
return nodes[start:end], prev, more
def get_nodes_table_data(self):
nodes, prev, more = self._nodes_info
if 'errors' in self.request.GET:
return api.node.filter_nodes(nodes, healthy=False)
if nodes:
all_resources = api.heat.Resource.list_all_resources(self.request)
for node in nodes:
try:
resource = api.heat.Resource.get_by_node(
self.request, node, all_resources=all_resources)
node.role_name = resource.role.name
node.role_id = resource.role.id
node.stack_id = resource.stack.id
except exceptions.NotFound:
node.role_name = '-'
return nodes
def has_prev_data(self, table):
return self._nodes_info[1]
def has_more_data(self, table):
return self._nodes_info[2]
class MaintenanceTab(tabs.TableTab):
table_classes = (tables.MaintenanceNodesTable,)
name = _("Maintenance")
slug = "maintenance"
template_name = "horizon/common/_detail_table.html"
def get_items_count(self):
return len(self.get_maintenance_nodes_table_data())
def get_maintenance_nodes_table_data(self):
redirect = urlresolvers.reverse('horizon:infrastructure:nodes:index')
nodes = api.node.Node.list(self.request, maintenance=True,
_error_redirect=redirect)
return nodes
class DetailOverviewTab(tabs.Tab):
name = _("Overview")
slug = "detail_overview"
template_name = 'infrastructure/nodes/_detail_overview.html'
def get_context_data(self, request):
node = self.tab_group.kwargs['node']
context = {'node': node}
try:
resource = api.heat.Resource.get_by_node(self.request, node)
context['role'] = resource.role
context['stack'] = resource.stack
except exceptions.NotFound:
pass
if node.instance_uuid:
if api_base.is_service_enabled(self.request, 'metering'):
# Meter configuration in the following format:
# (meter label, url part, barchart (True/False))
context['meter_conf'] = (
(_('System Load'),
metering_utils.url_part('hardware.cpu.load.1min', False),
None),
(_('CPU Utilization'),
metering_utils.url_part('hardware.system_stats.cpu.util',
True),
'100'),
(_('Swap Utilization'),
metering_utils.url_part('hardware.memory.swap.util',
True),
'100'),
(_('Disk I/O '),
metering_utils.url_part('disk-io', False),
None),
(_('Network I/O '),
metering_utils.url_part('network-io', False),
None),
)
return context
class NodeTabs(tabs.TabGroup):
slug = "nodes"
tabs = (OverviewTab, RegisteredTab)
sticky = True
template_name = "horizon/common/_items_count_tab_group.html"
def __init__(self, request, **kwargs):
if api.node.NodeClient.ironic_enabled(request):
self.tabs = self.tabs + (MaintenanceTab,)
super(NodeTabs, self).__init__(request, **kwargs)
class NodeDetailTabs(tabs.TabGroup):
slug = "node_details"
tabs = (DetailOverviewTab,)