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
This commit is contained in:
parent
8e87c0b600
commit
84af49ce97
@ -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
|
||||
|
||||
|
||||
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)
|
||||
_VALID_VERSIONS = ['v1', 'v2']
|
||||
|
||||
|
||||
class SessionClient(CinderClientMixin):
|
||||
def get_volume_api_from_url(url):
|
||||
scheme, netloc, path, query, frag = urlparse.urlsplit(url)
|
||||
components = path.split("/")
|
||||
|
||||
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
|
||||
for version in _VALID_VERSIONS:
|
||||
if version in components:
|
||||
return version[1:]
|
||||
|
||||
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
|
||||
msg = "Invalid client version '%s'. must be one of: %s" % (
|
||||
(version, ', '.join(valid_versions)))
|
||||
raise exceptions.UnsupportedVersion(msg)
|
||||
|
||||
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)
|
||||
|
||||
def request(self, url, method, **kwargs):
|
||||
class SessionClient(adapter.LegacyJsonAdapter):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
kwargs.setdefault('user_agent', 'python-cinderclient')
|
||||
kwargs.setdefault('auth', self.auth)
|
||||
kwargs.setdefault('service_type', 'volume')
|
||||
super(SessionClient, self).__init__(**kwargs)
|
||||
|
||||
def request(self, *args, **kwargs):
|
||||
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
|
||||
|
||||
return resp, body
|
||||
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)
|
||||
|
||||
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(CinderClientMixin):
|
||||
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):
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user