summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorricolin <rico.lin@easystack.cn>2017-05-18 14:55:26 +0800
committerRico Lin <rico.lin@easystack.cn>2017-09-27 01:48:59 +0000
commite671d93b1508650d1da3587f96a2f8561825e24c (patch)
treef8c03a9754c079676e9977dc8f31f7db74218bea
parente544ebc8593644cee314526725570a471b77222f (diff)
downloadheat-e671d93b1508650d1da3587f96a2f8561825e24c.tar.gz
Only validate properties once during create resource8.0.5
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 (cherry picked from commit 4a15c3387a258a66b366d6ace63c47192bb53fd1)
-rw-r--r--heat/engine/resource.py9
-rw-r--r--heat/tests/test_resource.py31
2 files changed, 38 insertions, 2 deletions
diff --git a/heat/engine/resource.py b/heat/engine/resource.py
index 706de990c..0d173090a 100644
--- a/heat/engine/resource.py
+++ b/heat/engine/resource.py
@@ -969,13 +969,18 @@ class Resource(object):
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
diff --git a/heat/tests/test_resource.py b/heat/tests/test_resource.py
index 6791a11a1..c84d0d3b8 100644
--- a/heat/tests/test_resource.py
+++ b/heat/tests/test_resource.py
@@ -965,6 +965,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'})