Merge "Remove handling for client status races"
This commit is contained in:
commit
607d73ea6f
@ -424,26 +424,6 @@ class StackResource(resource.Resource):
|
|||||||
if action != expected_action:
|
if action != expected_action:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Has the action really started?
|
|
||||||
#
|
|
||||||
# The rpc call to update does not guarantee that the stack will be
|
|
||||||
# placed into IN_PROGRESS by the time it returns (it runs stack.update
|
|
||||||
# in a thread) so you could also have a situation where we get into
|
|
||||||
# this method and the update hasn't even started.
|
|
||||||
#
|
|
||||||
# So we are using a mixture of state (action+status) and updated_at
|
|
||||||
# to see if the action has actually progressed.
|
|
||||||
# - very fast updates (like something with one RandomString) we will
|
|
||||||
# probably miss the state change, but we should catch the updated_at.
|
|
||||||
# - very slow updates we won't see the updated_at for quite a while,
|
|
||||||
# but should see the state change.
|
|
||||||
if cookie is not None:
|
|
||||||
prev_state = cookie['previous']['state']
|
|
||||||
prev_updated_at = cookie['previous']['updated_at']
|
|
||||||
if (prev_updated_at == updated_time and
|
|
||||||
prev_state == (action, status)):
|
|
||||||
return False
|
|
||||||
|
|
||||||
if status == self.IN_PROGRESS:
|
if status == self.IN_PROGRESS:
|
||||||
return False
|
return False
|
||||||
elif status == self.COMPLETE:
|
elif status == self.COMPLETE:
|
||||||
@ -533,9 +513,6 @@ class StackResource(resource.Resource):
|
|||||||
action, status, status_reason, updated_time = status_data
|
action, status, status_reason, updated_time = status_data
|
||||||
|
|
||||||
kwargs = self._stack_kwargs(user_params, child_template)
|
kwargs = self._stack_kwargs(user_params, child_template)
|
||||||
cookie = {'previous': {
|
|
||||||
'updated_at': updated_time,
|
|
||||||
'state': (action, status)}}
|
|
||||||
|
|
||||||
kwargs.update({
|
kwargs.update({
|
||||||
'stack_identity': dict(self.nested_identifier()),
|
'stack_identity': dict(self.nested_identifier()),
|
||||||
@ -549,7 +526,6 @@ class StackResource(resource.Resource):
|
|||||||
with excutils.save_and_reraise_exception():
|
with excutils.save_and_reraise_exception():
|
||||||
raw_template.RawTemplate.delete(self.context,
|
raw_template.RawTemplate.delete(self.context,
|
||||||
kwargs['template_id'])
|
kwargs['template_id'])
|
||||||
return cookie
|
|
||||||
|
|
||||||
def check_update_complete(self, cookie=None):
|
def check_update_complete(self, cookie=None):
|
||||||
if cookie is not None and 'target_action' in cookie:
|
if cookie is not None and 'target_action' in cookie:
|
||||||
|
@ -840,23 +840,6 @@ class StackResourceCheckCompleteTest(StackResourceBaseTest):
|
|||||||
self.mock_status.assert_called_once_with(
|
self.mock_status.assert_called_once_with(
|
||||||
self.parent_resource.context, self.parent_resource.resource_id)
|
self.parent_resource.context, self.parent_resource.resource_id)
|
||||||
|
|
||||||
def test_update_not_started(self):
|
|
||||||
if self.action != 'update':
|
|
||||||
# only valid for updates at the moment.
|
|
||||||
return
|
|
||||||
|
|
||||||
self.status[1] = 'COMPLETE'
|
|
||||||
self.status[3] = 'test'
|
|
||||||
cookie = {'previous': {'state': ('UPDATE', 'COMPLETE'),
|
|
||||||
'updated_at': 'test'}}
|
|
||||||
|
|
||||||
complete = getattr(self.parent_resource,
|
|
||||||
'check_%s_complete' % self.action)
|
|
||||||
|
|
||||||
self.assertFalse(complete(cookie=cookie))
|
|
||||||
self.mock_status.assert_called_once_with(
|
|
||||||
self.parent_resource.context, self.parent_resource.resource_id)
|
|
||||||
|
|
||||||
def test_wrong_action(self):
|
def test_wrong_action(self):
|
||||||
self.status[0] = 'COMPLETE'
|
self.status[0] = 'COMPLETE'
|
||||||
complete = getattr(self.parent_resource,
|
complete = getattr(self.parent_resource,
|
||||||
|
@ -92,7 +92,6 @@ class HeatIntegrationTest(testscenarios.WithScenarios,
|
|||||||
'No password configured')
|
'No password configured')
|
||||||
self.setup_clients(self.conf)
|
self.setup_clients(self.conf)
|
||||||
self.useFixture(fixtures.FakeLogger(format=_LOG_FORMAT))
|
self.useFixture(fixtures.FakeLogger(format=_LOG_FORMAT))
|
||||||
self.updated_time = {}
|
|
||||||
if self.conf.disable_ssl_certificate_validation:
|
if self.conf.disable_ssl_certificate_validation:
|
||||||
self.verify_cert = False
|
self.verify_cert = False
|
||||||
else:
|
else:
|
||||||
@ -278,17 +277,7 @@ class HeatIntegrationTest(testscenarios.WithScenarios,
|
|||||||
def _verify_status(self, stack, stack_identifier, status,
|
def _verify_status(self, stack, stack_identifier, status,
|
||||||
fail_regexp, is_action_cancelled=False):
|
fail_regexp, is_action_cancelled=False):
|
||||||
if stack.stack_status == status:
|
if stack.stack_status == status:
|
||||||
# Handle UPDATE_COMPLETE/FAILED case: Make sure we don't
|
if status == 'DELETE_COMPLETE' and stack.deletion_time is None:
|
||||||
# wait for a stale UPDATE_COMPLETE/FAILED status.
|
|
||||||
if status in ('UPDATE_FAILED', 'UPDATE_COMPLETE'):
|
|
||||||
if is_action_cancelled:
|
|
||||||
return True
|
|
||||||
|
|
||||||
if self.updated_time.get(
|
|
||||||
stack_identifier) != stack.updated_time:
|
|
||||||
self.updated_time[stack_identifier] = stack.updated_time
|
|
||||||
return True
|
|
||||||
elif status == 'DELETE_COMPLETE' and stack.deletion_time is None:
|
|
||||||
# Wait for deleted_time to be filled, so that we have more
|
# Wait for deleted_time to be filled, so that we have more
|
||||||
# confidence the operation is finished.
|
# confidence the operation is finished.
|
||||||
return False
|
return False
|
||||||
@ -298,20 +287,12 @@ class HeatIntegrationTest(testscenarios.WithScenarios,
|
|||||||
wait_for_action = status.split('_')[0]
|
wait_for_action = status.split('_')[0]
|
||||||
if (stack.action == wait_for_action and
|
if (stack.action == wait_for_action and
|
||||||
fail_regexp.search(stack.stack_status)):
|
fail_regexp.search(stack.stack_status)):
|
||||||
# Handle UPDATE_COMPLETE/UPDATE_FAILED case.
|
raise exceptions.StackBuildErrorException(
|
||||||
if status in ('UPDATE_FAILED', 'UPDATE_COMPLETE'):
|
stack_identifier=stack_identifier,
|
||||||
if self.updated_time.get(
|
stack_status=stack.stack_status,
|
||||||
stack_identifier) != stack.updated_time:
|
stack_status_reason=stack.stack_status_reason)
|
||||||
self.updated_time[stack_identifier] = stack.updated_time
|
|
||||||
raise exceptions.StackBuildErrorException(
|
return False
|
||||||
stack_identifier=stack_identifier,
|
|
||||||
stack_status=stack.stack_status,
|
|
||||||
stack_status_reason=stack.stack_status_reason)
|
|
||||||
else:
|
|
||||||
raise exceptions.StackBuildErrorException(
|
|
||||||
stack_identifier=stack_identifier,
|
|
||||||
stack_status=stack.stack_status,
|
|
||||||
stack_status_reason=stack.stack_status_reason)
|
|
||||||
|
|
||||||
def _wait_for_stack_status(self, stack_identifier, status,
|
def _wait_for_stack_status(self, stack_identifier, status,
|
||||||
failure_pattern=None,
|
failure_pattern=None,
|
||||||
@ -402,9 +383,6 @@ class HeatIntegrationTest(testscenarios.WithScenarios,
|
|||||||
env_files = files or {}
|
env_files = files or {}
|
||||||
parameters = parameters or {}
|
parameters = parameters or {}
|
||||||
|
|
||||||
self.updated_time[stack_identifier] = self.client.stacks.get(
|
|
||||||
stack_identifier, resolve_outputs=False).updated_time
|
|
||||||
|
|
||||||
self._handle_in_progress(
|
self._handle_in_progress(
|
||||||
self.client.stacks.update,
|
self.client.stacks.update,
|
||||||
stack_id=stack_identifier,
|
stack_id=stack_identifier,
|
||||||
@ -430,9 +408,6 @@ class HeatIntegrationTest(testscenarios.WithScenarios,
|
|||||||
|
|
||||||
stack_name = stack_identifier.split('/')[0]
|
stack_name = stack_identifier.split('/')[0]
|
||||||
|
|
||||||
self.updated_time[stack_identifier] = self.client.stacks.get(
|
|
||||||
stack_identifier, resolve_outputs=False).updated_time
|
|
||||||
|
|
||||||
if rollback:
|
if rollback:
|
||||||
self.client.actions.cancel_update(stack_name)
|
self.client.actions.cancel_update(stack_name)
|
||||||
else:
|
else:
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import time
|
|
||||||
|
|
||||||
from heat_integrationtests.functional import functional_base
|
from heat_integrationtests.functional import functional_base
|
||||||
|
|
||||||
@ -74,9 +73,6 @@ class UpdateRestrictedStackTest(functional_base.FunctionalTestsBase):
|
|||||||
self._check_for_restriction_reason(resource_events,
|
self._check_for_restriction_reason(resource_events,
|
||||||
reason_update_restrict))
|
reason_update_restrict))
|
||||||
|
|
||||||
# Ensure the timestamp changes, since this will be very quick
|
|
||||||
time.sleep(1)
|
|
||||||
|
|
||||||
# check update succeeds - with only 'replace' restricted
|
# check update succeeds - with only 'replace' restricted
|
||||||
self.update_stack(stack_identifier, update_template,
|
self.update_stack(stack_identifier, update_template,
|
||||||
env_replace_restrict,
|
env_replace_restrict,
|
||||||
@ -112,9 +108,6 @@ class UpdateRestrictedStackTest(functional_base.FunctionalTestsBase):
|
|||||||
self._check_for_restriction_reason(resource_events,
|
self._check_for_restriction_reason(resource_events,
|
||||||
reason_replace_restrict))
|
reason_replace_restrict))
|
||||||
|
|
||||||
# Ensure the timestamp changes, since this will be very quick
|
|
||||||
time.sleep(1)
|
|
||||||
|
|
||||||
# check replace fails - with only 'replace' restricted
|
# check replace fails - with only 'replace' restricted
|
||||||
self.update_stack(stack_identifier, update_template,
|
self.update_stack(stack_identifier, update_template,
|
||||||
env_replace_restrict,
|
env_replace_restrict,
|
||||||
@ -149,9 +142,6 @@ class UpdateRestrictedStackTest(functional_base.FunctionalTestsBase):
|
|||||||
self._check_for_restriction_reason(resource_events,
|
self._check_for_restriction_reason(resource_events,
|
||||||
reason_replace_restrict))
|
reason_replace_restrict))
|
||||||
|
|
||||||
# Ensure the timestamp changes, since this will be very quick
|
|
||||||
time.sleep(1)
|
|
||||||
|
|
||||||
# check replace fails - with only 'replace' restricted
|
# check replace fails - with only 'replace' restricted
|
||||||
self.update_stack(stack_identifier, update_template,
|
self.update_stack(stack_identifier, update_template,
|
||||||
env_replace_restrict,
|
env_replace_restrict,
|
||||||
|
Loading…
Reference in New Issue
Block a user