summaryrefslogtreecommitdiff
path: root/heat
diff options
context:
space:
mode:
authorZane Bitter <zbitter@redhat.com>2018-01-24 17:44:51 -0500
committerZane Bitter <zbitter@redhat.com>2018-06-18 16:42:37 -0400
commitc4318eff65122dde41ea363c53a3942f12259cd0 (patch)
treeaa217d54f0abd917e66d87615d28567f9271a301 /heat
parent714d9eea4c871cfc979664cc8fc846cc02fba798 (diff)
downloadheat-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.py12
-rw-r--r--heat/tests/openstack/neutron/test_neutron_router.py18
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 = {