Add OpenStackCloud object to Connection
Make a cloud attribute on Connection so that people with a Connection can also use shade features. This changes the default for shade's list_flavors to NOT fetching extra_specs, which is very much yay. Change-Id: I45a5f7f11a9c5ab3c77443a8f5df26089243334c
This commit is contained in:
parent
aff2b6ab40
commit
8483e1b139
openstack
@ -50,7 +50,6 @@ from openstack.cloud import meta
|
|||||||
from openstack.cloud import _utils
|
from openstack.cloud import _utils
|
||||||
import openstack.config
|
import openstack.config
|
||||||
import openstack.config.defaults
|
import openstack.config.defaults
|
||||||
import openstack.connection
|
|
||||||
from openstack import task_manager
|
from openstack import task_manager
|
||||||
from openstack import utils
|
from openstack import utils
|
||||||
|
|
||||||
@ -143,6 +142,7 @@ class OpenStackCloud(_normalize.Normalizer):
|
|||||||
app_name=None,
|
app_name=None,
|
||||||
app_version=None,
|
app_version=None,
|
||||||
use_direct_get=False,
|
use_direct_get=False,
|
||||||
|
conn=None,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
|
|
||||||
self.log = _log.setup_logging('openstack')
|
self.log = _log.setup_logging('openstack')
|
||||||
@ -162,12 +162,6 @@ class OpenStackCloud(_normalize.Normalizer):
|
|||||||
self.secgroup_source = cloud_config.config['secgroup_source']
|
self.secgroup_source = cloud_config.config['secgroup_source']
|
||||||
self.force_ipv4 = cloud_config.force_ipv4
|
self.force_ipv4 = cloud_config.force_ipv4
|
||||||
self.strict_mode = strict
|
self.strict_mode = strict
|
||||||
# TODO(shade) The openstack.cloud default for get_flavor_extra_specs
|
|
||||||
# should be changed and this should be removed completely
|
|
||||||
self._extra_config = cloud_config._openstack_config.get_extra_config(
|
|
||||||
'shade', {
|
|
||||||
'get_flavor_extra_specs': True,
|
|
||||||
})
|
|
||||||
|
|
||||||
if manager is not None:
|
if manager is not None:
|
||||||
self.manager = manager
|
self.manager = manager
|
||||||
@ -303,11 +297,14 @@ class OpenStackCloud(_normalize.Normalizer):
|
|||||||
_utils.localhost_supports_ipv6() if not self.force_ipv4 else False)
|
_utils.localhost_supports_ipv6() if not self.force_ipv4 else False)
|
||||||
|
|
||||||
self.cloud_config = cloud_config
|
self.cloud_config = cloud_config
|
||||||
self._conn_object = None
|
self._conn_object = conn
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _conn(self):
|
def _conn(self):
|
||||||
if not self._conn_object:
|
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(
|
self._conn_object = openstack.connection.Connection(
|
||||||
config=self.cloud_config, session=self._keystone_session)
|
config=self.cloud_config, session=self._keystone_session)
|
||||||
return self._conn_object
|
return self._conn_object
|
||||||
@ -1938,7 +1935,7 @@ class OpenStackCloud(_normalize.Normalizer):
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
@_utils.cache_on_arguments()
|
@_utils.cache_on_arguments()
|
||||||
def list_flavors(self, get_extra=None):
|
def list_flavors(self, get_extra=False):
|
||||||
"""List all available flavors.
|
"""List all available flavors.
|
||||||
|
|
||||||
:param get_extra: Whether or not to fetch extra specs for each flavor.
|
:param get_extra: Whether or not to fetch extra specs for each flavor.
|
||||||
@ -1948,8 +1945,6 @@ class OpenStackCloud(_normalize.Normalizer):
|
|||||||
:returns: A list of flavor ``munch.Munch``.
|
:returns: A list of flavor ``munch.Munch``.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if get_extra is None:
|
|
||||||
get_extra = self._extra_config['get_flavor_extra_specs']
|
|
||||||
data = _adapter._json_response(
|
data = _adapter._json_response(
|
||||||
self._conn.compute.get(
|
self._conn.compute.get(
|
||||||
'/flavors/detail', params=dict(is_public='None')),
|
'/flavors/detail', params=dict(is_public='None')),
|
||||||
@ -2986,7 +2981,7 @@ class OpenStackCloud(_normalize.Normalizer):
|
|||||||
self.search_flavors, get_extra=get_extra)
|
self.search_flavors, get_extra=get_extra)
|
||||||
return _utils._get_entity(self, search_func, name_or_id, filters)
|
return _utils._get_entity(self, search_func, name_or_id, filters)
|
||||||
|
|
||||||
def get_flavor_by_id(self, id, get_extra=True):
|
def get_flavor_by_id(self, id, get_extra=False):
|
||||||
""" Get a flavor by ID
|
""" Get a flavor by ID
|
||||||
|
|
||||||
:param id: ID of the flavor.
|
:param id: ID of the flavor.
|
||||||
@ -3002,9 +2997,6 @@ class OpenStackCloud(_normalize.Normalizer):
|
|||||||
flavor = self._normalize_flavor(
|
flavor = self._normalize_flavor(
|
||||||
self._get_and_munchify('flavor', data))
|
self._get_and_munchify('flavor', data))
|
||||||
|
|
||||||
if get_extra is None:
|
|
||||||
get_extra = self._extra_config['get_flavor_extra_specs']
|
|
||||||
|
|
||||||
if not flavor.extra_specs and get_extra:
|
if not flavor.extra_specs and get_extra:
|
||||||
endpoint = "/flavors/{id}/os-extra_specs".format(
|
endpoint = "/flavors/{id}/os-extra_specs".format(
|
||||||
id=flavor.id)
|
id=flavor.id)
|
||||||
|
@ -353,6 +353,7 @@ class CloudRegion(object):
|
|||||||
def get_cache_expiration_time(self):
|
def get_cache_expiration_time(self):
|
||||||
if self._openstack_config:
|
if self._openstack_config:
|
||||||
return self._openstack_config.get_cache_expiration_time()
|
return self._openstack_config.get_cache_expiration_time()
|
||||||
|
return 0
|
||||||
|
|
||||||
def get_cache_path(self):
|
def get_cache_path(self):
|
||||||
if self._openstack_config:
|
if self._openstack_config:
|
||||||
@ -361,6 +362,7 @@ class CloudRegion(object):
|
|||||||
def get_cache_class(self):
|
def get_cache_class(self):
|
||||||
if self._openstack_config:
|
if self._openstack_config:
|
||||||
return self._openstack_config.get_cache_class()
|
return self._openstack_config.get_cache_class()
|
||||||
|
return 'dogpile.cache.null'
|
||||||
|
|
||||||
def get_cache_arguments(self):
|
def get_cache_arguments(self):
|
||||||
if self._openstack_config:
|
if self._openstack_config:
|
||||||
@ -400,56 +402,56 @@ class CloudRegion(object):
|
|||||||
def get_external_networks(self):
|
def get_external_networks(self):
|
||||||
"""Get list of network names for external networks."""
|
"""Get list of network names for external networks."""
|
||||||
return [
|
return [
|
||||||
net['name'] for net in self.config['networks']
|
net['name'] for net in self.config.get('networks', [])
|
||||||
if net['routes_externally']]
|
if net['routes_externally']]
|
||||||
|
|
||||||
def get_external_ipv4_networks(self):
|
def get_external_ipv4_networks(self):
|
||||||
"""Get list of network names for external IPv4 networks."""
|
"""Get list of network names for external IPv4 networks."""
|
||||||
return [
|
return [
|
||||||
net['name'] for net in self.config['networks']
|
net['name'] for net in self.config.get('networks', [])
|
||||||
if net['routes_ipv4_externally']]
|
if net['routes_ipv4_externally']]
|
||||||
|
|
||||||
def get_external_ipv6_networks(self):
|
def get_external_ipv6_networks(self):
|
||||||
"""Get list of network names for external IPv6 networks."""
|
"""Get list of network names for external IPv6 networks."""
|
||||||
return [
|
return [
|
||||||
net['name'] for net in self.config['networks']
|
net['name'] for net in self.config.get('networks', [])
|
||||||
if net['routes_ipv6_externally']]
|
if net['routes_ipv6_externally']]
|
||||||
|
|
||||||
def get_internal_networks(self):
|
def get_internal_networks(self):
|
||||||
"""Get list of network names for internal networks."""
|
"""Get list of network names for internal networks."""
|
||||||
return [
|
return [
|
||||||
net['name'] for net in self.config['networks']
|
net['name'] for net in self.config.get('networks', [])
|
||||||
if not net['routes_externally']]
|
if not net['routes_externally']]
|
||||||
|
|
||||||
def get_internal_ipv4_networks(self):
|
def get_internal_ipv4_networks(self):
|
||||||
"""Get list of network names for internal IPv4 networks."""
|
"""Get list of network names for internal IPv4 networks."""
|
||||||
return [
|
return [
|
||||||
net['name'] for net in self.config['networks']
|
net['name'] for net in self.config.get('networks', [])
|
||||||
if not net['routes_ipv4_externally']]
|
if not net['routes_ipv4_externally']]
|
||||||
|
|
||||||
def get_internal_ipv6_networks(self):
|
def get_internal_ipv6_networks(self):
|
||||||
"""Get list of network names for internal IPv6 networks."""
|
"""Get list of network names for internal IPv6 networks."""
|
||||||
return [
|
return [
|
||||||
net['name'] for net in self.config['networks']
|
net['name'] for net in self.config.get('networks', [])
|
||||||
if not net['routes_ipv6_externally']]
|
if not net['routes_ipv6_externally']]
|
||||||
|
|
||||||
def get_default_network(self):
|
def get_default_network(self):
|
||||||
"""Get network used for default interactions."""
|
"""Get network used for default interactions."""
|
||||||
for net in self.config['networks']:
|
for net in self.config.get('networks', []):
|
||||||
if net['default_interface']:
|
if net['default_interface']:
|
||||||
return net['name']
|
return net['name']
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_nat_destination(self):
|
def get_nat_destination(self):
|
||||||
"""Get network used for NAT destination."""
|
"""Get network used for NAT destination."""
|
||||||
for net in self.config['networks']:
|
for net in self.config.get('networks', []):
|
||||||
if net['nat_destination']:
|
if net['nat_destination']:
|
||||||
return net['name']
|
return net['name']
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_nat_source(self):
|
def get_nat_source(self):
|
||||||
"""Get network used for NAT source."""
|
"""Get network used for NAT source."""
|
||||||
for net in self.config['networks']:
|
for net in self.config.get('networks', []):
|
||||||
if net.get('nat_source'):
|
if net.get('nat_source'):
|
||||||
return net['name']
|
return net['name']
|
||||||
return None
|
return None
|
||||||
|
@ -168,6 +168,7 @@ import six
|
|||||||
|
|
||||||
from openstack import _log
|
from openstack import _log
|
||||||
from openstack import _meta
|
from openstack import _meta
|
||||||
|
from openstack import cloud as _cloud
|
||||||
from openstack import config as _config
|
from openstack import config as _config
|
||||||
from openstack.config import cloud_region
|
from openstack.config import cloud_region
|
||||||
from openstack import exceptions
|
from openstack import exceptions
|
||||||
@ -311,6 +312,10 @@ class Connection(six.with_metaclass(_meta.ConnectionMeta)):
|
|||||||
self.session._sdk_connection = self
|
self.session._sdk_connection = self
|
||||||
|
|
||||||
self._proxies = {}
|
self._proxies = {}
|
||||||
|
self.cloud = _cloud.OpenStackCloud(
|
||||||
|
cloud_config=self.config,
|
||||||
|
manager=self.task_manager,
|
||||||
|
conn=self)
|
||||||
|
|
||||||
def add_service(self, service):
|
def add_service(self, service):
|
||||||
"""Add a service to the Connection.
|
"""Add a service to the Connection.
|
||||||
|
@ -157,7 +157,8 @@ class TestFlavor(base.BaseFunctionalTestCase):
|
|||||||
# Now set them
|
# Now set them
|
||||||
extra_specs = {'foo': 'aaa', 'bar': 'bbb'}
|
extra_specs = {'foo': 'aaa', 'bar': 'bbb'}
|
||||||
self.operator_cloud.set_flavor_specs(new_flavor['id'], extra_specs)
|
self.operator_cloud.set_flavor_specs(new_flavor['id'], extra_specs)
|
||||||
mod_flavor = self.operator_cloud.get_flavor(new_flavor['id'])
|
mod_flavor = self.operator_cloud.get_flavor(
|
||||||
|
new_flavor['id'], get_extra=True)
|
||||||
|
|
||||||
# Verify extra_specs were set
|
# Verify extra_specs were set
|
||||||
self.assertIn('extra_specs', mod_flavor)
|
self.assertIn('extra_specs', mod_flavor)
|
||||||
@ -165,7 +166,8 @@ class TestFlavor(base.BaseFunctionalTestCase):
|
|||||||
|
|
||||||
# Unset the 'foo' value
|
# Unset the 'foo' value
|
||||||
self.operator_cloud.unset_flavor_specs(mod_flavor['id'], ['foo'])
|
self.operator_cloud.unset_flavor_specs(mod_flavor['id'], ['foo'])
|
||||||
mod_flavor = self.operator_cloud.get_flavor_by_id(new_flavor['id'])
|
mod_flavor = self.operator_cloud.get_flavor_by_id(
|
||||||
|
new_flavor['id'], get_extra=True)
|
||||||
|
|
||||||
# Verify 'foo' is unset and 'bar' is still set
|
# Verify 'foo' is unset and 'bar' is still set
|
||||||
self.assertEqual({'bar': 'bbb'}, mod_flavor['extra_specs'])
|
self.assertEqual({'bar': 'bbb'}, mod_flavor['extra_specs'])
|
||||||
|
@ -437,12 +437,6 @@ class TestMemoryCache(base.RequestsMockTestCase):
|
|||||||
dict(method='GET', uri=mock_uri,
|
dict(method='GET', uri=mock_uri,
|
||||||
json={'flavors': fakes.FAKE_FLAVOR_LIST})
|
json={'flavors': fakes.FAKE_FLAVOR_LIST})
|
||||||
]
|
]
|
||||||
uris_to_mock.extend([
|
|
||||||
dict(method='GET',
|
|
||||||
uri='{endpoint}/flavors/{id}/os-extra_specs'.format(
|
|
||||||
endpoint=fakes.COMPUTE_ENDPOINT, id=flavor['id']),
|
|
||||||
json={'extra_specs': {}})
|
|
||||||
for flavor in fakes.FAKE_FLAVOR_LIST])
|
|
||||||
|
|
||||||
self.register_uris(uris_to_mock)
|
self.register_uris(uris_to_mock)
|
||||||
|
|
||||||
|
@ -82,6 +82,30 @@ class TestFlavors(base.RequestsMockTestCase):
|
|||||||
self.cloud.delete_flavor, 'vanilla')
|
self.cloud.delete_flavor, 'vanilla')
|
||||||
|
|
||||||
def test_list_flavors(self):
|
def test_list_flavors(self):
|
||||||
|
uris_to_mock = [
|
||||||
|
dict(method='GET',
|
||||||
|
uri='{endpoint}/flavors/detail?is_public=None'.format(
|
||||||
|
endpoint=fakes.COMPUTE_ENDPOINT),
|
||||||
|
json={'flavors': fakes.FAKE_FLAVOR_LIST}),
|
||||||
|
]
|
||||||
|
self.register_uris(uris_to_mock)
|
||||||
|
|
||||||
|
flavors = self.cloud.list_flavors()
|
||||||
|
|
||||||
|
# test that new flavor is created correctly
|
||||||
|
found = False
|
||||||
|
for flavor in flavors:
|
||||||
|
if flavor['name'] == 'vanilla':
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
self.assertTrue(found)
|
||||||
|
needed_keys = {'name', 'ram', 'vcpus', 'id', 'is_public', 'disk'}
|
||||||
|
if found:
|
||||||
|
# check flavor content
|
||||||
|
self.assertTrue(needed_keys.issubset(flavor.keys()))
|
||||||
|
self.assert_calls()
|
||||||
|
|
||||||
|
def test_list_flavors_with_extra(self):
|
||||||
uris_to_mock = [
|
uris_to_mock = [
|
||||||
dict(method='GET',
|
dict(method='GET',
|
||||||
uri='{endpoint}/flavors/detail?is_public=None'.format(
|
uri='{endpoint}/flavors/detail?is_public=None'.format(
|
||||||
@ -96,7 +120,7 @@ class TestFlavors(base.RequestsMockTestCase):
|
|||||||
for flavor in fakes.FAKE_FLAVOR_LIST])
|
for flavor in fakes.FAKE_FLAVOR_LIST])
|
||||||
self.register_uris(uris_to_mock)
|
self.register_uris(uris_to_mock)
|
||||||
|
|
||||||
flavors = self.cloud.list_flavors()
|
flavors = self.cloud.list_flavors(get_extra=True)
|
||||||
|
|
||||||
# test that new flavor is created correctly
|
# test that new flavor is created correctly
|
||||||
found = False
|
found = False
|
||||||
@ -238,6 +262,22 @@ class TestFlavors(base.RequestsMockTestCase):
|
|||||||
self.assert_calls()
|
self.assert_calls()
|
||||||
|
|
||||||
def test_get_flavor_by_id(self):
|
def test_get_flavor_by_id(self):
|
||||||
|
flavor_uri = '{endpoint}/flavors/1'.format(
|
||||||
|
endpoint=fakes.COMPUTE_ENDPOINT)
|
||||||
|
flavor_json = {'flavor': fakes.make_fake_flavor('1', 'vanilla')}
|
||||||
|
|
||||||
|
self.register_uris([
|
||||||
|
dict(method='GET', uri=flavor_uri, json=flavor_json),
|
||||||
|
])
|
||||||
|
|
||||||
|
flavor1 = self.cloud.get_flavor_by_id('1')
|
||||||
|
self.assertEqual('1', flavor1['id'])
|
||||||
|
self.assertEqual({}, flavor1.extra_specs)
|
||||||
|
flavor2 = self.cloud.get_flavor_by_id('1')
|
||||||
|
self.assertEqual('1', flavor2['id'])
|
||||||
|
self.assertEqual({}, flavor2.extra_specs)
|
||||||
|
|
||||||
|
def test_get_flavor_with_extra_specs(self):
|
||||||
flavor_uri = '{endpoint}/flavors/1'.format(
|
flavor_uri = '{endpoint}/flavors/1'.format(
|
||||||
endpoint=fakes.COMPUTE_ENDPOINT)
|
endpoint=fakes.COMPUTE_ENDPOINT)
|
||||||
flavor_extra_uri = '{endpoint}/flavors/1/os-extra_specs'.format(
|
flavor_extra_uri = '{endpoint}/flavors/1/os-extra_specs'.format(
|
||||||
@ -250,7 +290,7 @@ class TestFlavors(base.RequestsMockTestCase):
|
|||||||
dict(method='GET', uri=flavor_extra_uri, json=flavor_extra_json),
|
dict(method='GET', uri=flavor_extra_uri, json=flavor_extra_json),
|
||||||
])
|
])
|
||||||
|
|
||||||
flavor1 = self.cloud.get_flavor_by_id('1')
|
flavor1 = self.cloud.get_flavor_by_id('1', get_extra=True)
|
||||||
self.assertEqual('1', flavor1['id'])
|
self.assertEqual('1', flavor1['id'])
|
||||||
self.assertEqual({'name': 'test'}, flavor1.extra_specs)
|
self.assertEqual({'name': 'test'}, flavor1.extra_specs)
|
||||||
flavor2 = self.cloud.get_flavor_by_id('1', get_extra=False)
|
flavor2 = self.cloud.get_flavor_by_id('1', get_extra=False)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user