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):
|
class Resource(status.ResourceStatus):
|
||||||
BASE_ATTRIBUTES = (SHOW, ) = (attributes.SHOW_ATTR, )
|
BASE_ATTRIBUTES = (SHOW, ) = (attributes.SHOW_ATTR, )
|
||||||
|
|
||||||
LOCK_ACTIONS = (LOCK_NONE, LOCK_ACQUIRE, LOCK_RELEASE) = (
|
LOCK_ACTIONS = (
|
||||||
0, 1, -1)
|
LOCK_NONE, LOCK_ACQUIRE, LOCK_RELEASE, LOCK_RESPECT,
|
||||||
|
) = (
|
||||||
|
None, 1, -1, 0,
|
||||||
|
)
|
||||||
|
|
||||||
# If True, this resource must be created before it can be referenced.
|
# If True, this resource must be created before it can be referenced.
|
||||||
strict_dependency = True
|
strict_dependency = True
|
||||||
|
@ -1297,22 +1300,7 @@ class Resource(status.ResourceStatus):
|
||||||
if not persist:
|
if not persist:
|
||||||
return
|
return
|
||||||
|
|
||||||
rs = {'current_template_id': self.current_template_id,
|
self.store(lock=self.LOCK_RESPECT)
|
||||||
'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._calling_engine_id = engine_id
|
self._calling_engine_id = engine_id
|
||||||
registry = new_stack.env.registry
|
registry = new_stack.env.registry
|
||||||
|
@ -1502,8 +1490,10 @@ class Resource(status.ResourceStatus):
|
||||||
status_reason = _('Update status to COMPLETE for '
|
status_reason = _('Update status to COMPLETE for '
|
||||||
'FAILED resource neither update '
|
'FAILED resource neither update '
|
||||||
'nor replace.')
|
'nor replace.')
|
||||||
|
lock = (self.LOCK_RESPECT if self.stack.convergence
|
||||||
|
else self.LOCK_NONE)
|
||||||
self.state_set(self.action, self.COMPLETE,
|
self.state_set(self.action, self.COMPLETE,
|
||||||
status_reason)
|
status_reason, lock=lock)
|
||||||
return
|
return
|
||||||
|
|
||||||
if not self.stack.convergence:
|
if not self.stack.convergence:
|
||||||
|
@ -1969,9 +1959,13 @@ class Resource(status.ResourceStatus):
|
||||||
if lock == self.LOCK_ACQUIRE:
|
if lock == self.LOCK_ACQUIRE:
|
||||||
rs['engine_id'] = self._calling_engine_id
|
rs['engine_id'] = self._calling_engine_id
|
||||||
expected_engine_id = None
|
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
|
expected_engine_id = self._calling_engine_id
|
||||||
rs['engine_id'] = None
|
rs['engine_id'] = None
|
||||||
|
else:
|
||||||
|
assert False, "Invalid lock action: %s" % lock
|
||||||
if resource_objects.Resource.select_and_update_by_id(
|
if resource_objects.Resource.select_and_update_by_id(
|
||||||
self.context, self.id, rs, expected_engine_id,
|
self.context, self.id, rs, expected_engine_id,
|
||||||
self._atomic_key):
|
self._atomic_key):
|
||||||
|
|
Loading…
Reference in New Issue