diff --git a/openstack_dashboard/dashboards/admin/aggregates/panel.py b/openstack_dashboard/dashboards/admin/aggregates/panel.py index 2477295e4c..5c7add7a25 100644 --- a/openstack_dashboard/dashboards/admin/aggregates/panel.py +++ b/openstack_dashboard/dashboards/admin/aggregates/panel.py @@ -14,6 +14,7 @@ from django.utils.translation import ugettext_lazy as _ import horizon +from openstack_dashboard.api import nova from openstack_dashboard.dashboards.admin import dashboard @@ -22,5 +23,12 @@ class Aggregates(horizon.Panel): slug = 'aggregates' permissions = ('openstack.services.compute',) + def can_access(self, context): + # extend basic permission-based check with a check to see whether + # the Aggregates extension is even enabled in nova + if not nova.extension_supported('Aggregates', context['request']): + return False + return super(Aggregates, self).can_access(context) + dashboard.Admin.register(Aggregates) diff --git a/openstack_dashboard/dashboards/admin/aggregates/tests.py b/openstack_dashboard/dashboards/admin/aggregates/tests.py index 824ecdc9e2..9ec56a7944 100644 --- a/openstack_dashboard/dashboards/admin/aggregates/tests.py +++ b/openstack_dashboard/dashboards/admin/aggregates/tests.py @@ -12,6 +12,8 @@ import json +import mock + from django.core.urlresolvers import reverse from django import http from mox import IsA # noqa @@ -176,6 +178,13 @@ class CreateAggregateWorkflowTests(BaseAggregateWorkflowTests): class AggregatesViewTests(test.BaseAdminViewTests): + @mock.patch('openstack_dashboard.api.nova.extension_supported', + mock.Mock(return_value=False)) + def test_panel_not_available(self): + self.patchers['aggregates'].stop() + res = self.client.get(reverse('horizon:admin:overview:index')) + self.assertNotIn('Host Aggregates', res.content) + @test.create_stubs({api.nova: ('aggregate_details_list', 'availability_zone_list',), }) def test_index(self): diff --git a/openstack_dashboard/test/helpers.py b/openstack_dashboard/test/helpers.py index b271405ed9..634d8cdb7c 100644 --- a/openstack_dashboard/test/helpers.py +++ b/openstack_dashboard/test/helpers.py @@ -37,6 +37,7 @@ import glanceclient from heatclient import client as heat_client import httplib2 from keystoneclient.v2_0 import client as keystone_client +import mock import mox from neutronclient.v2_0 import client as neutron_client from novaclient.v1_1 import client as nova_client @@ -149,6 +150,12 @@ class TestCase(horizon_helpers.TestCase): self.request.session['token'] = self.token.id middleware.HorizonMiddleware().process_request(self.request) AuthenticationMiddleware().process_request(self.request) + self.patchers = {} + self.patchers['aggregates'] = mock.patch( + 'openstack_dashboard.dashboards.admin' + '.aggregates.panel.Aggregates.can_access', + mock.Mock(return_value=True)) + self.patchers['aggregates'].start() os.environ["HORIZON_TEST_RUN"] = "True" def tearDown(self): @@ -156,6 +163,7 @@ class TestCase(horizon_helpers.TestCase): httplib2.Http._conn_request = self._real_conn_request context_processors.openstack = self._real_context_processor utils.get_user = self._real_get_user + mock.patch.stopall() self.mox.VerifyAll() del os.environ["HORIZON_TEST_RUN"] @@ -396,11 +404,18 @@ class SeleniumTestCase(horizon_helpers.SeleniumTestCase): tenant_id=self.tenant.id, service_catalog=self.service_catalog, authorized_tenants=self.tenants.list()) + self.patchers = {} + self.patchers['aggregates'] = mock.patch( + 'openstack_dashboard.dashboards.admin' + '.aggregates.panel.Aggregates.can_access', + mock.Mock(return_value=True)) + self.patchers['aggregates'].start() os.environ["HORIZON_TEST_RUN"] = "True" def tearDown(self): self.mox.UnsetStubs() utils.get_user = self._real_get_user + mock.patch.stopall() self.mox.VerifyAll() del os.environ["HORIZON_TEST_RUN"] diff --git a/test-requirements.txt b/test-requirements.txt index f0b0801d76..740c22450d 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -11,6 +11,7 @@ hacking>=0.9.2,<0.10 # coverage>=3.6 django-nose +mock>=1.0 mox>=0.5.3 nodeenv>=0.9.4 # BSD License nose