Merge Connection and OpenStackCloud

There's no good reason to have the shade functions in a cloud attribute.
Go ahead and dive all the way in and make OpenStackCloud a mixin class.

There was one wrapped exception that got removed and thus the test to test
that we were wrapping it.

Change-Id: Iebd80fe5bc511ea879ea71aa88ce7d79c5e8fa58
This commit is contained in:
Monty Taylor 2018-01-30 16:22:20 -06:00
parent 8483e1b139
commit 0a6083b876
No known key found for this signature in database
GPG Key ID: 7BAE94BC7141A594
22 changed files with 227 additions and 299 deletions

View File

@ -24,6 +24,17 @@ already. For reference, those are:
* Plumbed Proxy use of Adapter through the Adapter subclass from shade that
uses the TaskManager to run REST calls.
* Finish migrating to Resource2 and Proxy2, rename them to Resource and Proxy.
* Merge OpenStackCloud into Connection. This should result
in being able to use the connection interact with the cloud using all three
interfaces. For instance:
.. code-block:: python
conn = connection.Connection()
servers = conn.list_servers() # High-level resource interface from shade
servers = conn.compute.servers() # SDK Service/Object Interface
response = conn.compute.get('/servers') # REST passthrough
Next steps
==========
@ -40,17 +51,6 @@ Next steps
shade integration
-----------------
* Merge OpenStackCloud into Connection. This should result
in being able to use the connection interact with the cloud using all three
interfaces. For instance:
.. code-block:: python
conn = connection.Connection()
servers = conn.list_servers() # High-level resource interface from shade
servers = conn.compute.servers() # SDK Service/Object Interface
response = conn.compute.get('/servers') # REST passthrough
* Invent some terminology that is clear and makes sense to distinguish between
the object interface that came originally from python-openstacksdk and the
interface that came from shade.

View File

@ -11,6 +11,7 @@ Connection Object
.. autoclass:: openstack.connection.Connection
:members:
:inherited-members:
Transitioning from Profile

View File

@ -56,6 +56,8 @@ def openstack_clouds(
def openstack_cloud(
config=None, strict=False, app_name=None, app_version=None, **kwargs):
# Late import while we unwind things
from openstack import connection
if not config:
config = _get_openstack_config(app_name, app_version)
try:
@ -63,4 +65,4 @@ def openstack_cloud(
except keystoneauth1.exceptions.auth_plugins.NoMatchingPlugin as e:
raise OpenStackCloudException(
"Invalid cloud configuration: {exc}".format(exc=str(e)))
return OpenStackCloud(cloud_config=cloud_region, strict=strict)
return connection.Connection(config=cloud_region, strict=strict)

View File

@ -518,8 +518,8 @@ class Normalizer(object):
ret['config_drive'] = config_drive
ret['project_id'] = project_id
ret['tenant_id'] = project_id
ret['region'] = self.region_name
ret['cloud'] = self.name
ret['region'] = self.config.region_name
ret['cloud'] = self.config.name
ret['az'] = az
for key, val in ret['properties'].items():
ret.setdefault(key, val)

View File

@ -14,8 +14,9 @@
import functools
import openstack.config
import openstack.cloud
from openstack.config import loader
from openstack import connection
from openstack import exceptions
from openstack.cloud import _utils
@ -30,24 +31,20 @@ class OpenStackInventory(object):
use_direct_get=False):
if config_files is None:
config_files = []
config = openstack.config.loader.OpenStackConfig(
config_files=openstack.config.loader.CONFIG_FILES + config_files)
config = loader.OpenStackConfig(
config_files=loader.CONFIG_FILES + config_files)
self.extra_config = config.get_extra_config(
config_key, config_defaults)
if cloud is None:
self.clouds = [
openstack.cloud.OpenStackCloud(cloud_config=cloud_region)
connection.Connection(config=cloud_region)
for cloud_region in config.get_all()
]
else:
try:
self.clouds = [
openstack.cloud.OpenStackCloud(
cloud_config=config.get_one(cloud))
]
except openstack.config.exceptions.OpenStackConfigException as e:
raise openstack.cloud.OpenStackCloudException(e)
self.clouds = [
connection.Connection(config=config.get_one(cloud))
]
if private:
for cloud in self.clouds:
@ -66,7 +63,7 @@ class OpenStackInventory(object):
# Cycle on servers
for server in cloud.list_servers(detailed=expand):
hostvars.append(server)
except openstack.cloud.OpenStackCloudException:
except exceptions.OpenStackCloudException:
# Don't fail on one particular cloud as others may work
if fail_on_cloud_config:
raise

View File

@ -317,7 +317,7 @@ def _get_interface_ip(cloud, server):
def get_groups_from_server(cloud, server, server_vars):
groups = []
region = cloud.region_name
region = cloud.config.region_name
cloud_name = cloud.name
# Create a group for the cloud

View File

@ -39,7 +39,6 @@ from six.moves import urllib
import keystoneauth1.exceptions
import keystoneauth1.session
from openstack import version as openstack_version
from openstack import _adapter
from openstack import _log
from openstack.cloud.exc import * # noqa
@ -118,65 +117,30 @@ class OpenStackCloud(_normalize.Normalizer):
and that Floating IP will be actualized either via neutron or via nova
depending on how this particular cloud has decided to arrange itself.
:param TaskManager manager: Optional task manager to use for running
OpenStack API tasks. Unless you're doing
rate limiting client side, you almost
certainly don't need this. (optional)
:param bool strict: Only return documented attributes for each resource
as per the Data Model contract. (Default False)
:param app_name: Name of the application to be appended to the user-agent
string. Optional, defaults to None.
:param app_version: Version of the application to be appended to the
user-agent string. Optional, defaults to None.
:param CloudRegion cloud_config: Cloud config object from os-client-config
In the future, this will be the only way
to pass in cloud configuration, but is
being phased in currently.
"""
def __init__(
self,
cloud_config=None,
manager=None,
strict=False,
app_name=None,
app_version=None,
use_direct_get=False,
conn=None,
**kwargs):
def __init__(self):
self.log = _log.setup_logging('openstack')
if not cloud_config:
config = openstack.config.OpenStackConfig(
app_name=app_name, app_version=app_version)
self.name = self.config.name
self.auth = self.config.get_auth_args()
self.default_interface = self.config.get_interface()
self.private = self.config.config.get('private', False)
self.image_api_use_tasks = self.config.config['image_api_use_tasks']
self.secgroup_source = self.config.config['secgroup_source']
self.force_ipv4 = self.config.force_ipv4
cloud_config = config.get_one(**kwargs)
self._external_ipv4_names = self.config.get_external_ipv4_networks()
self._internal_ipv4_names = self.config.get_internal_ipv4_networks()
self._external_ipv6_names = self.config.get_external_ipv6_networks()
self._internal_ipv6_names = self.config.get_internal_ipv6_networks()
self._nat_destination = self.config.get_nat_destination()
self._default_network = self.config.get_default_network()
self.name = cloud_config.name
self.auth = cloud_config.get_auth_args()
self.region_name = cloud_config.region_name
self.default_interface = cloud_config.get_interface()
self.private = cloud_config.config.get('private', False)
self.image_api_use_tasks = cloud_config.config['image_api_use_tasks']
self.secgroup_source = cloud_config.config['secgroup_source']
self.force_ipv4 = cloud_config.force_ipv4
self.strict_mode = strict
if manager is not None:
self.manager = manager
else:
self.manager = task_manager.TaskManager(
name=':'.join([self.name, self.region_name]))
self._external_ipv4_names = cloud_config.get_external_ipv4_networks()
self._internal_ipv4_names = cloud_config.get_internal_ipv4_networks()
self._external_ipv6_names = cloud_config.get_external_ipv6_networks()
self._internal_ipv6_names = cloud_config.get_internal_ipv6_networks()
self._nat_destination = cloud_config.get_nat_destination()
self._default_network = cloud_config.get_default_network()
self._floating_ip_source = cloud_config.config.get(
self._floating_ip_source = self.config.config.get(
'floating_ip_source')
if self._floating_ip_source:
if self._floating_ip_source.lower() == 'none':
@ -184,16 +148,12 @@ class OpenStackCloud(_normalize.Normalizer):
else:
self._floating_ip_source = self._floating_ip_source.lower()
self._use_external_network = cloud_config.config.get(
self._use_external_network = self.config.config.get(
'use_external_network', True)
self._use_internal_network = cloud_config.config.get(
self._use_internal_network = self.config.config.get(
'use_internal_network', True)
# Work around older TaskManager objects that don't have submit_task
if not hasattr(self.manager, 'submit_task'):
self.manager.submit_task = self.manager.submitTask
(self.verify, self.cert) = cloud_config.get_requests_verify_args()
(self.verify, self.cert) = self.config.get_requests_verify_args()
# Turn off urllib3 warnings about insecure certs if we have
# explicitly configured requests to tell it we do not want
# cert verification
@ -206,7 +166,6 @@ class OpenStackCloud(_normalize.Normalizer):
warnings.filterwarnings('ignore', category=category)
self._disable_warnings = {}
self.use_direct_get = use_direct_get
self._servers = None
self._servers_time = 0
@ -227,9 +186,9 @@ class OpenStackCloud(_normalize.Normalizer):
self._networks_lock = threading.Lock()
self._reset_network_caches()
cache_expiration_time = int(cloud_config.get_cache_expiration_time())
cache_class = cloud_config.get_cache_class()
cache_arguments = cloud_config.get_cache_arguments()
cache_expiration_time = int(self.config.get_cache_expiration_time())
cache_class = self.config.get_cache_class()
cache_arguments = self.config.get_cache_arguments()
self._resource_caches = {}
@ -237,7 +196,7 @@ class OpenStackCloud(_normalize.Normalizer):
self.cache_enabled = True
self._cache = self._make_cache(
cache_class, cache_expiration_time, cache_arguments)
expirations = cloud_config.get_cache_expiration()
expirations = self.config.get_cache_expiration()
for expire_key in expirations.keys():
# Only build caches for things we have list operations for
if getattr(
@ -279,36 +238,21 @@ class OpenStackCloud(_normalize.Normalizer):
# If server expiration time is set explicitly, use that. Otherwise
# fall back to whatever it was before
self._SERVER_AGE = cloud_config.get_cache_resource_expiration(
self._SERVER_AGE = self.config.get_cache_resource_expiration(
'server', self._SERVER_AGE)
self._PORT_AGE = cloud_config.get_cache_resource_expiration(
self._PORT_AGE = self.config.get_cache_resource_expiration(
'port', self._PORT_AGE)
self._FLOAT_AGE = cloud_config.get_cache_resource_expiration(
self._FLOAT_AGE = self.config.get_cache_resource_expiration(
'floating_ip', self._FLOAT_AGE)
self._container_cache = dict()
self._file_hash_cache = dict()
self._keystone_session = None
self._raw_clients = {}
self._local_ipv6 = (
_utils.localhost_supports_ipv6() if not self.force_ipv4 else False)
self.cloud_config = cloud_config
self._conn_object = conn
@property
def _conn(self):
if not self._conn_object:
# Importing late to avoid import cycle. If the OpenStackCloud
# object comes via Connection, it'll have connection passed in.
import openstack.connection
self._conn_object = openstack.connection.Connection(
config=self.cloud_config, session=self._keystone_session)
return self._conn_object
def connect_as(self, **kwargs):
"""Make a new OpenStackCloud object with new auth context.
@ -332,11 +276,12 @@ class OpenStackCloud(_normalize.Normalizer):
that do not want to be overridden can be ommitted.
"""
# TODO(mordred) Replace this with from_session
config = openstack.config.OpenStackConfig(
app_name=self.cloud_config._app_name,
app_version=self.cloud_config._app_version,
app_name=self.config._app_name,
app_version=self.config._app_version,
load_yaml_config=False)
params = copy.deepcopy(self.cloud_config.config)
params = copy.deepcopy(self.config.config)
# Remove profile from current cloud so that overridding works
params.pop('profile', None)
@ -373,7 +318,7 @@ class OpenStackCloud(_normalize.Normalizer):
def session_constructor(*args, **kwargs):
# We need to pass our current keystone session to the Session
# Constructor, otherwise the new auth plugin doesn't get used.
return keystoneauth1.session.Session(session=self.keystone_session)
return keystoneauth1.session.Session(session=self.session)
# Use cloud='defaults' so that we overlay settings properly
cloud_config = config.get_one(
@ -385,7 +330,7 @@ class OpenStackCloud(_normalize.Normalizer):
cloud_config.config['profile'] = self.name
# Use self.__class__ so that we return whatever this if, like if it's
# a subclass in the case of shade wrapping sdk.
return self.__class__(cloud_config=cloud_config)
return self.__class__(config=cloud_config)
def connect_as_project(self, project):
"""Make a new OpenStackCloud object with a new project.
@ -457,7 +402,7 @@ class OpenStackCloud(_normalize.Normalizer):
def _get_versioned_client(
self, service_type, min_version=None, max_version=None):
config_version = self.cloud_config.get_api_version(service_type)
config_version = self.config.get_api_version(service_type)
config_major = self._get_major_version_id(config_version)
max_major = self._get_major_version_id(max_version)
min_major = self._get_major_version_id(min_version)
@ -492,33 +437,33 @@ class OpenStackCloud(_normalize.Normalizer):
request_max_version = '{version}.latest'.format(
version=config_major)
adapter = _adapter.ShadeAdapter(
session=self.keystone_session,
task_manager=self.manager,
service_type=self.cloud_config.get_service_type(service_type),
service_name=self.cloud_config.get_service_name(service_type),
interface=self.cloud_config.get_interface(service_type),
endpoint_override=self.cloud_config.get_endpoint(service_type),
region_name=self.cloud_config.region_name,
session=self.session,
task_manager=self.task_manager,
service_type=self.config.get_service_type(service_type),
service_name=self.config.get_service_name(service_type),
interface=self.config.get_interface(service_type),
endpoint_override=self.config.get_endpoint(service_type),
region_name=self.config.region_name,
min_version=request_min_version,
max_version=request_max_version)
if adapter.get_endpoint():
return adapter
adapter = _adapter.ShadeAdapter(
session=self.keystone_session,
task_manager=self.manager,
service_type=self.cloud_config.get_service_type(service_type),
service_name=self.cloud_config.get_service_name(service_type),
interface=self.cloud_config.get_interface(service_type),
endpoint_override=self.cloud_config.get_endpoint(service_type),
region_name=self.cloud_config.region_name,
session=self.session,
task_manager=self.task_manager,
service_type=self.config.get_service_type(service_type),
service_name=self.config.get_service_name(service_type),
interface=self.config.get_interface(service_type),
endpoint_override=self.config.get_endpoint(service_type),
region_name=self.config.region_name,
min_version=min_version,
max_version=max_version)
# data.api_version can be None if no version was detected, such
# as with neutron
api_version = adapter.get_api_major_version(
endpoint_override=self.cloud_config.get_endpoint(service_type))
endpoint_override=self.config.get_endpoint(service_type))
api_major = self._get_major_version_id(api_version)
# If we detect a different version that was configured, warn the user.
@ -544,14 +489,14 @@ class OpenStackCloud(_normalize.Normalizer):
def _get_raw_client(
self, service_type, api_version=None, endpoint_override=None):
return _adapter.ShadeAdapter(
session=self.keystone_session,
task_manager=self.manager,
service_type=self.cloud_config.get_service_type(service_type),
service_name=self.cloud_config.get_service_name(service_type),
interface=self.cloud_config.get_interface(service_type),
endpoint_override=self.cloud_config.get_endpoint(
session=self.session,
task_manager=self.task_manager,
service_type=self.config.get_service_type(service_type),
service_name=self.config.get_service_name(service_type),
interface=self.config.get_interface(service_type),
endpoint_override=self.config.get_endpoint(
service_type) or endpoint_override,
region_name=self.cloud_config.region_name)
region_name=self.config.region_name)
def _is_client_version(self, client, version):
client_name = '_{client}_client'.format(client=client)
@ -673,23 +618,9 @@ class OpenStackCloud(_normalize.Normalizer):
new_resource = _utils._dictify_resource(resource)
return pprint.pformat(new_resource)
@property
def keystone_session(self):
if self._keystone_session is None:
try:
self._keystone_session = self.cloud_config.get_session()
if hasattr(self._keystone_session, 'additional_user_agent'):
self._keystone_session.additional_user_agent.append(
('openstacksdk', openstack_version.__version__))
except Exception as e:
raise OpenStackCloudException(
"Error authenticating to keystone: %s " % str(e))
return self._keystone_session
@property
def _keystone_catalog(self):
return self.keystone_session.auth.get_access(
self.keystone_session).service_catalog
return self.session.auth.get_access(self.session).service_catalog
@property
def service_catalog(self):
@ -703,13 +634,12 @@ class OpenStackCloud(_normalize.Normalizer):
def auth_token(self):
# Keystone's session will reuse a token if it is still valid.
# We don't need to track validity here, just get_token() each time.
return self.keystone_session.get_token()
return self.session.get_token()
@property
def current_user_id(self):
"""Get the id of the currently logged-in user from the token."""
return self.keystone_session.auth.get_access(
self.keystone_session).user_id
return self.session.auth.get_access(self.session).user_id
@property
def current_project_id(self):
@ -723,7 +653,7 @@ class OpenStackCloud(_normalize.Normalizer):
:raises keystoneauth1.exceptions.auth_plugins.MissingAuthPlugin:
if a plugin is not available.
"""
return self.keystone_session.get_project_id()
return self.session.get_project_id()
@property
def current_project(self):
@ -748,7 +678,7 @@ class OpenStackCloud(_normalize.Normalizer):
# If they don't match, that means we're an admin who has pulled
# an object from a different project, so adding info from the
# current token would be wrong.
auth_args = self.cloud_config.config.get('auth', {})
auth_args = self.config.config.get('auth', {})
project_info['id'] = self.current_project_id
project_info['name'] = auth_args.get('project_name')
project_info['domain_id'] = auth_args.get('project_domain_id')
@ -763,7 +693,7 @@ class OpenStackCloud(_normalize.Normalizer):
def _get_current_location(self, project_id=None, zone=None):
return munch.Munch(
cloud=self.name,
region_name=self.region_name,
region_name=self.config.region_name,
zone=zone,
project=self._get_project_info(project_id),
)
@ -1419,7 +1349,7 @@ class OpenStackCloud(_normalize.Normalizer):
return self.name
def get_region(self):
return self.region_name
return self.config.region_name
def get_flavor_name(self, flavor_id):
flavor = self.get_flavor(flavor_id, get_extra=False)
@ -1449,7 +1379,7 @@ class OpenStackCloud(_normalize.Normalizer):
def get_session_endpoint(self, service_key):
try:
return self.cloud_config.get_session_endpoint(service_key)
return self.config.get_session_endpoint(service_key)
except keystoneauth1.exceptions.catalog.EndpointNotFound as e:
self.log.debug(
"Endpoint not found in %s cloud: %s", self.name, str(e))
@ -1462,12 +1392,12 @@ class OpenStackCloud(_normalize.Normalizer):
" {error}".format(
service=service_key,
cloud=self.name,
region=self.region_name,
region=self.config.region_name,
error=str(e)))
return endpoint
def has_service(self, service_key):
if not self.cloud_config.config.get('has_%s' % service_key, True):
if not self.config.config.get('has_%s' % service_key, True):
# TODO(mordred) add a stamp here so that we only report this once
if not (service_key in self._disable_warnings
and self._disable_warnings[service_key]):
@ -1489,7 +1419,7 @@ class OpenStackCloud(_normalize.Normalizer):
def _nova_extensions(self):
extensions = set()
data = _adapter._json_response(
self._conn.compute.get('/extensions'),
self.compute.get('/extensions'),
error_message="Error fetching extension list for nova")
for extension in self._get_and_munchify('extensions', data):
@ -1694,7 +1624,7 @@ class OpenStackCloud(_normalize.Normalizer):
"""
data = _adapter._json_response(
self._conn.compute.get('/os-keypairs'),
self.compute.get('/os-keypairs'),
error_message="Error fetching keypair list")
return self._normalize_keypairs([
k['keypair'] for k in self._get_and_munchify('keypairs', data)])
@ -1921,7 +1851,7 @@ class OpenStackCloud(_normalize.Normalizer):
"""
try:
data = _adapter._json_response(
self._conn.compute.get('/os-availability-zone'))
self.compute.get('/os-availability-zone'))
except OpenStackCloudHTTPError:
self.log.debug(
"Availability zone list could not be fetched",
@ -1946,7 +1876,7 @@ class OpenStackCloud(_normalize.Normalizer):
"""
data = _adapter._json_response(
self._conn.compute.get(
self.compute.get(
'/flavors/detail', params=dict(is_public='None')),
error_message="Error fetching flavor list")
flavors = self._normalize_flavors(
@ -1958,7 +1888,7 @@ class OpenStackCloud(_normalize.Normalizer):
id=flavor.id)
try:
data = _adapter._json_response(
self._conn.compute.get(endpoint),
self.compute.get(endpoint),
error_message="Error fetching flavor extra specs")
flavor.extra_specs = self._get_and_munchify(
'extra_specs', data)
@ -1995,7 +1925,7 @@ class OpenStackCloud(_normalize.Normalizer):
return []
data = _adapter._json_response(
self._conn.compute.get(
self.compute.get(
'/servers/{server_id}/os-security-groups'.format(
server_id=server['id'])))
return self._normalize_secgroups(
@ -2051,7 +1981,7 @@ class OpenStackCloud(_normalize.Normalizer):
return False
for sg in security_groups:
_adapter._json_response(self._conn.compute.post(
_adapter._json_response(self.compute.post(
'/servers/%s/action' % server['id'],
json={'addSecurityGroup': {'name': sg.name}}))
@ -2079,7 +2009,7 @@ class OpenStackCloud(_normalize.Normalizer):
for sg in security_groups:
try:
_adapter._json_response(self._conn.compute.post(
_adapter._json_response(self.compute.post(
'/servers/%s/action' % server['id'],
json={'removeSecurityGroup': {'name': sg.name}}))
@ -2121,7 +2051,7 @@ class OpenStackCloud(_normalize.Normalizer):
# Handle nova security groups
else:
data = _adapter._json_response(self._conn.compute.get(
data = _adapter._json_response(self.compute.get(
'/os-security-groups', params=filters))
return self._normalize_secgroups(
self._get_and_munchify('security_groups', data))
@ -2169,13 +2099,13 @@ class OpenStackCloud(_normalize.Normalizer):
filters=None):
error_msg = "Error fetching server list on {cloud}:{region}:".format(
cloud=self.name,
region=self.region_name)
region=self.config.region_name)
params = filters or {}
if all_projects:
params['all_tenants'] = True
data = _adapter._json_response(
self._conn.compute.get(
self.compute.get(
'/servers/detail', params=params),
error_message=error_msg)
servers = self._normalize_servers(
@ -2192,7 +2122,7 @@ class OpenStackCloud(_normalize.Normalizer):
"""
data = _adapter._json_response(
self._conn.compute.get('/os-server-groups'),
self.compute.get('/os-server-groups'),
error_message="Error fetching server group list")
return self._get_and_munchify('server_groups', data)
@ -2219,7 +2149,7 @@ class OpenStackCloud(_normalize.Normalizer):
msg=error_msg, project=name_or_id)
data = _adapter._json_response(
self._conn.compute.get('/limits', params=params))
self.compute.get('/limits', params=params))
limits = self._get_and_munchify('limits', data)
return self._normalize_compute_limits(limits, project_id=project_id)
@ -2254,7 +2184,7 @@ class OpenStackCloud(_normalize.Normalizer):
# We didn't have glance, let's try nova
# If this doesn't work - we just let the exception propagate
response = _adapter._json_response(
self._conn.compute.get('/images/detail'))
self.compute.get('/images/detail'))
while 'next' in response:
image_list.extend(meta.obj_list_to_munch(response['images']))
endpoint = response['next']
@ -2295,7 +2225,7 @@ class OpenStackCloud(_normalize.Normalizer):
'Floating IP pools extension is not available on target cloud')
data = _adapter._json_response(
self._conn.compute.get('os-floating-ip-pools'),
self.compute.get('os-floating-ip-pools'),
error_message="Error fetching floating IP pool list")
pools = self._get_and_munchify('floating_ip_pools', data)
return [{'name': p['name']} for p in pools]
@ -2386,7 +2316,7 @@ class OpenStackCloud(_normalize.Normalizer):
def _nova_list_floating_ips(self):
try:
data = _adapter._json_response(
self._conn.compute.get('/os-floating-ips'))
self.compute.get('/os-floating-ips'))
except OpenStackCloudURINotFound:
return []
return self._get_and_munchify('floating_ips', data)
@ -2991,7 +2921,7 @@ class OpenStackCloud(_normalize.Normalizer):
:returns: A flavor ``munch.Munch``.
"""
data = _adapter._json_response(
self._conn.compute.get('/flavors/{id}'.format(id=id)),
self.compute.get('/flavors/{id}'.format(id=id)),
error_message="Error getting flavor with ID {id}".format(id=id)
)
flavor = self._normalize_flavor(
@ -3002,7 +2932,7 @@ class OpenStackCloud(_normalize.Normalizer):
id=flavor.id)
try:
data = _adapter._json_response(
self._conn.compute.get(endpoint),
self.compute.get(endpoint),
error_message="Error fetching flavor extra specs")
flavor.extra_specs = self._get_and_munchify(
'extra_specs', data)
@ -3058,7 +2988,7 @@ class OpenStackCloud(_normalize.Normalizer):
error_message=error_message)
else:
data = _adapter._json_response(
self._conn.compute.get(
self.compute.get(
'/os-security-groups/{id}'.format(id=id)),
error_message=error_message)
return self._normalize_secgroup(
@ -3091,7 +3021,7 @@ class OpenStackCloud(_normalize.Normalizer):
return ""
def _get_server_console_output(self, server_id, length=None):
data = _adapter._json_response(self._conn.compute.post(
data = _adapter._json_response(self.compute.post(
'/servers/{server_id}/action'.format(server_id=server_id),
json={'os-getConsoleOutput': {'length': length}}))
return self._get_and_munchify('output', data)
@ -3145,7 +3075,7 @@ class OpenStackCloud(_normalize.Normalizer):
def get_server_by_id(self, id):
data = _adapter._json_response(
self._conn.compute.get('/servers/{id}'.format(id=id)))
self.compute.get('/servers/{id}'.format(id=id)))
server = self._get_and_munchify('server', data)
return meta.add_server_interfaces(self, self._normalize_server(server))
@ -3304,7 +3234,7 @@ class OpenStackCloud(_normalize.Normalizer):
self._get_and_munchify('floatingip', data))
else:
data = _adapter._json_response(
self._conn.compute.get('/os-floating-ips/{id}'.format(id=id)),
self.compute.get('/os-floating-ips/{id}'.format(id=id)),
error_message=error_message)
return self._normalize_floating_ip(
self._get_and_munchify('floating_ip', data))
@ -3355,7 +3285,7 @@ class OpenStackCloud(_normalize.Normalizer):
if public_key:
keypair['public_key'] = public_key
data = _adapter._json_response(
self._conn.compute.post(
self.compute.post(
'/os-keypairs',
json={'keypair': keypair}),
error_message="Unable to create keypair {name}".format(name=name))
@ -3372,7 +3302,7 @@ class OpenStackCloud(_normalize.Normalizer):
:raises: OpenStackCloudException on operation error.
"""
try:
_adapter._json_response(self._conn.compute.delete(
_adapter._json_response(self.compute.delete(
'/os-keypairs/{name}'.format(name=name)))
except OpenStackCloudURINotFound:
self.log.debug("Keypair %s not found for deleting", name)
@ -4432,7 +4362,7 @@ class OpenStackCloud(_normalize.Normalizer):
" could not be snapshotted.".format(server=server))
server = server_obj
response = _adapter._json_response(
self._conn.compute.post(
self.compute.post(
'/servers/{server_id}/action'.format(server_id=server['id']),
json={
"createImage": {
@ -4523,7 +4453,7 @@ class OpenStackCloud(_normalize.Normalizer):
# Try appending the disk format
name_with_ext = '.'.join((
name, self.cloud_config.config['image_format']))
name, self.config.config['image_format']))
if os.path.exists(name_with_ext):
return (os.path.basename(name), name_with_ext)
@ -4615,7 +4545,7 @@ class OpenStackCloud(_normalize.Normalizer):
meta = {}
if not disk_format:
disk_format = self.cloud_config.config['image_format']
disk_format = self.config.config['image_format']
if not container_format:
# https://docs.openstack.org/image-guide/image-formats.html
container_format = 'bare'
@ -4661,7 +4591,7 @@ class OpenStackCloud(_normalize.Normalizer):
kwargs[IMAGE_OBJECT_KEY] = '/'.join([container, name])
if disable_vendor_agent:
kwargs.update(self.cloud_config.config['disable_vendor_agent'])
kwargs.update(self.config.config['disable_vendor_agent'])
# We can never have nice things. Glance v1 took "is_public" as a
# boolean. Glance v2 takes "visibility". If the user gives us
@ -5169,7 +5099,7 @@ class OpenStackCloud(_normalize.Normalizer):
:raises: OpenStackCloudException on operation error.
"""
_adapter._json_response(self._conn.compute.delete(
_adapter._json_response(self.compute.delete(
'/servers/{server_id}/os-volume_attachments/{volume_id}'.format(
server_id=server['id'], volume_id=volume['id'])),
error_message=(
@ -5237,7 +5167,7 @@ class OpenStackCloud(_normalize.Normalizer):
if device:
payload['device'] = device
data = _adapter._json_response(
self._conn.compute.post(
self.compute.post(
'/servers/{server_id}/os-volume_attachments'.format(
server_id=server['id']),
json=dict(volumeAttachment=payload)),
@ -5884,12 +5814,12 @@ class OpenStackCloud(_normalize.Normalizer):
"unable to find a floating ip pool")
pool = pools[0]['name']
data = _adapter._json_response(self._conn.compute.post(
data = _adapter._json_response(self.compute.post(
'/os-floating-ips', json=dict(pool=pool)))
pool_ip = self._get_and_munchify('floating_ip', data)
# TODO(mordred) Remove this - it's just for compat
data = _adapter._json_response(
self._conn.compute.get('/os-floating-ips/{id}'.format(
self.compute.get('/os-floating-ips/{id}'.format(
id=pool_ip['id'])))
return self._get_and_munchify('floating_ip', data)
@ -5959,7 +5889,7 @@ class OpenStackCloud(_normalize.Normalizer):
def _nova_delete_floating_ip(self, floating_ip_id):
try:
_adapter._json_response(
self._conn.compute.delete(
self.compute.delete(
'/os-floating-ips/{id}'.format(id=floating_ip_id)),
error_message='Unable to delete floating IP {fip_id}'.format(
fip_id=floating_ip_id))
@ -6209,7 +6139,7 @@ class OpenStackCloud(_normalize.Normalizer):
if fixed_address:
body['fixed_address'] = fixed_address
return _adapter._json_response(
self._conn.compute.post(
self.compute.post(
'/servers/{server_id}/action'.format(server_id=server_id),
json=dict(addFloatingIp=body)),
error_message=error_message)
@ -6261,7 +6191,7 @@ class OpenStackCloud(_normalize.Normalizer):
error_message = "Error detaching IP {ip} from instance {id}".format(
ip=floating_ip_id, id=server_id)
return _adapter._json_response(
self._conn.compute.post(
self.compute.post(
'/servers/{server_id}/action'.format(server_id=server_id),
json=dict(removeFloatingIp=dict(
address=f_ip['floating_ip_address']))),
@ -6512,7 +6442,7 @@ class OpenStackCloud(_normalize.Normalizer):
'Volume {boot_volume} is not a valid volume'
' in {cloud}:{region}'.format(
boot_volume=boot_volume,
cloud=self.name, region=self.region_name))
cloud=self.name, region=self.config.region_name))
block_mapping = {
'boot_index': '0',
'delete_on_termination': terminate_volume,
@ -6533,7 +6463,7 @@ class OpenStackCloud(_normalize.Normalizer):
'Image {image} is not a valid image in'
' {cloud}:{region}'.format(
image=image,
cloud=self.name, region=self.region_name))
cloud=self.name, region=self.config.region_name))
block_mapping = {
'boot_index': '0',
@ -6563,7 +6493,7 @@ class OpenStackCloud(_normalize.Normalizer):
'Volume {volume} is not a valid volume'
' in {cloud}:{region}'.format(
volume=volume,
cloud=self.name, region=self.region_name))
cloud=self.name, region=self.config.region_name))
block_mapping = {
'boot_index': '-1',
'delete_on_termination': False,
@ -6757,7 +6687,7 @@ class OpenStackCloud(_normalize.Normalizer):
'Network {network} is not a valid network in'
' {cloud}:{region}'.format(
network=network,
cloud=self.name, region=self.region_name))
cloud=self.name, region=self.config.region_name))
nics.append({'net-id': network_obj['id']})
kwargs['nics'] = nics
@ -6827,7 +6757,7 @@ class OpenStackCloud(_normalize.Normalizer):
endpoint = '/os-volumes_boot'
with _utils.shade_exceptions("Error in creating instance"):
data = _adapter._json_response(
self._conn.compute.post(endpoint, json={'server': kwargs}))
self.compute.post(endpoint, json={'server': kwargs}))
server = self._get_and_munchify('server', data)
admin_pass = server.get('adminPass') or kwargs.get('admin_pass')
if not wait:
@ -6947,7 +6877,7 @@ class OpenStackCloud(_normalize.Normalizer):
kwargs['adminPass'] = admin_pass
data = _adapter._json_response(
self._conn.compute.post(
self.compute.post(
'/servers/{server_id}/action'.format(server_id=server_id),
json={'rebuild': kwargs}),
error_message="Error in rebuilding instance")
@ -6997,7 +6927,7 @@ class OpenStackCloud(_normalize.Normalizer):
'Invalid Server {server}'.format(server=name_or_id))
_adapter._json_response(
self._conn.compute.post(
self.compute.post(
'/servers/{server_id}/metadata'.format(server_id=server['id']),
json={'metadata': metadata}),
error_message='Error updating server metadata')
@ -7021,7 +6951,7 @@ class OpenStackCloud(_normalize.Normalizer):
error_message = 'Error deleting metadata {key} on {server}'.format(
key=key, server=name_or_id)
_adapter._json_response(
self._conn.compute.delete(
self.compute.delete(
'/servers/{server_id}/metadata/{key}'.format(
server_id=server['id'],
key=key)),
@ -7095,7 +7025,7 @@ class OpenStackCloud(_normalize.Normalizer):
try:
_adapter._json_response(
self._conn.compute.delete(
self.compute.delete(
'/servers/{id}'.format(id=server['id'])),
error_message="Error in deleting server")
except OpenStackCloudURINotFound:
@ -7160,7 +7090,7 @@ class OpenStackCloud(_normalize.Normalizer):
"failed to find server '{server}'".format(server=name_or_id))
data = _adapter._json_response(
self._conn.compute.put(
self.compute.put(
'/servers/{server_id}'.format(server_id=server['id']),
json={'server': kwargs}),
error_message="Error updating server {0}".format(name_or_id))
@ -7179,7 +7109,7 @@ class OpenStackCloud(_normalize.Normalizer):
:raises: OpenStackCloudException on operation error.
"""
data = _adapter._json_response(
self._conn.compute.post(
self.compute.post(
'/os-server-groups',
json={
'server_group': {
@ -7205,7 +7135,7 @@ class OpenStackCloud(_normalize.Normalizer):
return False
_adapter._json_response(
self._conn.compute.delete(
self.compute.delete(
'/os-server-groups/{id}'.format(id=server_group['id'])),
error_message="Error deleting server group {name}".format(
name=name_or_id))
@ -8149,7 +8079,7 @@ class OpenStackCloud(_normalize.Normalizer):
json=security_group_json,
error_message="Error creating security group {0}".format(name))
else:
data = _adapter._json_response(self._conn.compute.post(
data = _adapter._json_response(self.compute.post(
'/os-security-groups', json=security_group_json))
return self._normalize_secgroup(
self._get_and_munchify('security_group', data))
@ -8188,7 +8118,7 @@ class OpenStackCloud(_normalize.Normalizer):
return True
else:
_adapter._json_response(self._conn.compute.delete(
_adapter._json_response(self.compute.delete(
'/os-security-groups/{id}'.format(id=secgroup['id'])))
return True
@ -8226,7 +8156,7 @@ class OpenStackCloud(_normalize.Normalizer):
for key in ('name', 'description'):
kwargs.setdefault(key, group[key])
data = _adapter._json_response(
self._conn.compute.put(
self.compute.put(
'/os-security-groups/{id}'.format(id=group['id']),
json={'security-group': kwargs}))
return self._normalize_secgroup(
@ -8361,7 +8291,7 @@ class OpenStackCloud(_normalize.Normalizer):
security_group_rule_dict[
'security_group_rule']['tenant_id'] = project_id
data = _adapter._json_response(
self._conn.compute.post(
self.compute.post(
'/os-security-group-rules',
json=security_group_rule_dict
))
@ -8396,7 +8326,7 @@ class OpenStackCloud(_normalize.Normalizer):
return True
else:
_adapter._json_response(self._conn.compute.delete(
_adapter._json_response(self.compute.delete(
'/os-security-group-rules/{id}'.format(id=rule_id)))
return True
@ -10509,7 +10439,7 @@ class OpenStackCloud(_normalize.Normalizer):
}
if flavorid == 'auto':
payload['id'] = None
data = _adapter._json_response(self._conn.compute.post(
data = _adapter._json_response(self.compute.post(
'/flavors',
json=dict(flavor=payload)))
@ -10532,7 +10462,7 @@ class OpenStackCloud(_normalize.Normalizer):
return False
_adapter._json_response(
self._conn.compute.delete(
self.compute.delete(
'/flavors/{id}'.format(id=flavor['id'])),
error_message="Unable to delete flavor {name}".format(
name=name_or_id))
@ -10549,7 +10479,7 @@ class OpenStackCloud(_normalize.Normalizer):
:raises: OpenStackCloudResourceNotFound if flavor ID is not found.
"""
_adapter._json_response(
self._conn.compute.post(
self.compute.post(
"/flavors/{id}/os-extra_specs".format(id=flavor_id),
json=dict(extra_specs=extra_specs)),
error_message="Unable to set flavor specs")
@ -10565,7 +10495,7 @@ class OpenStackCloud(_normalize.Normalizer):
"""
for key in keys:
_adapter._json_response(
self._conn.compute.delete(
self.compute.delete(
"/flavors/{id}/os-extra_specs/{key}".format(
id=flavor_id, key=key)),
error_message="Unable to delete flavor spec {0}".format(key))
@ -10581,7 +10511,7 @@ class OpenStackCloud(_normalize.Normalizer):
access_key = '{action}TenantAccess'.format(action=action)
_adapter._json_response(
self._conn.compute.post(endpoint, json={access_key: access}))
self.compute.post(endpoint, json={access_key: access}))
def add_flavor_access(self, flavor_id, project_id):
"""Grant access to a private flavor for a project/tenant.
@ -10613,7 +10543,7 @@ class OpenStackCloud(_normalize.Normalizer):
:raises: OpenStackCloudException on operation error.
"""
data = _adapter._json_response(
self._conn.compute.get(
self.compute.get(
'/flavors/{id}/os-flavor-access'.format(id=flavor_id)),
error_message=(
"Error trying to list access from flavorID {flavor}".format(
@ -10892,7 +10822,7 @@ class OpenStackCloud(_normalize.Normalizer):
"""
data = _adapter._json_response(
self._conn.compute.get('/os-hypervisors/detail'),
self.compute.get('/os-hypervisors/detail'),
error_message="Error fetching hypervisor list")
return self._get_and_munchify('hypervisors', data)
@ -10917,7 +10847,7 @@ class OpenStackCloud(_normalize.Normalizer):
"""
data = _adapter._json_response(
self._conn.compute.get('/os-aggregates'),
self.compute.get('/os-aggregates'),
error_message="Error fetching aggregate list")
return self._get_and_munchify('aggregates', data)
@ -10953,7 +10883,7 @@ class OpenStackCloud(_normalize.Normalizer):
:raises: OpenStackCloudException on operation error.
"""
data = _adapter._json_response(
self._conn.compute.post(
self.compute.post(
'/os-aggregates',
json={'aggregate': {
'name': name,
@ -10981,7 +10911,7 @@ class OpenStackCloud(_normalize.Normalizer):
"Host aggregate %s not found." % name_or_id)
data = _adapter._json_response(
self._conn.compute.put(
self.compute.put(
'/os-aggregates/{id}'.format(id=aggregate['id']),
json={'aggregate': kwargs}),
error_message="Error updating aggregate {name}".format(
@ -11003,7 +10933,7 @@ class OpenStackCloud(_normalize.Normalizer):
return False
return _adapter._json_response(
self._conn.compute.delete(
self.compute.delete(
'/os-aggregates/{id}'.format(id=aggregate['id'])),
error_message="Error deleting aggregate {name}".format(
name=name_or_id))
@ -11030,7 +10960,7 @@ class OpenStackCloud(_normalize.Normalizer):
name=name_or_id)
data = _adapter._json_response(
self._conn.compute.post(
self.compute.post(
'/os-aggregates/{id}/action'.format(id=aggregate['id']),
json={'set_metadata': {'metadata': metadata}}),
error_message=err_msg)
@ -11053,7 +10983,7 @@ class OpenStackCloud(_normalize.Normalizer):
host=host_name, name=name_or_id)
return _adapter._json_response(
self._conn.compute.post(
self.compute.post(
'/os-aggregates/{id}/action'.format(id=aggregate['id']),
json={'add_host': {'host': host_name}}),
error_message=err_msg)
@ -11075,7 +11005,7 @@ class OpenStackCloud(_normalize.Normalizer):
host=host_name, name=name_or_id)
return _adapter._json_response(
self._conn.compute.post(
self.compute.post(
'/os-aggregates/{id}/action'.format(id=aggregate['id']),
json={'remove_host': {'host': host_name}}),
error_message=err_msg)
@ -11167,7 +11097,7 @@ class OpenStackCloud(_normalize.Normalizer):
kwargs['force'] = True
_adapter._json_response(
self._conn.compute.put(
self.compute.put(
'/os-quota-sets/{project}'.format(project=proj.id),
json={'quota_set': kwargs}),
error_message="No valid quota or resource")
@ -11184,7 +11114,7 @@ class OpenStackCloud(_normalize.Normalizer):
if not proj:
raise OpenStackCloudException("project does not exist")
data = _adapter._json_response(
self._conn.compute.get(
self.compute.get(
'/os-quota-sets/{project}'.format(project=proj.id)))
return self._get_and_munchify('quota_set', data)
@ -11201,7 +11131,7 @@ class OpenStackCloud(_normalize.Normalizer):
if not proj:
raise OpenStackCloudException("project does not exist")
return _adapter._json_response(
self._conn.compute.delete(
self.compute.delete(
'/os-quota-sets/{project}'.format(project=proj.id)))
def get_compute_usage(self, name_or_id, start=None, end=None):
@ -11260,7 +11190,7 @@ class OpenStackCloud(_normalize.Normalizer):
name=proj.id))
data = _adapter._json_response(
self._conn.compute.get(
self.compute.get(
'/os-simple-tenant-usage/{project}'.format(project=proj.id),
params=dict(start=start.isoformat(), end=end.isoformat())),
error_message="Unable to get usage for project: {name}".format(

View File

@ -211,7 +211,8 @@ def from_config(cloud=None, config=None, options=None, **kwargs):
return Connection(config=config)
class Connection(six.with_metaclass(_meta.ConnectionMeta)):
class Connection(six.with_metaclass(_meta.ConnectionMeta,
_cloud.OpenStackCloud)):
def __init__(self, cloud=None, config=None, session=None,
app_name=None, app_version=None,
@ -219,6 +220,8 @@ class Connection(six.with_metaclass(_meta.ConnectionMeta)):
# python-openstackclient to not use the profile interface.
authenticator=None, profile=None,
extra_services=None,
strict=False,
use_direct_get=False,
**kwargs):
"""Create a connection to a cloud.
@ -305,17 +308,23 @@ class Connection(six.with_metaclass(_meta.ConnectionMeta)):
# TODO(mordred) Expose constructor option for this in OCC
self.config._keystone_session = session
self.session = self.config.get_session()
# Hide a reference to the connection on the session to help with
# backwards compatibility for folks trying to just pass conn.session
# to a Resource method's session argument.
self.session._sdk_connection = self
self._session = None
self._proxies = {}
self.cloud = _cloud.OpenStackCloud(
cloud_config=self.config,
manager=self.task_manager,
conn=self)
self.use_direct_get = use_direct_get
self.strict_mode = strict
# Call the OpenStackCloud constructor while we work on integrating
# things better.
_cloud.OpenStackCloud.__init__(self)
@property
def session(self):
if not self._session:
self._session = self.config.get_session()
# Hide a reference to the connection on the session to help with
# backwards compatibility for folks trying to just pass
# conn.session to a Resource method's session argument.
self.session._sdk_connection = self
return self._session
def add_service(self, service):
"""Add a service to the Connection.

View File

@ -16,7 +16,7 @@ import os
import openstack.config as occ
import openstack.cloud
from openstack import connection
from openstack.tests import base
@ -33,19 +33,17 @@ class BaseFunctionalTestCase(base.TestCase):
self._set_operator_cloud()
self.identity_version = \
self.operator_cloud.cloud_config.get_api_version('identity')
self.operator_cloud.config.get_api_version('identity')
def _set_user_cloud(self, **kwargs):
user_config = self.config.get_one(
cloud=self._demo_name, **kwargs)
self.user_cloud = openstack.cloud.OpenStackCloud(
cloud_config=user_config)
self.user_cloud = connection.Connection(config=user_config)
def _set_operator_cloud(self, **kwargs):
operator_config = self.config.get_one(
cloud=self._op_name, **kwargs)
self.operator_cloud = openstack.cloud.OpenStackCloud(
cloud_config=operator_config)
self.operator_cloud = connection.Connection(config=operator_config)
def pick_image(self):
images = self.user_cloud.list_images()

View File

@ -27,7 +27,7 @@ class TestDomain(base.BaseFunctionalTestCase):
def setUp(self):
super(TestDomain, self).setUp()
i_ver = self.operator_cloud.cloud_config.get_api_version('identity')
i_ver = self.operator_cloud.config.get_api_version('identity')
if i_ver in ('2', '2.0'):
self.skipTest('Identity service does not support domains')
self.domain_prefix = self.getUniqueString('domain')

View File

@ -103,7 +103,7 @@ class TestEndpoints(base.KeystoneBaseFunctionalTestCase):
self.assertIsNotNone(endpoints[0].get('id'))
def test_update_endpoint(self):
ver = self.operator_cloud.cloud_config.get_api_version('identity')
ver = self.operator_cloud.config.get_api_version('identity')
if ver.startswith('2'):
# NOTE(SamYaple): Update endpoint only works with v3 api
self.assertRaises(OpenStackCloudUnavailableFeature,

View File

@ -27,7 +27,7 @@ class TestGroup(base.BaseFunctionalTestCase):
def setUp(self):
super(TestGroup, self).setUp()
i_ver = self.operator_cloud.cloud_config.get_api_version('identity')
i_ver = self.operator_cloud.config.get_api_version('identity')
if i_ver in ('2', '2.0'):
self.skipTest('Identity service does not support groups')
self.group_prefix = self.getUniqueString('group')

View File

@ -73,7 +73,7 @@ class TestProject(base.KeystoneBaseFunctionalTestCase):
new_cloud = self.operator_cloud.connect_as_project(project)
self.add_info_on_exception(
'new_cloud_config', pprint.pformat(new_cloud.cloud_config.config))
'new_cloud_config', pprint.pformat(new_cloud.config.config))
location = new_cloud.current_location
self.assertEqual(project_name, location['project']['name'])

View File

@ -65,7 +65,7 @@ class TestServices(base.KeystoneBaseFunctionalTestCase):
self.assertIsNotNone(service.get('id'))
def test_update_service(self):
ver = self.operator_cloud.cloud_config.get_api_version('identity')
ver = self.operator_cloud.config.get_api_version('identity')
if ver.startswith('2'):
# NOTE(SamYaple): Update service only works with v3 api
self.assertRaises(OpenStackCloudUnavailableFeature,

View File

@ -42,7 +42,7 @@ class TestUsers(base.KeystoneBaseFunctionalTestCase):
def _create_user(self, **kwargs):
domain_id = None
i_ver = self.operator_cloud.cloud_config.get_api_version('identity')
i_ver = self.operator_cloud.config.get_api_version('identity')
if i_ver not in ('2', '2.0'):
domain = self.operator_cloud.get_domain('default')
domain_id = domain['id']
@ -143,7 +143,7 @@ class TestUsers(base.KeystoneBaseFunctionalTestCase):
self.assertIsNotNone(new_cloud.service_catalog)
def test_users_and_groups(self):
i_ver = self.operator_cloud.cloud_config.get_api_version('identity')
i_ver = self.operator_cloud.config.get_api_version('identity')
if i_ver in ('2', '2.0'):
self.skipTest('Identity service does not support groups')

View File

@ -119,10 +119,11 @@ class BaseTestCase(base.TestCase):
secure_files=['non-existant'])
self.cloud_config = self.config.get_one(
cloud=test_cloud, validate=False)
self.cloud = openstack.cloud.OpenStackCloud(
cloud_config=self.cloud_config)
self.strict_cloud = openstack.cloud.OpenStackCloud(
cloud_config=self.cloud_config,
self.cloud = openstack.connection.Connection(
config=self.cloud_config,
strict=False)
self.strict_cloud = openstack.connection.Connection(
config=self.cloud_config,
strict=True)
@ -460,8 +461,7 @@ class RequestsMockTestCase(BaseTestCase):
cloud=test_cloud, validate=True, **kwargs)
self.conn = openstack.connection.Connection(
config=self.cloud_config)
self.cloud = openstack.cloud.OpenStackCloud(
cloud_config=self.cloud_config)
self.cloud = self.conn
def get_glance_discovery_mock_dict(
self,

View File

@ -58,7 +58,7 @@ class TestImage(BaseTestImage):
self.use_glance()
def test_config_v1(self):
self.cloud.cloud_config.config['image_api_version'] = '1'
self.cloud.config.config['image_api_version'] = '1'
# We override the scheme of the endpoint with the scheme of the service
# because glance has a bug where it doesn't return https properly.
self.assertEqual(
@ -68,7 +68,7 @@ class TestImage(BaseTestImage):
'1', self.cloud_config.get_api_version('image'))
def test_config_v2(self):
self.cloud.cloud_config.config['image_api_version'] = '2'
self.cloud.config.config['image_api_version'] = '2'
# We override the scheme of the endpoint with the scheme of the service
# because glance has a bug where it doesn't return https properly.
self.assertEqual(
@ -937,7 +937,7 @@ class TestImageV1Only(base.RequestsMockTestCase):
def test_config_v1(self):
self.cloud.cloud_config.config['image_api_version'] = '1'
self.cloud.config.config['image_api_version'] = '1'
# We override the scheme of the endpoint with the scheme of the service
# because glance has a bug where it doesn't return https properly.
self.assertEqual(
@ -946,7 +946,7 @@ class TestImageV1Only(base.RequestsMockTestCase):
self.assertTrue(self.cloud._is_client_version('image', 1))
def test_config_v2(self):
self.cloud.cloud_config.config['image_api_version'] = '2'
self.cloud.config.config['image_api_version'] = '2'
# We override the scheme of the endpoint with the scheme of the service
# because glance has a bug where it doesn't return https properly.
self.assertEqual(
@ -962,7 +962,7 @@ class TestImageV2Only(base.RequestsMockTestCase):
self.use_glance(image_version_json='image-version-v2.json')
def test_config_v1(self):
self.cloud.cloud_config.config['image_api_version'] = '1'
self.cloud.config.config['image_api_version'] = '1'
# We override the scheme of the endpoint with the scheme of the service
# because glance has a bug where it doesn't return https properly.
self.assertEqual(
@ -971,7 +971,7 @@ class TestImageV2Only(base.RequestsMockTestCase):
self.assertTrue(self.cloud._is_client_version('image', 2))
def test_config_v2(self):
self.cloud.cloud_config.config['image_api_version'] = '2'
self.cloud.config.config['image_api_version'] = '2'
# We override the scheme of the endpoint with the scheme of the service
# because glance has a bug where it doesn't return https properly.
self.assertEqual(

View File

@ -12,10 +12,8 @@
import mock
from openstack.cloud import exc
from openstack.cloud import inventory
import openstack.config
from openstack.config import exceptions as occ_exc
from openstack.tests import fakes
from openstack.tests.unit import base
@ -26,7 +24,7 @@ class TestInventory(base.TestCase):
super(TestInventory, self).setUp()
@mock.patch("openstack.config.loader.OpenStackConfig")
@mock.patch("openstack.cloud.OpenStackCloud")
@mock.patch("openstack.connection.Connection")
def test__init(self, mock_cloud, mock_config):
mock_config.return_value.get_all.return_value = [{}]
@ -40,7 +38,7 @@ class TestInventory(base.TestCase):
self.assertTrue(mock_config.return_value.get_all.called)
@mock.patch("openstack.config.loader.OpenStackConfig")
@mock.patch("openstack.cloud.OpenStackCloud")
@mock.patch("openstack.connection.Connection")
def test__init_one_cloud(self, mock_cloud, mock_config):
mock_config.return_value.get_one.return_value = [{}]
@ -56,23 +54,7 @@ class TestInventory(base.TestCase):
'supercloud')
@mock.patch("openstack.config.loader.OpenStackConfig")
@mock.patch("openstack.cloud.OpenStackCloud")
def test__raise_exception_on_no_cloud(self, mock_cloud, mock_config):
"""
Test that when os-client-config can't find a named cloud, a
shade exception is emitted.
"""
mock_config.return_value.get_one.side_effect = (
occ_exc.OpenStackConfigException()
)
self.assertRaises(exc.OpenStackCloudException,
inventory.OpenStackInventory,
cloud='supercloud')
mock_config.return_value.get_one.assert_called_once_with(
'supercloud')
@mock.patch("openstack.config.loader.OpenStackConfig")
@mock.patch("openstack.cloud.OpenStackCloud")
@mock.patch("openstack.connection.Connection")
def test_list_hosts(self, mock_cloud, mock_config):
mock_config.return_value.get_all.return_value = [{}]
@ -91,7 +73,7 @@ class TestInventory(base.TestCase):
self.assertEqual([server], ret)
@mock.patch("openstack.config.loader.OpenStackConfig")
@mock.patch("openstack.cloud.OpenStackCloud")
@mock.patch("openstack.connection.Connection")
def test_list_hosts_no_detail(self, mock_cloud, mock_config):
mock_config.return_value.get_all.return_value = [{}]
@ -110,7 +92,7 @@ class TestInventory(base.TestCase):
self.assertFalse(inv.clouds[0].get_openstack_vars.called)
@mock.patch("openstack.config.loader.OpenStackConfig")
@mock.patch("openstack.cloud.OpenStackCloud")
@mock.patch("openstack.connection.Connection")
def test_search_hosts(self, mock_cloud, mock_config):
mock_config.return_value.get_all.return_value = [{}]
@ -126,7 +108,7 @@ class TestInventory(base.TestCase):
self.assertEqual([server], ret)
@mock.patch("openstack.config.loader.OpenStackConfig")
@mock.patch("openstack.cloud.OpenStackCloud")
@mock.patch("openstack.connection.Connection")
def test_get_host(self, mock_cloud, mock_config):
mock_config.return_value.get_all.return_value = [{}]

View File

@ -1,4 +1,4 @@
# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
# Copyrigh
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -24,8 +24,12 @@ PUBLIC_V4 = '192.0.2.99'
PUBLIC_V6 = '2001:0db8:face:0da0:face::0b00:1c' # rfc3849
class FakeCloud(object):
class FakeConfig(object):
region_name = 'test-region'
class FakeCloud(object):
config = FakeConfig()
name = 'test-name'
private = False
force_ipv4 = False
@ -586,7 +590,7 @@ class TestMeta(base.RequestsMockTestCase):
def test_get_server_cloud_rackspace_v6(
self, mock_get_flavor_name, mock_get_image_name,
mock_get_volumes):
self.cloud.cloud_config.config['has_network'] = False
self.cloud.config.config['has_network'] = False
self.cloud._floating_ip_source = None
self.cloud.force_ipv4 = False
self.cloud._local_ipv6 = True
@ -830,7 +834,7 @@ class TestMeta(base.RequestsMockTestCase):
def test_get_server_external_ipv4_nova_public(self):
# Testing Clouds w/o Neutron and a network named public
self.cloud.cloud_config.config['has_network'] = False
self.cloud.config.config['has_network'] = False
srv = fakes.make_fake_server(
server_id='test-id', name='test-name', status='ACTIVE',
@ -841,7 +845,7 @@ class TestMeta(base.RequestsMockTestCase):
def test_get_server_external_ipv4_nova_none(self):
# Testing Clouds w/o Neutron or a globally routable IP
self.cloud.cloud_config.config['has_network'] = False
self.cloud.config.config['has_network'] = False
srv = fakes.make_fake_server(
server_id='test-id', name='test-name', status='ACTIVE',

View File

@ -46,7 +46,7 @@ class TestOperatorCloud(base.RequestsMockTestCase):
session_mock.get_endpoint.side_effect = side_effect
get_session_mock.return_value = session_mock
self.cloud.name = 'testcloud'
self.cloud.region_name = 'testregion'
self.cloud.config.region_name = 'testregion'
with testtools.ExpectedException(
exc.OpenStackCloudException,
"Error getting image endpoint on testcloud:testregion:"

View File

@ -30,7 +30,7 @@ class TestFromSession(base.RequestsMockTestCase):
def test_from_session(self):
config = cloud_region.from_session(
self.cloud.keystone_session, region_name=self.test_region)
self.cloud.session, region_name=self.test_region)
self.assertEqual(config.name, 'identity.example.com')
if not self.test_region:
self.assertIsNone(config.region_name)

View File

@ -0,0 +1,5 @@
---
features:
- |
All of the methods formerly part of the ``shade`` library have been added
to the `openstack.connection.Connection`` object.