Only validate properties once during create resource

While create a resource, we might retry to create or delete that resource.
Within every action properties validate was act as pre-function before
actually call any action. While the first creat run, if anything goes wrong
during property validation, a validation error will raise right away. Which
will definitely riase in the very first action run. But if it successed,
it still required to revalidate each time an action triggered (whatever is
creat or delete). This patch will ignore properties validate if it's not
the first create run.
Closes-Bug: #1691672

Change-Id: Ibf592a254a862613eddb77ea5933ec6ba0cd2d1a
This commit is contained in:
ricolin 2017-05-18 14:55:26 +08:00 committed by Rico Lin
parent d85361bd9f
commit 4a15c3387a
2 changed files with 38 additions and 2 deletions

View File

@ -1104,13 +1104,18 @@ class Resource(status.ResourceStatus):
while (count[self.CREATE] <= retry_limit and
count[self.DELETE] <= retry_limit):
if count[action]:
pre_func = None
if count[action] > 0:
delay = timeutils.retry_backoff_delay(count[action],
jitter_max=2.0)
waiter = scheduler.TaskRunner(self.pause)
yield waiter.as_task(timeout=delay)
elif action == self.CREATE:
# Only validate properties in first create call.
pre_func = self.properties.validate
try:
yield self._do_action(action, self.properties.validate)
yield self._do_action(action, pre_func)
if action == self.CREATE:
first_failure = None
break

View File

@ -1022,6 +1022,37 @@ class ResourceTest(common.HeatTestCase):
scheduler.TaskRunner(res.create)()
self.assertEqual((res.CREATE, res.COMPLETE), res.state)
@mock.patch.object(properties.Properties, 'validate')
@mock.patch.object(timeutils, 'retry_backoff_delay')
def test_create_validate(self, m_re, m_v):
tmpl = rsrc_defn.ResourceDefinition('test_resource', 'Foo',
{'Foo': 'abc'})
res = generic_rsrc.ResourceWithProps('test_resource', tmpl, self.stack)
generic_rsrc.ResourceWithProps.handle_create = mock.Mock()
generic_rsrc.ResourceWithProps.handle_delete = mock.Mock()
m_v.side_effect = [True, exception.StackValidationFailed()]
generic_rsrc.ResourceWithProps.handle_create.side_effect = [
exception.ResourceInError(resource_name='test_resource',
resource_status='ERROR',
resource_type='GenericResourceType',
resource_action='CREATE',
status_reason='just because'),
exception.ResourceInError(resource_name='test_resource',
resource_status='ERROR',
resource_type='GenericResourceType',
resource_action='CREATE',
status_reason='just because'),
None
]
generic_rsrc.ResourceWithProps.handle_delete.return_value = None
m_re.return_value = 0.01
scheduler.TaskRunner(res.create)()
self.assertEqual(2, m_re.call_count)
self.assertEqual(1, m_v.call_count)
self.assertEqual((res.CREATE, res.COMPLETE), res.state)
def test_create_fail_retry(self):
tmpl = rsrc_defn.ResourceDefinition('test_resource', 'Foo',
{'Foo': 'abc'})