diff --git a/bin/swift b/bin/swift index 550a7f12..e69dcd05 100755 --- a/bin/swift +++ b/bin/swift @@ -1028,6 +1028,7 @@ def parse_args(parser, args, enforce_requires=True): 'endpoint_type': options.os_endpoint_type, 'auth_token': options.os_auth_token, 'object_storage_url': options.os_storage_url, + 'region_name': options.os_region_name, } # Handle trailing '/' in URL @@ -1127,6 +1128,13 @@ Example: 'Defaults to env[OS_STORAGE_URL]') parser.add_option('--os_storage_url', help=SUPPRESS_HELP) + parser.add_option('--os-region-name', + metavar='<region-name>', + default=environ.get('OS_REGION_NAME'), + help='Openstack region name. ' + 'Defaults to env[OS_REGION_NAME]') + parser.add_option('--os_region_name', + help=SUPPRESS_HELP) parser.add_option('--os-service-type', metavar='<service-type>', default=environ.get('OS_SERVICE_TYPE'), diff --git a/swiftclient/client.py b/swiftclient/client.py index 5425312b..65a721ef 100644 --- a/swiftclient/client.py +++ b/swiftclient/client.py @@ -236,6 +236,7 @@ def get_keystoneclient_2_0(auth_url, user, key, os_options): We are using the keystoneclient library for our 2.0 authentication. """ from keystoneclient.v2_0 import client as ksclient + from keystoneclient import exceptions _ksclient = ksclient.Client(username=user, password=key, tenant_name=os_options.get('tenant_name'), @@ -243,9 +244,15 @@ def get_keystoneclient_2_0(auth_url, user, key, os_options): auth_url=auth_url) service_type = os_options.get('service_type') or 'object-store' endpoint_type = os_options.get('endpoint_type') or 'publicURL' - endpoint = _ksclient.service_catalog.url_for( - service_type=service_type, - endpoint_type=endpoint_type) + try: + endpoint = _ksclient.service_catalog.url_for( + attr='region', + filter_value=os_options.get('region_name'), + service_type=service_type, + endpoint_type=endpoint_type) + except exceptions.EndpointNotFound: + raise ClientException('Endpoint for %s not found - ' + 'have you specified a region?' % service_type) return (endpoint, _ksclient.auth_token) @@ -924,7 +931,7 @@ class Connection(object): to a auth 2.0 system. :param os_options: The OpenStack options which can have tenant_id, auth_token, service_type, endpoint_type, - tenant_name, object_storage_url + tenant_name, object_storage_url, region_name """ self.authurl = authurl self.user = user diff --git a/tests/test_swiftclient.py b/tests/test_swiftclient.py index 0584d399..08bf6cc8 100644 --- a/tests/test_swiftclient.py +++ b/tests/test_swiftclient.py @@ -220,6 +220,25 @@ class TestGetAuth(MockHttpTest): self.assertTrue(url.startswith("http")) self.assertTrue(token) + def test_auth_v2_with_os_region_name(self): + os_options={'region_name': 'good-region', + 'tenant_name': 'asdf'} + c.get_keystoneclient_2_0 = fake_get_keystoneclient_2_0(os_options) + url, token = c.get_auth('http://www.test.com', 'asdf', 'asdf', + os_options=os_options, + auth_version="2.0") + self.assertTrue(url.startswith("http")) + self.assertTrue(token) + + def test_auth_v2_no_endpoint(self): + os_options={'region_name': 'unknown_region', + 'tenant_name': 'asdf'} + c.get_keystoneclient_2_0 = fake_get_keystoneclient_2_0( + os_options, + c.ClientException) + self.assertRaises(c.ClientException, c.get_auth, + 'http://www.tests.com', 'asdf', 'asdf', + os_options=os_options, auth_version='2.0') class TestGetAccount(MockHttpTest): diff --git a/tests/utils.py b/tests/utils.py index ea6aeb3a..570c2ea9 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -16,11 +16,13 @@ from httplib import HTTPException from eventlet import Timeout, sleep -def fake_get_keystoneclient_2_0(os_options): +def fake_get_keystoneclient_2_0(os_options, exc=None): def fake_get_keystoneclient_2_0(auth_url, user, key, actual_os_options): + if exc: + raise exc('test') if actual_os_options != os_options: return "", None return ("http://url/", "token")