diff options
author | Zane Bitter <zbitter@redhat.com> | 2018-01-24 17:44:51 -0500 |
---|---|---|
committer | Zane Bitter <zbitter@redhat.com> | 2018-06-18 16:42:37 -0400 |
commit | c4318eff65122dde41ea363c53a3942f12259cd0 (patch) | |
tree | aa217d54f0abd917e66d87615d28567f9271a301 /heat | |
parent | 714d9eea4c871cfc979664cc8fc846cc02fba798 (diff) | |
download | heat-c4318eff65122dde41ea363c53a3942f12259cd0.tar.gz |
Retry resource creation on conflict
If resource creation fails with an HTTP Conflict error, this is presumably
due to a race condition with one of the underlying services. In this case,
allow Heat to retry the resource creation so that hopefully in most cases
the user will never have to deal with the error.
Change-Id: I301bb28231fcdc249f86ec1a2f09cb993023785b
Story: #1745010
Task: 17344
Diffstat (limited to 'heat')
-rw-r--r-- | heat/engine/resource.py | 12 | ||||
-rw-r--r-- | heat/tests/openstack/neutron/test_neutron_router.py | 18 |
2 files changed, 25 insertions, 5 deletions
diff --git a/heat/engine/resource.py b/heat/engine/resource.py index 8d72bd705..5b3eba3ee 100644 --- a/heat/engine/resource.py +++ b/heat/engine/resource.py @@ -1259,19 +1259,21 @@ class Resource(status.ResourceStatus): else: action = self.CREATE except exception.ResourceFailure as failure: - if isinstance(failure.exc, exception.StackValidationFailed): + exc = failure.exc + if isinstance(exc, exception.StackValidationFailed): path = [self.t.name] - path.extend(failure.exc.path) + path.extend(exc.path) raise exception.ResourceFailure( exception_or_error=exception.StackValidationFailed( - error=failure.exc.error, + error=exc.error, path=path, - message=failure.exc.error_message + message=exc.error_message ), resource=failure.resource, action=failure.action ) - if not isinstance(failure.exc, exception.ResourceInError): + if not (isinstance(exc, exception.ResourceInError) or + self._default_client_plugin().is_conflict(exc)): raise failure count[action] += 1 diff --git a/heat/tests/openstack/neutron/test_neutron_router.py b/heat/tests/openstack/neutron/test_neutron_router.py index 64ad1a443..9046822ae 100644 --- a/heat/tests/openstack/neutron/test_neutron_router.py +++ b/heat/tests/openstack/neutron/test_neutron_router.py @@ -540,6 +540,24 @@ class NeutronRouterTest(common.HeatTestCase): rsrc.state_set(rsrc.CREATE, rsrc.COMPLETE, 'to delete again') scheduler.TaskRunner(rsrc.delete)() + def test_router_interface_conflict(self): + self.add_if_mock.side_effect = [qe.Conflict, None] + + t = template_format.parse(neutron_template) + stack = utils.parse_stack(t) + props = { + 'router': '3e46229d-8fce-4733-819a-b5fe630550f8', + 'subnet': '91e47a57-7508-46fe-afc9-fc454e8580e1' + } + + def find_rsrc(resource, name_or_id, cmd_resource=None): + return props.get(resource, resource) + + self.find_rsrc_mock.side_effect = find_rsrc + self.create_router_interface( + t, stack, 'router_interface', properties=props) + self.assertEqual(2, self.add_if_mock.call_count) + def test_router_interface_validate(self): def find_rsrc(resource, name_or_id, cmd_resource=None): id_mapping = { |