diff --git a/nova/tests/functional/regressions/test_bug_2062425.py b/nova/tests/functional/regressions/test_bug_2062425.py index b7e6156b566f..42899cff7e39 100644 --- a/nova/tests/functional/regressions/test_bug_2062425.py +++ b/nova/tests/functional/regressions/test_bug_2062425.py @@ -25,6 +25,7 @@ class TestSchedulingForImageCPUProperty(base.ServersTestBase): reference arch list https://docs.openstack.org/glance/latest/admin/useful-image-properties.html#image-property-keys-and-values + https://github.com/openstack/nova/blob/df5454021543e8aa3c73289224158c9090f0da6a/nova/scheduler/request_filter.py#L208-L216 """ microversion = 'latest' @@ -41,12 +42,21 @@ class TestSchedulingForImageCPUProperty(base.ServersTestBase): cpu_arch_image['id'] = uuids.cpu_arch_image self.glance.create(None, cpu_arch_image) - server = self._create_server( + self._create_server( image_uuid=uuids.cpu_arch_image, networks='none', - # FIXME(auniyal): Server failed to spawn - expected_state='ERROR' + expected_state='ACTIVE' + ) + + def test_server_create_with_valid_emul_arch(self): + emul_arch = "x86_64" + emul_image = copy.deepcopy(self.glance.image1) + emul_image['properties']['hw_emulation_architecture'] = emul_arch + emul_image['id'] = uuids.emul_image + self.glance.create(None, emul_image) + + self._create_server( + image_uuid=uuids.emul_image, + networks='none', + expected_state='ACTIVE' ) - # this is a bug, with valid hw_arch, - # scheduler should be able to find host - self.assertIn("No valid host was found", server['fault']['message']) diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index e56e9759bf51..c8e41977253c 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -3609,6 +3609,16 @@ class LibvirtConnTestCase(test.NoDBTestCase, mock_designer.assert_called_once_with(cfg) + @mock.patch.object(host.Host, 'get_domain_capabilities') + def test__get_cpu_emulation_arch_traits(self, fake_domain_caps): + self._setup_fake_domain_caps(fake_domain_caps) + # as in mock setup we have set {'x86_64': {'q35': domain_caps}} + expected = {'COMPUTE_ARCH_X86_64': True} + drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True) + traits = drvr._get_cpu_emulation_arch_traits() + # traits must be a dict object + self.assertDictEqual(traits, expected) + def test_get_guest_memory_backing_config_file_backed(self): self.flags(file_backed_memory=1024, group="libvirt") @@ -28584,6 +28594,21 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin): '''], 1) + def _fake_get_host_capabilities(self, **args): + cpu = vconfig.LibvirtConfigGuestCPU() + cpu.arch = fields.Architecture.X86_64 + + caps = vconfig.LibvirtConfigCaps() + caps.host = vconfig.LibvirtConfigCapsHost() + caps.host.cpu = cpu + return caps + + def test__get_cpu_arch_traits(self): + with mock.patch.object(host.Host, "get_capabilities", + side_effect=self._fake_get_host_capabilities): + traits = self.drvr._get_cpu_arch_traits() + self.assertTrue(traits.get('HW_ARCH_X86_64')) + @mock.patch('oslo_utils.fileutils.ensure_tree') @mock.patch('os.path.isdir') @mock.patch('os.path.exists') diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 2d57941e68fc..405ad252618b 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -13083,6 +13083,8 @@ class LibvirtDriver(driver.ComputeDriver): traits = self._get_cpu_feature_traits() traits[ot.HW_CPU_X86_AMD_SEV] = self._host.supports_amd_sev traits[ot.HW_CPU_HYPERTHREADING] = self._host.has_hyperthreading + traits.update(self._get_cpu_arch_traits()) + traits.update(self._get_cpu_emulation_arch_traits()) return traits @@ -13151,6 +13153,28 @@ class LibvirtDriver(driver.ComputeDriver): return libvirt_utils.cpu_features_to_traits(features) + def _get_cpu_arch_traits(self): + """Get CPU arch trait based on the host arch. + """ + arch = self._host.get_capabilities().host.cpu.arch.upper() + # we only set for valid arch, rest will be assumed invalid + trait = 'HW_ARCH_' + arch + return {trait: trait in ot.get_traits(prefix='HW_ARCH_')} + + def _get_cpu_emulation_arch_traits(self): + """Get CPU arch emulation traits + """ + # get list of architecture supported by host for + # hw emulation + caps = self._host.get_domain_capabilities().keys() + traits = {} + for arch in caps: + trait = 'COMPUTE_ARCH_' + arch.upper() + if trait in ot.get_traits(prefix='COMPUTE_ARCH_'): + traits[trait] = True + + return traits + def _get_guest_baseline_cpu_features(self, xml_str): """Calls libvirt's baselineCPU API to compute the biggest set of CPU features which is compatible with the given host CPU.