Respect locks when changing FAILED resource to COMPLETE
If a resource is in a FAILED state, but the plugin overrides
_needs_update() to not raise UpdateReplace, and also no actual update is
required, we simply change the resource's state to UPDATE_COMPLETE.
However, since the locking/unlocking steps were merged with the resource
state updates in a7376f7494
, in doing so we
were ignoring the lock (since at this stage the resource is still unlocked,
and we don't need to take a lock). If another update traversal had acquired
the lock in the meantime, we would still write to the locked resource.
This change adds a new LOCK_RESPECT lock mode to Resource.store(). In this
mode the lock is not acquired or released, but an error will be raised if
the resource is found to be locked.
Change-Id: I8b5cd1e05b88dd13abc13899a73f23810f7e6135
Closes-Bug: #1705794
Related-Bug: #1662585
This commit is contained in:
parent
bdddeee602
commit
1da0790e0d
|
@ -98,8 +98,11 @@ class PollDelay(Exception):
|
|||
class Resource(status.ResourceStatus):
|
||||
BASE_ATTRIBUTES = (SHOW, ) = (attributes.SHOW_ATTR, )
|
||||
|
||||
LOCK_ACTIONS = (LOCK_NONE, LOCK_ACQUIRE, LOCK_RELEASE) = (
|
||||
0, 1, -1)
|
||||
LOCK_ACTIONS = (
|
||||
LOCK_NONE, LOCK_ACQUIRE, LOCK_RELEASE, LOCK_RESPECT,
|
||||
) = (
|
||||
None, 1, -1, 0,
|
||||
)
|
||||
|
||||
# If True, this resource must be created before it can be referenced.
|
||||
strict_dependency = True
|
||||
|
@ -1297,22 +1300,7 @@ class Resource(status.ResourceStatus):
|
|||
if not persist:
|
||||
return
|
||||
|
||||
rs = {'current_template_id': self.current_template_id,
|
||||
'updated_at': self.updated_time,
|
||||
'requires': self.requires}
|
||||
if not resource_objects.Resource.select_and_update_by_id(
|
||||
self.context, self.id, rs, expected_engine_id=None,
|
||||
atomic_key=self._atomic_key):
|
||||
LOG.info("Resource %s is locked, can't set template",
|
||||
six.text_type(self))
|
||||
LOG.debug('Resource id:%(resource_id)s locked. '
|
||||
'Expected atomic_key:%(atomic_key)s, '
|
||||
'accessing from engine_id:%(engine_id)s',
|
||||
{'resource_id': self.id,
|
||||
'atomic_key': self._atomic_key,
|
||||
'engine_id': self._calling_engine_id})
|
||||
raise exception.UpdateInProgress(self.name)
|
||||
self._incr_atomic_key(self._atomic_key)
|
||||
self.store(lock=self.LOCK_RESPECT)
|
||||
|
||||
self._calling_engine_id = engine_id
|
||||
registry = new_stack.env.registry
|
||||
|
@ -1502,8 +1490,10 @@ class Resource(status.ResourceStatus):
|
|||
status_reason = _('Update status to COMPLETE for '
|
||||
'FAILED resource neither update '
|
||||
'nor replace.')
|
||||
lock = (self.LOCK_RESPECT if self.stack.convergence
|
||||
else self.LOCK_NONE)
|
||||
self.state_set(self.action, self.COMPLETE,
|
||||
status_reason)
|
||||
status_reason, lock=lock)
|
||||
return
|
||||
|
||||
if not self.stack.convergence:
|
||||
|
@ -1969,9 +1959,13 @@ class Resource(status.ResourceStatus):
|
|||
if lock == self.LOCK_ACQUIRE:
|
||||
rs['engine_id'] = self._calling_engine_id
|
||||
expected_engine_id = None
|
||||
else: # self.LOCK_RELEASE
|
||||
elif lock == self.LOCK_RESPECT:
|
||||
expected_engine_id = None
|
||||
elif lock == self.LOCK_RELEASE:
|
||||
expected_engine_id = self._calling_engine_id
|
||||
rs['engine_id'] = None
|
||||
else:
|
||||
assert False, "Invalid lock action: %s" % lock
|
||||
if resource_objects.Resource.select_and_update_by_id(
|
||||
self.context, self.id, rs, expected_engine_id,
|
||||
self._atomic_key):
|
||||
|
|
Loading…
Reference in New Issue