diff --git a/tuskar_ui/api.py b/tuskar_ui/api.py index 66f6e2dc2..42a0a70de 100644 --- a/tuskar_ui/api.py +++ b/tuskar_ui/api.py @@ -194,6 +194,26 @@ class Overcloud(base.APIDictWrapper): return self.stack.stack_status in ('CREATE_COMPLETE', 'UPDATE_COMPLETE') + @cached_property + def is_deploying(self): + """Check if this Overcloud is currently deploying or updating. + + :return: True if deployment is in progress, False otherwise. + :rtype: bool + """ + return self.stack.stack_status in ('CREATE_IN_PROGRESS', + 'UPDATE_IN_PROGRESS') + + @cached_property + def is_failed(self): + """Check if this Overcloud failed to update or deploy. + + :return: True if deployment there was an error, False otherwise. + :rtype: bool + """ + return self.stack.stack_status in ('CREATE_FAILED', + 'UPDATE_FAILED') + @memoized.memoized def all_resources(self, with_joins=True): """Return a list of all Overcloud Resources @@ -249,6 +269,11 @@ class Overcloud(base.APIDictWrapper): return filtered_resources + @cached_property + def dashboard_url(self): + # TODO(rdopieralski) Implement this. + return "http://horizon.example.com" + class Node(base.APIResourceWrapper): # FIXME(lsmola) uncomment this and delete equivalent methods diff --git a/tuskar_ui/infrastructure/overcloud/tabs.py b/tuskar_ui/infrastructure/overcloud/tabs.py index 8d0af4251..a9fa28883 100644 --- a/tuskar_ui/infrastructure/overcloud/tabs.py +++ b/tuskar_ui/infrastructure/overcloud/tabs.py @@ -15,6 +15,7 @@ # under the License. from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import ungettext_lazy from horizon import exceptions from horizon import tabs @@ -23,47 +24,66 @@ from tuskar_ui import api from tuskar_ui.infrastructure.overcloud import tables +def _get_role_data(overcloud, role): + resources = overcloud.resources(role, with_joins=True) + nodes = [r.node for r in resources] + node_count = len(nodes) + data = { + 'role': role, + 'name': role.name, + 'node_count': node_count, + } + if nodes: + running_node_count = sum(1 for node in nodes + if node.instance.status == 'ACTIVE') + error_node_count = sum(1 for node in nodes + if node.instance.status == 'ERROR') + deploying_node_count = (node_count - error_node_count - + running_node_count) + data.update({ + 'running_node_count': running_node_count, + 'error_node_count': error_node_count, + 'error_node_message': ungettext_lazy("node is down", + "nodes are down", + error_node_count), + 'deploying_node_count': deploying_node_count, + 'deploying_node_message': ungettext_lazy("node is deploying", + "nodes are deploying", + deploying_node_count), + }) + # TODO(rdopieralski) get this from ceilometer + # data['capacity'] = 20 + return data + + class OverviewTab(tabs.Tab): name = _("Overview") slug = "overview" template_name = ("infrastructure/overcloud/_detail_overview.html") - def get_context_data(self, request): - context = {} + def get_context_data(self, request, **kwargs): overcloud = self.tab_group.kwargs['overcloud'] - try: roles = api.OvercloudRole.list(request) except Exception: - roles = {} + roles = [] exceptions.handle(request, - _('Unable to retrieve overcloud roles.')) - - context['overcloud'] = overcloud - context['roles'] = [] - for role in roles: - context['roles'].append( - self._get_role_data(overcloud, role)) - - # also get expected node counts - return context - - def _get_role_data(self, overcloud, role): - resources = overcloud.resources(role, with_joins=True) - nodes = [r.node for r in resources] - - role.node_count = len(nodes) - if role.node_count > 0: - role.running_node_count = len( - [n for n in nodes if n.instance.status == 'ACTIVE']) - role.error_node_count = len( - [n for n in nodes if n.instance.status == 'ERROR']) - role.other_node_count = role.node_count - \ - (role.running_node_count + - role.error_node_count) - role.running_node_percentage = 100 * \ - role.running_node_count / role.node_count - return role + _("Unable to retrieve overcloud roles.")) + role_data = [_get_role_data(overcloud, role) for role in roles] + total = sum(d['node_count'] for d in role_data) + progress = 100 * sum(d.get('running_node_count', 0) + for d in role_data) // (total or 1) + try: + last_event = overcloud.stack_events[-1] + except IndexError: + last_event = None + return { + 'overcloud': overcloud, + 'roles': role_data, + 'progress': progress, + 'dashboard_url': overcloud.dashboard_url, + 'last_event': last_event, + } class ConfigurationTab(tabs.Tab): diff --git a/tuskar_ui/infrastructure/overcloud/templates/overcloud/_detail_overview.html b/tuskar_ui/infrastructure/overcloud/templates/overcloud/_detail_overview.html index bacaa889b..8aa09dc17 100644 --- a/tuskar_ui/infrastructure/overcloud/templates/overcloud/_detail_overview.html +++ b/tuskar_ui/infrastructure/overcloud/templates/overcloud/_detail_overview.html @@ -1,28 +1,109 @@ {% load i18n %} {% load url from future%} -
+ + {{ last_event.resource_name }} + {{ last_event.resource_status }} +
{% endif %} - {% if role.other_node_count > 0 %} - {{ role.other_node_count }} {% trans "nodes are building" %} -