Move legacy client constructors to mixin
Remove them from the main class to make them slightly less obvious. Change-Id: I72b32d992c71777155c22b51ce4c7868e19d44c1
This commit is contained in:
parent
103bc13862
commit
1c0a95ba8f
197
shade/_legacy_clients.py
Normal file
197
shade/_legacy_clients.py
Normal file
@ -0,0 +1,197 @@
|
||||
# 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.
|
||||
import importlib
|
||||
import warnings
|
||||
|
||||
from os_client_config import constructors
|
||||
|
||||
from shade import _utils
|
||||
|
||||
|
||||
class LegacyClientFactoryMixin(object):
|
||||
"""Mixin Class containing factory functions for legacy client objects.
|
||||
|
||||
Methods in this class exist for backwards compatibility so will not go
|
||||
away any time - but they are all things whose use is discouraged. They're
|
||||
in a mixin to unclutter the main class file.
|
||||
"""
|
||||
|
||||
def _create_legacy_client(
|
||||
self, client, service, deprecated=True,
|
||||
module_name=None, **kwargs):
|
||||
if client not in self._legacy_clients:
|
||||
if deprecated:
|
||||
self._deprecated_import_check(client)
|
||||
if module_name:
|
||||
constructors.get_constructor_mapping()[service] = module_name
|
||||
self._legacy_clients[client] = self._get_client(service, **kwargs)
|
||||
return self._legacy_clients[client]
|
||||
|
||||
def _deprecated_import_check(self, client):
|
||||
module_name = '{client}client'
|
||||
warnings.warn(
|
||||
'Using shade to get a {module_name} object is deprecated. If you'
|
||||
' need a {module_name} object, please use make_legacy_client in'
|
||||
' os-client-config instead'.format(module_name=module_name))
|
||||
try:
|
||||
importlib.import_module(module_name)
|
||||
except ImportError:
|
||||
self.log.error(
|
||||
'{module_name} is no longer a dependency of shade. You need to'
|
||||
' install python-{module_name} directly.'.format(
|
||||
module_name=module_name))
|
||||
raise
|
||||
|
||||
@property
|
||||
def trove_client(self):
|
||||
return self._create_legacy_client('trove', 'database')
|
||||
|
||||
@property
|
||||
def magnum_client(self):
|
||||
return self._create_legacy_client('magnum', 'container-infra')
|
||||
|
||||
@property
|
||||
def neutron_client(self):
|
||||
return self._create_or_return_legacy_client('neutron', 'network')
|
||||
|
||||
@property
|
||||
def nova_client(self):
|
||||
return self._create_legacy_client(
|
||||
'nova', 'compute', version='2.0', deprecated=False)
|
||||
|
||||
@property
|
||||
def glance_client(self):
|
||||
return self._create_legacy_client('glance', 'image')
|
||||
|
||||
@property
|
||||
def heat_client(self):
|
||||
return self._create_legacy_client('heat', 'orchestration')
|
||||
|
||||
@property
|
||||
def swift_client(self):
|
||||
return self._create_legacy_client('swift', 'object-store')
|
||||
|
||||
@property
|
||||
def cinder_client(self):
|
||||
return self._create_legacy_client('cinder', 'volume')
|
||||
|
||||
@property
|
||||
def designate_client(self):
|
||||
return self._create_legacy_client('designate', 'dns', deprecated=False)
|
||||
|
||||
@property
|
||||
def keystone_client(self):
|
||||
return self._create_legacy_client(
|
||||
'keystone', 'identity', deprecated=False)
|
||||
|
||||
# Set the ironic API microversion to a known-good
|
||||
# supported/tested with the contents of shade.
|
||||
#
|
||||
# NOTE(TheJulia): Defaulted to version 1.6 as the ironic
|
||||
# state machine changes which will increment the version
|
||||
# and break an automatic transition of an enrolled node
|
||||
# to an available state. Locking the version is intended
|
||||
# to utilize the original transition until shade supports
|
||||
# calling for node inspection to allow the transition to
|
||||
# take place automatically.
|
||||
# NOTE(mordred): shade will handle microversions more
|
||||
# directly in the REST layer. This microversion property
|
||||
# will never change. When we implement REST, we should
|
||||
# start at 1.6 since that's what we've been requesting
|
||||
# via ironic_client
|
||||
@property
|
||||
def ironic_api_microversion(self):
|
||||
# NOTE(mordred) Abuse _legacy_clients to only show
|
||||
# this warning once
|
||||
if 'ironic-microversion' not in self._legacy_clients:
|
||||
warnings.warn(
|
||||
'shade is transitioning to direct REST calls which'
|
||||
' will handle microversions with no action needed'
|
||||
' on the part of the user. The ironic_api_microversion'
|
||||
' property is only used by the legacy ironic_client'
|
||||
' constructor and will never change. If you are using'
|
||||
' it for any reason, either switch to just using'
|
||||
' shade ironic-related API calls, or use os-client-config'
|
||||
' make_legacy_client directly and pass os_ironic_api_version'
|
||||
' to it as an argument. It is highly recommended to'
|
||||
' stop using this property.')
|
||||
self._legacy_clients['ironic-microversion'] = True
|
||||
return self._get_legacy_ironic_microversion()
|
||||
|
||||
def _get_legacy_ironic_microversion(self):
|
||||
return '1.6'
|
||||
|
||||
@property
|
||||
def ironic_client(self):
|
||||
return self._create_legacy_client(
|
||||
'ironic', 'baremetal', deprecated=False,
|
||||
module_name='ironicclient.client.Client',
|
||||
os_ironic_api_version=self._get_legacy_ironic_microversion())
|
||||
|
||||
def _get_swift_kwargs(self):
|
||||
auth_version = self.cloud_config.get_api_version('identity')
|
||||
auth_args = self.cloud_config.config.get('auth', {})
|
||||
os_options = {'auth_version': auth_version}
|
||||
if auth_version == '2.0':
|
||||
os_options['os_tenant_name'] = auth_args.get('project_name')
|
||||
os_options['os_tenant_id'] = auth_args.get('project_id')
|
||||
else:
|
||||
os_options['os_project_name'] = auth_args.get('project_name')
|
||||
os_options['os_project_id'] = auth_args.get('project_id')
|
||||
|
||||
for key in (
|
||||
'username',
|
||||
'password',
|
||||
'auth_url',
|
||||
'user_id',
|
||||
'project_domain_id',
|
||||
'project_domain_name',
|
||||
'user_domain_id',
|
||||
'user_domain_name'):
|
||||
os_options['os_{key}'.format(key=key)] = auth_args.get(key)
|
||||
return os_options
|
||||
|
||||
@property
|
||||
def swift_service(self):
|
||||
suppress_warning = 'swift-service' not in self._legacy_clients
|
||||
return self.make_swift_service_object(suppress_warning)
|
||||
|
||||
def make_swift_service(self, suppress_warning=False):
|
||||
# NOTE(mordred): Not using helper functions because the
|
||||
# error message needs to be different
|
||||
if not suppress_warning:
|
||||
warnings.warn(
|
||||
'Using shade to get a SwiftService object is deprecated. shade'
|
||||
' will automatically do the things SwiftServices does as part'
|
||||
' of the normal object resource calls. If you are having'
|
||||
' trouble using those such that you still need to use'
|
||||
' SwiftService, please file a bug with shade.'
|
||||
' If you understand the issues and want to make this warning'
|
||||
' go away, use cloud.make_swift_service(True) instead of'
|
||||
' cloud.swift_service')
|
||||
# Abuse self._legacy_clients so that we only give the warning
|
||||
# once. We don't cache SwiftService objects.
|
||||
self._legacy_clients['swift-service'] = True
|
||||
try:
|
||||
import swiftclient.service
|
||||
except ImportError:
|
||||
self.log.error(
|
||||
'swiftclient is no longer a dependency of shade. You need to'
|
||||
' install python-swiftclient directly.')
|
||||
with _utils.shade_exceptions("Error constructing SwiftService"):
|
||||
endpoint = self.get_session_endpoint(
|
||||
service_key='object-store')
|
||||
options = dict(os_auth_token=self.auth_token,
|
||||
os_storage_url=endpoint,
|
||||
os_region_name=self.region_name)
|
||||
options.update(self._get_swift_kwargs())
|
||||
return swiftclient.service.SwiftService(options=options)
|
@ -13,7 +13,6 @@
|
||||
import collections
|
||||
import functools
|
||||
import hashlib
|
||||
import importlib
|
||||
import ipaddress
|
||||
import json
|
||||
import jsonpatch
|
||||
@ -40,6 +39,7 @@ from shade import _adapter
|
||||
from shade._heat import event_utils
|
||||
from shade._heat import template_utils
|
||||
from shade import _log
|
||||
from shade import _legacy_clients
|
||||
from shade import _normalize
|
||||
from shade import meta
|
||||
from shade import task_manager
|
||||
@ -92,7 +92,9 @@ def _no_pending_stacks(stacks):
|
||||
return True
|
||||
|
||||
|
||||
class OpenStackCloud(_normalize.Normalizer):
|
||||
class OpenStackCloud(
|
||||
_normalize.Normalizer,
|
||||
_legacy_clients.LegacyClientFactoryMixin):
|
||||
"""Represent a connection to an OpenStack Cloud.
|
||||
|
||||
OpenStackCloud is the entry point for all cloud operations, regardless
|
||||
@ -296,18 +298,7 @@ class OpenStackCloud(_normalize.Normalizer):
|
||||
|
||||
self._keystone_session = None
|
||||
|
||||
self._cinder_client = None
|
||||
self._glance_client = None
|
||||
self._glance_endpoint = None
|
||||
self._heat_client = None
|
||||
self._keystone_client = None
|
||||
self._neutron_client = None
|
||||
self._nova_client = None
|
||||
self._trove_client = None
|
||||
self._designate_client = None
|
||||
self._magnum_client = None
|
||||
self._swift_client = None
|
||||
|
||||
self._legacy_clients = {}
|
||||
self._raw_clients = {}
|
||||
|
||||
self._local_ipv6 = _utils.localhost_supports_ipv6()
|
||||
@ -543,134 +534,6 @@ class OpenStackCloud(_normalize.Normalizer):
|
||||
new_resource = _utils._dictify_resource(resource)
|
||||
return pprint.pformat(new_resource)
|
||||
|
||||
# LEGACY CLIENT IMPORTS
|
||||
def _deprecated_import_check(self, module_name):
|
||||
warnings.warn(
|
||||
'Using shade to get a {module_name} object is deprecated. If you'
|
||||
' need a {module_name} object, please use make_legacy_client in'
|
||||
' os-client-config instead'.format(module_name=module_name))
|
||||
try:
|
||||
importlib.import_module(module_name)
|
||||
except ImportError:
|
||||
self.log.error(
|
||||
'{module_name} is no longer a dependency of shade. You need to'
|
||||
' install python-{module_name} directly.'.format(
|
||||
module_name=module_name))
|
||||
raise
|
||||
|
||||
@property
|
||||
def trove_client(self):
|
||||
if self._trove_client is None:
|
||||
_deprecated_import_check('troveclient')
|
||||
self._trove_client = self._get_client('database')
|
||||
return self._trove_client
|
||||
|
||||
@property
|
||||
def magnum_client(self):
|
||||
if self._magnum_client is None:
|
||||
_deprecated_import_check('magnumclient')
|
||||
self._magnum_client = self._get_client('container-infra')
|
||||
return self._magnum_client
|
||||
|
||||
@property
|
||||
def neutron_client(self):
|
||||
if self._neutron_client is None:
|
||||
_deprecated_import_check('neutronclient')
|
||||
self._neutron_client = self._get_client('network')
|
||||
return self._neutron_client
|
||||
|
||||
@property
|
||||
def nova_client(self):
|
||||
if self._nova_client is None:
|
||||
self._nova_client = self._get_client('compute', version='2.0')
|
||||
return self._nova_client
|
||||
|
||||
@property
|
||||
def glance_client(self):
|
||||
if self._glance_client is None:
|
||||
_deprecated_import_check('glanceclient')
|
||||
self._glance_client = self._get_client('image')
|
||||
return self._glance_client
|
||||
|
||||
@property
|
||||
def heat_client(self):
|
||||
if self._heat_client is None:
|
||||
_deprecated_import_check('heatclient')
|
||||
self._heat_client = self._get_client('orchestration')
|
||||
return self._heat_client
|
||||
|
||||
@property
|
||||
def swift_client(self):
|
||||
if self._swift_client is None:
|
||||
_deprecated_import_check('swiftclient')
|
||||
self._swift_client = self._get_client('object-store')
|
||||
return self._swift_client
|
||||
|
||||
def _get_swift_kwargs(self):
|
||||
auth_version = self.cloud_config.get_api_version('identity')
|
||||
auth_args = self.cloud_config.config.get('auth', {})
|
||||
os_options = {'auth_version': auth_version}
|
||||
if auth_version == '2.0':
|
||||
os_options['os_tenant_name'] = auth_args.get('project_name')
|
||||
os_options['os_tenant_id'] = auth_args.get('project_id')
|
||||
else:
|
||||
os_options['os_project_name'] = auth_args.get('project_name')
|
||||
os_options['os_project_id'] = auth_args.get('project_id')
|
||||
|
||||
for key in (
|
||||
'username',
|
||||
'password',
|
||||
'auth_url',
|
||||
'user_id',
|
||||
'project_domain_id',
|
||||
'project_domain_name',
|
||||
'user_domain_id',
|
||||
'user_domain_name'):
|
||||
os_options['os_{key}'.format(key=key)] = auth_args.get(key)
|
||||
return os_options
|
||||
|
||||
@property
|
||||
def swift_service(self):
|
||||
# NOTE(mordred): Not using deprecated_client_check because the
|
||||
# error message needs to be different
|
||||
try:
|
||||
import swiftclient.service
|
||||
except ImportError:
|
||||
self.log.error(
|
||||
'swiftclient is no longer a dependency of shade. You need to'
|
||||
' install python-swiftclient directly.')
|
||||
with _utils.shade_exceptions("Error constructing "
|
||||
"swift client"):
|
||||
endpoint = self.get_session_endpoint(
|
||||
service_key='object-store')
|
||||
options = dict(os_auth_token=self.auth_token,
|
||||
os_storage_url=endpoint,
|
||||
os_region_name=self.region_name)
|
||||
options.update(self._get_swift_kwargs())
|
||||
return swiftclient.service.SwiftService(options=options)
|
||||
|
||||
@property
|
||||
def cinder_client(self):
|
||||
if self._cinder_client is None:
|
||||
_deprecated_import_check('cinderclient')
|
||||
self._cinder_client = self._get_client('volume')
|
||||
return self._cinder_client
|
||||
|
||||
@property
|
||||
def designate_client(self):
|
||||
# Note: Explicit constructor is needed until occ 1.27.0
|
||||
import designateclient.client # flake8: noqa
|
||||
if self._designate_client is None:
|
||||
self._designate_client = self._get_client(
|
||||
'dns', designateclient.client.Client)
|
||||
return self._designate_client
|
||||
|
||||
@property
|
||||
def keystone_client(self):
|
||||
if self._keystone_client is None:
|
||||
self._keystone_client = self._get_client('identity')
|
||||
return self._keystone_client
|
||||
|
||||
@property
|
||||
def keystone_session(self):
|
||||
if self._keystone_session is None:
|
||||
|
@ -13,7 +13,6 @@
|
||||
import datetime
|
||||
import jsonpatch
|
||||
|
||||
from ironicclient import client as ironic_client
|
||||
from ironicclient import exceptions as ironic_exceptions
|
||||
from novaclient import exceptions as nova_exceptions
|
||||
|
||||
@ -32,30 +31,6 @@ class OperatorCloud(openstackcloud.OpenStackCloud):
|
||||
See the :class:`OpenStackCloud` class for a description of most options.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(OperatorCloud, self).__init__(*args, **kwargs)
|
||||
self._ironic_client = None
|
||||
|
||||
# Set the ironic API microversion to a known-good
|
||||
# supported/tested with the contents of shade.
|
||||
#
|
||||
# Note(TheJulia): Defaulted to version 1.6 as the ironic
|
||||
# state machine changes which will increment the version
|
||||
# and break an automatic transition of an enrolled node
|
||||
# to an available state. Locking the version is intended
|
||||
# to utilize the original transition until shade supports
|
||||
# calling for node inspection to allow the transition to
|
||||
# take place automatically.
|
||||
ironic_api_microversion = '1.6'
|
||||
|
||||
@property
|
||||
def ironic_client(self):
|
||||
if self._ironic_client is None:
|
||||
self._ironic_client = self._get_client(
|
||||
'baremetal', ironic_client.Client,
|
||||
os_ironic_api_version=self.ironic_api_microversion)
|
||||
return self._ironic_client
|
||||
|
||||
def list_nics(self):
|
||||
with _utils.shade_exceptions("Error fetching machine port list"):
|
||||
return self.manager.submit_task(_tasks.MachinePortList())
|
||||
|
Loading…
x
Reference in New Issue
Block a user