From: Zack Cerza Date: Fri, 10 Feb 2017 17:25:53 +0000 (-0700) Subject: cloud.openstack: Cache authentication tokens X-Git-Tag: 1.1.0~456^2~2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=ba436ba4a0ce12d0bf4439348e421bc355b5b652;p=teuthology.git cloud.openstack: Cache authentication tokens Constantly causing Keystone to regenerate auth tokens was the cause of our hitting rate limits during testing. This will let us reuse auth tokens - including across processes - to avoid hitting those limits. Signed-off-by: Zack Cerza --- diff --git a/teuthology/provision/cloud/base.py b/teuthology/provision/cloud/base.py index c403829c1b..e06972e072 100644 --- a/teuthology/provision/cloud/base.py +++ b/teuthology/provision/cloud/base.py @@ -20,17 +20,20 @@ class Provider(object): self.conf = conf self.driver_name = self.conf['driver'] - @property - def driver(self): + def _get_driver(self): driver_type = get_driver( getattr(lc_Provider, self.driver_name.upper()) ) - driver_args = deepcopy(self.conf['driver_args']) + driver_args = self._get_driver_args() driver = driver_type( *[driver_args.pop(arg_name) for arg_name in self._driver_posargs], **driver_args ) return driver + driver = property(fget=_get_driver) + + def _get_driver_args(self): + return deepcopy(self.conf['driver_args']) class Provisioner(object): diff --git a/teuthology/provision/cloud/openstack.py b/teuthology/provision/cloud/openstack.py index 71e3962ebe..3a78d71a44 100644 --- a/teuthology/provision/cloud/openstack.py +++ b/teuthology/provision/cloud/openstack.py @@ -50,6 +50,29 @@ def retry(function, *args, **kwargs): class OpenStackProvider(Provider): _driver_posargs = ['username', 'password'] + def _get_driver(self): + self._auth_token = util.AuthToken(name='teuthology_%s' % self.name) + with self._auth_token as token: + driver = super(OpenStackProvider, self)._get_driver() + # We must apparently call get_service_catalog() so that + # get_endpoint() works. + driver.connection.get_service_catalog() + if not token.value: + token.write( + driver.connection.auth_token, + driver.connection.auth_token_expires, + driver.connection.get_endpoint(), + ) + return driver + driver = property(fget=_get_driver) + + def _get_driver_args(self): + driver_args = super(OpenStackProvider, self)._get_driver_args() + if self._auth_token.value: + driver_args['ex_force_auth_token'] = self._auth_token.value + driver_args['ex_force_base_url'] = self._auth_token.endpoint + return driver_args + @property def images(self): if not hasattr(self, '_images'): @@ -132,7 +155,7 @@ class OpenStackProvisioner(base.Provisioner): :return: None """ - driver_name = self.provider.driver.name.lower() + driver_name = self.provider.driver_name.lower() full_conf = conf or dict() driver_conf = full_conf.get(driver_name, dict()) legacy_conf = getattr(config, driver_name) or dict() diff --git a/teuthology/provision/cloud/test/test_openstack.py b/teuthology/provision/cloud/test/test_openstack.py index ac07fdf896..d2f259580e 100644 --- a/teuthology/provision/cloud/test/test_openstack.py +++ b/teuthology/provision/cloud/test/test_openstack.py @@ -123,6 +123,17 @@ class TestOpenStackBase(object): 'libcloud.compute.drivers.openstack' '.OpenStackNodeDriver.destroy_volume' ) + self.patchers['m_get_service_catalog'] = patch( + 'libcloud.common.openstack' + '.OpenStackBaseConnection.get_service_catalog' + ) + self.patchers['m_auth_token'] = patch( + 'teuthology.provision.cloud.util.AuthToken' + ) + self.patchers['m_get_endpoint'] = patch( + 'libcloud.common.openstack' + '.OpenStackBaseConnection.get_endpoint', + ) self.patchers['m_sleep'] = patch( 'time.sleep' ) @@ -132,6 +143,7 @@ class TestOpenStackBase(object): self.mocks = dict() for name, patcher in self.patchers.items(): self.mocks[name] = patcher.start() + self.mocks['m_get_endpoint'].return_value = 'endpoint' def teardown(self): for patcher in self.patchers.values(): @@ -148,8 +160,12 @@ class TestOpenStackProvider(TestOpenStackBase): assert obj.conf == test_config['providers']['my_provider'] def test_driver(self): + token = self.mocks['m_auth_token'].return_value + self.mocks['m_auth_token'].return_value.__enter__.return_value = token + token.value = None obj = cloud.get_provider('my_provider') assert isinstance(obj.driver, get_driver('openstack')) + assert obj._auth_token.value is None def test_images(self): obj = cloud.get_provider('my_provider')