From 68d1550f15a6ec6f51973af2e27f3a6943b6305f Mon Sep 17 00:00:00 2001
From: Donagh McCabe <donagh.mccabe@hp.com>
Date: Wed, 5 Sep 2012 15:55:53 +0100
Subject: [PATCH] Add region_name support

Add --os-region-name (and OS_REGION_NAME env) to bin/swift
Add region_name to the os_options in Connection class.

bug 1019832

Change-Id: Id8515d97e5351638dce10581c7368f61518e1fa7
---
 bin/swift                 |  8 ++++++++
 swiftclient/client.py     | 15 +++++++++++----
 tests/test_swiftclient.py | 19 +++++++++++++++++++
 tests/utils.py            |  4 +++-
 4 files changed, 41 insertions(+), 5 deletions(-)

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")