Don't block stack deletion if user creds fail

In some deployments, user passwords are generated by other
authentication infrastructures where the length of the Base64 encoded
credentials is longer than the DB limit.  When this incorrect behavior
happens silently, the user credential can not be retrieved.
In this case, stack deletion will abort due to uncaught exception.

This patch enables a stack deletion to handle this error so that stack
can be properly deleted.

Change-Id: Iaf80b18a83c7752465621c232335dcf32afbcbf3
Closes-Bug: 1386213
This commit is contained in:
tengqm 2014-12-05 09:39:16 +08:00
parent c16f539c53
commit 9698da6804
2 changed files with 42 additions and 5 deletions

View File

@ -868,13 +868,25 @@ class Stack(collections.Mapping):
stack.delete(backup=True)
def _try_get_user_creds(self, user_creds_id):
# There are cases where the user_creds cannot be returned
# due to credentials truncated when being saved to DB.
# Ignore this error instead of blocking stack deletion.
user_creds = None
try:
user_creds = db_api.user_creds_get(self.user_creds_id)
except exception.Error as err:
LOG.exception(err)
pass
return user_creds
def _delete_credentials(self, stack_status, reason, abandon):
# Cleanup stored user_creds so they aren't accessible via
# the soft-deleted stack which remains in the DB
# The stack_status and reason passed in are current values, which
# may get rewritten and returned from this method
if self.user_creds_id:
user_creds = db_api.user_creds_get(self.user_creds_id)
user_creds = self._try_get_user_creds(self.user_creds_id)
# If we created a trust, delete it
if user_creds is not None:
trust_id = user_creds.get('trust_id')

View File

@ -1399,10 +1399,12 @@ class StackTest(common.HeatTestCase):
self.stack.state)
def test_delete_user_creds_gone_missing(self):
'''It may happen that user_creds were deleted when a delete
operation was stopped. We should be resilient to this and still
complete the delete operation.
'''
'''Do not block stack deletion if user_creds is missing.
It may happen that user_creds were deleted when a delete operation was
stopped. We should be resilient to this and still complete the delete
operation.
'''
self.stack = parser.Stack(self.ctx, 'delete_test',
self.tmpl)
stack_id = self.stack.store()
@ -1427,6 +1429,29 @@ class StackTest(common.HeatTestCase):
self.assertEqual((parser.Stack.DELETE, parser.Stack.COMPLETE),
self.stack.state)
def test_delete_user_creds_fail(self):
'''Do not stop deleting stacks even failed deleting user_creds.
It may happen that user_creds were incorrectly saved (truncated) and
thus cannot be correctly retrieved (and decrypted). In this case,
stack delete should not be stopped.
'''
self.stack = parser.Stack(self.ctx, 'delete_test', self.tmpl)
stack_id = self.stack.store()
db_s = db_api.stack_get(self.ctx, stack_id)
self.assertIsNotNone(db_s)
self.assertIsNotNone(db_s.user_creds_id)
exc = exception.Error('Cannot get user credentials')
self.patchobject(db_api, 'user_creds_get').side_effect = exc
self.stack.delete()
db_s = db_api.stack_get(self.ctx, stack_id)
self.assertIsNone(db_s)
self.assertEqual((parser.Stack.DELETE, parser.Stack.COMPLETE),
self.stack.state)
def test_delete_trust(self):
cfg.CONF.set_override('deferred_auth_method', 'trusts')
self.stub_keystoneclient()