Merge "Add Instance and InstanceList v2.0 objects"

This commit is contained in:
Jenkins
2015-09-05 01:53:39 +00:00
committed by Gerrit Code Review
4 changed files with 139 additions and 64 deletions
+39 -2
View File
@@ -1043,8 +1043,29 @@ class InstanceV1(_BaseInstance):
getattr(self, attrname), ftype)
@base.NovaObjectRegistry.register
class InstanceV2(_BaseInstance):
# Version 2.0: Initial version
VERSION = '2.0'
def obj_make_compatible(self, primitive, target_version):
if target_version.startswith('1.'):
# NOTE(danms): Special case to backport to 1.x. Serialize
# ourselves, change the version, deserialize that, and get
# that to continue the backport of this primitive to
# whatever 1.x version was actually requested. We can get
# away with this because InstanceV2 is structurally a
# subset of V1.
# FIXME(danms): Remove this when we drop v1.x compatibility
my_prim = self.obj_to_primitive()
my_prim['nova_object.version'] = InstanceV1.VERSION
instv1 = InstanceV1.obj_from_primitive(my_prim)
return instv1.obj_make_compatible(primitive, target_version)
super(InstanceV2, self).obj_make_compatible(primitive, target_version)
# NOTE(danms): For the unit tests...
Instance = InstanceV1
Instance = InstanceV2
def _make_instance_list(context, inst_list, db_inst_list, expected_attrs):
@@ -1270,5 +1291,21 @@ class InstanceListV1(_BaseInstanceList):
}
@base.NovaObjectRegistry.register
class InstanceListV2(_BaseInstanceList):
# Version 2.0: Initial version
VERSION = '2.0'
NOVA_OBJ_INSTANCE_CLS = InstanceV2
def obj_make_compatible(self, primitive, target_version):
if target_version.startswith('1.'):
my_prim = self.obj_to_primitive()
my_prim['nova_object.version'] = InstanceListV1.VERSION
instv1 = InstanceListV1.obj_from_primitive(my_prim)
return instv1.obj_make_compatible(primitive, target_version)
super(InstanceListV2, self).obj_make_compatible(primitive,
target_version)
# NOTE(danms): For the unit tests...
InstanceList = InstanceListV1
InstanceList = InstanceListV2
+5 -3
View File
@@ -99,7 +99,9 @@ def fake_db_instance(**updates):
return db_instance
def fake_instance_obj(context, **updates):
def fake_instance_obj(context, obj_instance_class=None, **updates):
if obj_instance_class is None:
obj_instance_class = objects.Instance
expected_attrs = updates.pop('expected_attrs', None)
flavor = updates.pop('flavor', None)
if not flavor:
@@ -114,8 +116,8 @@ def fake_instance_obj(context, **updates):
extra_specs={},
projects=[])
flavor.obj_reset_changes()
inst = objects.Instance._from_db_object(context,
objects.Instance(), fake_db_instance(**updates),
inst = obj_instance_class._from_db_object(context,
obj_instance_class(), fake_db_instance(**updates),
expected_attrs=expected_attrs)
if flavor:
inst.flavor = flavor
+90 -56
View File
@@ -14,6 +14,7 @@
import datetime
import fixtures
import mock
from mox3 import mox
import netaddr
@@ -426,17 +427,6 @@ class _TestInstanceObject(object):
inst.save()
self.assertTrue(save_mock.called)
@mock.patch('nova.db.instance_update_and_get_original')
@mock.patch.object(instance._BaseInstance, '_from_db_object')
def test_save_skip_scheduled_at(self, mock_fdo, mock_update):
mock_update.return_value = None, None
inst = objects.Instance(context=self.context, id=123)
inst.uuid = 'foo'
inst.scheduled_at = None
inst.save()
self.assertNotIn('scheduled_at',
mock_update.call_args_list[0][0][2])
@mock.patch('nova.db.instance_update_and_get_original')
@mock.patch.object(instance._BaseInstance, '_from_db_object')
def test_save_does_not_refresh_pci_devices(self, mock_fdo, mock_update):
@@ -1049,40 +1039,6 @@ class _TestInstanceObject(object):
expected_attrs=['info_cache'])
self.assertIs(info_cache, inst.info_cache)
def test_compat_strings(self):
unicode_attributes = ['user_id', 'project_id', 'image_ref',
'kernel_id', 'ramdisk_id', 'hostname',
'key_name', 'key_data', 'host', 'node',
'user_data', 'availability_zone',
'display_name', 'display_description',
'launched_on', 'locked_by', 'os_type',
'architecture', 'vm_mode', 'root_device_name',
'default_ephemeral_device',
'default_swap_device', 'config_drive',
'cell_name']
inst = objects.Instance()
expected = {}
for key in unicode_attributes:
inst[key] = u'\u2603'
expected[key] = b'?'
primitive = inst.obj_to_primitive(target_version='1.6')
self.assertJsonEqual(expected, primitive['nova_object.data'])
self.assertEqual('1.6', primitive['nova_object.version'])
def test_compat_pci_devices(self):
inst = objects.Instance()
inst.pci_devices = pci_device.PciDeviceList()
primitive = inst.obj_to_primitive(target_version='1.5')
self.assertNotIn('pci_devices', primitive)
def test_compat_info_cache(self):
inst = objects.Instance()
inst.info_cache = instance_info_cache.InstanceInfoCache()
primitive = inst.obj_to_primitive(target_version='1.9')
self.assertEqual(
'1.4',
primitive['nova_object.data']['info_cache']['nova_object.version'])
@mock.patch('nova.objects.InstancePCIRequests.get_by_instance_uuid')
def test_get_with_pci_requests(self, mock_get):
mock_get.return_value = objects.InstancePCIRequests()
@@ -1286,16 +1242,6 @@ class _TestInstanceObject(object):
self.context, uuid, expected_attrs=['pci_requests'])
self.assertTrue(inst.obj_attr_is_set('pci_requests'))
def test_backport_flavor(self):
flavor = flavors.get_default_flavor()
inst = objects.Instance(context=self.context, flavor=flavor,
system_metadata={'foo': 'bar'},
new_flavor=None,
old_flavor=None)
primitive = inst.obj_to_primitive(target_version='1.17')
self.assertIn('instance_type_id',
primitive['nova_object.data']['system_metadata'])
class TestInstanceObject(test_objects._LocalTest,
_TestInstanceObject):
@@ -1325,7 +1271,95 @@ class TestInstanceObject(test_objects._LocalTest,
class TestRemoteInstanceObject(test_objects._RemoteTest,
_TestInstanceObject):
pass
def setUp(self):
super(TestRemoteInstanceObject, self).setUp()
self.useFixture(fixtures.MonkeyPatch('nova.objects.Instance',
instance.InstanceV2))
class TestInstanceV1RemoteObject(test_objects._RemoteTest,
_TestInstanceObject):
def setUp(self):
super(TestInstanceV1RemoteObject, self).setUp()
self.useFixture(fixtures.MonkeyPatch('nova.objects.Instance',
instance.InstanceV1))
@mock.patch('nova.db.instance_update_and_get_original')
@mock.patch.object(instance._BaseInstance, '_from_db_object')
def test_save_skip_scheduled_at(self, mock_fdo, mock_update):
mock_update.return_value = None, None
inst = objects.Instance(context=self.context, id=123)
inst.uuid = 'foo'
inst.scheduled_at = None
inst.save()
self.assertNotIn('scheduled_at',
mock_update.call_args_list[0][0][2])
def test_backport_flavor(self):
flavor = flavors.get_default_flavor()
inst = objects.Instance(context=self.context, flavor=flavor,
system_metadata={'foo': 'bar'},
new_flavor=None,
old_flavor=None)
primitive = inst.obj_to_primitive(target_version='1.17')
self.assertIn('instance_type_id',
primitive['nova_object.data']['system_metadata'])
def test_compat_strings(self):
unicode_attributes = ['user_id', 'project_id', 'image_ref',
'kernel_id', 'ramdisk_id', 'hostname',
'key_name', 'key_data', 'host', 'node',
'user_data', 'availability_zone',
'display_name', 'display_description',
'launched_on', 'locked_by', 'os_type',
'architecture', 'vm_mode', 'root_device_name',
'default_ephemeral_device',
'default_swap_device', 'config_drive',
'cell_name']
inst = objects.Instance()
expected = {}
for key in unicode_attributes:
inst[key] = u'\u2603'
expected[key] = b'?'
primitive = inst.obj_to_primitive(target_version='1.6')
self.assertJsonEqual(expected, primitive['nova_object.data'])
self.assertEqual('1.6', primitive['nova_object.version'])
def test_compat_pci_devices(self):
inst = objects.Instance()
inst.pci_devices = pci_device.PciDeviceList()
primitive = inst.obj_to_primitive(target_version='1.5')
self.assertNotIn('pci_devices', primitive)
def test_compat_info_cache(self):
inst = objects.Instance()
inst.info_cache = instance_info_cache.InstanceInfoCache()
primitive = inst.obj_to_primitive(target_version='1.9')
self.assertEqual(
'1.4',
primitive['nova_object.data']['info_cache']['nova_object.version'])
def test_backport_v2_to_v1(self):
inst2 = fake_instance.fake_instance_obj(
self.context, obj_instance_class=instance.InstanceV2)
inst1 = instance.InstanceV1.obj_from_primitive(
inst2.obj_to_primitive(target_version=instance.InstanceV1.VERSION))
self.assertEqual(instance.InstanceV1.VERSION, inst1.VERSION)
self.assertIsInstance(inst1, instance.InstanceV1)
self.assertEqual(inst2.uuid, inst1.uuid)
def test_backport_list_v2_to_v1(self):
inst2 = fake_instance.fake_instance_obj(
self.context, obj_instance_class=instance.InstanceV2)
list2 = instance.InstanceListV2(objects=[inst2])
list1 = instance.InstanceListV1.obj_from_primitive(
list2.obj_to_primitive(
target_version=instance.InstanceListV1.VERSION))
self.assertEqual(instance.InstanceListV1.VERSION, list1.VERSION)
self.assertEqual(instance.InstanceV1.VERSION, list1[0].VERSION)
self.assertIsInstance(list1, instance.InstanceListV1)
self.assertIsInstance(list1[0], instance.InstanceV1)
self.assertEqual(list2[0].uuid, list1[0].uuid)
class _TestInstanceListObject(object):
+5 -3
View File
@@ -1186,7 +1186,8 @@ object_data = {
'HVSpec': '1.1-6b4f7c0f688cbd03e24142a44eb9010d',
'ImageMeta': '1.6-642d1b2eb3e880a367f37d72dd76162d',
'ImageMetaProps': '1.6-07a6d9f3576c4927220331584661ce45',
'Instance': '1.23-4e68422207667f4abff5fa730a5edc98',
'Instance': '2.0-ff56804dce87d81d9a04834d4bd1e3d2',
'Instance1': '1.23-4e68422207667f4abff5fa730a5edc98',
'InstanceAction': '1.1-f9f293e526b66fca0d05c3b3a2d13914',
'InstanceActionEvent': '1.1-e56a64fa4710e43ef7af2ad9d6028b33',
'InstanceActionEventList': '1.1-13d92fb953030cdbfee56481756e02be',
@@ -1197,7 +1198,8 @@ object_data = {
'InstanceGroup': '1.10-1a0c8c7447dc7ecb9da53849430c4a5f',
'InstanceGroupList': '1.7-be18078220513316abd0ae1b2d916873',
'InstanceInfoCache': '1.5-cd8b96fefe0fc8d4d337243ba0bf0e1e',
'InstanceList': '1.22-6c8ba6147cca3082b1e4643f795068bf',
'InstanceList': '2.0-6c8ba6147cca3082b1e4643f795068bf',
'InstanceList1': '1.22-6c8ba6147cca3082b1e4643f795068bf',
'InstanceMapping': '1.0-47ef26034dfcbea78427565d9177fe50',
'InstanceMappingList': '1.0-9e982e3de1613b9ada85e35f69b23d47',
'InstanceNUMACell': '1.2-535ef30e0de2d6a0d26a71bd58ecafc4',
@@ -1380,7 +1382,7 @@ class TestObjectVersions(test.NoDBTestCase):
# 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 = []
new_objects = ['Instance', 'InstanceList']
versions = base.NovaObjectRegistry.obj_classes()[name]
if len(versions) > 1 and name in new_objects: