Merge "Clean up tests for dropping obj_relationships"
This commit is contained in:
commit
2009b8831b
@ -75,46 +75,6 @@ class NovaObject(ovoo_base.VersionedObject):
|
||||
OBJ_SERIAL_NAMESPACE = 'nova_object'
|
||||
OBJ_PROJECT_NAMESPACE = 'nova'
|
||||
|
||||
# NOTE(danms): Keep the compatibility bits in nova separate from o.vo
|
||||
# for the time being so that we can keep changes required to use
|
||||
# the base version of those risky methods separate from the rest of the
|
||||
# simple inherited methods.
|
||||
def obj_calculate_child_version(self, target_version, child):
|
||||
"""Calculate the appropriate version for a child object.
|
||||
|
||||
This is to be used when backporting an object for an older client.
|
||||
A sub-object will need to be backported to a suitable version for
|
||||
the client as well, and this method will calculate what that
|
||||
version should be, based on obj_relationships.
|
||||
|
||||
:param target_version: Version this object is being backported to
|
||||
:param child: The child field for which the appropriate version
|
||||
is to be calculated
|
||||
:returns: None if the child should be omitted from the backport,
|
||||
otherwise, the version to which the child should be
|
||||
backported
|
||||
"""
|
||||
target_version = utils.convert_version_to_tuple(target_version)
|
||||
for index, versions in enumerate(self.obj_relationships[child]):
|
||||
my_version, child_version = versions
|
||||
my_version = utils.convert_version_to_tuple(my_version)
|
||||
if target_version < my_version:
|
||||
if index == 0:
|
||||
# We're backporting to a version from before this
|
||||
# subobject was added: delete it from the primitive.
|
||||
return None
|
||||
else:
|
||||
# We're in the gap between index-1 and index, so
|
||||
# backport to the older version
|
||||
return self.obj_relationships[child][index - 1][1]
|
||||
elif target_version == my_version:
|
||||
# This is the first mapping that satisfies the
|
||||
# target_version request: backport the object.
|
||||
return child_version
|
||||
# No need to backport, as far as we know, so return the latest
|
||||
# version of the sub-object we know about
|
||||
return self.obj_relationships[child][-1][1]
|
||||
|
||||
# NOTE(danms): This has some minor change between the nova and o.vo
|
||||
# version, so avoid inheriting it for the moment so we can make that
|
||||
# transition separately for clarity.
|
||||
|
@ -17,6 +17,7 @@ import mock
|
||||
import netaddr
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_utils import timeutils
|
||||
from oslo_versionedobjects import base as ovo_base
|
||||
from oslo_versionedobjects import exception as ovo_exc
|
||||
|
||||
from nova import db
|
||||
@ -429,13 +430,17 @@ class _TestComputeNodeObject(object):
|
||||
|
||||
def test_compat_numa_topology(self):
|
||||
compute = compute_node.ComputeNode()
|
||||
primitive = compute.obj_to_primitive(target_version='1.4')
|
||||
versions = ovo_base.obj_tree_get_versions('ComputeNode')
|
||||
primitive = compute.obj_to_primitive(target_version='1.4',
|
||||
version_manifest=versions)
|
||||
self.assertNotIn('numa_topology', primitive)
|
||||
|
||||
def test_compat_supported_hv_specs(self):
|
||||
compute = compute_node.ComputeNode()
|
||||
compute.supported_hv_specs = fake_supported_hv_specs
|
||||
primitive = compute.obj_to_primitive(target_version='1.5')
|
||||
versions = ovo_base.obj_tree_get_versions('ComputeNode')
|
||||
primitive = compute.obj_to_primitive(target_version='1.5',
|
||||
version_manifest=versions)
|
||||
self.assertNotIn('supported_hv_specs', primitive)
|
||||
|
||||
def test_compat_host(self):
|
||||
@ -446,7 +451,9 @@ class _TestComputeNodeObject(object):
|
||||
def test_compat_pci_device_pools(self):
|
||||
compute = compute_node.ComputeNode()
|
||||
compute.pci_device_pools = fake_pci_device_pools.fake_pool_list
|
||||
primitive = compute.obj_to_primitive(target_version='1.8')
|
||||
versions = ovo_base.obj_tree_get_versions('ComputeNode')
|
||||
primitive = compute.obj_to_primitive(target_version='1.8',
|
||||
version_manifest=versions)
|
||||
self.assertNotIn('pci_device_pools', primitive)
|
||||
|
||||
@mock.patch('nova.objects.Service.get_by_compute_host')
|
||||
|
@ -18,6 +18,7 @@ import iso8601
|
||||
import mock
|
||||
import netaddr
|
||||
from oslo_utils import timeutils
|
||||
from oslo_versionedobjects import base as ovo_base
|
||||
|
||||
from nova import exception
|
||||
from nova.objects import fixed_ip
|
||||
@ -349,7 +350,11 @@ class _TestFixedIPObject(object):
|
||||
self.context, {'id': 0}, host='fake-host')
|
||||
primitive = fixed_ips[0].obj_to_primitive()
|
||||
self.assertIn('default_route', primitive['nova_object.data'])
|
||||
fixed_ips[0].obj_make_compatible(primitive['nova_object.data'], '1.1')
|
||||
versions = ovo_base.obj_tree_get_versions('FixedIP')
|
||||
fixed_ips[0].obj_make_compatible_from_manifest(
|
||||
primitive['nova_object.data'],
|
||||
target_version='1.1',
|
||||
version_manifest=versions)
|
||||
self.assertNotIn('default_route', primitive['nova_object.data'])
|
||||
|
||||
|
||||
|
@ -15,6 +15,8 @@
|
||||
import mock
|
||||
import netaddr
|
||||
|
||||
from oslo_versionedobjects import base as ovo_base
|
||||
|
||||
from nova import exception
|
||||
from nova import objects
|
||||
from nova.objects import floating_ip
|
||||
@ -245,7 +247,10 @@ class _TestFloatingIPObject(object):
|
||||
floating = objects.FloatingIP()
|
||||
fixed = objects.FixedIP()
|
||||
floating.fixed_ip = fixed
|
||||
primitive = floating.obj_to_primitive(target_version='1.1')
|
||||
versions = ovo_base.obj_tree_get_versions('FloatingIP')
|
||||
versions['FixedIP'] = '1.1'
|
||||
primitive = floating.obj_to_primitive(target_version='1.1',
|
||||
version_manifest=versions)
|
||||
self.assertEqual('1.1',
|
||||
primitive['nova_object.data']['fixed_ip']['nova_object.version'])
|
||||
|
||||
|
@ -133,14 +133,6 @@ class _TestNUMA(object):
|
||||
inst_cell = objects.NUMACell()
|
||||
self.assertEqual(0, len(inst_cell.obj_get_changes()))
|
||||
|
||||
def test_obj_cell_relationships(self):
|
||||
obj = objects.NUMATopology(cells=[objects.NUMACell()])
|
||||
rel = objects.NUMATopology.obj_relationships['cells']
|
||||
for topo_ver, cell_ver in rel:
|
||||
prim = obj.obj_to_primitive(target_version=topo_ver)
|
||||
cell = objects.NUMATopology.obj_from_primitive(prim).cells[0]
|
||||
self.assertEqual(cell_ver, cell.VERSION)
|
||||
|
||||
def test_numa_pages_equivalent(self):
|
||||
pt1 = objects.NUMAPagesTopology(size_kb=1024, total=32, used=0)
|
||||
pt2 = objects.NUMAPagesTopology(size_kb=1024, total=32, used=0)
|
||||
|
@ -1382,79 +1382,6 @@ class TestObjectVersions(test.NoDBTestCase):
|
||||
return field._type._element_type._type._obj_name
|
||||
return None
|
||||
|
||||
def _get_obj_cls(self, name):
|
||||
# NOTE(danms): We're moving to using manifest-based backports,
|
||||
# which don't depend on relationships. Given that we only had
|
||||
# one major version of each object before that change, we can
|
||||
# make sure to pull the older version of objects that have
|
||||
# a 2.0 version while calculating the old-style relationship
|
||||
# mapping. Once we drop all the 1.x versions, we can drop this
|
||||
# relationship test altogether.
|
||||
new_objects = ['Instance', 'InstanceList']
|
||||
|
||||
versions = base.NovaObjectRegistry.obj_classes()[name]
|
||||
if len(versions) > 1 and name in new_objects:
|
||||
return versions[1]
|
||||
else:
|
||||
return versions[0]
|
||||
|
||||
def _build_tree(self, tree, obj_class, get_current_versions=True):
|
||||
obj_name = obj_class.obj_name()
|
||||
if obj_name in tree:
|
||||
return
|
||||
|
||||
for name, field in obj_class.fields.items():
|
||||
sub_obj_name = self._get_object_field_name(field)
|
||||
if sub_obj_name:
|
||||
sub_obj_class = self._get_obj_cls(sub_obj_name)
|
||||
tree.setdefault(obj_name, {})
|
||||
if get_current_versions:
|
||||
sub_obj_ver = sub_obj_class.VERSION
|
||||
else:
|
||||
# get the most recent subobject version
|
||||
# from obj_relationships
|
||||
sub_obj_ver = obj_class.obj_relationships[name][-1][1]
|
||||
tree[obj_name][sub_obj_name] = sub_obj_ver
|
||||
|
||||
def test_relationships(self):
|
||||
# This test asserts that the obj_relationship map of all objects
|
||||
# contain the current versions of any subobjects.
|
||||
current_versions_tree = {}
|
||||
obj_relationships_tree = {}
|
||||
obj_classes = base.NovaObjectRegistry.obj_classes()
|
||||
for obj_name in obj_classes.keys():
|
||||
obj_cls = self._get_obj_cls(obj_name)
|
||||
self._build_tree(current_versions_tree, obj_cls)
|
||||
self._build_tree(obj_relationships_tree, obj_cls,
|
||||
get_current_versions=False)
|
||||
|
||||
stored = set([(x, str(y))
|
||||
for x, y in obj_relationships_tree.items()])
|
||||
computed = set([(x, str(y))
|
||||
for x, y in current_versions_tree.items()])
|
||||
changed = stored.symmetric_difference(computed)
|
||||
expected = {}
|
||||
actual = {}
|
||||
for name, deps in changed:
|
||||
expected[name] = current_versions_tree.get(name)
|
||||
actual[name] = obj_relationships_tree.get(name)
|
||||
|
||||
# If this assertion is failing, this means an object is holding a
|
||||
# non-current version of another object.
|
||||
# Example: if Instance is bumped from version 1.1 to 1.2,
|
||||
# and InstanceList is still only has obj_relationships with 1.1,
|
||||
# this assertion will fail. InstanceList will need to also be bumped
|
||||
# a version, with the relationship to Instance 1.2 added.
|
||||
self.assertEqual(expected, actual,
|
||||
'Some objects have changed dependencies. '
|
||||
'Please make sure to bump the versions of '
|
||||
'parent objects and provide a rule in their '
|
||||
'obj_make_compatible() routines to backlevel '
|
||||
'the child object. The expected dict is the '
|
||||
'current versions of all objects held by other '
|
||||
'objects, and the actual dict is what is held '
|
||||
'within obj_relationships on the given objects.')
|
||||
|
||||
def test_obj_make_compatible(self):
|
||||
# Iterate all object classes and verify that we can run
|
||||
# obj_make_compatible with every older version than current.
|
||||
@ -1463,13 +1390,15 @@ class TestObjectVersions(test.NoDBTestCase):
|
||||
# expecting the wrong version format.
|
||||
obj_classes = base.NovaObjectRegistry.obj_classes()
|
||||
for obj_name in obj_classes:
|
||||
versions = ovo_base.obj_tree_get_versions(obj_name)
|
||||
obj_class = obj_classes[obj_name][0]
|
||||
version = utils.convert_version_to_tuple(obj_class.VERSION)
|
||||
for n in range(version[1]):
|
||||
test_version = '%d.%d' % (version[0], n)
|
||||
LOG.info('testing obj: %s version: %s' %
|
||||
(obj_name, test_version))
|
||||
obj_class().obj_to_primitive(target_version=test_version)
|
||||
obj_class().obj_to_primitive(target_version=test_version,
|
||||
version_manifest=versions)
|
||||
|
||||
def test_list_obj_make_compatible(self):
|
||||
@base.NovaObjectRegistry.register_if(False)
|
||||
@ -1527,190 +1456,6 @@ class TestObjectVersions(test.NoDBTestCase):
|
||||
"List was backported to before 'objects' existed."
|
||||
" 'objects' should not be in the primitive.")
|
||||
|
||||
def test_obj_bad_relationships(self):
|
||||
# Make sure having an object with bad relationships is caught by
|
||||
# _build_tree()
|
||||
@base.NovaObjectRegistry.register
|
||||
class TestObj(base.NovaObject):
|
||||
VERSION = '1.1'
|
||||
fields = {'foo': fields.IntegerField()}
|
||||
|
||||
@base.NovaObjectRegistry.register
|
||||
class OtherTestObj(base.NovaObject):
|
||||
VERSION = '1.2'
|
||||
fields = {'test': fields.ObjectField('TestObj')}
|
||||
obj_relationships = {'test': [('1.0', '1.0')]}
|
||||
|
||||
current_versions_tree = {}
|
||||
obj_relationships_tree = {}
|
||||
obj_classes = base.NovaObjectRegistry.obj_classes()
|
||||
expected_current = {'OtherTestObj': {'TestObj': '1.1'}}
|
||||
self._build_tree(current_versions_tree,
|
||||
obj_classes['OtherTestObj'][0])
|
||||
|
||||
expected_obj_relationships = {'OtherTestObj': {'TestObj': '1.0'}}
|
||||
self._build_tree(obj_relationships_tree,
|
||||
obj_classes['OtherTestObj'][0],
|
||||
get_current_versions=False)
|
||||
|
||||
self.assertEqual(expected_current, current_versions_tree)
|
||||
self.assertEqual(expected_obj_relationships, obj_relationships_tree)
|
||||
|
||||
def _get_obj_same_major(self, this_cls, obj_name):
|
||||
this_major = this_cls.VERSION.split('.')[0]
|
||||
obj_classes = base.NovaObjectRegistry.obj_classes()
|
||||
for cls_version in obj_classes[obj_name]:
|
||||
major = cls_version.VERSION.split('.')[0]
|
||||
if major == this_major:
|
||||
return cls_version
|
||||
|
||||
def _get_obj_to_test(self, obj_class):
|
||||
obj = obj_class()
|
||||
for fname, ftype in obj.fields.items():
|
||||
if isinstance(ftype, fields.ObjectField):
|
||||
fobjname = ftype.AUTO_TYPE._obj_name
|
||||
fobjcls = self._get_obj_same_major(obj_class, fobjname)
|
||||
setattr(obj, fname, self._get_obj_to_test(fobjcls))
|
||||
elif isinstance(ftype, fields.ListOfObjectsField):
|
||||
# FIXME(danms): This will result in no tests for this
|
||||
# field type...
|
||||
setattr(obj, fname, [])
|
||||
return obj
|
||||
|
||||
def _find_version_mapping(self, my_ver, versions):
|
||||
closest = None
|
||||
my_ver = utils.convert_version_to_tuple(my_ver)
|
||||
for _my, _child in versions:
|
||||
_my = utils.convert_version_to_tuple(_my)
|
||||
_child = utils.convert_version_to_tuple(_child)
|
||||
if _my == my_ver:
|
||||
return '%s.%s' % _child
|
||||
elif _my < my_ver:
|
||||
closest = _child
|
||||
if closest:
|
||||
return '%s.%s' % closest
|
||||
else:
|
||||
return None
|
||||
|
||||
def _validate_object_fields(self, obj_class, primitive):
|
||||
for fname, ftype in obj_class.fields.items():
|
||||
if isinstance(ftype, fields.ObjectField):
|
||||
exp_vers = obj_class.obj_relationships[fname]
|
||||
exp_ver = self._find_version_mapping(
|
||||
primitive['nova_object.version'], exp_vers)
|
||||
if exp_ver is None:
|
||||
self.assertNotIn(fname, primitive['nova_object.data'])
|
||||
else:
|
||||
child_p = primitive['nova_object.data'][fname]
|
||||
self.assertEqual(exp_ver,
|
||||
child_p['nova_object.version'])
|
||||
|
||||
def test_obj_make_compatible_with_data(self):
|
||||
# Iterate all object classes and verify that we can run
|
||||
# obj_make_compatible with every older version than current.
|
||||
# This doesn't actually test the data conversions, but it at least
|
||||
# makes sure the method doesn't blow up on something basic like
|
||||
# expecting the wrong version format.
|
||||
obj_classes = base.NovaObjectRegistry.obj_classes()
|
||||
for obj_name in obj_classes:
|
||||
for obj_class in obj_classes[obj_name]:
|
||||
if obj_class.VERSION.startswith('2'):
|
||||
# NOTE(danms): Objects with major versions >=2 will
|
||||
# use version_manifest for backports, which is a
|
||||
# different test than this one, so skip.
|
||||
continue
|
||||
if 'tests.unit' in obj_class.__module__:
|
||||
# NOTE(danms): Skip test objects. When we move to
|
||||
# oslo.versionedobjects, we won't have to do this
|
||||
continue
|
||||
version = utils.convert_version_to_tuple(obj_class.VERSION)
|
||||
for n in range(version[1]):
|
||||
test_version = '%d.%d' % (version[0], n)
|
||||
LOG.info('testing obj: %s version: %s' %
|
||||
(obj_name, test_version))
|
||||
test_object = self._get_obj_to_test(obj_class)
|
||||
obj_p = test_object.obj_to_primitive(
|
||||
target_version=test_version)
|
||||
self._validate_object_fields(obj_class, obj_p)
|
||||
|
||||
def test_obj_relationships_in_order(self):
|
||||
# Iterate all object classes and verify that we can run
|
||||
# obj_make_compatible with every older version than current.
|
||||
# This doesn't actually test the data conversions, but it at least
|
||||
# makes sure the method doesn't blow up on something basic like
|
||||
# expecting the wrong version format.
|
||||
obj_classes = base.NovaObjectRegistry.obj_classes()
|
||||
for obj_name in obj_classes:
|
||||
obj_class = obj_classes[obj_name][0]
|
||||
for field, versions in obj_class.obj_relationships.items():
|
||||
last_my_version = (0, 0)
|
||||
last_child_version = (0, 0)
|
||||
for my_version, child_version in versions:
|
||||
_my_version = utils.convert_version_to_tuple(my_version)
|
||||
_ch_version = utils.convert_version_to_tuple(child_version)
|
||||
self.assertTrue((last_my_version < _my_version
|
||||
and last_child_version <= _ch_version),
|
||||
'Object %s relationship '
|
||||
'%s->%s for field %s is out of order' % (
|
||||
obj_name, my_version, child_version,
|
||||
field))
|
||||
last_my_version = _my_version
|
||||
last_child_version = _ch_version
|
||||
|
||||
def test_objects_use_obj_relationships(self):
|
||||
obj_classes = base.NovaObjectRegistry.obj_classes()
|
||||
for obj_name in obj_classes:
|
||||
obj_class = obj_classes[obj_name][0]
|
||||
self.assertFalse((hasattr(obj_class, 'child_versions')
|
||||
and obj_class.child_versions),
|
||||
'Object %s should be using obj_relationships, '
|
||||
'not child_versions.' % obj_name)
|
||||
|
||||
def test_obj_relationships_not_past_current_parent_version(self):
|
||||
# Iterate all object classes to verify that all versions of the parent
|
||||
# held in obj_relationships are at or before the current version
|
||||
obj_classes = base.NovaObjectRegistry.obj_classes()
|
||||
for obj_name in obj_classes:
|
||||
obj_class = obj_classes[obj_name][0]
|
||||
cur_version = utils.convert_version_to_tuple(obj_class.VERSION)
|
||||
for field, versions in obj_class.obj_relationships.items():
|
||||
for my_version, child_version in versions:
|
||||
tup_version = utils.convert_version_to_tuple(my_version)
|
||||
self.assertTrue(tup_version <= cur_version,
|
||||
"Field '%(field)s' of %(obj)s contains a "
|
||||
"relationship that is past the current "
|
||||
"version. Relationship version is %(ov)s."
|
||||
" Current version is %(cv)s." %
|
||||
{'field': field, 'obj': obj_name,
|
||||
'ov': my_version,
|
||||
'cv': obj_class.VERSION})
|
||||
|
||||
def test_obj_relationships_not_past_current_child_version(self):
|
||||
# Iterate all object classes to verify that all versions of subobjects
|
||||
# held in obj_relationships are at or before the current version
|
||||
obj_classes = base.NovaObjectRegistry.obj_classes()
|
||||
for obj_name in obj_classes:
|
||||
obj_class = obj_classes[obj_name][0]
|
||||
for field, versions in obj_class.obj_relationships.items():
|
||||
obj_field = obj_class.fields[field]
|
||||
child_name = self._get_object_field_name(obj_field)
|
||||
child_class = obj_classes[child_name][0]
|
||||
curr_child_ver = child_class.VERSION
|
||||
tup_curr_child_ver = utils.convert_version_to_tuple(
|
||||
curr_child_ver)
|
||||
|
||||
for parent_ver, child_ver in versions:
|
||||
tup_version = utils.convert_version_to_tuple(child_ver)
|
||||
self.assertTrue(tup_version <= tup_curr_child_ver,
|
||||
"Field '%(field)s' of %(obj)s contains a "
|
||||
"relationship that is past the current "
|
||||
"version of %(child_obj)s. Relationship "
|
||||
"version is %(ov)s. Current version is "
|
||||
"%(cv)s." %
|
||||
{'field': field, 'obj': obj_name,
|
||||
'child_obj': child_name,
|
||||
'ov': child_ver, 'cv': curr_child_ver})
|
||||
|
||||
|
||||
class TestObjEqualPrims(_BaseTestCase):
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user