diff --git a/nova/objects/migrate_data.py b/nova/objects/migrate_data.py index a42d1dbc6c..bab85f4d2e 100644 --- a/nova/objects/migrate_data.py +++ b/nova/objects/migrate_data.py @@ -256,7 +256,8 @@ class LibvirtLiveMigrateData(LiveMigrateData): # source_mdev_types and target_mdevs fields # Version 1.12: Added dst_cpu_shared_set_info # Version 1.13: Inherited pci_dev_map_src_dst from LiveMigrateData - VERSION = '1.13' + # Version 1.14: Added vtpm_secret_uuid and vtpm_secret_value + VERSION = '1.14' fields = { 'filename': fields.StringField(), @@ -295,12 +296,29 @@ class LibvirtLiveMigrateData(LiveMigrateData): # key is source mdev UUID and value is the destination mdev UUID. 'target_mdevs': fields.DictOfStringsField(), 'dst_cpu_shared_set_info': fields.SetOfIntegersField(), + 'vtpm_secret_uuid': fields.UUIDField(nullable=True), + 'vtpm_secret_value': fields.SensitiveStringField(nullable=True), } def obj_make_compatible(self, primitive, target_version): super(LibvirtLiveMigrateData, self).obj_make_compatible( primitive, target_version) target_version = versionutils.convert_version_to_tuple(target_version) + if (target_version < (1, 14)): + # In an object primitive, a field will be included if and only if + # it is set to something (including None, if the field is + # nullable). So instances with no vTPM will not have these fields + # set. + vtpm_fields = ['vtpm_secret_uuid', 'vtpm_secret_value'] + if any(field in vtpm_fields for field in primitive): + # If either field is set, then we know this object was passed + # from newer compute which could support vTPM live migration. + # We raise here instead of silently removing the fields because + # we cannot backport the object to something compatible. + raise exception.ObjectActionError( + action='obj_make_compatible', + reason='Unable to backport newer vTPM support to ' + 'requested version %d.%d' % target_version) if (target_version < (1, 13)): primitive.pop('pci_dev_map_src_dst', None) if (target_version < (1, 12)): diff --git a/nova/tests/unit/objects/test_migrate_data.py b/nova/tests/unit/objects/test_migrate_data.py index 14759a721d..830d0516ca 100644 --- a/nova/tests/unit/objects/test_migrate_data.py +++ b/nova/tests/unit/objects/test_migrate_data.py @@ -161,6 +161,18 @@ class _TestLibvirtLiveMigrateData(object): self.assertIn( 'encryption_secret_uuid', primitive['nova_object.data']) + def test_vtpm_obj_make_compatible(self): + obj = migrate_data.LibvirtLiveMigrateData( + vtpm_secret_uuid=uuids.vtpm_secret, + vtpm_secret_value='password') + manifest = ovo_base.obj_tree_get_versions(obj.obj_name()) + ex = self.assertRaises( + exception.ObjectActionError, obj.obj_to_primitive, + target_version='1.13', version_manifest=manifest) + self.assertIn( + 'Unable to backport newer vTPM support to requested version ' + '1.13', str(ex)) + def test_vif_migrate_data(self): source_vif = network_model.VIF( id=uuids.port_id, diff --git a/nova/tests/unit/objects/test_objects.py b/nova/tests/unit/objects/test_objects.py index 4a60fd4086..d96b372dac 100644 --- a/nova/tests/unit/objects/test_objects.py +++ b/nova/tests/unit/objects/test_objects.py @@ -1128,7 +1128,7 @@ object_data = { 'KeyPair': '1.4-1244e8d1b103cc69d038ed78ab3a8cc6', 'KeyPairList': '1.3-94aad3ac5c938eef4b5e83da0212f506', 'LibvirtLiveMigrateBDMInfo': '1.1-5f4a68873560b6f834b74e7861d71aaf', - 'LibvirtLiveMigrateData': '1.13-c92e9c98bfccafe84e52c08efbec41d8', + 'LibvirtLiveMigrateData': '1.14-0d605656259dc382c242f7496419ca76', 'LibvirtLiveMigrateNUMAInfo': '1.0-0e777677f3459d0ed1634eabbdb6c22f', 'LibvirtVPMEMDevice': '1.0-17ffaf47585199eeb9a2b83d6bde069f', 'MemoryDiagnostics': '1.0-2c995ae0f2223bb0f8e523c5cc0b83da',