From ddfa667d02c8e417102412df5c41580dd514630f Mon Sep 17 00:00:00 2001 From: Ying Zuo Date: Mon, 20 Jun 2016 15:31:00 -0700 Subject: [PATCH] Add instance locked status on instances table Added a column to show the locked status on project/admin instances table. There will be a locked or unlocked icon with help tooltip if nova 2.9 or above is used. See openstack_dashboard/api/microversions.py Added the locked field on project/admin instance details panel. Change-Id: If31ae281d2782c71cd6112f3bd6228647a6130e4 Closes-bug: #1593903 --- openstack_dashboard/api/nova.py | 12 ++++++++--- .../dashboards/admin/instances/tables.py | 3 +++ .../dashboards/project/instances/tables.py | 21 +++++++++++++++++++ .../templates/instances/_detail_overview.html | 4 ++++ .../test/api_tests/neutron_tests.py | 2 ++ .../test/api_tests/nova_tests.py | 14 +++++++++++++ openstack_dashboard/test/helpers.py | 5 ++++- .../notes/bug-1593903-8fb8721dc2449f71.yaml | 6 ++++++ 8 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 releasenotes/notes/bug-1593903-8fb8721dc2449f71.yaml diff --git a/openstack_dashboard/api/nova.py b/openstack_dashboard/api/nova.py index 4eb4973447..56652a2e7e 100644 --- a/openstack_dashboard/api/nova.py +++ b/openstack_dashboard/api/nova.py @@ -493,15 +493,21 @@ def server_delete(request, instance_id): novaclient(request).servers.delete(instance_id) +def get_novaclient_with_locked_status(request): + microversion = get_microversion(request, "locked_attribute") + return novaclient(request, version=microversion) + + @profiler.trace def server_get(request, instance_id): - return Server(novaclient(request).servers.get(instance_id), request) + return Server(get_novaclient_with_locked_status(request).servers.get( + instance_id), request) @profiler.trace def server_list(request, search_opts=None, all_tenants=False, detailed=True): + nova_client = get_novaclient_with_locked_status(request) page_size = utils.get_page_size(request) - c = novaclient(request) paginate = False if search_opts is None: search_opts = {} @@ -515,7 +521,7 @@ def server_list(request, search_opts=None, all_tenants=False, detailed=True): else: search_opts['project_id'] = request.user.tenant_id servers = [Server(s, request) - for s in c.servers.list(detailed, search_opts)] + for s in nova_client.servers.list(detailed, search_opts)] has_more_data = False if paginate and len(servers) > page_size: diff --git a/openstack_dashboard/dashboards/admin/instances/tables.py b/openstack_dashboard/dashboards/admin/instances/tables.py index 3791fc5df6..28c6476335 100644 --- a/openstack_dashboard/dashboards/admin/instances/tables.py +++ b/openstack_dashboard/dashboards/admin/instances/tables.py @@ -152,6 +152,9 @@ class AdminInstancesTable(tables.DataTable): status=True, status_choices=STATUS_CHOICES, display_choices=project_tables.STATUS_DISPLAY_CHOICES) + locked = tables.Column(project_tables.render_locked, + verbose_name=_(" "), + sortable=False) task = tables.Column("OS-EXT-STS:task_state", verbose_name=_("Task"), empty_value=project_tables.TASK_DISPLAY_NONE, diff --git a/openstack_dashboard/dashboards/project/instances/tables.py b/openstack_dashboard/dashboards/project/instances/tables.py index 3f52f6cc4f..f2bf1eebb8 100644 --- a/openstack_dashboard/dashboards/project/instances/tables.py +++ b/openstack_dashboard/dashboards/project/instances/tables.py @@ -22,6 +22,7 @@ from django import shortcuts from django import template from django.template.defaultfilters import title from django.utils.http import urlencode +from django.utils.safestring import mark_safe from django.utils.translation import npgettext_lazy from django.utils.translation import pgettext_lazy from django.utils.translation import string_concat @@ -1183,6 +1184,23 @@ class InstancesFilterAction(tables.FilterAction): filter_choices = INSTANCE_FILTER_CHOICES +def render_locked(instance): + if not hasattr(instance, 'locked'): + return "" + if instance.locked: + icon_classes = "fa fa-fw fa-lock" + help_tooltip = _("This instance is currently locked. To enable more " + "actions on it, please unlock it by selecting Unlock " + "Instance from the actions menu.") + else: + icon_classes = "fa fa-fw fa-unlock text-muted" + help_tooltip = _("This instance is unlocked.") + + locked_status = ('' + '').format(help_tooltip, icon_classes) + return mark_safe(locked_status) + + class InstancesTable(tables.DataTable): TASK_STATUS_CHOICES = ( (None, True), @@ -1216,6 +1234,9 @@ class InstancesTable(tables.DataTable): status=True, status_choices=STATUS_CHOICES, display_choices=STATUS_DISPLAY_CHOICES) + locked = tables.Column(render_locked, + verbose_name="", + sortable=False) az = tables.Column("availability_zone", verbose_name=_("Availability Zone")) task = tables.Column("OS-EXT-STS:task_state", diff --git a/openstack_dashboard/dashboards/project/instances/templates/instances/_detail_overview.html b/openstack_dashboard/dashboards/project/instances/templates/instances/_detail_overview.html index fce3b05994..6b1500fd2e 100644 --- a/openstack_dashboard/dashboards/project/instances/templates/instances/_detail_overview.html +++ b/openstack_dashboard/dashboards/project/instances/templates/instances/_detail_overview.html @@ -8,6 +8,10 @@
{{ instance.id }}
{% trans "Status" %}
{{ instance.status_label|title }}
+ {% if instance.locked != None %} +
{% trans "Locked" %}
+
{{ instance.locked }}
+ {% endif %}
{% trans "Availability Zone" %}
{{ instance.availability_zone|default:_("-") }}
{% trans "Created" %}
diff --git a/openstack_dashboard/test/api_tests/neutron_tests.py b/openstack_dashboard/test/api_tests/neutron_tests.py index 0e288e4dea..2854f5d0c2 100644 --- a/openstack_dashboard/test/api_tests/neutron_tests.py +++ b/openstack_dashboard/test/api_tests/neutron_tests.py @@ -1093,6 +1093,8 @@ class NeutronApiFloatingIpTests(NeutronApiTestBase): servers = self.servers.list() novaclient = self.stub_novaclient() novaclient.servers = self.mox.CreateMockAnything() + novaclient.versions = self.mox.CreateMockAnything() + novaclient.versions.get_current().AndReturn("2.45") search_opts = {'project_id': self.request.user.tenant_id} novaclient.servers.list(False, search_opts).AndReturn(servers) diff --git a/openstack_dashboard/test/api_tests/nova_tests.py b/openstack_dashboard/test/api_tests/nova_tests.py index 2583dee9ee..1c5eefa7dc 100644 --- a/openstack_dashboard/test/api_tests/nova_tests.py +++ b/openstack_dashboard/test/api_tests/nova_tests.py @@ -141,6 +141,8 @@ class ComputeApiTests(test.APITestCase): novaclient = self.stub_novaclient() novaclient.servers = self.mox.CreateMockAnything() + novaclient.versions = self.mox.CreateMockAnything() + novaclient.versions.get_current().AndReturn("2.45") novaclient.servers.list(True, {'all_tenants': True}).AndReturn(servers) self.mox.ReplayAll() @@ -154,6 +156,8 @@ class ComputeApiTests(test.APITestCase): servers = self.servers.list() novaclient = self.stub_novaclient() novaclient.servers = self.mox.CreateMockAnything() + novaclient.versions = self.mox.CreateMockAnything() + novaclient.versions.get_current().AndReturn("2.45") novaclient.servers.list(True, {'all_tenants': True, 'marker': None, @@ -174,6 +178,8 @@ class ComputeApiTests(test.APITestCase): servers = self.servers.list() novaclient = self.stub_novaclient() novaclient.servers = self.mox.CreateMockAnything() + novaclient.versions = self.mox.CreateMockAnything() + novaclient.versions.get_current().AndReturn("2.45") novaclient.servers.list(True, {'all_tenants': True, 'marker': None, @@ -267,6 +273,8 @@ class ComputeApiTests(test.APITestCase): server = self.servers.first() novaclient = self.stub_novaclient() + novaclient.versions = self.mox.CreateMockAnything() + novaclient.versions.get_current().AndReturn("2.45") novaclient.servers = self.mox.CreateMockAnything() novaclient.servers.get(server.id).AndReturn(server) self.mox.ReplayAll() @@ -385,6 +393,8 @@ class ComputeApiTests(test.APITestCase): novaclient = self.stub_novaclient() server_uuid = hypervisor.servers[0]["uuid"] + novaclient.versions = self.mox.CreateMockAnything() + novaclient.versions.get_current().AndReturn("2.45") novaclient.hypervisors = self.mox.CreateMockAnything() novaclient.hypervisors.search('host', True).AndReturn([hypervisor]) @@ -405,6 +415,8 @@ class ComputeApiTests(test.APITestCase): novaclient = self.stub_novaclient() server_uuid = hypervisor.servers[0]["uuid"] + novaclient.versions = self.mox.CreateMockAnything() + novaclient.versions.get_current().AndReturn("2.45") novaclient.hypervisors = self.mox.CreateMockAnything() novaclient.hypervisors.search('host', True).AndReturn([hypervisor]) @@ -425,6 +437,8 @@ class ComputeApiTests(test.APITestCase): novaclient = self.stub_novaclient() server_uuid = hypervisor.servers[0]["uuid"] + novaclient.versions = self.mox.CreateMockAnything() + novaclient.versions.get_current().AndReturn("2.45") novaclient.hypervisors = self.mox.CreateMockAnything() novaclient.hypervisors.search('host', True).AndReturn([hypervisor]) diff --git a/openstack_dashboard/test/helpers.py b/openstack_dashboard/test/helpers.py index df5be0cfba..a775743050 100644 --- a/openstack_dashboard/test/helpers.py +++ b/openstack_dashboard/test/helpers.py @@ -417,6 +417,9 @@ class APITestCase(TestCase): """ return self.stub_glanceclient() + def fake_novaclient(request, version=None): + return self.stub_novaclient() + # Store the original clients self._original_glanceclient = api.glance.glanceclient self._original_keystoneclient = api.keystone.keystoneclient @@ -428,7 +431,7 @@ class APITestCase(TestCase): # Replace the clients with our stubs. api.glance.glanceclient = fake_glanceclient api.keystone.keystoneclient = fake_keystoneclient - api.nova.novaclient = lambda request: self.stub_novaclient() + api.nova.novaclient = fake_novaclient api.neutron.neutronclient = lambda request: self.stub_neutronclient() api.cinder.cinderclient = lambda request: self.stub_cinderclient() api.heat.heatclient = (lambda request, password=None: diff --git a/releasenotes/notes/bug-1593903-8fb8721dc2449f71.yaml b/releasenotes/notes/bug-1593903-8fb8721dc2449f71.yaml new file mode 100644 index 0000000000..9f0403ea50 --- /dev/null +++ b/releasenotes/notes/bug-1593903-8fb8721dc2449f71.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + Added a locked status column on admin/project instances table. It will + show a locked or unlocked icon if nova 2.9 or above is used. The locked + status is also available on instance details panel.