]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
objects.qos.policy: forbid deletion when attached to a port or a network
authorIhar Hrachyshka <ihrachys@redhat.com>
Sun, 2 Aug 2015 15:27:56 +0000 (17:27 +0200)
committerIhar Hrachyshka <ihrachys@redhat.com>
Sun, 2 Aug 2015 18:23:03 +0000 (20:23 +0200)
Similar to security groups, we forbid removing a policy that is attached
to any port or a network.

Change-Id: I0854c8ebc3b690c9195beeca92fe37f1121b410a
Partially-Implements: blueprint quantum-qos-api

neutron/common/exceptions.py
neutron/objects/qos/policy.py
neutron/tests/api/test_qos.py
neutron/tests/unit/objects/qos/test_policy.py
neutron/tests/unit/services/qos/test_qos_plugin.py

index 7dc39bf4800ccba5713d5b0c7698df746c2e92aa..8360f9957f25fd1f26f65899d6697af04f2819d4 100644 (file)
@@ -132,6 +132,11 @@ class InUse(NeutronException):
     message = _("The resource is inuse")
 
 
+class QosPolicyInUse(InUse):
+    message = _("QoS Policy %(policy_id)s is used by "
+                "%(object_type)s %(object_id)s.")
+
+
 class NetworkInUse(InUse):
     message = _("Unable to complete operation on network %(net_id)s. "
                 "There are one or more ports still in use on the network.")
index f35c8684c008a209f0695f6a7b9f908d81c92b67..b3b7a44e375018ffe73b059a5f9b4da2ee8e4b46 100644 (file)
@@ -124,6 +124,23 @@ class QosPolicy(base.NeutronDbObject):
             super(QosPolicy, self).create()
             self._load_rules()
 
+    def delete(self):
+        models = (
+            ('network', self.network_binding_model),
+            ('port', self.port_binding_model)
+        )
+        with db_api.autonested_transaction(self._context.session):
+            for object_type, model in models:
+                binding_db_obj = db_api.get_object(self._context, model,
+                                                   policy_id=self.id)
+                if binding_db_obj:
+                    raise exceptions.QosPolicyInUse(
+                        policy_id=self.id,
+                        object_type=object_type,
+                        object_id=binding_db_obj['%s_id' % object_type])
+
+            super(QosPolicy, self).delete()
+
     def attach_network(self, network_id):
         qos_db_api.create_policy_network_binding(self._context,
                                                  policy_id=self.id,
index d3b1c4f93d4d7ae422bc40bae454143f232cad82..1238273d8b70194427f01543e2560d17cc1aa930 100644 (file)
@@ -217,6 +217,36 @@ class QosTestJSON(base.BaseAdminNetworkTest):
 
         self._disassociate_port(port['id'])
 
+    @test.attr(type='smoke')
+    @test.idempotent_id('18163237-8ba9-4db5-9525-bad6d2343c75')
+    def test_delete_not_allowed_if_policy_in_use_by_network(self):
+        policy = self.create_qos_policy(name='test-policy',
+                                        description='test policy',
+                                        shared=True)
+        network = self.create_shared_network(
+            'test network', qos_policy_id=policy['id'])
+        self.assertRaises(
+            exceptions.Conflict,
+            self.admin_client.delete_qos_policy, policy['id'])
+
+        self._disassociate_network(self.admin_client, network['id'])
+        self.admin_client.delete_qos_policy(policy['id'])
+
+    @test.attr(type='smoke')
+    @test.idempotent_id('24153230-84a9-4dd5-9525-bad6d2343c75')
+    def test_delete_not_allowed_if_policy_in_use_by_port(self):
+        policy = self.create_qos_policy(name='test-policy',
+                                        description='test policy',
+                                        shared=True)
+        network = self.create_shared_network('test network')
+        port = self.create_port(network, qos_policy_id=policy['id'])
+        self.assertRaises(
+            exceptions.Conflict,
+            self.admin_client.delete_qos_policy, policy['id'])
+
+        self._disassociate_port(port['id'])
+        self.admin_client.delete_qos_policy(policy['id'])
+
 
 class QosBandwidthLimitRuleTestJSON(base.BaseAdminNetworkTest):
     @classmethod
index 20807c904363c58ef47584dc2e8330843c9652fa..e8ddfa167767844d1fa2aac9ce15ef8a8d624473 100644 (file)
@@ -248,3 +248,21 @@ class QosPolicyDbObjectTestCase(test_base.BaseDbObjectTestCase,
         self.db_obj.pop('shared')
         obj = self._test_class(self.context, **self.db_obj)
         self.assertEqual(False, obj.shared)
+
+    def test_delete_not_allowed_if_policy_in_use_by_port(self):
+        obj = self._create_test_policy()
+        obj.attach_port(self._port['id'])
+
+        self.assertRaises(n_exc.QosPolicyInUse, obj.delete)
+
+        obj.detach_port(self._port['id'])
+        obj.delete()
+
+    def test_delete_not_allowed_if_policy_in_use_by_network(self):
+        obj = self._create_test_policy()
+        obj.attach_network(self._network['id'])
+
+        self.assertRaises(n_exc.QosPolicyInUse, obj.delete)
+
+        obj.detach_network(self._network['id'])
+        obj.delete()
index df26a4eaa4b55c5107469331caa60478075bb794..92ef36a0039e356e48d92b4b88e9a4816500ddae 100644 (file)
@@ -87,7 +87,8 @@ class TestQosPlugin(base.BaseTestCase):
             self.ctxt, self.policy.id, {'policy': fields})
         self._validate_registry_params(events.UPDATED)
 
-    def test_delete_policy(self):
+    @mock.patch('neutron.db.api.get_object', return_value=None)
+    def test_delete_policy(self, *mocks):
         self.qos_plugin.delete_policy(self.ctxt, self.policy.id)
         self._validate_registry_params(events.DELETED)