]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
Wait until quantum resources are deleted.
authorSteve Baker <sbaker@redhat.com>
Fri, 12 Jul 2013 01:31:09 +0000 (13:31 +1200)
committerSteve Baker <sbaker@redhat.com>
Fri, 12 Jul 2013 02:10:36 +0000 (14:10 +1200)
Races on delete have occured where a quantum resource cannot
be deleted due to an associated resource delete being incomplete.

Fixes bug: #1195596

Change-Id: I52a358d05d30b9c50a771864d036156f00df67ab

heat/engine/resources/quantum/net.py
heat/engine/resources/quantum/port.py
heat/engine/resources/quantum/quantum.py
heat/engine/resources/quantum/router.py
heat/engine/resources/quantum/subnet.py
heat/tests/test_quantum.py

index b5a5a5802ee8d3afe8d3aaaf9978bce22f0ddcc7..8a8bfe6c7dc7a5b5b78c0e0c4d3799f572a8cf92 100644 (file)
@@ -16,6 +16,7 @@
 from heat.engine import clients
 from heat.openstack.common import log as logging
 from heat.engine.resources.quantum import quantum
+from heat.engine import scheduler
 
 if clients.quantumclient is not None:
     from quantumclient.common.exceptions import QuantumClientException
@@ -60,6 +61,8 @@ class Net(quantum.QuantumResource):
         except QuantumClientException as ex:
             if ex.status_code != 404:
                 raise ex
+        else:
+            return scheduler.TaskRunner(self._confirm_delete)()
 
 
 def resource_mapping():
index 5ddc96f4d1ab70eff477824fbb92665e32bb5018..f3c3f8f564bda69a1c0ce4c53cc5972015db6d7d 100644 (file)
@@ -16,6 +16,7 @@
 from heat.engine import clients
 from heat.openstack.common import log as logging
 from heat.engine.resources.quantum import quantum
+from heat.engine import scheduler
 
 if clients.quantumclient is not None:
     from quantumclient.common.exceptions import QuantumClientException
@@ -91,6 +92,8 @@ class Port(quantum.QuantumResource):
         except QuantumClientException as ex:
             if ex.status_code != 404:
                 raise ex
+        else:
+            return scheduler.TaskRunner(self._confirm_delete)()
 
 
 def resource_mapping():
index 34bf0afc925609e8b5f8fee7542edc803b83aa02..b3024f1d658f3657eda314092042609c00872099 100644 (file)
@@ -102,5 +102,15 @@ class QuantumResource(resource.Resource):
             return None
         return self.handle_get_attributes(self.name, name, attributes)
 
+    def _confirm_delete(self):
+        while True:
+            try:
+                yield
+                self._show_resource()
+            except QuantumClientException as ex:
+                if ex.status_code != 404:
+                    raise ex
+                return
+
     def FnGetRefId(self):
         return unicode(self.resource_id)
index 7a62898542934b3fdb8e66327ef0edda0c226a4e..bb5324f2ad59bf412bf3fbb9524c0be727e92957 100644 (file)
@@ -15,6 +15,7 @@
 
 from heat.engine import clients
 from heat.engine.resources.quantum import quantum
+from heat.engine import scheduler
 
 if clients.quantumclient is not None:
     from quantumclient.common.exceptions import QuantumClientException
@@ -61,6 +62,8 @@ class Router(quantum.QuantumResource):
         except QuantumClientException as ex:
             if ex.status_code != 404:
                 raise ex
+        else:
+            return scheduler.TaskRunner(self._confirm_delete)()
 
 
 class RouterInterface(quantum.QuantumResource):
index ee02e5ec01c8b96dc0d344993e7ddcf511a8d526..a810eb11cc6f8c395ee2e95bd2949e37d857e9ed 100644 (file)
@@ -16,6 +16,7 @@
 from heat.engine import clients
 from heat.openstack.common import log as logging
 from heat.engine.resources.quantum import quantum
+from heat.engine import scheduler
 
 if clients.quantumclient is not None:
     from quantumclient.common.exceptions import QuantumClientException
@@ -77,6 +78,8 @@ class Subnet(quantum.QuantumResource):
         except QuantumClientException as ex:
             if ex.status_code != 404:
                 raise ex
+        else:
+            return scheduler.TaskRunner(self._confirm_delete)()
 
     def _show_resource(self):
         return self.quantum().show_subnet(self.resource_id)['subnet']
index a543c712346db67c3a94cd80557345fa2a8bdd8f..25613c602c15bf24b10d54f51a9678774d390386 100644 (file)
@@ -262,7 +262,19 @@ class QuantumNetTest(HeatTestCase):
 
         quantumclient.Client.show_network(
             'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
-        ).MultipleTimes().AndReturn({"network": {
+        ).AndReturn({"network": {
+            "status": "ACTIVE",
+            "subnets": [],
+            "name": "name",
+            "admin_state_up": False,
+            "shared": False,
+            "tenant_id": "c1210485b2424d48804aad5d39c61b8f",
+            "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766"
+        }})
+
+        quantumclient.Client.show_network(
+            'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
+        ).AndReturn({"network": {
             "status": "ACTIVE",
             "subnets": [],
             "name": "name",
@@ -276,6 +288,10 @@ class QuantumNetTest(HeatTestCase):
             'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
         ).AndReturn(None)
 
+        quantumclient.Client.show_network(
+            'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
+        ).AndRaise(qe.QuantumClientException(status_code=404))
+
         quantumclient.Client.delete_network(
             'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
         ).AndRaise(qe.QuantumClientException(status_code=404))
@@ -308,9 +324,9 @@ class QuantumNetTest(HeatTestCase):
         self.assertRaises(resource.UpdateReplace,
                           rsrc.handle_update, {}, {}, {})
 
-        rsrc.delete()
+        scheduler.TaskRunner(rsrc.delete)()
         rsrc.state_set(rsrc.CREATE, rsrc.COMPLETE, 'to delete again')
-        rsrc.delete()
+        scheduler.TaskRunner(rsrc.delete)()
         self.m.VerifyAll()
 
 
@@ -361,26 +377,36 @@ class QuantumSubnetTest(HeatTestCase):
         quantumclient.Client.show_subnet(
             '91e47a57-7508-46fe-afc9-fc454e8580e1').AndRaise(
                 qe.QuantumClientException(status_code=404))
+        sn = {
+            "subnet": {
+                "name": "name",
+                "network_id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766",
+                "tenant_id": "c1210485b2424d48804aad5d39c61b8f",
+                "allocation_pools": [
+                    {"start": "10.0.3.20", "end": "10.0.3.150"}],
+                "gateway_ip": "10.0.3.1",
+                "ip_version": 4,
+                "cidr": "10.0.3.0/24",
+                "dns_nameservers": ["8.8.8.8"],
+                "id": "91e47a57-7508-46fe-afc9-fc454e8580e1",
+                "enable_dhcp": True,
+            }
+        }
         quantumclient.Client.show_subnet(
-            '91e47a57-7508-46fe-afc9-fc454e8580e1').MultipleTimes().AndReturn({
-                "subnet": {
-                    "name": "name",
-                    "network_id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766",
-                    "tenant_id": "c1210485b2424d48804aad5d39c61b8f",
-                    "allocation_pools": [
-                        {"start": "10.0.3.20", "end": "10.0.3.150"}],
-                    "gateway_ip": "10.0.3.1",
-                    "ip_version": 4,
-                    "cidr": "10.0.3.0/24",
-                    "dns_nameservers": ["8.8.8.8"],
-                    "id": "91e47a57-7508-46fe-afc9-fc454e8580e1",
-                    "enable_dhcp": True,
-                }
-            })
+            '91e47a57-7508-46fe-afc9-fc454e8580e1').AndReturn(sn)
+        quantumclient.Client.show_subnet(
+            '91e47a57-7508-46fe-afc9-fc454e8580e1').AndReturn(sn)
+        quantumclient.Client.show_subnet(
+            '91e47a57-7508-46fe-afc9-fc454e8580e1').AndReturn(sn)
 
         quantumclient.Client.delete_subnet(
             '91e47a57-7508-46fe-afc9-fc454e8580e1'
         ).AndReturn(None)
+
+        quantumclient.Client.show_subnet(
+            '91e47a57-7508-46fe-afc9-fc454e8580e1'
+        ).AndRaise(qe.QuantumClientException(status_code=404))
+
         quantumclient.Client.delete_subnet(
             '91e47a57-7508-46fe-afc9-fc454e8580e1'
         ).AndRaise(qe.QuantumClientException(status_code=404))
@@ -410,9 +436,9 @@ class QuantumSubnetTest(HeatTestCase):
         self.assertRaises(resource.UpdateReplace,
                           rsrc.handle_update, {}, {}, {})
 
-        self.assertEqual(rsrc.delete(), None)
+        self.assertEqual(scheduler.TaskRunner(rsrc.delete)(), None)
         rsrc.state_set(rsrc.CREATE, rsrc.COMPLETE, 'to delete again')
-        self.assertEqual(rsrc.delete(), None)
+        self.assertEqual(scheduler.TaskRunner(rsrc.delete)(), None)
         self.m.VerifyAll()
 
     def test_subnet_disable_dhcp(self):
@@ -465,6 +491,10 @@ class QuantumSubnetTest(HeatTestCase):
             '91e47a57-7508-46fe-afc9-fc454e8580e1'
         ).AndReturn(None)
 
+        quantumclient.Client.show_subnet(
+            '91e47a57-7508-46fe-afc9-fc454e8580e1'
+        ).AndRaise(qe.QuantumClientException(status_code=404))
+
         self.m.ReplayAll()
         t = template_format.parse(quantum_template)
         t['Resources']['subnet']['Properties']['enable_dhcp'] = 'False'
@@ -564,7 +594,19 @@ class QuantumRouterTest(HeatTestCase):
             '3e46229d-8fce-4733-819a-b5fe630550f8').AndRaise(
                 qe.QuantumClientException(status_code=404))
         quantumclient.Client.show_router(
-            '3e46229d-8fce-4733-819a-b5fe630550f8').MultipleTimes().AndReturn({
+            '3e46229d-8fce-4733-819a-b5fe630550f8').AndReturn({
+                "router": {
+                    "status": "ACTIVE",
+                    "external_gateway_info": None,
+                    "name": utils.PhysName('test_stack', 'router'),
+                    "admin_state_up": True,
+                    "tenant_id": "3e21026f2dc94372b105808c0e721661",
+                    "routes": [],
+                    "id": "3e46229d-8fce-4733-819a-b5fe630550f8"
+                }
+            })
+        quantumclient.Client.show_router(
+            '3e46229d-8fce-4733-819a-b5fe630550f8').AndReturn({
                 "router": {
                     "status": "ACTIVE",
                     "external_gateway_info": None,
@@ -579,6 +621,11 @@ class QuantumRouterTest(HeatTestCase):
         quantumclient.Client.delete_router(
             '3e46229d-8fce-4733-819a-b5fe630550f8'
         ).AndReturn(None)
+
+        quantumclient.Client.show_router(
+            '3e46229d-8fce-4733-819a-b5fe630550f8'
+        ).AndRaise(qe.QuantumClientException(status_code=404))
+
         quantumclient.Client.delete_router(
             '3e46229d-8fce-4733-819a-b5fe630550f8'
         ).AndRaise(qe.QuantumClientException(status_code=404))
@@ -602,9 +649,9 @@ class QuantumRouterTest(HeatTestCase):
         self.assertRaises(resource.UpdateReplace,
                           rsrc.handle_update, {}, {}, {})
 
-        self.assertEqual(rsrc.delete(), None)
+        self.assertEqual(scheduler.TaskRunner(rsrc.delete)(), None)
         rsrc.state_set(rsrc.CREATE, rsrc.COMPLETE, 'to delete again')
-        self.assertEqual(rsrc.delete(), None)
+        self.assertEqual(scheduler.TaskRunner(rsrc.delete)(), None)
         self.m.VerifyAll()
 
     def test_router_interface(self):
@@ -846,6 +893,10 @@ class QuantumFloatingIPTest(HeatTestCase):
             'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
         ).AndReturn(None)
 
+        quantumclient.Client.show_port(
+            'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
+        ).AndRaise(qe.QuantumClientException(status_code=404))
+
         quantumclient.Client.delete_floatingip(
             'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
         ).AndReturn(None)
@@ -891,7 +942,7 @@ class QuantumFloatingIPTest(HeatTestCase):
                           fipa.handle_update, {}, {}, {})
 
         self.assertEqual(fipa.delete(), None)
-        self.assertEqual(p.delete(), None)
+        self.assertEqual(scheduler.TaskRunner(p.delete)(), None)
         self.assertEqual(fip.delete(), None)
 
         fipa.state_set(fipa.CREATE, fipa.COMPLETE, 'to delete again')
@@ -899,7 +950,7 @@ class QuantumFloatingIPTest(HeatTestCase):
         p.state_set(p.CREATE, p.COMPLETE, 'to delete again')
 
         self.assertEqual(fipa.delete(), None)
-        self.assertEqual(p.delete(), None)
+        self.assertEqual(scheduler.TaskRunner(p.delete)(), None)
         self.assertEqual(fip.delete(), None)
 
         self.m.VerifyAll()