Merge "Improve compute flavor handling"
This commit is contained in:
commit
9d3ee1d321
@ -43,18 +43,20 @@ class Flavor(resource.Resource):
|
||||
#: The description of the flavor.
|
||||
description = resource.Body('description')
|
||||
#: Size of the disk this flavor offers. *Type: int*
|
||||
disk = resource.Body('disk', type=int)
|
||||
disk = resource.Body('disk', type=int, default=0)
|
||||
#: ``True`` if this is a publicly visible flavor. ``False`` if this is
|
||||
#: a private image. *Type: bool*
|
||||
is_public = resource.Body('os-flavor-access:is_public', type=bool)
|
||||
is_public = resource.Body(
|
||||
'os-flavor-access:is_public', type=bool, default=True)
|
||||
#: The amount of RAM (in MB) this flavor offers. *Type: int*
|
||||
ram = resource.Body('ram', type=int)
|
||||
ram = resource.Body('ram', type=int, default=0)
|
||||
#: The number of virtual CPUs this flavor offers. *Type: int*
|
||||
vcpus = resource.Body('vcpus', type=int)
|
||||
vcpus = resource.Body('vcpus', type=int, default=0)
|
||||
#: Size of the swap partitions.
|
||||
swap = resource.Body('swap')
|
||||
swap = resource.Body('swap', default=0)
|
||||
#: Size of the ephemeral data disk attached to this server. *Type: int*
|
||||
ephemeral = resource.Body('OS-FLV-EXT-DATA:ephemeral', type=int)
|
||||
ephemeral = resource.Body(
|
||||
'OS-FLV-EXT-DATA:ephemeral', type=int, default=0)
|
||||
#: ``True`` if this flavor is disabled, ``False`` if not. *Type: bool*
|
||||
is_disabled = resource.Body('OS-FLV-DISABLED:disabled', type=bool)
|
||||
#: The bandwidth scaling factor this flavor receives on the network.
|
||||
@ -64,6 +66,25 @@ class Flavor(resource.Resource):
|
||||
#: A dictionary of the flavor's extra-specs key-and-value pairs.
|
||||
extra_specs = resource.Body('extra_specs', type=dict, default={})
|
||||
|
||||
def __getattribute__(self, name):
|
||||
"""Return an attribute on this instance
|
||||
|
||||
This is mostly a pass-through except for a specialization on
|
||||
the 'id' name, as this can exist under a different name via the
|
||||
`alternate_id` argument to resource.Body.
|
||||
"""
|
||||
if name == "id":
|
||||
# ID handling in flavor is very tricky. Sometimes we get ID back,
|
||||
# sometimes we get only name (but it is same as id), sometimes we
|
||||
# get original_name back, but it is still id.
|
||||
# To get this handled try sequentially to access it from various
|
||||
# places until we find first non-empty value.
|
||||
for xname in ["id", "name", "original_name"]:
|
||||
if xname in self._body and self._body[xname]:
|
||||
return self._body[xname]
|
||||
else:
|
||||
return super().__getattribute__(name)
|
||||
|
||||
@classmethod
|
||||
def list(cls, session, paginated=True, base_path='/flavors/detail',
|
||||
allow_unknown_params=False, **params):
|
||||
|
@ -11,6 +11,7 @@
|
||||
# under the License.
|
||||
from openstack.common import metadata
|
||||
from openstack.common import tag
|
||||
from openstack.compute.v2 import flavor
|
||||
from openstack.compute.v2 import volume_attachment
|
||||
from openstack import exceptions
|
||||
from openstack.image.v2 import image
|
||||
@ -109,8 +110,7 @@ class Server(resource.Resource, metadata.MetadataMixin, tag.TagMixin):
|
||||
#: this server.
|
||||
flavor_id = resource.Body('flavorRef')
|
||||
#: The flavor property as returned from server.
|
||||
# TODO(gtema): replace with flavor.Flavor addressing flavor.original_name
|
||||
flavor = resource.Body('flavor', type=dict)
|
||||
flavor = resource.Body('flavor', type=flavor.Flavor)
|
||||
#: Indicates whether a configuration drive enables metadata injection.
|
||||
#: Not all cloud providers enable this feature.
|
||||
has_config_drive = resource.Body('config_drive')
|
||||
|
@ -47,7 +47,6 @@ class TestInventory(base.BaseFunctionalTest):
|
||||
|
||||
def _test_host_content(self, host):
|
||||
self.assertEqual(host['image']['id'], self.image.id)
|
||||
self.assertNotIn('id', host['flavor'])
|
||||
self.assertIsInstance(host['volumes'], list)
|
||||
self.assertIsInstance(host['metadata'], dict)
|
||||
self.assertIn('interface_ip', host)
|
||||
@ -78,9 +77,6 @@ class TestInventory(base.BaseFunctionalTest):
|
||||
self.assertEqual(host['image']['id'], self.image.id)
|
||||
self.assertNotIn('links', host['image'])
|
||||
self.assertNotIn('name', host['name'])
|
||||
self.assertNotIn('id', host['flavor'])
|
||||
self.assertNotIn('links', host['flavor'])
|
||||
self.assertNotIn('name', host['flavor'])
|
||||
self.assertIn('ram', host['flavor'])
|
||||
|
||||
host_found = False
|
||||
|
@ -33,6 +33,11 @@ BASIC_EXAMPLE = {
|
||||
'OS-FLV-DISABLED:disabled': False,
|
||||
'rxtx_factor': 11.0
|
||||
}
|
||||
DEFAULTS_EXAMPLE = {
|
||||
'links': '2',
|
||||
'original_name': IDENTIFIER,
|
||||
'description': 'Testing flavor',
|
||||
}
|
||||
|
||||
|
||||
class TestFlavor(base.TestCase):
|
||||
@ -80,6 +85,28 @@ class TestFlavor(base.TestCase):
|
||||
sot.is_disabled)
|
||||
self.assertEqual(BASIC_EXAMPLE['rxtx_factor'], sot.rxtx_factor)
|
||||
|
||||
def test_make_defaults(self):
|
||||
sot = flavor.Flavor(**DEFAULTS_EXAMPLE)
|
||||
self.assertEqual(DEFAULTS_EXAMPLE['original_name'], sot.name)
|
||||
self.assertEqual(0, sot.disk)
|
||||
self.assertEqual(True, sot.is_public)
|
||||
self.assertEqual(0, sot.ram)
|
||||
self.assertEqual(0, sot.vcpus)
|
||||
self.assertEqual(0, sot.swap)
|
||||
self.assertEqual(0, sot.ephemeral)
|
||||
self.assertEqual(IDENTIFIER, sot.id)
|
||||
|
||||
def test_flavor_id(self):
|
||||
id = 'fake_id'
|
||||
sot = flavor.Flavor(id=id)
|
||||
self.assertEqual(sot.id, id)
|
||||
sot = flavor.Flavor(name=id)
|
||||
self.assertEqual(sot.id, id)
|
||||
self.assertEqual(sot.name, id)
|
||||
sot = flavor.Flavor(original_name=id)
|
||||
self.assertEqual(sot.id, id)
|
||||
self.assertEqual(sot.original_name, id)
|
||||
|
||||
def test_add_tenant_access(self):
|
||||
sot = flavor.Flavor(**BASIC_EXAMPLE)
|
||||
resp = mock.Mock()
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
from unittest import mock
|
||||
|
||||
from openstack.compute.v2 import flavor
|
||||
from openstack.compute.v2 import server
|
||||
from openstack.image.v2 import image
|
||||
from openstack.tests.unit import base
|
||||
@ -64,7 +65,6 @@ EXAMPLE = {
|
||||
'original_name': 'm1.tiny.specs',
|
||||
'ram': 512,
|
||||
'swap': 0,
|
||||
'vcpus': 1
|
||||
},
|
||||
'hostId': '2091634baaccdc4c5a1d57069c833e402921df696b7f970791b12ec6',
|
||||
'host_status': 'UP',
|
||||
@ -194,7 +194,7 @@ class TestServer(base.TestCase):
|
||||
self.assertEqual(EXAMPLE['created'], sot.created_at)
|
||||
self.assertEqual(EXAMPLE['config_drive'], sot.has_config_drive)
|
||||
self.assertEqual(EXAMPLE['flavorRef'], sot.flavor_id)
|
||||
self.assertEqual(EXAMPLE['flavor'], sot.flavor)
|
||||
self.assertEqual(flavor.Flavor(**EXAMPLE['flavor']), sot.flavor)
|
||||
self.assertEqual(EXAMPLE['hostId'], sot.host_id)
|
||||
self.assertEqual(EXAMPLE['host_status'], sot.host_status)
|
||||
self.assertEqual(EXAMPLE['id'], sot.id)
|
||||
@ -251,6 +251,13 @@ class TestServer(base.TestCase):
|
||||
self.assertEqual(EXAMPLE['trusted_image_certificates'],
|
||||
sot.trusted_image_certificates)
|
||||
|
||||
def test_to_dict_flavor(self):
|
||||
# Ensure to_dict properly resolves flavor and uses defaults for not
|
||||
# specified flavor proerties.
|
||||
sot = server.Server(**EXAMPLE)
|
||||
dct = sot.to_dict()
|
||||
self.assertEqual(0, dct['flavor']['vcpus'])
|
||||
|
||||
def test__prepare_server(self):
|
||||
zone = 1
|
||||
data = 2
|
||||
|
Loading…
x
Reference in New Issue
Block a user