From: Steve Baker Date: Fri, 12 Jul 2013 01:31:09 +0000 (+1200) Subject: Wait until quantum resources are deleted. X-Git-Tag: 2014.1~370^2 X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=324475bd2a63d9d36914fddfed6ad672d13f8ebf;p=openstack-build%2Fheat-build.git Wait until quantum resources are deleted. 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 --- diff --git a/heat/engine/resources/quantum/net.py b/heat/engine/resources/quantum/net.py index b5a5a580..8a8bfe6c 100644 --- a/heat/engine/resources/quantum/net.py +++ b/heat/engine/resources/quantum/net.py @@ -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(): diff --git a/heat/engine/resources/quantum/port.py b/heat/engine/resources/quantum/port.py index 5ddc96f4..f3c3f8f5 100644 --- a/heat/engine/resources/quantum/port.py +++ b/heat/engine/resources/quantum/port.py @@ -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(): diff --git a/heat/engine/resources/quantum/quantum.py b/heat/engine/resources/quantum/quantum.py index 34bf0afc..b3024f1d 100644 --- a/heat/engine/resources/quantum/quantum.py +++ b/heat/engine/resources/quantum/quantum.py @@ -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) diff --git a/heat/engine/resources/quantum/router.py b/heat/engine/resources/quantum/router.py index 7a628985..bb5324f2 100644 --- a/heat/engine/resources/quantum/router.py +++ b/heat/engine/resources/quantum/router.py @@ -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): diff --git a/heat/engine/resources/quantum/subnet.py b/heat/engine/resources/quantum/subnet.py index ee02e5ec..a810eb11 100644 --- a/heat/engine/resources/quantum/subnet.py +++ b/heat/engine/resources/quantum/subnet.py @@ -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'] diff --git a/heat/tests/test_quantum.py b/heat/tests/test_quantum.py index a543c712..25613c60 100644 --- a/heat/tests/test_quantum.py +++ b/heat/tests/test_quantum.py @@ -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()