From f0533f6d5c7b01e02d34c0712edf18dd09491d5f Mon Sep 17 00:00:00 2001 From: Radomir Dopieralski Date: Tue, 30 Sep 2014 16:01:35 +0200 Subject: [PATCH] Refresh progress page with AJAX Instead of reloading the progress page constantly, update it with JavaScript. Only refresh when the deployment finished. Change-Id: I2c08c6f213dad59f410f6e5612fd1c2ed89f7eec --- .../overview/deployment_progress.html | 22 +++++++ .../overview/templates/overview/index.html | 7 --- .../templates/overview/role_nodes_status.html | 33 +++++++---- tuskar_ui/infrastructure/overview/views.py | 57 ++++++++++++++++--- .../js/tuskar.deployment_progress.js | 41 +++++++++++++ .../templates/infrastructure/_scripts.html | 1 + 6 files changed, 135 insertions(+), 26 deletions(-) create mode 100644 tuskar_ui/infrastructure/static/infrastructure/js/tuskar.deployment_progress.js diff --git a/tuskar_ui/infrastructure/overview/templates/overview/deployment_progress.html b/tuskar_ui/infrastructure/overview/templates/overview/deployment_progress.html index e55450656..04ed27be9 100644 --- a/tuskar_ui/infrastructure/overview/templates/overview/deployment_progress.html +++ b/tuskar_ui/infrastructure/overview/templates/overview/deployment_progress.html @@ -2,6 +2,7 @@ {% load i18n %} {% load url from future%} +{% load horizon %} {% block deployment-icon %} @@ -28,6 +29,7 @@ >{{ progress }}% {% trans "Complete" %} {% endif %} +
{% for event in last_failed_events %} @@ -46,6 +48,7 @@ {% endfor %} {% endif %}

See full log

+
{% endblock %} {% block deployment-buttons %} @@ -59,3 +62,22 @@ {% endif %} {% endblock %} +{% block templates %} + +{% endblock %} diff --git a/tuskar_ui/infrastructure/overview/templates/overview/index.html b/tuskar_ui/infrastructure/overview/templates/overview/index.html index 60ac0d49c..ff13c043a 100644 --- a/tuskar_ui/infrastructure/overview/templates/overview/index.html +++ b/tuskar_ui/infrastructure/overview/templates/overview/index.html @@ -4,13 +4,6 @@ {% block title %}{% trans 'My OpenStack Deployment' %}{% endblock %} -{% block css %} - {% if stack.is_deploying %} - - {% endif %} - {{ block.super }} -{% endblock %} - {% block page_header %} {% include 'horizon/common/_domain_page_header.html' with title=_('My OpenStack Deployment') %} {% endblock page_header %} diff --git a/tuskar_ui/infrastructure/overview/templates/overview/role_nodes_status.html b/tuskar_ui/infrastructure/overview/templates/overview/role_nodes_status.html index 688835ab6..701229da3 100644 --- a/tuskar_ui/infrastructure/overview/templates/overview/role_nodes_status.html +++ b/tuskar_ui/infrastructure/overview/templates/overview/role_nodes_status.html @@ -1,19 +1,13 @@ {% load i18n %} {% load url from future %} +{% load horizon %}

{% trans "Deployment Roles" %}

+
{% for role in roles %} -
+
- {% if role.deployed_node_count < role.planned_node_count %} + {% if role.finished %} {{ role.deployed_node_count }}/{{ role.planned_node_count }} {% else %} {{ role.planned_node_count }} @@ -26,3 +20,22 @@
{% endfor %} +
+ + + diff --git a/tuskar_ui/infrastructure/overview/views.py b/tuskar_ui/infrastructure/overview/views.py index 7e6632029..c76d7acad 100644 --- a/tuskar_ui/infrastructure/overview/views.py +++ b/tuskar_ui/infrastructure/overview/views.py @@ -42,7 +42,7 @@ def _get_role_data(plan, stack, form, role): 'role': role, 'name': role.name, 'planned_node_count': plan.get_role_node_count(role), - 'field': form['%s-count' % role.id], + 'field': form['%s-count' % role.id] if form else '', } if stack: @@ -55,6 +55,7 @@ def _get_role_data(plan, stack, form, role): error_node_count = 0 waiting_node_count = node_count + status = 'warning' if nodes: deployed_node_count = sum(1 for node in nodes if node.instance.status == 'ACTIVE') @@ -64,7 +65,16 @@ def _get_role_data(plan, stack, form, role): if node.instance.status == 'ERROR') waiting_node_count = (node_count - deployed_node_count - deploying_node_count - error_node_count) + if error_node_count: + status = 'danger' + elif deployed_node_count == data['planned_node_count']: + status = 'success' + else: + status = 'info' + data.update({ + 'status': status, + 'finished': deployed_node_count == data['planned_node_count'], 'total_node_count': node_count, 'deployed_node_count': deployed_node_count, 'deploying_node_count': deploying_node_count, @@ -93,6 +103,33 @@ class IndexView(horizon.forms.ModalFormView, StackMixin): form_class = forms.EditPlan success_url = reverse_lazy(INDEX_URL) + def get(self, request, *args, **kwargs): + if request.META.get('HTTP_X_HORIZON_PROGRESS', ''): + data = self.get_data(request, {}) + return http.HttpResponse(json.dumps({ + 'progress': data.get('progress'), + 'last_failed_events': [{ + 'event_time': event.event_time, + 'resource_name': event.resource_name, + 'resource_status': event.resource_status, + 'resource_statys_reason': event.resource_statys_reason, + } for event in data.get('last_failed_events', [])], + 'roles': [{ + 'status': role.get('status', 'warning'), + 'finished': role.get('finished', False), + 'name': role.get('name', ''), + 'id': role.get('id', ''), + 'total_node_count': role.get('node_count', 0), + 'deployed_node_count': role.get('deployed_node_count', 0), + 'deploying_node_count': role.get('deploying_node_count', + 0), + 'waiting_node_count': role.get('waiting_node_count', 0), + 'error_node_count': role.get('error_node_count', 0), + 'planned_node_count': role.get('planned_node_count', 0), + } for role in data.get('roles', [])], + }), mimetype='application/json') + return super(IndexView, self).get(request, *args, **kwargs) + def get_form(self, form_class): return form_class(self.request, **self.get_form_kwargs()) @@ -104,7 +141,7 @@ class IndexView(horizon.forms.ModalFormView, StackMixin): def get_data(self, request, context, *args, **kwargs): plan = api.tuskar.Plan.get_the_plan(request) stack = self.get_stack() - form = context['form'] + form = context.get('form') context['plan'] = plan context['stack'] = stack @@ -141,19 +178,21 @@ class IndexView(horizon.forms.ModalFormView, StackMixin): total_num_nodes_count = max( resources_count, total_num_nodes_count) - context['progress'] = max( - 5, 100 * (total_num_nodes_count - resources_count)) + context['progress'] = min(95, max( + 5, 100 * float(resources_count) / total_num_nodes_count)) + elif stack.is_deploying: + total = sum(d['total_node_count'] for d in roles) + context['progress'] = min(95, max( + 5, 100 * sum(float(d.get('deployed_node_count', 0)) + for d in roles) / (total or 1) + )) else: # stack is active + context['progress'] = 100 controller_role = plan.get_role_by_name("controller") context['admin_password'] = plan.parameter_value( controller_role.parameter_prefix + 'AdminPassword') - total = sum(d['total_node_count'] for d in roles) - context['progress'] = max( - 5, 100 * sum(d.get('deployed_node_count', 0) - for d in roles) // (total or 1) - ) context['dashboard_urls'] = stack.dashboard_urls else: messages = forms.validate_plan(request, plan) diff --git a/tuskar_ui/infrastructure/static/infrastructure/js/tuskar.deployment_progress.js b/tuskar_ui/infrastructure/static/infrastructure/js/tuskar.deployment_progress.js new file mode 100644 index 000000000..2c308c146 --- /dev/null +++ b/tuskar_ui/infrastructure/static/infrastructure/js/tuskar.deployment_progress.js @@ -0,0 +1,41 @@ +tuskar.deployment_progress = (function () { + 'use strict'; + + var module = {}; + + module.init = function () { + if (!$('div.deployment-box div.progress')) { return; } + module.interval = setInterval(module.check_progress, 30000); + module.events_template = Hogan.compile($('#events-template').html() || ''); + module.roles_template = Hogan.compile($('#roles-template').html() || ''); + }; + + module.check_progress = function () { + var $form = $('form.deployment-roles-form'); + $.ajax({ + type: 'GET', + headers: {'X-Horizon-Progress': 'true'}, + url: $form.attr('action'), + dataType: 'json', + async: true, + success: module.update_progress + }); + }; + + module.update_progress = function (data) { + if (data.progress >= 100 || data.progress <= 0) { + window.location.reload(true); + } + var $bar = $('div.deployment-box div.progress div.progress-bar'); + $bar.css('width', '' + data.progress + '%'); + if (data.last_failed_events) { + $('div.deploy-last-events').html(module.events_template.render(data)); + } else { + $('div.deploy-last-events').html(''); + } + $('div.deploy-role-status').html(module.roles_template.render(data)); + }; + + horizon.addInitFunction(module.init); + return module; +} ()); diff --git a/tuskar_ui/infrastructure/templates/infrastructure/_scripts.html b/tuskar_ui/infrastructure/templates/infrastructure/_scripts.html index 02af1e71b..d1c9b77c1 100644 --- a/tuskar_ui/infrastructure/templates/infrastructure/_scripts.html +++ b/tuskar_ui/infrastructure/templates/infrastructure/_scripts.html @@ -8,6 +8,7 @@ + {% endblock %} {% comment %} Tuskar-UI Client-side Templates (These should *not* be inside the "compress" tag.) {% endcomment %}