From dd9c27f999221001bae9faa03571645824d2a681 Mon Sep 17 00:00:00 2001 From: Stanislaw Pitucha Date: Thu, 28 Feb 2013 19:50:21 +0000 Subject: Delegate authentication to quantumclient Quantumclient can deal with authentication, getting the token and refreshing it when needed. There should be no need for nova to do those explicitly. Additionally nova can save some time not having to recreate the Client object on each request. Fix a couple of places that relied on the exceptions module being imported inside quantumv2. Part of blueprint fewer-networking-token-checks Fixed bug 1177579 Change-Id: I007cef1f0bd688036fa45d79792e6e350c145f05 --- nova/network/quantumv2/__init__.py | 59 ++++++++++++++++++++++-------------- nova/network/quantumv2/api.py | 4 ++- nova/tests/network/test_quantumv2.py | 15 ++++++++- 3 files changed, 53 insertions(+), 25 deletions(-) diff --git a/nova/network/quantumv2/__init__.py b/nova/network/quantumv2/__init__.py index 6d6e7c7bc..89c08311f 100644 --- a/nova/network/quantumv2/__init__.py +++ b/nova/network/quantumv2/__init__.py @@ -16,9 +16,7 @@ # under the License. from oslo.config import cfg -from quantumclient import client -from quantumclient.common import exceptions -from quantumclient.v2_0 import client as clientv20 +from quantumclient.v2_0 import client from nova.openstack.common import excutils from nova.openstack.common import log as logging @@ -27,27 +25,24 @@ CONF = cfg.CONF LOG = logging.getLogger(__name__) -def _get_auth_token(): - try: - httpclient = client.HTTPClient( - username=CONF.quantum_admin_username, - tenant_name=CONF.quantum_admin_tenant_name, - region_name=CONF.quantum_region_name, - password=CONF.quantum_admin_password, - auth_url=CONF.quantum_admin_auth_url, - timeout=CONF.quantum_url_timeout, - auth_strategy=CONF.quantum_auth_strategy, - insecure=CONF.quantum_api_insecure) - httpclient.authenticate() - return httpclient.auth_token - except exceptions.QuantumClientException as e: - with excutils.save_and_reraise_exception(): - LOG.error(_('Quantum client authentication failed: %s'), e) +cached_admin_client = None + + +def _fill_admin_details(params): + params['username'] = CONF.quantum_admin_username + params['tenant_name'] = CONF.quantum_admin_tenant_name + params['region_name'] = CONF.quantum_region_name + params['password'] = CONF.quantum_admin_password + params['auth_url'] = CONF.quantum_admin_auth_url + params['timeout'] = CONF.quantum_url_timeout + params['auth_strategy'] = CONF.quantum_auth_strategy + params['insecure'] = CONF.quantum_api_insecure def _get_client(token=None): - if not token and CONF.quantum_auth_strategy: - token = _get_auth_token() + global cached_admin_client + + should_cache = False params = { 'endpoint_url': CONF.quantum_url, 'timeout': CONF.quantum_url_timeout, @@ -56,12 +51,30 @@ def _get_client(token=None): if token: params['token'] = token else: - params['auth_strategy'] = None - return clientv20.Client(**params) + if CONF.quantum_auth_strategy: + should_cache = True + _fill_admin_details(params) + else: + params['auth_strategy'] = None + + new_client = client.Client(**params) + if should_cache: + # in this case, we don't have the token yet + try: + new_client.httpclient.authenticate() + except Exception: + with excutils.save_and_reraise_exception(): + LOG.exception(_("quantum authentication failed")) + + cached_admin_client = new_client + return new_client def get_client(context, admin=False): if admin: + if cached_admin_client is not None: + return cached_admin_client + token = None else: token = context.auth_token diff --git a/nova/network/quantumv2/api.py b/nova/network/quantumv2/api.py index 8da43a3d8..c577ebce8 100644 --- a/nova/network/quantumv2/api.py +++ b/nova/network/quantumv2/api.py @@ -33,6 +33,8 @@ from nova.openstack.common import excutils from nova.openstack.common import log as logging from nova.openstack.common import uuidutils +import quantumclient.common.exceptions + quantum_opts = [ cfg.StrOpt('quantum_url', default='http://127.0.0.1:9696', @@ -719,7 +721,7 @@ class API(base.Base): port_id=port) # If a quantum plugin does not implement the L3 API a 404 from # list_floatingips will be raised. - except quantumv2.exceptions.QuantumClientException as e: + except quantumclient.common.exceptions.QuantumClientException as e: if e.status_code == 404: return [] raise diff --git a/nova/tests/network/test_quantumv2.py b/nova/tests/network/test_quantumv2.py index ec1e88d86..3a2b8a7c4 100644 --- a/nova/tests/network/test_quantumv2.py +++ b/nova/tests/network/test_quantumv2.py @@ -19,6 +19,8 @@ import uuid import mox from oslo.config import cfg +from quantumclient import client as quantum_client +from quantumclient.common import exceptions as quantum_exceptions from quantumclient.v2_0 import client from nova.compute import flavors @@ -102,6 +104,17 @@ class TestQuantumClient(test.TestCase): self.mox.ReplayAll() quantumv2.get_client(my_context) + def test_cached_admin_client(self): + self.mox.StubOutWithMock(quantum_client.HTTPClient, "authenticate") + + # should be called one time only + quantum_client.HTTPClient.authenticate() + self.mox.ReplayAll() + + admin1 = quantumv2.get_client(None, admin=True) + admin2 = quantumv2.get_client(None, admin=True) + self.assertIs(admin1, admin2) + def test_withouttoken_keystone_connection_error(self): self.flags(quantum_auth_strategy='keystone') self.flags(quantum_url='http://anyhost/') @@ -1223,7 +1236,7 @@ class TestQuantumv2(test.TestCase): def test_list_floating_ips_without_l3_support(self): api = quantumapi.API() - QuantumNotFound = quantumv2.exceptions.QuantumClientException( + QuantumNotFound = quantum_exceptions.QuantumClientException( status_code=404) self.moxed_client.list_floatingips( fixed_ip_address='1.1.1.1', port_id=1).AndRaise(QuantumNotFound) -- cgit