From 8c23e357095b986ddd966c2d280feb2eabb933bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C5=82awek=20Kap=C5=82o=C5=84ski?= Date: Thu, 22 Feb 2018 13:36:43 +0100 Subject: [PATCH] Fix creation of port when network has admin's QoS policy set In case when admin user creats QoS policy and will attach it to user's namespace there was an issue with getting such QoS policy with user's context to validate it. This patch changes it, that QoS policy is always get with elevated context during port/network create/update validation. Change-Id: I464888ca3920b42edd6ab638f6a317ee51ef0994 Closes-Bug: #1750591 --- neutron/services/qos/qos_plugin.py | 10 ++++++--- .../unit/services/qos/test_qos_plugin.py | 22 ++++++++++++++----- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/neutron/services/qos/qos_plugin.py b/neutron/services/qos/qos_plugin.py index fe699631196..aa771163448 100644 --- a/neutron/services/qos/qos_plugin.py +++ b/neutron/services/qos/qos_plugin.py @@ -93,7 +93,8 @@ class QoSPlugin(qos.QoSPluginBase): if policy_id is None: return - policy = policy_object.QosPolicy.get_object(context, id=policy_id) + policy = policy_object.QosPolicy.get_object( + context.elevated(), id=policy_id) self.validate_policy_for_port(policy, port) def _validate_update_port_callback(self, resource, event, trigger, @@ -108,7 +109,9 @@ class QoSPlugin(qos.QoSPluginBase): updated_port = ports_object.Port.get_object( context, id=kwargs['port']['id']) - policy = policy_object.QosPolicy.get_object(context, id=policy_id) + + policy = policy_object.QosPolicy.get_object( + context.elevated(), id=policy_id) self.validate_policy_for_port(policy, updated_port) @@ -124,7 +127,8 @@ class QoSPlugin(qos.QoSPluginBase): if policy_id is None or policy_id == original_policy_id: return - policy = policy_object.QosPolicy.get_object(context, id=policy_id) + policy = policy_object.QosPolicy.get_object( + context.elevated(), id=policy_id) ports = ports_object.Port.get_objects( context, network_id=updated_network['id']) # Filter only this ports which don't have overwritten policy diff --git a/neutron/tests/unit/services/qos/test_qos_plugin.py b/neutron/tests/unit/services/qos/test_qos_plugin.py index d1c7faaa02b..b2d5d223413 100644 --- a/neutron/tests/unit/services/qos/test_qos_plugin.py +++ b/neutron/tests/unit/services/qos/test_qos_plugin.py @@ -67,6 +67,7 @@ class TestQosPlugin(base.BaseQosTestCase): '.ResourcesPushRpcApi.push').start() self.ctxt = context.Context('fake_user', 'fake_tenant') + self.admin_ctxt = context.get_admin_context() mock.patch.object(self.ctxt.session, 'refresh').start() mock.patch.object(self.ctxt.session, 'expunge').start() @@ -145,6 +146,7 @@ class TestQosPlugin(base.BaseQosTestCase): network_mock = mock.MagicMock( id=uuidutils.generate_uuid(), qos_policy_id=network_policy_id) policy_mock = mock.MagicMock(id=policy_id) + admin_ctxt = mock.Mock() expected_policy_id = policy_id or network_policy_id with mock.patch( 'neutron.objects.ports.Port.get_object', @@ -157,11 +159,13 @@ class TestQosPlugin(base.BaseQosTestCase): return_value=policy_mock ) as get_policy, mock.patch.object( self.qos_plugin, "validate_policy_for_port" - ) as validate_policy_for_port: + ) as validate_policy_for_port, mock.patch.object( + self.ctxt, "elevated", return_value=admin_ctxt + ): self.qos_plugin._validate_create_port_callback( "PORT", "precommit_create", "test_plugin", **kwargs) if policy_id or network_policy_id: - get_policy.assert_called_once_with(self.ctxt, + get_policy.assert_called_once_with(admin_ctxt, id=expected_policy_id) validate_policy_for_port.assert_called_once_with(policy_mock, port_mock) @@ -201,6 +205,7 @@ class TestQosPlugin(base.BaseQosTestCase): } port_mock = mock.MagicMock(id=port_id, qos_policy_id=policy_id) policy_mock = mock.MagicMock(id=policy_id) + admin_ctxt = mock.Mock() with mock.patch( 'neutron.objects.ports.Port.get_object', return_value=port_mock @@ -209,7 +214,9 @@ class TestQosPlugin(base.BaseQosTestCase): return_value=policy_mock ) as get_policy, mock.patch.object( self.qos_plugin, "validate_policy_for_port" - ) as validate_policy_for_port: + ) as validate_policy_for_port, mock.patch.object( + self.ctxt, "elevated", return_value=admin_ctxt + ): self.qos_plugin._validate_update_port_callback( "PORT", "precommit_update", "test_plugin", **kwargs) if policy_id is None or policy_id == original_policy_id: @@ -218,7 +225,7 @@ class TestQosPlugin(base.BaseQosTestCase): validate_policy_for_port.assert_not_called() else: get_port.assert_called_once_with(self.ctxt, id=port_id) - get_policy.assert_called_once_with(self.ctxt, id=policy_id) + get_policy.assert_called_once_with(admin_ctxt, id=policy_id) validate_policy_for_port.assert_called_once_with(policy_mock, port_mock) @@ -256,6 +263,7 @@ class TestQosPlugin(base.BaseQosTestCase): id=uuidutils.generate_uuid(), qos_policy_id=None) ports = [port_mock_with_own_policy, port_mock_without_own_policy] policy_mock = mock.MagicMock(id=policy_id) + admin_ctxt = mock.Mock() with mock.patch( 'neutron.objects.ports.Port.get_objects', return_value=ports @@ -264,7 +272,9 @@ class TestQosPlugin(base.BaseQosTestCase): return_value=policy_mock ) as get_policy, mock.patch.object( self.qos_plugin, "validate_policy_for_ports" - ) as validate_policy_for_ports: + ) as validate_policy_for_ports, mock.patch.object( + self.ctxt, "elevated", return_value=admin_ctxt + ): self.qos_plugin._validate_update_network_callback( "NETWORK", "precommit_update", "test_plugin", **kwargs) if policy_id is None or policy_id == original_policy_id: @@ -272,7 +282,7 @@ class TestQosPlugin(base.BaseQosTestCase): get_ports.assert_not_called() validate_policy_for_ports.assert_not_called() else: - get_policy.assert_called_once_with(self.ctxt, id=policy_id) + get_policy.assert_called_once_with(admin_ctxt, id=policy_id) get_ports.assert_called_once_with(self.ctxt, network_id=network_id) validate_policy_for_ports.assert_called_once_with(