]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Pass region name to Nova client
authorAdrien Vergé <adrien.verge@numergy.com>
Thu, 12 Feb 2015 16:09:47 +0000 (17:09 +0100)
committerAdrien Vergé <adrien.verge@numergy.com>
Fri, 20 Feb 2015 13:56:29 +0000 (13:56 +0000)
When using a Novaclient method on a multi-region infrastructure,
requests sometimes fail with an AmbiguousEndpoints Exception,
because more than one Nova endpoint is returned in the catalog.

This patch passes `region_name` and `endpoint_type` from conf to
Novaclient, so this error case is avoided.

Change-Id: Ic4810a1c5223575c6d6300156491437ea67c4a7a
Closes-Bug: #1421314

cinder/compute/nova.py
cinder/tests/compute/test_nova.py

index 2a2fc82d9eb201808684462eef1f1e9b20021de3..af7dd8c05c5e525ec5221fb1787749581f29eee7 100644 (file)
@@ -96,6 +96,13 @@ def novaclient(context, admin_endpoint=False, privileged_user=False,
     if admin_endpoint:
         nova_endpoint_template = CONF.nova_endpoint_admin_template
         nova_catalog_info = CONF.nova_catalog_admin_info
+    service_type, service_name, endpoint_type = nova_catalog_info.split(':')
+
+    # Extract the region if set in configuration
+    if CONF.os_region_name:
+        region_filter = {'attr': 'region', 'filter_value': CONF.os_region_name}
+    else:
+        region_filter = {}
 
     if privileged_user and CONF.os_privileged_user_name:
         context = ctx.RequestContext(
@@ -104,8 +111,13 @@ def novaclient(context, admin_endpoint=False, privileged_user=False,
             project_name=CONF.os_privileged_user_tenant,
             service_catalog=context.service_catalog)
 
-        # The admin user needs to authenticate before querying Nova
-        url = sc.url_for(service_type='identity')
+        # When privileged_user is used, it needs to authenticate to Keystone
+        # before querying Nova, so we set auth_url to the identity service
+        # endpoint. We then pass region_name, endpoint_type, etc. to the
+        # Client() constructor so that the final endpoint is chosen correctly.
+        url = sc.url_for(service_type='identity',
+                         endpoint_type=endpoint_type,
+                         **region_filter)
 
         LOG.debug('Creating a Nova client using "%s" user' %
                   CONF.os_privileged_user_name)
@@ -113,20 +125,10 @@ def novaclient(context, admin_endpoint=False, privileged_user=False,
         if nova_endpoint_template:
             url = nova_endpoint_template % context.to_dict()
         else:
-            info = nova_catalog_info
-            service_type, service_name, endpoint_type = info.split(':')
-            # extract the region if set in configuration
-            if CONF.os_region_name:
-                attr = 'region'
-                filter_value = CONF.os_region_name
-            else:
-                attr = None
-                filter_value = None
-            url = sc.url_for(attr=attr,
-                             filter_value=filter_value,
-                             service_type=service_type,
+            url = sc.url_for(service_type=service_type,
                              service_name=service_name,
-                             endpoint_type=endpoint_type)
+                             endpoint_type=endpoint_type,
+                             **region_filter)
 
         LOG.debug('Nova client connection created using URL: %s' % url)
 
@@ -136,6 +138,8 @@ def novaclient(context, admin_endpoint=False, privileged_user=False,
                            auth_url=url,
                            insecure=CONF.nova_api_insecure,
                            timeout=timeout,
+                           region_name=CONF.os_region_name,
+                           endpoint_type=endpoint_type,
                            cacert=CONF.nova_ca_certificates_file,
                            extensions=nova_extensions)
 
index 00608575c009e6bfbc04723380864b3fe1ecea6e..f655ee5a21c9d29f5b5bd60684de59449437e646 100644 (file)
@@ -44,28 +44,38 @@ class NovaClientTestCase(test.TestCase):
     def test_nova_client_regular(self, p_client):
         nova.novaclient(self.ctx)
         p_client.assert_called_once_with(
-            'regularuser', 'token', None,
+            'regularuser', 'token', None, region_name=None,
             auth_url='http://novahost:8774/v2/e3f0833dc08b4cea',
-            insecure=False, cacert=None, timeout=None,
-            extensions=nova.nova_extensions)
+            insecure=False, endpoint_type='publicURL', cacert=None,
+            timeout=None, extensions=nova.nova_extensions)
 
     @mock.patch('novaclient.v1_1.client.Client')
     def test_nova_client_admin_endpoint(self, p_client):
         nova.novaclient(self.ctx, admin_endpoint=True)
         p_client.assert_called_once_with(
-            'regularuser', 'token', None,
+            'regularuser', 'token', None, region_name=None,
             auth_url='http://novaadmhost:4778/v2/e3f0833dc08b4cea',
-            insecure=False, cacert=None, timeout=None,
-            extensions=nova.nova_extensions)
+            insecure=False, endpoint_type='adminURL', cacert=None,
+            timeout=None, extensions=nova.nova_extensions)
 
     @mock.patch('novaclient.v1_1.client.Client')
     def test_nova_client_privileged_user(self, p_client):
         nova.novaclient(self.ctx, privileged_user=True)
         p_client.assert_called_once_with(
-            'adminuser', 'strongpassword', None,
+            'adminuser', 'strongpassword', None, region_name=None,
             auth_url='http://keystonehost:5000/v2.0',
-            insecure=False, cacert=None, timeout=None,
-            extensions=nova.nova_extensions)
+            insecure=False, endpoint_type='publicURL', cacert=None,
+            timeout=None, extensions=nova.nova_extensions)
+
+    @mock.patch('novaclient.v1_1.client.Client')
+    def test_nova_client_custom_region(self, p_client):
+        self.override_config('os_region_name', 'farfaraway')
+        nova.novaclient(self.ctx)
+        p_client.assert_called_once_with(
+            'regularuser', 'token', None, region_name='farfaraway',
+            auth_url='http://novahost:8774/v2/e3f0833dc08b4cea',
+            insecure=False, endpoint_type='publicURL', cacert=None,
+            timeout=None, extensions=nova.nova_extensions)
 
 
 class FakeNovaClient(object):