Catch v3 keystone unauthorized error when creating stack

If v3 keystone unauthorized error raise during creating stack,
then this stack will remaid in status of create_in_progress. This
patch modify heat keystoneclient to catch unauthorized error and
set stack status to failed.

Closes-Bug: #1376213
Closes-Bug: #1450923
Change-Id: I9a34c20fc6ac3ce235aaba4eac25a6d5ceb43f5f
(cherry picked from commit dca8e37e65)
This commit is contained in:
Ethan Lynn 2014-11-12 14:01:19 +08:00 committed by Rakesh H S
parent 70fb2e8d05
commit 46bef7ae3b
4 changed files with 32 additions and 8 deletions

View File

@ -127,9 +127,10 @@ class KeystoneClientV3(object):
admin_creds = self._service_admin_creds()
admin_creds.update(self._ssl_options())
c = kc_v3.Client(**admin_creds)
if c.authenticate():
try:
c.authenticate()
self._admin_client = c
else:
except kc_exception.Unauthorized:
LOG.error(_LE("Admin client authentication failed"))
raise exception.AuthorizationFailure()
return self._admin_client
@ -147,9 +148,10 @@ class KeystoneClientV3(object):
auth_kwargs = {'domain_id': self.stack_domain}
else:
auth_kwargs = {'domain_name': self.stack_domain}
if c.authenticate(**auth_kwargs):
try:
c.authenticate(**auth_kwargs)
self._domain_admin_client = c
else:
except kc_exception.Unauthorized:
LOG.error(_LE("Domain admin client authentication failed"))
raise exception.AuthorizationFailure()
return self._domain_admin_client
@ -200,7 +202,11 @@ class KeystoneClientV3(object):
# If auth_ref has already be specified via auth_token_info, don't
# authenticate as we want to reuse, rather than request a new token
if 'auth_ref' not in kwargs:
client.authenticate()
try:
client.authenticate()
except kc_exception.Unauthorized:
LOG.error(_LE("Keystone client authentication failed"))
raise exception.AuthorizationFailure()
# If we are authenticating with a trust set the context auth_token
# with the trust scoped token

View File

@ -618,7 +618,11 @@ class EngineService(service.Service):
def _stack_create(stack):
if not stack.stack_user_project_id:
stack.create_stack_user_project_id()
try:
stack.create_stack_user_project_id()
except exception.AuthorizationFailure as ex:
stack.state_set(stack.action, stack.FAILED,
six.text_type(ex))
# Create/Adopt a stack, and create the periodic task if successful
if stack.adopt_stack_data:
@ -626,7 +630,7 @@ class EngineService(service.Service):
raise exception.NotSupported(feature='Stack Adopt')
stack.adopt()
else:
elif stack.status != stack.FAILED:
stack.create()
if (stack.action in (stack.CREATE, stack.ADOPT)

View File

@ -597,6 +597,17 @@ class StackServiceCreateUpdateDeleteTest(HeatTestCase):
self.ctx, stack_name,
stack.t.t, {}, None, {})
def test_stack_create_AuthorizationFailure(self):
stack_name = 'service_create_test_stack_AuthorizationFailure'
stack = get_wordpress_stack(stack_name, self.ctx)
self.m.StubOutWithMock(parser.Stack, 'create_stack_user_project_id')
parser.Stack.create_stack_user_project_id().AndRaise(
exception.AuthorizationFailure)
self.assertRaises(dispatcher.ExpectedException,
self.man.create_stack,
self.ctx, stack_name,
stack.t.t, {}, None, {})
def test_stack_create_no_credentials(self):
stack_name = 'test_stack_create_no_credentials'
params = {'foo': 'bar'}

View File

@ -74,10 +74,13 @@ class KeystoneClientTest(HeatTestCase):
project_name='service',
username='heat').AndReturn(self.mock_admin_client)
self.mock_admin_client.domains = self.mock_ks_v3_client_domain_mngr
self.mock_admin_client.authenticate().AndReturn(auth_ok)
if auth_ok:
self.mock_admin_client.authenticate().AndReturn(auth_ok)
self.mock_admin_client.auth_ref = self.m.CreateMockAnything()
self.mock_admin_client.auth_ref.user_id = '1234'
else:
self.mock_admin_client.authenticate().AndRaise(
kc_exception.Unauthorized)
def _stub_domain_admin_client(self, auth_ok=True):
kc_v3.Client(