From 35ab880e0fccfd05df012dadb49f97a7ccf73e73 Mon Sep 17 00:00:00 2001 From: Steven Hillman Date: Thu, 7 Aug 2014 11:52:19 -0700 Subject: [PATCH] Add config for visibility of cisco-policy-profile This change adds a configuration option to cisco_plugin.ini to control the visibility of cisco-policy-profile among tenants. The default is false or unrestricted, so all tenants can view all policy profiles. If the option is set to true, tenants can only view policy profiles that are assigned to that tenant. The admin user can always view all policy profiles. This was implemented by adding a check of the configuration option in get_policy_profiles(). Change-Id: I5d77544d75366d39714def971eb949cfdc40023e Implements: blueprint cisco-policy-profile-visibility --- etc/neutron/plugins/cisco/cisco_plugins.ini | 6 + neutron/plugins/cisco/common/config.py | 3 + neutron/plugins/cisco/db/n1kv_db_v2.py | 3 +- .../tests/unit/cisco/n1kv/test_n1kv_plugin.py | 103 +++++++++++++++++- 4 files changed, 112 insertions(+), 3 deletions(-) diff --git a/etc/neutron/plugins/cisco/cisco_plugins.ini b/etc/neutron/plugins/cisco/cisco_plugins.ini index 22c11d4ce..0b5a9bf2f 100644 --- a/etc/neutron/plugins/cisco/cisco_plugins.ini +++ b/etc/neutron/plugins/cisco/cisco_plugins.ini @@ -133,6 +133,12 @@ # poll_duration = # Example: poll_duration = 180 +# (BoolOpt) Specify whether tenants are restricted from accessing all the +# policy profiles. +# Default value: False, indicating all tenants can access all policy profiles. +# +# restrict_policy_profiles = False + # (IntOpt) Number of threads to use to make HTTP requests to the VSM. # # http_pool_size = 4 diff --git a/neutron/plugins/cisco/common/config.py b/neutron/plugins/cisco/common/config.py index bc764474e..4211400e6 100644 --- a/neutron/plugins/cisco/common/config.py +++ b/neutron/plugins/cisco/common/config.py @@ -78,6 +78,9 @@ cisco_n1k_opts = [ help=_("N1K policy profile for network node")), cfg.IntOpt('poll_duration', default=10, help=_("N1K Policy profile polling duration in seconds")), + cfg.BoolOpt('restrict_policy_profiles', default=False, + help=_("Restrict the visibility of policy profiles to the " + "tenants")), cfg.IntOpt('http_pool_size', default=4, help=_("Number of threads to use to make HTTP requests")), cfg.IntOpt('http_timeout', default=15, diff --git a/neutron/plugins/cisco/db/n1kv_db_v2.py b/neutron/plugins/cisco/db/n1kv_db_v2.py index d746a7b17..b7cf14be5 100644 --- a/neutron/plugins/cisco/db/n1kv_db_v2.py +++ b/neutron/plugins/cisco/db/n1kv_db_v2.py @@ -30,6 +30,7 @@ from neutron.db import models_v2 from neutron.openstack.common import log as logging from neutron.plugins.cisco.common import cisco_constants as c_const from neutron.plugins.cisco.common import cisco_exceptions as c_exc +from neutron.plugins.cisco.common import config as c_conf from neutron.plugins.cisco.db import n1kv_models_v2 LOG = logging.getLogger(__name__) @@ -1469,7 +1470,7 @@ class PolicyProfile_db_mixin(object): profile dictionary. Only these fields will be returned :returns: list of all policy profiles """ - if context.is_admin: + if context.is_admin or not c_conf.CISCO_N1K.restrict_policy_profiles: return self._get_collection(context, n1kv_models_v2.PolicyProfile, self._make_policy_profile_dict, filters=filters, fields=fields) diff --git a/neutron/tests/unit/cisco/n1kv/test_n1kv_plugin.py b/neutron/tests/unit/cisco/n1kv/test_n1kv_plugin.py index 0d71bf4ab..02b338f63 100644 --- a/neutron/tests/unit/cisco/n1kv/test_n1kv_plugin.py +++ b/neutron/tests/unit/cisco/n1kv/test_n1kv_plugin.py @@ -26,12 +26,14 @@ from neutron.extensions import portbindings from neutron import manager from neutron.plugins.cisco.common import cisco_constants as c_const from neutron.plugins.cisco.common import cisco_exceptions as c_exc +from neutron.plugins.cisco.common import config as c_conf from neutron.plugins.cisco.db import n1kv_db_v2 from neutron.plugins.cisco.db import n1kv_models_v2 from neutron.plugins.cisco.db import network_db_v2 as cdb from neutron.plugins.cisco import extensions from neutron.plugins.cisco.extensions import n1kv from neutron.plugins.cisco.extensions import network_profile +from neutron.plugins.cisco.extensions import policy_profile from neutron.plugins.cisco.n1kv import n1kv_client from neutron.plugins.cisco.n1kv import n1kv_neutron_plugin from neutron.tests.unit import _test_extension_portbindings as test_bindings @@ -89,6 +91,24 @@ class NetworkProfileTestExtensionManager(object): return [] +class PolicyProfileTestExtensionManager(object): + + def get_resources(self): + # Add the resources to the global attribute map + # This is done here as the setup process won't + # initialize the main API router which extends + # the global attribute map + attributes.RESOURCE_ATTRIBUTE_MAP.update( + policy_profile.RESOURCE_ATTRIBUTE_MAP) + return policy_profile.Policy_profile.get_resources() + + def get_actions(self): + return [] + + def get_request_extensions(self): + return [] + + class N1kvPluginTestCase(test_plugin.NeutronDbPluginV2TestCase): _plugin_name = ('neutron.plugins.cisco.n1kv.' @@ -144,7 +164,7 @@ class N1kvPluginTestCase(test_plugin.NeutronDbPluginV2TestCase): n1kv_db_v2.sync_vlan_allocations(db_session, net_p) return net_p - def setUp(self): + def setUp(self, ext_mgr=NetworkProfileTestExtensionManager()): """ Setup method for n1kv plugin tests. @@ -199,7 +219,6 @@ class N1kvPluginTestCase(test_plugin.NeutronDbPluginV2TestCase): n1kv_neutron_plugin.N1kvNeutronPluginV2._setup_vsm = _fake_setup_vsm neutron_extensions.append_api_extensions_path(extensions.__path__) - ext_mgr = NetworkProfileTestExtensionManager() # Save the original RESOURCE_ATTRIBUTE_MAP self.saved_attr_map = {} @@ -682,6 +701,17 @@ class TestN1kvPorts(test_plugin.TestPortsV2, class TestN1kvPolicyProfiles(N1kvPluginTestCase): + def setUp(self): + """ + Setup function for policy profile tests. + + We need to use the policy profile extension manager for these + test cases, so call the super class setup, but pass in the + policy profile extension manager. + """ + super(TestN1kvPolicyProfiles, self).setUp( + ext_mgr=PolicyProfileTestExtensionManager()) + def test_populate_policy_profile(self): client_patch = mock.patch(n1kv_client.__name__ + ".Client", new=fake_client.TestClient) @@ -729,6 +759,75 @@ class TestN1kvPolicyProfiles(N1kvPluginTestCase): db_session, '00000000-0000-0000-0000-000000000003') + def _init_get_policy_profiles(self): + # Get the profiles + mock.patch(n1kv_client.__name__ + ".Client", + new=fake_client.TestClient).start() + instance = n1kv_neutron_plugin.N1kvNeutronPluginV2() + instance._populate_policy_profiles() + db_session = db.get_session() + return [ + n1kv_db_v2.get_policy_profile( + db_session, '00000000-0000-0000-0000-000000000001'), + n1kv_db_v2.get_policy_profile( + db_session, '00000000-0000-0000-0000-000000000002') + ] + + def _test_get_policy_profiles(self, expected_profiles, admin): + resource = 'policy_profiles' + if admin: + ctx = context.Context(user_id='admin', + tenant_id='tenant1', + is_admin=True) + else: + ctx = context.Context(user_id='non_admin', + tenant_id='tenant1', + is_admin=False) + res = self._list(resource, neutron_context=ctx) + self.assertEqual(len(expected_profiles), len(res[resource])) + profiles = sorted(res[resource]) + for i in range(len(profiles)): + self.assertEqual(expected_profiles[i].id, + profiles[i]['id']) + self.assertEqual(expected_profiles[i].name, + profiles[i]['name']) + + def test_get_profiles_unrestricted(self): + """ + Test unrestricted policy profile retrieval. + + Test getting policy profiles using the normal unrestricted + behavior. We set the flag and attempt to retrieve the port + profiles. It should work for both admin and non-admin. + """ + # Get the profiles + profiles = self._init_get_policy_profiles() + # Set the restriction flag + c_conf.CONF.set_override('restrict_policy_profiles', False, + 'CISCO_N1K') + # Request the list using non-admin and verify it returns + self._test_get_policy_profiles(expected_profiles=profiles, admin=False) + # Request the list using admin and verify it returns + self._test_get_policy_profiles(expected_profiles=profiles, admin=True) + + def test_get_profiles_restricted(self): + """ + Test restricted policy profile retrieval. + + Test getting policy profiles using the restricted behavior. + We set the flag and attempt to retrieve the port profiles. It + should work for admin and fail for non-admin. + """ + # Get the profiles + profiles = self._init_get_policy_profiles() + # Set the restriction flag + c_conf.CONF.set_override('restrict_policy_profiles', True, + 'CISCO_N1K') + # Request the list using non-admin and verify it returns no data + self._test_get_policy_profiles(expected_profiles=[], admin=False) + # Request the list using admin and verify it returns + self._test_get_policy_profiles(expected_profiles=profiles, admin=True) + class TestN1kvNetworks(test_plugin.TestNetworksV2, N1kvPluginTestCase): -- 2.45.2