From e80d27213cf4489aeeda48e2bdb5a890d8b56433 Mon Sep 17 00:00:00 2001 From: Rabi Mishra Date: Fri, 29 Jan 2016 22:23:21 +0530 Subject: [PATCH] Accommodate v2 and v3 auth for integration tests devstack has moved default Keystone API version to v3[1]. [1] https://github.com/openstack-dev/devstack/commit/f4ce44bf3fbf06e53c2ae3ec6aa4996831cf4605 Though the above patch has been reverted, this would help if devstack removes v2 support in the future. Change-Id: I393750d00b3712a015e48a3cf38ab5f95bb61dae Closes-Bug: #1539692 --- heat_integrationtests/common/clients.py | 103 +++++++++++++----- heat_integrationtests/common/config.py | 13 ++- .../functional/test_aws_stack.py | 2 +- .../functional/test_conditional_exposure.py | 8 +- .../functional/test_preview.py | 2 +- 5 files changed, 85 insertions(+), 43 deletions(-) diff --git a/heat_integrationtests/common/clients.py b/heat_integrationtests/common/clients.py index 9718d036d0..0ba7131530 100644 --- a/heat_integrationtests/common/clients.py +++ b/heat_integrationtests/common/clients.py @@ -15,13 +15,49 @@ import os import ceilometerclient.client import cinderclient.client import heatclient.client +from keystoneclient.auth.identity.generic import password +import keystoneclient.client import keystoneclient.exceptions -import keystoneclient.v2_0.client +from keystoneclient import session import neutronclient.v2_0.client import novaclient.client import swiftclient +class KeystoneWrapperClient(object): + """Wrapper object for keystone client + + This Wraps keystone client,so we can encpasulate certain + added properties like auth_token, project_id etc. + """ + def __init__(self, auth_plugin, verify=True): + self.auth_plugin = auth_plugin + self.session = session.Session( + auth=auth_plugin, + verify=verify) + + @property + def auth_token(self): + return self.auth_plugin.get_token(self.session) + + @property + def auth_ref(self): + return self.auth_plugin.get_access(self.session) + + @property + def project_id(self): + return self.auth_plugin.get_project_id(self.session) + + def get_endpoint_url(self, service_type, region=None): + kwargs = { + 'service_type': service_type, + 'endpoint_type': 'publicURL'} + if region: + kwargs.update({'attr': 'region', + 'filter_value': region}) + return self.auth_ref.service_catalog.url_for(**kwargs) + + class ClientManager(object): """Provides access to the official python clients for calling various APIs. @@ -36,6 +72,8 @@ class ClientManager(object): def __init__(self, conf): self.conf = conf + self.v2_auth_url = self.conf.auth_url.replace('/v3', '/v2.0') + self.auth_version = self.conf.auth_url.split('/v')[1] self.identity_client = self._get_identity_client() self.orchestration_client = self._get_orchestration_client() self.compute_client = self._get_compute_client() @@ -45,20 +83,15 @@ class ClientManager(object): self.metering_client = self._get_metering_client() def _get_orchestration_client(self): - region = self.conf.region endpoint = os.environ.get('HEAT_URL') if os.environ.get('OS_NO_CLIENT_AUTH') == 'True': token = None else: - keystone = self._get_identity_client() - token = keystone.auth_token + token = self.identity_client.auth_token try: if endpoint is None: - endpoint = keystone.service_catalog.url_for( - attr='region', - filter_value=region, - service_type='orchestration', - endpoint_type='publicURL') + endpoint = self.identity_client.get_endpoint_url( + 'orchestration', self.conf.region) except keystoneclient.exceptions.EndpointNotFound: return None else: @@ -70,12 +103,22 @@ class ClientManager(object): password=self.conf.password) def _get_identity_client(self): - return keystoneclient.v2_0.client.Client( - username=self.conf.username, - password=self.conf.password, - tenant_name=self.conf.tenant_name, - auth_url=self.conf.auth_url, - insecure=self.conf.disable_ssl_certificate_validation) + domain = self.conf.domain_name + kwargs = { + 'username': self.conf.username, + 'password': self.conf.password, + 'tenant_name': self.conf.tenant_name, + 'auth_url': self.conf.auth_url + } + # keystone v2 can't ignore domain details + if self.auth_version == '3': + kwargs.update({ + 'project_domain_name': domain, + 'user_domain_name': domain}) + auth = password.Password(**kwargs) + return KeystoneWrapperClient( + auth, + not self.conf.disable_ssl_certificate_validation) def _get_compute_client(self): @@ -86,7 +129,8 @@ class ClientManager(object): self.conf.username, self.conf.password, self.conf.tenant_name, - self.conf.auth_url + # novaclient can not use v3 url + self.v2_auth_url ) # Create our default Nova client to use in testing @@ -101,7 +145,6 @@ class ClientManager(object): http_log_debug=True) def _get_network_client(self): - auth_url = self.conf.auth_url dscv = self.conf.disable_ssl_certificate_validation return neutronclient.v2_0.client.Client( @@ -109,11 +152,11 @@ class ClientManager(object): password=self.conf.password, tenant_name=self.conf.tenant_name, endpoint_type='publicURL', - auth_url=auth_url, + # neutronclient can not use v3 url + auth_url=self.v2_auth_url, insecure=dscv) def _get_volume_client(self): - auth_url = self.conf.auth_url region = self.conf.region endpoint_type = 'publicURL' dscv = self.conf.disable_ssl_certificate_validation @@ -122,7 +165,8 @@ class ClientManager(object): self.conf.username, self.conf.password, self.conf.tenant_name, - auth_url, + # cinderclient can not use v3 url + self.v2_auth_url, region_name=region, endpoint_type=endpoint_type, insecure=dscv, @@ -131,7 +175,7 @@ class ClientManager(object): def _get_object_client(self): dscv = self.conf.disable_ssl_certificate_validation args = { - 'auth_version': '2.0', + 'auth_version': self.auth_version, 'tenant_name': self.conf.tenant_name, 'user': self.conf.username, 'key': self.conf.password, @@ -143,15 +187,10 @@ class ClientManager(object): def _get_metering_client(self): dscv = self.conf.disable_ssl_certificate_validation - - keystone = self._get_identity_client() + domain = self.conf.domain_name try: - endpoint = keystone.service_catalog.url_for( - attr='region', - filter_value=self.conf.region, - service_type='metering', - endpoint_type='publicURL') - + endpoint = self.identity_client.get_endpoint_url('metering', + self.conf.region) except keystoneclient.exceptions.EndpointNotFound: return None else: @@ -165,6 +204,12 @@ class ClientManager(object): 'endpoint_type': 'publicURL', 'service_type': 'metering', } + # ceilometerclient can't ignore domain details for + # v2 auth_url + if self.auth_version == '3': + args.update( + {'user_domain_name': domain, + 'project_domain_name': domain}) return ceilometerclient.client.Client(self.CEILOMETER_VERSION, endpoint, **args) diff --git a/heat_integrationtests/common/config.py b/heat_integrationtests/common/config.py index 9ad6337082..39c084681a 100644 --- a/heat_integrationtests/common/config.py +++ b/heat_integrationtests/common/config.py @@ -32,10 +32,14 @@ IntegrationTestGroup = [ help="Tenant name to use for API requests."), cfg.StrOpt('auth_url', default=os.environ.get('OS_AUTH_URL'), - help="Full URI of the OpenStack Identity API (Keystone), v2"), + help="Full URI of the OpenStack Identity API (Keystone)"), + cfg.StrOpt('domain_name', + default='default', + help="User/project domain name, if keystone v3 auth_url" + "is used"), cfg.StrOpt('region', default=os.environ.get('OS_REGION_NAME'), - help="The region name to us"), + help="The region name to use"), cfg.StrOpt('instance_type', help="Instance type for tests. Needs to be big enough for a " "full OS plus the test workload"), @@ -48,10 +52,6 @@ IntegrationTestGroup = [ cfg.StrOpt('minimal_image_ref', help="Name of minimal (e.g cirros) image to use when " "launching test instances."), - cfg.StrOpt('auth_version', - default='v2', - help="Identity API version to be used for authentication " - "for API tests."), cfg.BoolOpt('disable_ssl_certificate_validation', default=False, help="Set to True if using self-signed SSL certificates."), @@ -124,6 +124,7 @@ IntegrationTestGroup = [ cfg.StrOpt('heat-config-notify-script', default=('heat-config-notify'), help="Path to the script heat-config-notify"), + ] diff --git a/heat_integrationtests/functional/test_aws_stack.py b/heat_integrationtests/functional/test_aws_stack.py index 678ce7ed4f..9649a0236d 100644 --- a/heat_integrationtests/functional/test_aws_stack.py +++ b/heat_integrationtests/functional/test_aws_stack.py @@ -77,7 +77,7 @@ Outputs: def setUp(self): super(AwsStackTest, self).setUp() self.object_container_name = test.rand_name() - self.project_id = self.identity_client.auth_ref.project_id + self.project_id = self.identity_client.project_id self.swift_key = hashlib.sha224( str(random.getrandbits(256))).hexdigest()[:32] key_header = 'x-container-meta-temp-url-key' diff --git a/heat_integrationtests/functional/test_conditional_exposure.py b/heat_integrationtests/functional/test_conditional_exposure.py index 90f7d7aa49..c1175f178d 100644 --- a/heat_integrationtests/functional/test_conditional_exposure.py +++ b/heat_integrationtests/functional/test_conditional_exposure.py @@ -42,13 +42,9 @@ resources: "Sahara resources availability.") def _is_sahara_deployed(self): - keystone = self.identity_client try: - keystone.service_catalog.url_for( - attr='region', - filter_value=self.conf.region, - service_type='data-processing', - endpoint_type='publicURL') + self.identity_client.get_endpoint_url('data-processing', + self.conf.region) except keystoneclient.exceptions.EndpointNotFound: return False return True diff --git a/heat_integrationtests/functional/test_preview.py b/heat_integrationtests/functional/test_preview.py index b927a25ac5..5846523fbf 100644 --- a/heat_integrationtests/functional/test_preview.py +++ b/heat_integrationtests/functional/test_preview.py @@ -43,7 +43,7 @@ parameters: def setUp(self): super(StackPreviewTest, self).setUp() self.client = self.orchestration_client - self.project_id = self.identity_client.auth_ref.project_id + self.project_id = self.identity_client.project_id def _assert_resource(self, res, stack_name): self.assertEqual(stack_name, res['stack_name'])