From 83d4107efb734fef949a7db0b05347673a322bfe Mon Sep 17 00:00:00 2001 From: Radomir Dopieralski Date: Mon, 1 Dec 2014 14:30:34 +0100 Subject: [PATCH] Make the live deployment view match wireframes * Add system load graphs * Add node distribution * Remove node status Change-Id: Ic240d65c681bdc9948057e71577b207f75c96e56 --- tuskar_boxes/overview/views.py | 30 ++++++++++++++-- .../tuskar_boxes/scss/tuskar_boxes.scss | 22 ++++++++++++ .../tuskar_boxes/overview/index.html | 28 ++++++++++++++- .../overview/role_nodes_live.html | 35 +++++++++++++++++++ 4 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 tuskar_boxes/templates/tuskar_boxes/overview/role_nodes_live.html diff --git a/tuskar_boxes/overview/views.py b/tuskar_boxes/overview/views.py index f0f456f..11f9c44 100644 --- a/tuskar_boxes/overview/views.py +++ b/tuskar_boxes/overview/views.py @@ -12,10 +12,15 @@ # License for the specific language governing permissions and limitations # under the License. +import collections + +from django.core.urlresolvers import reverse import django.utils.text +from openstack_dashboard.api import base as api_base + from tuskar_ui import api from tuskar_ui.infrastructure.overview import views - +from tuskar_ui.utils import metering from tuskar_boxes.overview import forms @@ -114,10 +119,31 @@ class IndexView(views.IndexView): context['flavors'] = list( _flavor_data(self.request, flavors, flavor_roles)) else: - context['nodes'] = list(_node_data( + nodes = list(_node_data( self.request, api.node.Node.list(self.request, maintenance=False), )) + + nodes.sort(key=lambda node: node.get('role_name')) + nodes.reverse() + + context['nodes'] = nodes + distribution = collections.Counter() + + for node in nodes: + distribution[node['role_name']] += 1 + for role in context['roles']: + role['distribution'] = int(float(distribution[role['name']]) / + len(nodes) * 100) + + if api_base.is_service_enabled(self.request, 'metering'): + for role in context['roles']: + role['graph_url'] = ( + reverse('horizon:infrastructure:roles:performance', + args=[role['id']]) + '?' + + metering.url_part('hardware.cpu.load.1min', False) + + '&date_options=1' + ) return context def get_progress_update(self, request, data): diff --git a/tuskar_boxes/static/tuskar_boxes/scss/tuskar_boxes.scss b/tuskar_boxes/static/tuskar_boxes/scss/tuskar_boxes.scss index 918a228..234293a 100644 --- a/tuskar_boxes/static/tuskar_boxes/scss/tuskar_boxes.scss +++ b/tuskar_boxes/static/tuskar_boxes/scss/tuskar_boxes.scss @@ -112,3 +112,25 @@ .boxes-flavor { padding-bottom: 10px; } + +.role-distribution { + .roles-graph-label { + margin-top: 8px; + } + .role-controller { + color: #ce5c00; + } + .role-compute { + color: #4e9a06; + } + .role-swift-storage { + color: #204a87; + } + .role-cinder-storage { + color: #5c3566; + } +} + +.roles-graph-label { + margin-top: 12px; +} diff --git a/tuskar_boxes/templates/tuskar_boxes/overview/index.html b/tuskar_boxes/templates/tuskar_boxes/overview/index.html index 0d0b522..ea9fd49 100644 --- a/tuskar_boxes/templates/tuskar_boxes/overview/index.html +++ b/tuskar_boxes/templates/tuskar_boxes/overview/index.html @@ -43,13 +43,39 @@
{% if stack %} - {% include "tuskar_boxes/overview/role_nodes_status.html" %} + {% if stack.is_deployed and stack.is_initialized %} + {% include "tuskar_boxes/overview/role_nodes_live.html" %} + {% else %} + {% include "tuskar_boxes/overview/role_nodes_status.html" %} + {% endif %} {% else %} {% include "tuskar_boxes/overview/role_nodes_edit.html" %} {% endif %}
+
+
+ {% if stack and stack.is_deployed and stack.is_initialized %} +

Nodes Distribution

+
+ {% for role in roles %} + {% if role.distribution %} + + {{ role.name|capfirst }}: {{ role.distribution }}% + + {% endif %} + {% endfor %} +
+
+ {% for node in nodes %}{% spaceless %} +
+ {% endspaceless %}{% endfor %} +
+ {% endif %} +
+
+