summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJamie Lennox <jamielennox@redhat.com>2014-08-25 16:11:16 +1000
committerJamie Lennox <jamielennox@redhat.com>2014-09-02 12:38:03 +1000
commit84af49ce97f481731939344c9c45752ea62db5af (patch)
treec5558edf95a44b3f97902a6909bb04fc651c3732
parent8e87c0b600d0742fbdd69ab770dbeb9dca7cf58c (diff)
downloadpython-cinderclient-84af49ce97f481731939344c9c45752ea62db5af.tar.gz
Use adapter from keystoneclient
The keystoneclient provides an adapter which maintains the client state around the session. We should re-use this rather than copy it and it also means we will get new adapter functions and parameters as they become available. Change-Id: I05c0d650dcdd69f7e77a06563d735efe521a41ae
-rw-r--r--cinderclient/client.py226
-rw-r--r--cinderclient/v1/client.py13
-rw-r--r--cinderclient/v2/client.py14
3 files changed, 110 insertions, 143 deletions
diff --git a/cinderclient/client.py b/cinderclient/client.py
index d1dbe18..a436841 100644
--- a/cinderclient/client.py
+++ b/cinderclient/client.py
@@ -22,14 +22,15 @@ from __future__ import print_function
import logging
+from keystoneclient import access
+from keystoneclient import adapter
+from keystoneclient.auth.identity import base
+import requests
+
from cinderclient import exceptions
from cinderclient.openstack.common import strutils
from cinderclient import utils
-from keystoneclient import access
-from keystoneclient.auth.identity import v3 as v3_auth
-import requests
-
try:
import urlparse
@@ -51,117 +52,90 @@ if not hasattr(urlparse, 'parse_qsl'):
import cgi
urlparse.parse_qsl = cgi.parse_qsl
+_VALID_VERSIONS = ['v1', 'v2']
-class CinderClientMixin(object):
- def get_volume_api_version_from_endpoint(self):
- magic_tuple = urlparse.urlsplit(self.management_url)
- scheme, netloc, path, query, frag = magic_tuple
- components = path.split("/")
- valid_versions = ['v1', 'v2']
- for version in valid_versions:
- if version in components:
- return version[1:]
- msg = "Invalid client version '%s'. must be one of: %s" % (
- (version, ', '.join(valid_versions)))
- raise exceptions.UnsupportedVersion(msg)
+def get_volume_api_from_url(url):
+ scheme, netloc, path, query, frag = urlparse.urlsplit(url)
+ components = path.split("/")
+ for version in _VALID_VERSIONS:
+ if version in components:
+ return version[1:]
-class SessionClient(CinderClientMixin):
+ msg = "Invalid client version '%s'. must be one of: %s" % (
+ (version, ', '.join(valid_versions)))
+ raise exceptions.UnsupportedVersion(msg)
- def __init__(self, session, auth, interface=None,
- service_type=None, service_name=None,
- region_name=None, http_log_debug=False):
- self.session = session
- self.auth = auth
-
- self.interface = interface
- self.service_type = service_type
- self.service_name = service_name
- self.region_name = region_name
- self.auth_token = None
- self.endpoint_url = None
- self.management_url = self.endpoint_url
- self.http_log_debug = http_log_debug
- self._logger = logging.getLogger(__name__)
- if self.http_log_debug:
- # Use keystoneclient's logs instead of writing our own
- ks_logger = logging.getLogger("keystoneclient")
- ks_logger.setLevel(logging.DEBUG)
+class SessionClient(adapter.LegacyJsonAdapter):
- def request(self, url, method, **kwargs):
+ def __init__(self, **kwargs):
kwargs.setdefault('user_agent', 'python-cinderclient')
- kwargs.setdefault('auth', self.auth)
- kwargs.setdefault('authenticated', False)
-
- try:
- kwargs['json'] = kwargs.pop('body')
- except KeyError:
- pass
-
- endpoint_filter = kwargs.setdefault('endpoint_filter', {})
- endpoint_filter.setdefault('interface', self.interface)
- endpoint_filter.setdefault('service_type', self.service_type)
- endpoint_filter.setdefault('service_name', self.service_name)
- endpoint_filter.setdefault('region_name', self.region_name)
-
- resp = self.session.request(url, method, **kwargs)
-
- body = None
- if resp.text:
- try:
- body = resp.json()
- except ValueError:
- pass
+ kwargs.setdefault('service_type', 'volume')
+ super(SessionClient, self).__init__(**kwargs)
- return resp, body
+ def request(self, *args, **kwargs):
+ kwargs.setdefault('authenticated', False)
+ return super(SessionClient, self).request(*args, **kwargs)
def _cs_request(self, url, method, **kwargs):
# this function is mostly redundant but makes compatibility easier
kwargs.setdefault('authenticated', True)
return self.request(url, method, **kwargs)
- def do_request(self, url, method, **kwargs):
- # this function is mostly redundant but makes compatibility easier
- kwargs.setdefault('headers', {})
- if self.auth_token is None:
- self.authenticate()
- kwargs['headers']['X-Auth-Token'] = self.auth_token
- if self.access_info is not None:
- kwargs['headers'][
- 'X-Auth-Project-Id'] = self.access_info.project_id
-
- resp, body = self._cs_request(
- self.endpoint_url + url, method, **kwargs)
- return resp, body
-
- def authenticate(self):
- self.auth_token = self.session.get_token(self.auth)
- self.access_info = self.session.auth.get_access(self.session)
-
- self.endpoint_url = self.session.get_endpoint(
- self.auth,
- service_type=self.service_type,
- region_name=self.region_name,
- interface=self.interface)
- self.management_url = self.endpoint_url
- self.service_catalog = self.access_info.service_catalog
-
def get(self, url, **kwargs):
- return self.do_request(url, 'GET', **kwargs)
+ return self._cs_request(url, 'GET', **kwargs)
def post(self, url, **kwargs):
- return self.do_request(url, 'POST', **kwargs)
+ return self._cs_request(url, 'POST', **kwargs)
def put(self, url, **kwargs):
- return self.do_request(url, 'PUT', **kwargs)
+ return self._cs_request(url, 'PUT', **kwargs)
def delete(self, url, **kwargs):
- return self.do_request(url, 'DELETE', **kwargs)
+ return self._cs_request(url, 'DELETE', **kwargs)
+ def _invalidate(self, auth=None):
+ # NOTE(jamielennox): This is being implemented in keystoneclient
+ return self.session.invalidate(auth or self.auth)
+
+ def _get_token(self, auth=None):
+ # NOTE(jamielennox): This is being implemented in keystoneclient
+ return self.session.get_token(auth or self.auth)
+
+ def _get_endpoint(self, auth=None, **kwargs):
+ # NOTE(jamielennox): This is being implemented in keystoneclient
+ if self.service_type:
+ kwargs.setdefault('service_type', self.service_type)
+ if self.service_name:
+ kwargs.setdefault('service_name', self.service_name)
+ if self.interface:
+ kwargs.setdefault('interface', self.interface)
+ if self.region_name:
+ kwargs.setdefault('region_name', self.region_name)
+ return self.session.get_endpoint(auth or self.auth, **kwargs)
-class HTTPClient(CinderClientMixin):
+ def get_volume_api_version_from_endpoint(self):
+ return get_volume_api_from_url(self._get_endpoint())
+
+ def authenticate(self, auth=None):
+ self._invalidate(auth)
+ return self._get_token(auth)
+
+ @property
+ def service_catalog(self):
+ # NOTE(jamielennox): This is ugly and should be deprecated.
+ auth = self.auth or self.session.auth
+
+ if isinstance(auth, base.BaseIdentityPlugin):
+ return auth.get_access(self.session).service_catalog
+
+ raise AttributeError('There is no service catalog for this type of '
+ 'auth plugin.')
+
+
+class HTTPClient(object):
USER_AGENT = 'python-cinderclient'
@@ -336,6 +310,9 @@ class HTTPClient(CinderClientMixin):
def delete(self, url, **kwargs):
return self._cs_request(url, 'DELETE', **kwargs)
+ def get_volume_api_version_from_endpoint(self):
+ return get_volume_api_from_url(self.management_url)
+
def _extract_service_catalog(self, url, resp, body, extract_token=True):
"""See what the auth service told us and process the response.
We may get redirected to another site, fail or actually get
@@ -504,51 +481,40 @@ def _construct_http_client(username=None, password=None, project_id=None,
auth_system='keystone', auth_plugin=None,
cacert=None, tenant_id=None,
session=None,
- auth=None):
-
- # Don't use sessions if third party plugin is used
- if session and not auth_plugin:
-
- # If auth pluggin is specified use that pluggin
- session.auth = auth or session.auth
-
- if isinstance(session.auth, v3_auth.Password):
- # In v3 and v2 interace names are different
- interface_map = {"publicURL": "public",
- "adminURL": "admin"}
-
- endpoint_type = interface_map[endpoint_type]
+ auth=None,
+ **kwargs):
+ if session:
+ kwargs.setdefault('interface', endpoint_type)
return SessionClient(session=session,
auth=auth,
- interface=endpoint_type,
service_type=service_type,
service_name=service_name,
region_name=region_name,
- http_log_debug=http_log_debug)
-
- # FIXME(jamielennox): username and password are now optional. Need
- # to test that they were provided in this mode.
- return HTTPClient(username,
- password,
- projectid=project_id,
- auth_url=auth_url,
- insecure=insecure,
- timeout=timeout,
- tenant_id=tenant_id,
- proxy_token=proxy_token,
- proxy_tenant_id=proxy_tenant_id,
- region_name=region_name,
- endpoint_type=endpoint_type,
- service_type=service_type,
- service_name=service_name,
- volume_service_name=volume_service_name,
- retries=retries,
- http_log_debug=http_log_debug,
- cacert=cacert,
- auth_system=auth_system,
- auth_plugin=auth_plugin,
- )
+ **kwargs)
+ else:
+ # FIXME(jamielennox): username and password are now optional. Need
+ # to test that they were provided in this mode.
+ return HTTPClient(username,
+ password,
+ projectid=project_id,
+ auth_url=auth_url,
+ insecure=insecure,
+ timeout=timeout,
+ tenant_id=tenant_id,
+ proxy_token=proxy_token,
+ proxy_tenant_id=proxy_tenant_id,
+ region_name=region_name,
+ endpoint_type=endpoint_type,
+ service_type=service_type,
+ service_name=service_name,
+ volume_service_name=volume_service_name,
+ retries=retries,
+ http_log_debug=http_log_debug,
+ cacert=cacert,
+ auth_system=auth_system,
+ auth_plugin=auth_plugin,
+ )
def get_client_class(version):
diff --git a/cinderclient/v1/client.py b/cinderclient/v1/client.py
index 9b375b8..c11a954 100644
--- a/cinderclient/v1/client.py
+++ b/cinderclient/v1/client.py
@@ -44,14 +44,14 @@ class Client(object):
"""
- def __init__(self, username, api_key, project_id=None, auth_url='',
- insecure=False, timeout=None, tenant_id=None,
+ def __init__(self, username=None, api_key=None, project_id=None,
+ auth_url='', insecure=False, timeout=None, tenant_id=None,
proxy_tenant_id=None, proxy_token=None, region_name=None,
endpoint_type='publicURL', extensions=None,
service_type='volume', service_name=None,
- volume_service_name=None, retries=None,
- http_log_debug=False, cacert=None,
- auth_system='keystone', auth_plugin=None, session=None):
+ volume_service_name=None, retries=None, http_log_debug=False,
+ cacert=None, auth_system='keystone', auth_plugin=None,
+ session=None, **kwargs):
# FIXME(comstud): Rename the api_key argument above when we
# know it's not being used as keyword argument
password = api_key
@@ -100,7 +100,8 @@ class Client(object):
cacert=cacert,
auth_system=auth_system,
auth_plugin=auth_plugin,
- session=session)
+ session=session,
+ **kwargs)
def authenticate(self):
"""
diff --git a/cinderclient/v2/client.py b/cinderclient/v2/client.py
index a4016db..a7edfbb 100644
--- a/cinderclient/v2/client.py
+++ b/cinderclient/v2/client.py
@@ -42,15 +42,14 @@ class Client(object):
...
"""
- def __init__(self, username, api_key, project_id=None, auth_url='',
- insecure=False, timeout=None, tenant_id=None,
+ def __init__(self, username=None, api_key=None, project_id=None,
+ auth_url='', insecure=False, timeout=None, tenant_id=None,
proxy_tenant_id=None, proxy_token=None, region_name=None,
endpoint_type='publicURL', extensions=None,
service_type='volumev2', service_name=None,
- volume_service_name=None, retries=None,
- http_log_debug=False, cacert=None,
- auth_system='keystone', auth_plugin=None,
- session=None):
+ volume_service_name=None, retries=None, http_log_debug=False,
+ cacert=None, auth_system='keystone', auth_plugin=None,
+ session=None, **kwargs):
# FIXME(comstud): Rename the api_key argument above when we
# know it's not being used as keyword argument
password = api_key
@@ -99,7 +98,8 @@ class Client(object):
cacert=cacert,
auth_system=auth_system,
auth_plugin=auth_plugin,
- session=session)
+ session=session,
+ **kwargs)
def authenticate(self):
"""Authenticate against the server.