Files
deb-python-ceilometerclient/ceilometerclient/client.py
Fabio Giannetti 6082ae31ed Update python-ceilometerclient to support Keystone V3 API
Keystone is now deprecating the V2 API in favor of the V3 API.
The ceilometer client is now using the keystone session to
delegate the discovery of the version that is going to be used,
this eliminates the need of updating the client every time there
is a new API version.

DocImpact

blueprint support-keystone-v3-api

Change-Id: I6ebacce7adf70f24bdede9b920853ab9851071cf
2014-06-26 09:39:38 -07:00

217 lines
8.4 KiB
Python

# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from keystoneclient.auth.identity import v2 as v2_auth
from keystoneclient.auth.identity import v3 as v3_auth
from keystoneclient import discover
from keystoneclient import session
import six
from ceilometerclient.common import utils
from ceilometerclient import exc
def _get_keystone_session(**kwargs):
# TODO(fabgia): the heavy lifting here should be really done by Keystone.
# Unfortunately Keystone does not support a richer method to perform
# discovery and return a single viable URL. A bug against Keystone has
# been filed: https://bugs.launchpad.net/pyhton-keystoneclient/+bug/1330677
# first create a Keystone session
cacert = kwargs.pop('cacert', None)
cert = kwargs.pop('cert', None)
key = kwargs.pop('key', None)
insecure = kwargs.pop('insecure', False)
auth_url = kwargs.pop('auth_url', None)
project_id = kwargs.pop('project_id', None)
project_name = kwargs.pop('project_name', None)
if insecure:
verify = False
else:
verify = cacert or True
if cert and key:
# passing cert and key together is deprecated in favour of the
# requests lib form of having the cert and key as a tuple
cert = (cert, key)
# create the keystone client session
ks_session = session.Session(verify=verify, cert=cert)
try:
# discover the supported keystone versions using the auth endpoint url
ks_discover = discover.Discover(session=ks_session, auth_url=auth_url)
# Determine which authentication plugin to use.
v2_auth_url = ks_discover.url_for('2.0')
v3_auth_url = ks_discover.url_for('3.0')
except Exception:
raise exc.CommandError('Unable to determine the Keystone version '
'to authenticate with using the given '
'auth_url: %s' % auth_url)
username = kwargs.pop('username', None)
user_id = kwargs.pop('user_id', None)
user_domain_name = kwargs.pop('user_domain_name', None)
user_domain_id = kwargs.pop('user_domain_id', None)
project_domain_name = kwargs.pop('project_domain_name', None)
project_domain_id = kwargs.pop('project_domain_id', None)
auth = None
if v3_auth_url and v2_auth_url:
# the auth_url does not have the versions specified
# e.g. http://no.where:5000
# Keystone will return both v2 and v3 as viable options
# but we need to decide based on the arguments passed
# what version is callable
if (user_domain_name or user_domain_id or project_domain_name or
project_domain_id):
# domain is supported only in v3
auth = v3_auth.Password(
v3_auth_url,
username=username,
user_id=user_id,
user_domain_name=user_domain_name,
user_domain_id=user_domain_id,
project_domain_name=project_domain_name,
project_domain_id=project_domain_id,
**kwargs)
else:
# no domain, then use v2
auth = v2_auth.Password(
v2_auth_url,
username,
kwargs.pop('password', None),
tenant_id=project_id,
tenant_name=project_name)
elif v3_auth_url:
# the auth_url as v3 specified
# e.g. http://no.where:5000/v3
# Keystone will return only v3 as viable option
auth = v3_auth.Password(
v3_auth_url,
username=username,
user_id=user_id,
user_domain_name=user_domain_name,
user_domain_id=user_domain_id,
project_domain_name=project_domain_name,
project_domain_id=project_domain_id,
**kwargs)
elif v2_auth_url:
# the auth_url as v2 specified
# e.g. http://no.where:5000/v2.0
# Keystone will return only v2 as viable option
auth = v2_auth.Password(
v2_auth_url,
username,
kwargs.pop('password', None),
tenant_id=project_id,
tenant_name=project_name)
else:
raise exc.CommandError('Unable to determine the Keystone version '
'to authenticate with using the given '
'auth_url.')
ks_session.auth = auth
return ks_session
def _get_endpoint(ks_session, **kwargs):
"""Get an endpoint using the provided keystone session."""
# set service specific endpoint types
endpoint_type = kwargs.get('endpoint_type') or 'publicURL'
service_type = kwargs.get('service_type') or 'metering'
endpoint = ks_session.get_endpoint(service_type=service_type,
endpoint_type=endpoint_type,
region_name=kwargs.get('region_name'))
return endpoint
def get_client(api_version, **kwargs):
"""Get an authtenticated client, based on the credentials
in the keyword args.
:param api_version: the API version to use ('1' or '2')
:param kwargs: keyword args containing credentials, either:
* os_auth_token: pre-existing token to re-use
* ceilometer_url: ceilometer API endpoint
or:
* os_username: name of user
* os_password: user's password
* os_user_id: user's id
* os_user_domain_id: the domain id of the user
* os_user_domain_name: the domain name of the user
* os_project_id: the user project id
* os_tenant_id: V2 alternative to os_project_id
* os_project_name: the user project name
* os_tenant_name: V2 alternative to os_project_name
* os_project_domain_name: domain name for the user project
* os_project_domain_id: domain id for the user project
* os_auth_url: endpoint to authenticate against
* os_cert|os_cacert: path of CA TLS certificate
* os_key: SSL private key
* insecure: allow insecure SSL (no cert verification)
"""
token = kwargs.get('os_auth_token')
if token and not six.callable(token):
token = lambda: kwargs.get('os_auth_token')
if token and kwargs.get('ceilometer_url'):
endpoint = kwargs.get('ceilometer_url')
else:
project_id = kwargs.get('os_project_id') or kwargs.get('os_tenant_id')
project_name = (kwargs.get('os_project_name') or
kwargs.get('os_tenant_name'))
ks_kwargs = {
'username': kwargs.get('os_username'),
'password': kwargs.get('os_password'),
'user_id': kwargs.get('os_user_id'),
'user_domain_id': kwargs.get('os_user_domain_id'),
'user_domain_name': kwargs.get('os_user_domain_name'),
'project_id': project_id,
'project_name': project_name,
'project_domain_name': kwargs.get('os_project_domain_name'),
'project_domain_id': kwargs.get('os_project_domain_id'),
'auth_url': kwargs.get('os_auth_url'),
'cacert': kwargs.get('os_cacert'),
'cert': kwargs.get('os_cert'),
'key': kwargs.get('os_key'),
'insecure': kwargs.get('insecure')
}
# retrieve session
ks_session = _get_keystone_session(**ks_kwargs)
token = token or (lambda: ks_session.get_token())
endpoint = kwargs.get('ceilometer_url') or \
_get_endpoint(ks_session, **ks_kwargs)
cli_kwargs = {
'token': token,
'insecure': kwargs.get('insecure'),
'timeout': kwargs.get('timeout'),
'cacert': kwargs.get('os_cacert'),
'cert_file': kwargs.get('os_cert'),
'key_file': kwargs.get('os_key')
}
return Client(api_version, endpoint, **cli_kwargs)
def Client(version, *args, **kwargs):
module = utils.import_versioned_module(version, 'client')
client_class = getattr(module, 'Client')
return client_class(*args, **kwargs)