From 45ba74af0531a1986985b6da351faa57bfeb901d Mon Sep 17 00:00:00 2001 From: Diana Whitten Date: Mon, 14 Jul 2014 13:02:45 -0700 Subject: [PATCH] Instance Action Dashboard Blueprint Create a new dashboard in Horizon to show the actions taken on the tenant's instances in reverse date order (latest first). This provides the user with a view of what's been happening in their environment, and any errors that have occurred. Co-Authored-By: Nicolas Simonds Co-Authored-By: David Lapsley Co-Authored-By: Diana Whitten Implements: blueprint instance-actions-dashboard Change-Id: I9cf54db7c2c65ac4679587fa2d8d185a04ae25dc --- openstack_dashboard/api/nova.py | 6 ++++ .../project/instances/audit_tables.py | 36 +++++++++++++++++++ .../dashboards/project/instances/tabs.py | 24 ++++++++++++- .../templates/instances/_detail_audit.html | 7 ++++ 4 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 openstack_dashboard/dashboards/project/instances/audit_tables.py create mode 100644 openstack_dashboard/dashboards/project/instances/templates/instances/_detail_audit.html diff --git a/openstack_dashboard/api/nova.py b/openstack_dashboard/api/nova.py index 0338d010ee..0a321339ac 100644 --- a/openstack_dashboard/api/nova.py +++ b/openstack_dashboard/api/nova.py @@ -28,6 +28,7 @@ from django.utils.translation import ugettext_lazy as _ from novaclient import exceptions as nova_exceptions from novaclient.v1_1 import client as nova_client +from novaclient.v1_1.contrib import instance_action as nova_instance_action from novaclient.v1_1.contrib import list_extensions as nova_list_extensions from novaclient.v1_1 import security_group_rules as nova_rules from novaclient.v1_1 import security_groups as nova_security_groups @@ -781,3 +782,8 @@ def extension_supported(extension_name, request): def can_set_server_password(): features = getattr(settings, 'OPENSTACK_HYPERVISOR_FEATURES', {}) return features.get('can_set_password', False) + + +def instance_action_list(request, instance_id): + return nova_instance_action.InstanceActionManager( + novaclient(request)).list(instance_id) diff --git a/openstack_dashboard/dashboards/project/instances/audit_tables.py b/openstack_dashboard/dashboards/project/instances/audit_tables.py new file mode 100644 index 0000000000..b026550cf6 --- /dev/null +++ b/openstack_dashboard/dashboards/project/instances/audit_tables.py @@ -0,0 +1,36 @@ +# Copyright 2013 Metacloud, 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. + + +from django.utils.translation import ugettext_lazy as _ + +from horizon import tables +from horizon.utils import filters + + +class AuditTable(tables.DataTable): + request_id = tables.Column('request_id', + verbose_name=_('Request ID')) + action = tables.Column('action', verbose_name=_('Action')) + start_time = tables.Column('start_time', verbose_name=_('Start Time'), + filters=[filters.parse_isotime]) + user_id = tables.Column('user_id', verbose_name=_('User ID')) + message = tables.Column('message', verbose_name=_('Message')) + + class Meta: + name = 'audit' + verbose_name = _('Instance Action List') + + def get_object_id(self, datum): + return datum.request_id diff --git a/openstack_dashboard/dashboards/project/instances/tabs.py b/openstack_dashboard/dashboards/project/instances/tabs.py index 1547daea2d..8e0a526e66 100644 --- a/openstack_dashboard/dashboards/project/instances/tabs.py +++ b/openstack_dashboard/dashboards/project/instances/tabs.py @@ -18,6 +18,9 @@ from django.utils.translation import ugettext_lazy as _ from horizon import exceptions from horizon import tabs +from openstack_dashboard.dashboards.project.instances \ + import audit_tables as a_tables + from openstack_dashboard import api from openstack_dashboard.dashboards.project.instances import console @@ -69,7 +72,26 @@ class ConsoleTab(tabs.Tab): return {'console_url': console_url, 'instance_id': instance.id} +class AuditTab(tabs.TableTab): + name = _("Action Log") + slug = "audit" + table_classes = (a_tables.AuditTable,) + template_name = "project/instances/_detail_audit.html" + preload = False + + def get_audit_data(self): + actions = [] + try: + actions = api.nova.instance_action_list( + self.request, self.tab_group.kwargs['instance_id']) + except Exception: + exceptions.handle(self.request, + _('Unable to retrieve instance action list.')) + + return sorted(actions, reverse=True, key=lambda y: y.start_time) + + class InstanceDetailTabs(tabs.TabGroup): slug = "instance_details" - tabs = (OverviewTab, LogTab, ConsoleTab) + tabs = (OverviewTab, LogTab, ConsoleTab, AuditTab) sticky = True diff --git a/openstack_dashboard/dashboards/project/instances/templates/instances/_detail_audit.html b/openstack_dashboard/dashboards/project/instances/templates/instances/_detail_audit.html new file mode 100644 index 0000000000..82705ea15a --- /dev/null +++ b/openstack_dashboard/dashboards/project/instances/templates/instances/_detail_audit.html @@ -0,0 +1,7 @@ +{% load i18n %} + +
+
+ {{ table.render }} +
+