Remove dependency on admin creds

This patch changes the way refstack-client gets keystone service id.
Now non-admin creds should be enought for that.
This patch adds support for Keystone API V3.
Keystone API version selected from tempest.conf
Section: 'identity-feature-enabled', key: 'api_v3'

Closes-Bug: #1495671
Change-Id: I1f9edffba88cf99c39b2c8b99f792088d35dbd2e
This commit is contained in:
sslypushenko 2015-09-11 14:56:24 +03:00
parent bd2205afc0
commit ecba34b7dd
3 changed files with 97 additions and 41 deletions

View File

@ -37,7 +37,8 @@ import time
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from keystoneclient.v2_0 import client as ksclient
from keystoneclient.v2_0 import client as ksclient2
from keystoneclient.v3 import client as ksclient3
import requests
import requests.exceptions
import six.moves
@ -126,23 +127,54 @@ class RefstackClient:
def _get_cpid_from_keystone(self, conf_file):
'''This will get the Keystone service ID which is used as the CPID.'''
try:
args = {'auth_url': conf_file.get('identity', 'uri'),
'username': conf_file.get('identity', 'admin_username'),
'password': conf_file.get('identity', 'admin_password'),
'insecure': self.args.insecure}
# Prefer Keystone V3 API if it is enabled
auth_version = (
'v3' if (conf_file.has_option('identity-feature-enabled',
'api_v3')
and conf_file.get('identity-feature-enabled',
'api_v3')
and conf_file.has_option('identity', 'uri_v3'))
else 'v2')
args = {'insecure': self.args.insecure}
if self.conf.has_option('identity', 'admin_tenant_id'):
args['tenant_id'] = conf_file.get('identity',
'admin_tenant_id')
auth_args = {
'username': conf_file.get('identity', 'username'),
'password': conf_file.get('identity', 'password')
}
if self.conf.has_option('identity', 'tenant_id'):
auth_args['tenant_id'] = conf_file.get('identity',
'tenant_id')
else:
args['tenant_name'] = conf_file.get('identity',
'admin_tenant_name')
auth_args['tenant_name'] = conf_file.get('identity',
'tenant_name')
client = ksclient.Client(**args)
services = client.services.list()
for service in services:
if service.type == "identity":
return service.id
args.update(auth_args)
if auth_version == 'v2':
args['auth_url'] = conf_file.get('identity', 'uri')
client = ksclient2.Client(**args)
token = client.tokens.authenticate(**auth_args)
for service in token.serviceCatalog:
if service['type'] == 'identity':
return service['endpoints'][0]['id']
elif auth_version == 'v3':
args['auth_url'] = conf_file.get('identity', 'uri_v3')
if conf_file.has_option('identity', 'domain_name'):
args['project_domain_name'] = conf_file.get('identity',
'domain_name')
args['user_domain_name'] = conf_file.get('identity',
'domain_name')
if conf_file.has_option('identity', 'region'):
args['region_name'] = conf_file.get('identity',
'region')
client = ksclient3.Client(**args)
token = client.auth_ref
for service in token['catalog']:
if service['type'] == 'identity':
return service['id']
else:
raise ValueError('Auth_version %s is unsupported'
'' % auth_version)
except ConfigParser.Error as e:
# Most likely a missing section or option in the config file.

View File

@ -1,5 +1,10 @@
[identity]
uri = 0.0.0.0:35357
admin_username = admin
admin_password = test
admin_tenant_id = admin_tenant_id
auth_version = v2
uri = 0.0.0.0:35357/v2.0
uri_v3 = 0.0.0.0:35357/v3
username = admin
password = test
tenant_id = admin_tenant_id
[identity-feature-enabled]
api_v2 = true

View File

@ -70,15 +70,27 @@ class TestRefstackClient(unittest.TestCase):
"""
Mock the Keystone client methods.
"""
self.mock_identity_service = MagicMock(
name='service', **{'type': 'identity', 'id': 'test-id'})
self.mock_ks_client = MagicMock(
self.mock_identity_service_v2 = {'type': 'identity',
'endpoints': [{'id': 'test-id'}]}
self.mock_identity_service_v3 = {'type': 'identity',
'id': 'test-id'}
self.mock_ks2_client = MagicMock(
name='ks_client',
**{'services.list.return_value': [self.mock_identity_service]}
**{'tokens.authenticate.return_value.serviceCatalog':
[self.mock_identity_service_v2]}
)
self.ks_client_builder = self.patch(
'refstack_client.refstack_client.ksclient.Client',
return_value=self.mock_ks_client
self.mock_ks3_client = MagicMock(
name='ks_client',
**{'auth_ref':
{'catalog': [self.mock_identity_service_v3]}}
)
self.ks2_client_builder = self.patch(
'refstack_client.refstack_client.ksclient2.Client',
return_value=self.mock_ks2_client
)
self.ks3_client_builder = self.patch(
'refstack_client.refstack_client.ksclient3.Client',
return_value=self.mock_ks3_client
)
def setUp(self):
@ -146,9 +158,9 @@ class TestRefstackClient(unittest.TestCase):
client._prep_test()
self.mock_keystone()
cpid = client._get_cpid_from_keystone(client.conf)
self.ks_client_builder.assert_called_with(
self.ks2_client_builder.assert_called_with(
username='admin', tenant_id='admin_tenant_id',
password='test', auth_url='0.0.0.0:35357', insecure=False
password='test', auth_url='0.0.0.0:35357/v2.0', insecure=False
)
self.assertEqual('test-id', cpid)
@ -160,13 +172,13 @@ class TestRefstackClient(unittest.TestCase):
client = rc.RefstackClient(args)
client.tempest_dir = self.test_path
client._prep_test()
client.conf.remove_option('identity', 'admin_tenant_id')
client.conf.set('identity', 'admin_tenant_name', 'admin_tenant_name')
client.conf.remove_option('identity', 'tenant_id')
client.conf.set('identity', 'tenant_name', 'tenant_name')
self.mock_keystone()
cpid = client._get_cpid_from_keystone(client.conf)
self.ks_client_builder.assert_called_with(
username='admin', tenant_name='admin_tenant_name',
password='test', auth_url='0.0.0.0:35357', insecure=False
self.ks2_client_builder.assert_called_with(
username='admin', tenant_name='tenant_name',
password='test', auth_url='0.0.0.0:35357/v2.0', insecure=False
)
self.assertEqual('test-id', cpid)
@ -182,22 +194,29 @@ class TestRefstackClient(unittest.TestCase):
client._prep_test()
self.mock_keystone()
client._get_cpid_from_keystone(client.conf)
self.ks_client_builder.assert_called_with(
self.ks2_client_builder.assert_called_with(
username='admin', tenant_id='admin_tenant_id',
password='test', auth_url='0.0.0.0:35357', insecure=True
password='test', auth_url='0.0.0.0:35357/v2.0', insecure=True
)
def test_get_cpid_from_keystone_no_admin_tenant(self):
def test_get_cpid_from_keystone_v3(self):
"""
Test exit under absence of information about admin tenant info.
Test getting the CPID from Keystone API v3.
"""
args = rc.parse_cli_args(self.mock_argv(verbose='-vv'))
args = rc.parse_cli_args(self.mock_argv())
client = rc.RefstackClient(args)
client.tempest_dir = self.test_path
client._prep_test()
client.conf.remove_option('identity', 'admin_tenant_id')
self.assertRaises(SystemExit, client._get_cpid_from_keystone,
client.conf)
client.conf.remove_option('identity', 'tenant_id')
client.conf.set('identity', 'tenant_name', 'tenant_name')
client.conf.set('identity-feature-enabled', 'api_v3', 'true')
self.mock_keystone()
cpid = client._get_cpid_from_keystone(client.conf)
self.ks3_client_builder.assert_called_with(
username='admin', tenant_name='tenant_name',
password='test', auth_url='0.0.0.0:35357/v3', insecure=False
)
self.assertEqual('test-id', cpid)
def test_form_result_content(self):
"""