Stack updated error if creation fails

template https://github.com/openstack/heat-templates/blob/
67301b6ff45b9f1c220ee0a0ab3aecd3a415032b/cfn/F17/
AutoScalingCeilometer.yaml
can have update error when execute on some resources
which did not even created due to creation failed.

Add check logic in _needs_update to make sure even resource still
stay in init complete state can proceed update process by
raise resource.UpdateReplace.

For nested stack, StackResource should have the same status check
logic in _needs_update method to avoid this error occur(nested()
is None due to resource in failed state after create failed).

Change-Id: I3fa6a61436e79409fe7f28cf66dfdfd9f609b576
Closes-Bug: #1459719
(cherry picked from commit 878473d922)
This commit is contained in:
Rico Lin 2015-06-10 14:14:54 +08:00 committed by Ethan Lynn
parent 721fe7babe
commit 382d038892
8 changed files with 68 additions and 6 deletions

View File

@ -257,7 +257,7 @@ class RackspaceDnsTest(common.HeatTestCase):
ut = rsrc_defn.ResourceDefinition(instance.name,
instance.type(),
uprops)
instance.state_set(instance.CREATE, instance.COMPLETE)
scheduler.TaskRunner(instance.update, ut)()
self.assertEqual((instance.UPDATE, instance.COMPLETE), instance.state)
self.m.VerifyAll()
@ -316,6 +316,7 @@ class RackspaceDnsTest(common.HeatTestCase):
ut = rsrc_defn.ResourceDefinition(instance.name,
instance.type(),
uprops)
instance.state_set(instance.CREATE, instance.COMPLETE)
scheduler.TaskRunner(instance.update, ut)()
self.assertEqual((instance.UPDATE, instance.COMPLETE), instance.state)

View File

@ -701,7 +701,8 @@ class Resource(object):
def _needs_update(self, after, before, after_props, before_props,
prev_resource):
if self.status == self.FAILED:
if self.status == self.FAILED or \
(self.action == self.INIT and self.status == self.COMPLETE):
raise UpdateReplace(self)
if prev_resource is not None:

View File

@ -557,6 +557,7 @@ backend servers
save it to the db.
rely on the cfn-hup to reconfigure HAProxy
'''
new_props = json_snippet.properties(self.properties_schema,
self.context)

View File

@ -79,8 +79,17 @@ class StackResource(resource.Resource):
def _needs_update(self, after, before, after_props, before_props,
prev_resource):
# Always issue an update to the nested stack and let the individual
# Issue an update to the nested stack if the stack resource
# is able to update. If return true, let the individual
# resources in it decide if they need updating.
# FIXME (ricolin): seems currently can not call super here
if self.nested() is None and (
self.status == self.FAILED
or (self.action == self.INIT
and self.status == self.COMPLETE)):
raise resource.UpdateReplace(self)
return True
def nested(self, force_reload=False, show_deleted=False):

View File

@ -88,7 +88,8 @@ class LBUtilsTest(common.HeatTestCase):
'LB_1': lb1,
'LB_2': lb2
}
lb1.action = mock.Mock(return_value=lb1.CREATE)
lb2.action = mock.Mock(return_value=lb2.CREATE)
lb1.handle_update = mock.Mock()
lb2.handle_update = mock.Mock()
prop_diff = {'Instances': ['ID1', 'ID2', 'ID3']}
@ -108,6 +109,8 @@ class LBUtilsTest(common.HeatTestCase):
lb1 = self.stack['neutron_lb_1']
lb2 = self.stack['neutron_lb_2']
lb1.action = mock.Mock(return_value=lb1.CREATE)
lb2.action = mock.Mock(return_value=lb2.CREATE)
lbs = {
'LB_1': lb1,
'LB_2': lb2

View File

@ -307,6 +307,7 @@ class LoadbalancerReloadTest(common.HeatTestCase):
stack = utils.parse_stack(t, params=inline_templates.as_params)
lb = stack['ElasticLoadBalancer']
lb.state_set(lb.CREATE, lb.COMPLETE)
lb.handle_update = mock.Mock(return_value=None)
group = stack['WebServerGroup']
group._lb_reload()

View File

@ -285,6 +285,7 @@ class ResourceTest(common.HeatTestCase):
stored_time = res.updated_time
utmpl = rsrc_defn.ResourceDefinition('test_resource', 'Foo')
res.state_set(res.CREATE, res.COMPLETE)
scheduler.TaskRunner(res.update, utmpl)()
self.assertIsNotNone(res.updated_time)
self.assertNotEqual(res.updated_time, stored_time)
@ -813,6 +814,18 @@ class ResourceTest(common.HeatTestCase):
six.text_type(ex))
self.m.VerifyAll()
def test_need_update_in_init_complete_state_for_resource(self):
tmpl = rsrc_defn.ResourceDefinition('test_resource',
'GenericResourceType',
{'Foo': 'abc'})
res = generic_rsrc.ResourceWithProps('test_resource', tmpl, self.stack)
res.update_allowed_properties = ('Foo',)
self.assertEqual((res.INIT, res.COMPLETE), res.state)
prop = {'Foo': 'abc'}
self.assertRaises(resource.UpdateReplace,
res._needs_update, tmpl, tmpl, prop, prop, res)
def test_update_fail_missing_req_prop(self):
tmpl = rsrc_defn.ResourceDefinition('test_resource',
'GenericResourceType',

View File

@ -510,11 +510,12 @@ class StackResourceTest(common.HeatTestCase):
rpcc.return_value.delete_stack.assert_called_once_with(
self.parent_resource.context, mock.ANY)
def test_need_update_in_failed_state_for_nested_resource(self):
def test_need_update_for_nested_resource(self):
"""
The resource in any state and has nested stack,
The resource in Create or Update state and has nested stack,
should need update.
"""
self.parent_resource.action = self.parent_resource.CREATE
need_update = self.parent_resource._needs_update(
self.parent_resource.t,
self.parent_resource.t,
@ -524,6 +525,38 @@ class StackResourceTest(common.HeatTestCase):
self.assertEqual(True, need_update)
def test_need_update_in_failed_state_for_nested_resource(self):
"""
The resource in failed state and has no nested stack,
should need update with UpdateReplace.
"""
self.parent_resource.state_set(self.parent_resource.INIT,
self.parent_resource.FAILED)
self.parent_resource._nested = None
self.assertRaises(resource.UpdateReplace,
self.parent_resource._needs_update,
self.parent_resource.t,
self.parent_resource.t,
self.parent_resource.properties,
self.parent_resource.properties,
self.parent_resource)
def test_need_update_in_init_complete_state_for_nested_resource(self):
"""
The resource in failed state and has no nested stack,
should need update with UpdateReplace.
"""
self.parent_resource.state_set(self.parent_resource.INIT,
self.parent_resource.COMPLETE)
self.parent_resource._nested = None
self.assertRaises(resource.UpdateReplace,
self.parent_resource._needs_update,
self.parent_resource.t,
self.parent_resource.t,
self.parent_resource.properties,
self.parent_resource.properties,
self.parent_resource)
class StackResourceLimitTest(common.HeatTestCase):
scenarios = [