f38c51c1b9
* Add compatibility for plugin v2 interface removed from osc-lib * ClientManager.is_network_endpoint_enabled() is wrapper for new is_service_available() Change-Id: I6f26ce9e4d0702f50c7949bacfbeeb0f98cddb5d
188 lines
6.4 KiB
Python
188 lines
6.4 KiB
Python
# Copyright 2012-2013 OpenStack Foundation
|
|
#
|
|
# 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.
|
|
#
|
|
|
|
"""Manage access to the clients, including authenticating when needed."""
|
|
|
|
import logging
|
|
import pkg_resources
|
|
import sys
|
|
|
|
from keystoneauth1.loading import base
|
|
from osc_lib.api import auth
|
|
from osc_lib import clientmanager
|
|
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
PLUGIN_MODULES = []
|
|
|
|
USER_AGENT = 'python-openstackclient'
|
|
|
|
|
|
# NOTE(dtroyer): Bringing back select_auth_plugin() and build_auth_params()
|
|
# temporarily because osc-lib 0.3.0 removed it a wee bit early
|
|
def select_auth_plugin(options):
|
|
"""Pick an auth plugin based on --os-auth-type or other options"""
|
|
|
|
auth_plugin_name = None
|
|
|
|
# Do the token/url check first as this must override the default
|
|
# 'password' set by os-client-config
|
|
# Also, url and token are not copied into o-c-c's auth dict (yet?)
|
|
if options.auth.get('url') and options.auth.get('token'):
|
|
# service token authentication
|
|
auth_plugin_name = 'token_endpoint'
|
|
elif options.auth_type in auth.PLUGIN_LIST:
|
|
# A direct plugin name was given, use it
|
|
auth_plugin_name = options.auth_type
|
|
elif options.auth.get('username'):
|
|
if options.identity_api_version == '3':
|
|
auth_plugin_name = 'v3password'
|
|
elif options.identity_api_version.startswith('2'):
|
|
auth_plugin_name = 'v2password'
|
|
else:
|
|
# let keystoneauth figure it out itself
|
|
auth_plugin_name = 'password'
|
|
elif options.auth.get('token'):
|
|
if options.identity_api_version == '3':
|
|
auth_plugin_name = 'v3token'
|
|
elif options.identity_api_version.startswith('2'):
|
|
auth_plugin_name = 'v2token'
|
|
else:
|
|
# let keystoneauth figure it out itself
|
|
auth_plugin_name = 'token'
|
|
else:
|
|
# The ultimate default is similar to the original behaviour,
|
|
# but this time with version discovery
|
|
auth_plugin_name = 'password'
|
|
LOG.debug("Auth plugin %s selected", auth_plugin_name)
|
|
return auth_plugin_name
|
|
|
|
|
|
def build_auth_params(auth_plugin_name, cmd_options):
|
|
if auth_plugin_name:
|
|
LOG.debug('auth_type: %s', auth_plugin_name)
|
|
auth_plugin_loader = base.get_plugin_loader(auth_plugin_name)
|
|
auth_params = {
|
|
opt.dest: opt.default
|
|
for opt in base.get_plugin_options(auth_plugin_name)
|
|
}
|
|
auth_params.update(dict(cmd_options.auth))
|
|
# grab tenant from project for v2.0 API compatibility
|
|
if auth_plugin_name.startswith("v2"):
|
|
if 'project_id' in auth_params:
|
|
auth_params['tenant_id'] = auth_params['project_id']
|
|
del auth_params['project_id']
|
|
if 'project_name' in auth_params:
|
|
auth_params['tenant_name'] = auth_params['project_name']
|
|
del auth_params['project_name']
|
|
else:
|
|
LOG.debug('no auth_type')
|
|
# delay the plugin choice, grab every option
|
|
auth_plugin_loader = None
|
|
auth_params = dict(cmd_options.auth)
|
|
plugin_options = set(
|
|
[o.replace('-', '_') for o in auth.get_options_list()]
|
|
)
|
|
for option in plugin_options:
|
|
LOG.debug('fetching option %s', option)
|
|
auth_params[option] = getattr(cmd_options.auth, option, None)
|
|
return (auth_plugin_loader, auth_params)
|
|
|
|
|
|
class ClientManager(clientmanager.ClientManager):
|
|
"""Manages access to API clients, including authentication
|
|
|
|
Wrap osc_lib's ClientManager to maintain compatibility for the existing
|
|
plugin V2 interface. Some currently private attributes become public
|
|
in osc-lib so we need to maintain a transition period.
|
|
"""
|
|
|
|
# A simple incrementing version for the plugin to know what is available
|
|
PLUGIN_INTERFACE_VERSION = "2"
|
|
|
|
def __init__(
|
|
self,
|
|
cli_options=None,
|
|
api_version=None,
|
|
pw_func=None,
|
|
):
|
|
super(ClientManager, self).__init__(
|
|
cli_options=cli_options,
|
|
api_version=api_version,
|
|
pw_func=pw_func,
|
|
)
|
|
|
|
# TODO(dtroyer): For compatibility; mark this for removal when plugin
|
|
# interface v2 is removed
|
|
self._region_name = self.region_name
|
|
self._interface = self.interface
|
|
self._cacert = self.cacert
|
|
self._insecure = not self.verify
|
|
|
|
def is_network_endpoint_enabled(self):
|
|
"""Check if the network endpoint is enabled"""
|
|
|
|
# NOTE(dtroyer): is_service_available() can also return None if
|
|
# there is no Service Catalog, callers here are
|
|
# not expecting that so fold None into True to
|
|
# use Network API by default
|
|
return self.is_service_available('network') is not False
|
|
|
|
|
|
# Plugin Support
|
|
|
|
def get_plugin_modules(group):
|
|
"""Find plugin entry points"""
|
|
mod_list = []
|
|
for ep in pkg_resources.iter_entry_points(group):
|
|
LOG.debug('Found plugin %r', ep.name)
|
|
|
|
__import__(ep.module_name)
|
|
module = sys.modules[ep.module_name]
|
|
mod_list.append(module)
|
|
init_func = getattr(module, 'Initialize', None)
|
|
if init_func:
|
|
init_func('x')
|
|
|
|
# Add the plugin to the ClientManager
|
|
setattr(
|
|
ClientManager,
|
|
module.API_NAME,
|
|
clientmanager.ClientCache(
|
|
getattr(sys.modules[ep.module_name], 'make_client', None)
|
|
),
|
|
)
|
|
return mod_list
|
|
|
|
|
|
def build_plugin_option_parser(parser):
|
|
"""Add plugin options to the parser"""
|
|
|
|
# Loop through extensions to get parser additions
|
|
for mod in PLUGIN_MODULES:
|
|
parser = mod.build_option_parser(parser)
|
|
return parser
|
|
|
|
|
|
# Get list of base plugin modules
|
|
PLUGIN_MODULES = get_plugin_modules(
|
|
'openstack.cli.base',
|
|
)
|
|
# Append list of external plugin modules
|
|
PLUGIN_MODULES.extend(get_plugin_modules(
|
|
'openstack.cli.extension',
|
|
))
|