From e8274fa57df3a833f8e46be2e9a6feff366e4b5c Mon Sep 17 00:00:00 2001
From: "Derrick J. Wippler" <thrawn01@gmail.com>
Date: Wed, 19 Aug 2015 15:48:27 -0500
Subject: [PATCH] No longer ignores CINDER_SERVICE_NAME

Cinderclient now utilizes the CINDER_SERVICE_NAME when deciding what
endpoint to choose.

Closes-Bug: #1486256
Change-Id: I494a34afe5799e7832b1359b9c24c31ead68b6d1
UpgradeImpact: Existing configurations may select a different endpoint
after this patch.
---
 cinderclient/client.py                        |  3 +-
 .../unit/fixture_data/keystone_client.py      | 66 +++++++++++++------
 cinderclient/tests/unit/test_shell.py         | 19 ++++++
 3 files changed, 66 insertions(+), 22 deletions(-)

diff --git a/cinderclient/client.py b/cinderclient/client.py
index 2a6b9775f..6393c1b26 100644
--- a/cinderclient/client.py
+++ b/cinderclient/client.py
@@ -332,7 +332,8 @@ class HTTPClient(object):
                 management_url = self.service_catalog.url_for(
                     region_name=self.region_name,
                     endpoint_type=self.endpoint_type,
-                    service_type=self.service_type)
+                    service_type=self.service_type,
+                    service_name=self.service_name)
                 self.management_url = management_url.rstrip('/')
                 return None
             except exceptions.AmbiguousEndpoints:
diff --git a/cinderclient/tests/unit/fixture_data/keystone_client.py b/cinderclient/tests/unit/fixture_data/keystone_client.py
index dc4c6c6d1..c94977ef8 100644
--- a/cinderclient/tests/unit/fixture_data/keystone_client.py
+++ b/cinderclient/tests/unit/fixture_data/keystone_client.py
@@ -115,28 +115,49 @@ def generate_v2_project_scoped_token(**kwargs):
                              }
                     }}
 
-    # we only care about Neutron and Keystone endpoints
+    # Add endpoint Keystone
     o['access']['serviceCatalog'] = [
-        {'endpoints': [
-            {'publicURL': 'public_' + ref.get('cinder_url'),
-             'internalURL': 'internal_' + ref.get('cinder_url'),
-             'adminURL': 'admin_' + (ref.get('auth_url') or ""),
-             'id': uuid.uuid4().hex,
-             'region': 'RegionOne'
-             }],
-         'endpoints_links': [],
-         'name': 'Neutron',
-         'type': 'network'},
-        {'endpoints': [
-            {'publicURL': ref.get('auth_url'),
-             'adminURL': ref.get('auth_url'),
-             'internalURL': ref.get('auth_url'),
-             'id': uuid.uuid4().hex,
-             'region': 'RegionOne'
-             }],
-         'endpoint_links': [],
-         'name': 'keystone',
-         'type': 'identity'}]
+        {
+            'endpoints': [
+            {
+                'publicURL': ref.get('auth_url'),
+                'adminURL': ref.get('auth_url'),
+                'internalURL': ref.get('auth_url'),
+                'id': uuid.uuid4().hex,
+                'region': 'RegionOne'
+            }],
+            'endpoint_links': [],
+            'name': 'keystone',
+            'type': 'identity'
+        }
+    ]
+
+    cinder_endpoint = {
+        'endpoints': [
+            {
+                'publicURL': 'public_' + ref.get('cinder_url'),
+                'internalURL': 'internal_' + ref.get('cinder_url'),
+                'adminURL': 'admin_' + (ref.get('auth_url') or ""),
+                'id': uuid.uuid4().hex,
+                'region': 'RegionOne'
+            }
+        ],
+        'endpoints_links': [],
+        'name': None,
+        'type': 'volumev2'
+    }
+
+    # Add multiple Cinder endpoints
+    for count in range(1, 4):
+        # Copy the endpoint and create a service name
+        endpoint_copy = copy.deepcopy(cinder_endpoint)
+        name = "cinder%i" % count
+        # Assign the service name and a unique endpoint
+        endpoint_copy['endpoints'][0]['publicURL'] = \
+            'http://%s.api.com/v2' % name
+        endpoint_copy['name'] = name
+
+        o['access']['serviceCatalog'].append(endpoint_copy)
 
     return token, o
 
@@ -218,6 +239,9 @@ def keystone_request_callback(request, context):
     elif request.url == BASE_URL + "/v2.0":
         token_id, token_data = generate_v2_project_scoped_token()
         return token_data
+    elif request.url.startswith("http://multiple.service.names"):
+        token_id, token_data = generate_v2_project_scoped_token()
+        return json.dumps(token_data)
     elif request.url == BASE_URL + "/v3":
         token_id, token_data = generate_v3_project_scoped_token()
         context.headers["X-Subject-Token"] = token_id
diff --git a/cinderclient/tests/unit/test_shell.py b/cinderclient/tests/unit/test_shell.py
index 3407a267f..af6d1fa0a 100644
--- a/cinderclient/tests/unit/test_shell.py
+++ b/cinderclient/tests/unit/test_shell.py
@@ -122,6 +122,25 @@ class ShellTest(utils.TestCase):
         self.assertEqual(v3_url, os_auth_url, "Expected v3 url")
         self.assertIsNone(v2_url, "Expected no v2 url")
 
+    @requests_mock.Mocker()
+    def list_volumes_on_service(self, count, mocker):
+        os_auth_url = "http://multiple.service.names/v2.0"
+        mocker.register_uri('POST', os_auth_url + "/tokens",
+                            text=keystone_client.keystone_request_callback)
+        mocker.register_uri('GET',
+                            "http://cinder%i.api.com/v2/volumes/detail"
+                            % count, text='{"volumes": []}')
+        self.make_env(include={'OS_AUTH_URL': os_auth_url,
+                               'CINDER_SERVICE_NAME': 'cinder%i' % count})
+        _shell = shell.OpenStackCinderShell()
+        _shell.main(['list'])
+
+    def test_cinder_service_name(self):
+        # Failing with 'No mock address' means we are not
+        # choosing the correct endpoint
+        for count in range(1, 4):
+            self.list_volumes_on_service(count)
+
     @mock.patch('keystoneclient.adapter.Adapter.get_token',
                 side_effect=ks_exc.ConnectionRefused())
     @mock.patch('keystoneclient.discover.Discover',