diff --git a/nova/tests/fixtures.py b/nova/tests/fixtures.py index 6fa360abef8f..17c89f4db901 100644 --- a/nova/tests/fixtures.py +++ b/nova/tests/fixtures.py @@ -3174,5 +3174,16 @@ class GenericPoisonFixture(fixtures.Fixture): super(GenericPoisonFixture, self).setUp() for meth, why in self.POISON_THESE: - self.useFixture(fixtures.MonkeyPatch( - meth, poison_configure(meth, why))) + # attempt to mock only if not already mocked + location, attribute = meth.rsplit('.', 1) + components = location.split('.') + try: + current = __import__(components[0], {}, {}) + for component in components[1:]: + current = getattr(current, component) + if not isinstance(getattr(current, attribute), mock.Mock): + self.useFixture(fixtures.MonkeyPatch( + meth, poison_configure(meth, why))) + except ImportError: + self.useFixture(fixtures.MonkeyPatch( + meth, poison_configure(meth, why))) diff --git a/nova/tests/unit/virt/libvirt/fake_libvirt_data.py b/nova/tests/unit/virt/libvirt/fake_libvirt_data.py index ad10e151a9d7..75f0fd4bf42d 100644 --- a/nova/tests/unit/virt/libvirt/fake_libvirt_data.py +++ b/nova/tests/unit/virt/libvirt/fake_libvirt_data.py @@ -249,8 +249,7 @@ FAKE_KVM_GUEST = """ """ - -CAPABILITIES_HOST_TEMPLATE = ''' +CAPABILITIES_HOST_X86_64_TEMPLATE = """ cef19ce0-0ca2-11df-855d-b19fbce37686 @@ -271,6 +270,9 @@ CAPABILITIES_HOST_TEMPLATE = ''' + + + @@ -283,7 +285,114 @@ CAPABILITIES_HOST_TEMPLATE = ''' apparmor 0 - ''' + """ + +# NOTE(stephenfin): This is incomplete +CAPABILITIES_HOST_I686_TEMPLATE = """ + + cef19ce0-0ca2-11df-855d-b19fbce37686 + + i686 + + + + """ + +CAPABILITIES_HOST_AARCH64_TEMPLATE = """ + + cef19ce0-0ca2-11df-855d-b19fbce37686 + + aarch64 + host + + + + + + + + + tcp + rdma + + + %(topology)s + + apparmor + 0 + + + dac + 0 + +0:+0 + +0:+0 + + """ + +# NOTE(stephenfin): This is incomplete +CAPABILITIES_HOST_ARMV7_TEMPLATE = """ + + + armv7l + + + + """ + +# NOTE(stephenfin): This is incomplete +CAPABILITIES_HOST_PPC_TEMPLATE = """ + + cef19ce0-0ca2-11df-855d-b19fbce37686 + + ppc + + + + """ + +# NOTE(stephenfin): This is incomplete +CAPABILITIES_HOST_PPC64_TEMPLATE = """ + + cef19ce0-0ca2-11df-855d-b19fbce37686 + + ppc64 + + + + """ + +# NOTE(stephenfin): This is incomplete +CAPABILITIES_HOST_PPC64LE_TEMPLATE = """ + + cef19ce0-0ca2-11df-855d-b19fbce37686 + + ppc64le + + + + """ + +# NOTE(stephenfin): This is incomplete +CAPABILITIES_HOST_S390X_TEMPLATE = """ + + cef19ce0-0ca2-11df-855d-b19fbce37686 + + s390x + + + + """ + +CAPABILITIES_HOST_TEMPLATES = { + Architecture.X86_64: CAPABILITIES_HOST_X86_64_TEMPLATE, + Architecture.I686: CAPABILITIES_HOST_I686_TEMPLATE, + Architecture.AARCH64: CAPABILITIES_HOST_AARCH64_TEMPLATE, + Architecture.ARMV7: CAPABILITIES_HOST_ARMV7_TEMPLATE, + Architecture.PPC: CAPABILITIES_HOST_PPC_TEMPLATE, + Architecture.PPC64: CAPABILITIES_HOST_PPC64_TEMPLATE, + Architecture.PPC64LE: CAPABILITIES_HOST_PPC64LE_TEMPLATE, + Architecture.S390X: CAPABILITIES_HOST_S390X_TEMPLATE, +} # NOTE(aspiers): HostTestCase has tests which assert that for any # given (arch, domain) listed in the guest capabilities here, all @@ -500,6 +609,100 @@ CAPABILITIES_GUEST = { ''', + 'aarch64': ''' + + hvm + + 64 + /usr/bin/qemu-system-aarch64 + integratorcp + ast2600-evb + borzoi + spitz + virt-2.7 + nuri + mcimx7d-sabre + romulus-bmc + virt-3.0 + virt-5.0 + virt-2.10 + virt-2.8 + musca-b1 + realview-pbx-a9 + versatileab + kzm + musca-a + virt-3.1 + mcimx6ul-evk + virt-5.1 + virt + smdkc210 + sx1 + raspi2 + virt-2.11 + imx25-pdk + virt-2.9 + orangepi-pc + z2 + xilinx-zynq-a9 + xlnx-zcu102 + raspi3 + tosa + virt-2.12 + mps2-an521 + sabrelite + mps2-an511 + canon-a1100 + realview-eb + emcraft-sf2 + realview-pb-a8 + sbsa-ref + virt-4.0 + palmetto-bmc + sx1-v1 + n810 + tacoma-bmc + n800 + virt-4.1 + versatilepb + terrier + mainstone + realview-eb-mpcore + virt-4.2 + witherspoon-bmc + swift-bmc + vexpress-a9 + midway + musicpal + lm3s811evb + lm3s6965evb + microbit + mps2-an505 + mps2-an385 + cubieboard + verdex + netduino2 + xlnx-versal-virt + vexpress-a15 + sonorapass-bmc + cheetah + virt-2.6 + ast2500-evb + highbank + akita + connex + netduinoplus2 + collie + + + + + + + + + ''', + 'armv7l': ''' hvm @@ -628,20 +831,6 @@ CAPABILITIES_GUEST = { ''' } -CAPABILITIES_TEMPLATE = ( - "\n" + - CAPABILITIES_HOST_TEMPLATE + - CAPABILITIES_GUEST['i686'] + - CAPABILITIES_GUEST['x86_64'] + - CAPABILITIES_GUEST['armv7l'] + - CAPABILITIES_GUEST['mips'] + - CAPABILITIES_GUEST['mipsel'] + - CAPABILITIES_GUEST['sparc'] + - CAPABILITIES_GUEST['ppc'] + - "\n" -) - - DOMCAPABILITIES_SPARC = """ /usr/bin/qemu-system-sparc @@ -719,7 +908,7 @@ DOMCAPABILITIES_SPARC = """ """ -DOMCAPABILITIES_ARMV7L = """ +DOMCAPABILITIES_ARMV7 = """ /usr/bin/qemu-system-arm qemu @@ -836,6 +1025,164 @@ DOMCAPABILITIES_ARMV7L = """ """ +DOMCAPABILITIES_AARCH64 = """ + + /usr/bin/qemu-system-aarch64 + qemu + virt-5.1 + aarch64 + + + + + efi + + + /usr/share/AAVMF/AAVMF_CODE.fd + + rom + pflash + + + yes + no + + + no + yes + + + + + + + + pxa270-c0 + cortex-a15 + pxa270-b0 + cortex-a57 + cortex-m4 + pxa270-a0 + arm1176 + pxa270-b1 + cortex-a7 + pxa270-a1 + cortex-a8 + cortex-r5 + ti925t + cortex-r5f + arm1026 + cortex-a9 + cortex-m7 + pxa270 + pxa260 + pxa250 + pxa270-c5 + pxa261 + pxa262 + sa1110 + sa1100 + max + cortex-a53 + cortex-m0 + cortex-m33 + cortex-a72 + arm946 + pxa255 + arm11mpcore + arm926 + arm1136 + arm1136-r2 + cortex-m3 + + + + + + disk + cdrom + floppy + lun + + + fdc + scsi + virtio + usb + sata + + + virtio + virtio-transitional + virtio-non-transitional + + + + + sdl + vnc + spice + + + + + + subsystem + + + default + mandatory + requisite + optional + + + usb + pci + scsi + + + + + + + virtio + virtio-transitional + virtio-non-transitional + + + random + egd + builtin + + + + + + + 2 + 3 + + + + + + + + + +""" + DOMCAPABILITIES_PPC = """ /usr/bin/qemu-system-ppc @@ -1234,7 +1581,8 @@ DOMCAPABILITIES_I686 = """ """ STATIC_DOMCAPABILITIES = { - Architecture.ARMV7: DOMCAPABILITIES_ARMV7L, + Architecture.ARMV7: DOMCAPABILITIES_ARMV7, + Architecture.AARCH64: DOMCAPABILITIES_AARCH64, Architecture.SPARC: DOMCAPABILITIES_SPARC, Architecture.PPC: DOMCAPABILITIES_PPC, Architecture.MIPS: DOMCAPABILITIES_MIPS, diff --git a/nova/tests/unit/virt/libvirt/fakelibvirt.py b/nova/tests/unit/virt/libvirt/fakelibvirt.py index 878f7ebd9e36..99e2ed03775e 100644 --- a/nova/tests/unit/virt/libvirt/fakelibvirt.py +++ b/nova/tests/unit/virt/libvirt/fakelibvirt.py @@ -13,6 +13,7 @@ # under the License. import collections +import os import sys import textwrap import time @@ -1607,11 +1608,22 @@ class Connection(object): cpu_map = [True for cpu_num in range(total_cpus)] return (total_cpus, cpu_map, total_cpus) - def getDomainCapabilities(self, emulatorbin, arch, machine_type, - virt_type, flags): + def getDomainCapabilities( + self, emulatorbin, arch, machine_type, virt_type, flags, + ): """Return spoofed domain capabilities.""" if arch in fake_libvirt_data.STATIC_DOMCAPABILITIES: - return fake_libvirt_data.STATIC_DOMCAPABILITIES[arch] + xml = fake_libvirt_data.STATIC_DOMCAPABILITIES[arch] + if machine_type: + # if we request a specific machine type, we should get + # information on that and not something else + tree = etree.fromstring(xml) + if machine_type not in tree.find('./machine').text: + raise Exception( + 'Expected machine type of ~%s but got %s' % ( + machine_type, tree.find('./machine').text, + )) + return xml if arch == 'x86_64': aliases = {'pc': 'pc-i440fx-2.11', 'q35': 'pc-q35-2.11'} @@ -1706,11 +1718,21 @@ class Connection(object): if isinstance(numa_topology, vconfig.LibvirtConfigCapsNUMATopology): numa_topology = numa_topology.to_xml() - return (fake_libvirt_data.CAPABILITIES_TEMPLATE - % {'sockets': self.host_info.cpu_sockets, - 'cores': self.host_info.cpu_cores, - 'threads': self.host_info.cpu_threads, - 'topology': numa_topology}) + # we rely on os.uname() having been mocked already to ensure we have + # the correct "host" architecture + _capabilities = [ + '\n', + fake_libvirt_data.CAPABILITIES_HOST_TEMPLATES[os.uname().machine], + ] + list(fake_libvirt_data.CAPABILITIES_GUEST.values()) + [ + '', + ] + + return ''.join(_capabilities) % { + 'sockets': self.host_info.cpu_sockets, + 'cores': self.host_info.cpu_cores, + 'threads': self.host_info.cpu_threads, + 'topology': numa_topology, + } def compareCPU(self, xml, flags): tree = etree.fromstring(xml) @@ -1941,6 +1963,14 @@ class FakeLibvirtFixture(fixtures.Fixture): self.useFixture( fixtures.MockPatch('os.uname', return_value=fake_uname)) + # Ensure UEFI checks don't actually check the host + def fake_has_uefi_support(): + return os.uname().machine == obj_fields.Architecture.AARCH64 + + self.useFixture(fixtures.MockPatch( + 'nova.virt.libvirt.driver.LibvirtDriver._has_uefi_support', + side_effect=fake_has_uefi_support)) + disable_event_thread(self) if self.stub_os_vif: diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index 16969c29f569..5f34695ff177 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -5252,26 +5252,6 @@ class LibvirtConnTestCase(test.NoDBTestCase, self.assertIsInstance(cfg.devices[10], vconfig.LibvirtConfigMemoryBalloon) - def test_has_uefi_support_not_supported_arch(self): - drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True) - self._stub_host_capabilities_cpu_arch(fields.Architecture.ALPHA) - self.assertFalse(drvr._has_uefi_support()) - - @mock.patch('os.path.exists', return_value=False) - def test_has_uefi_support_with_no_loader_existed(self, mock_exist): - drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True) - self.assertFalse(drvr._has_uefi_support()) - - @mock.patch('os.path.exists', return_value=True) - def test_has_uefi_support(self, mock_has_version): - drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True) - - self._stub_host_capabilities_cpu_arch(fields.Architecture.X86_64) - - with mock.patch.object(drvr._host, - 'has_min_version', return_value=True): - self.assertTrue(drvr._has_uefi_support()) - def test_get_guest_config_with_uefi(self): drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True) @@ -5290,11 +5270,11 @@ class LibvirtConnTestCase(test.NoDBTestCase, mock_support.assert_called_once_with() self.assertEqual(cfg.os_loader_type, "pflash") - @mock.patch('os.path.exists', return_value=True) - def test_check_uefi_support_aarch64(self, mock_exist): + def test_check_uefi_support_aarch64(self): + self.mock_uname.return_value = fakelibvirt.os_uname( + 'Linux', '', '5.4.0-0-generic', '', fields.Architecture.AARCH64) drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True) - self._stub_host_capabilities_cpu_arch(fields.Architecture.AARCH64) - self.assertTrue(drvr._has_uefi_support()) + drvr._has_uefi_support = mock.Mock(return_value=True) self.assertTrue(drvr._check_uefi_support(None)) def test_get_guest_config_with_block_device(self): @@ -7653,16 +7633,6 @@ class LibvirtConnTestCase(test.NoDBTestCase, "_get_guest_storage_config") @mock.patch.object(libvirt_driver.LibvirtDriver, "_has_numa_support") def test_get_guest_config_armv7(self, mock_numa, mock_storage): - - def get_host_capabilities_stub(self): - cpu = vconfig.LibvirtConfigGuestCPU() - cpu.arch = fields.Architecture.ARMV7 - - caps = vconfig.LibvirtConfigCaps() - caps.host = vconfig.LibvirtConfigCapsHost() - caps.host.cpu = cpu - return caps - self.flags(virt_type="kvm", group="libvirt") self.mock_uname.return_value = fakelibvirt.os_uname( 'Linux', '', '5.4.0-0-generic', '', fields.Architecture.ARMV7) @@ -7674,9 +7644,6 @@ class LibvirtConnTestCase(test.NoDBTestCase, instance_ref, image_meta) - self.stub_out('nova.virt.libvirt.host.Host.get_capabilities', - get_host_capabilities_stub) - drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True) cfg = drvr._get_guest_config(instance_ref, _fake_network_info(self), @@ -7691,22 +7658,11 @@ class LibvirtConnTestCase(test.NoDBTestCase, def test_get_guest_config_aarch64( self, mock_path_exists, mock_numa, mock_storage, ): - - def get_host_capabilities_stub(self): - cpu = vconfig.LibvirtConfigGuestCPU() - cpu.arch = fields.Architecture.AARCH64 - - caps = vconfig.LibvirtConfigCaps() - caps.host = vconfig.LibvirtConfigCapsHost() - caps.host.cpu = cpu - return caps - TEST_AMOUNT_OF_PCIE_SLOTS = 8 CONF.set_override("num_pcie_ports", TEST_AMOUNT_OF_PCIE_SLOTS, group='libvirt') - self.flags(virt_type="kvm", - group="libvirt") + self.flags(virt_type="kvm", group="libvirt") self.mock_uname.return_value = fakelibvirt.os_uname( 'Linux', '', '5.4.0-0-generic', '', fields.Architecture.AARCH64) @@ -7717,9 +7673,6 @@ class LibvirtConnTestCase(test.NoDBTestCase, instance_ref, image_meta) - self.stub_out('nova.virt.libvirt.host.Host.get_capabilities', - get_host_capabilities_stub) - drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True) cfg = drvr._get_guest_config(instance_ref, _fake_network_info(self), @@ -7749,20 +7702,8 @@ class LibvirtConnTestCase(test.NoDBTestCase, def test_get_guest_config_aarch64_with_graphics( self, mock_path_exists, mock_numa, mock_storage, ): - - def get_host_capabilities_stub(self): - cpu = vconfig.LibvirtConfigGuestCPU() - cpu.arch = fields.Architecture.AARCH64 - - caps = vconfig.LibvirtConfigCaps() - caps.host = vconfig.LibvirtConfigCapsHost() - caps.host.cpu = cpu - return caps - self.mock_uname.return_value = fakelibvirt.os_uname( 'Linux', '', '5.4.0-0-generic', '', fields.Architecture.AARCH64) - self.stub_out('nova.virt.libvirt.host.Host.get_capabilities', - get_host_capabilities_stub) self.flags(enabled=True, server_listen='10.0.0.1', group='vnc') self.flags(virt_type='kvm', group='libvirt') self.flags(enabled=False, group='spice') @@ -8061,27 +8002,19 @@ class LibvirtConnTestCase(test.NoDBTestCase, fields.Architecture.AARCH64: "host-passthrough", } for guestarch, expect_mode in expected.items(): - caps = vconfig.LibvirtConfigCaps() - caps.host = vconfig.LibvirtConfigCapsHost() - caps.host.cpu = vconfig.LibvirtConfigCPU() - caps.host.cpu.arch = guestarch - with mock.patch.object(host.Host, "get_capabilities", - return_value=caps): - drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True) - if caps.host.cpu.arch == fields.Architecture.AARCH64: - drvr._has_uefi_support = mock.Mock(return_value=True) - instance_ref = objects.Instance(**self.test_instance) - image_meta = objects.ImageMeta.from_dict(self.test_image_meta) + self.mock_uname.return_value = fakelibvirt.os_uname( + 'Linux', '', '5.4.0-0-generic', '', guestarch) - disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type, - instance_ref, - image_meta) - conf = drvr._get_guest_config(instance_ref, - _fake_network_info(self), - image_meta, disk_info) - self.assertIsInstance(conf.cpu, - vconfig.LibvirtConfigGuestCPU) - self.assertEqual(conf.cpu.mode, expect_mode) + drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True) + instance_ref = objects.Instance(**self.test_instance) + image_meta = objects.ImageMeta.from_dict(self.test_image_meta) + + disk_info = blockinfo.get_disk_info( + CONF.libvirt.virt_type, instance_ref, image_meta) + conf = drvr._get_guest_config( + instance_ref, _fake_network_info(self), image_meta, disk_info) + self.assertIsInstance(conf.cpu, vconfig.LibvirtConfigGuestCPU) + self.assertEqual(conf.cpu.mode, expect_mode) def test_get_guest_cpu_config_host_model(self): drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True) @@ -8126,34 +8059,20 @@ class LibvirtConnTestCase(test.NoDBTestCase, self.assertEqual(conf.cpu.threads, 1) def test_get_guest_cpu_config_qemu_custom_aarch64(self): - self.flags(cpu_mode="custom", group='libvirt', - cpu_models=["max"]) - expected = { - fields.Architecture.AARCH64: "custom", - } + self.flags(cpu_mode='custom', group='libvirt', cpu_models=['max']) + self.mock_uname.return_value = fakelibvirt.os_uname( + 'Linux', '', '5.4.0-0-generic', '', fields.Architecture.AARCH64) - for guestarch, expect_mode in expected.items(): - caps = vconfig.LibvirtConfigCaps() - caps.host = vconfig.LibvirtConfigCapsHost() - caps.host.cpu = vconfig.LibvirtConfigCPU() - caps.host.cpu.arch = guestarch - with mock.patch.object(host.Host, "get_capabilities", - return_value=caps): - drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True) - if caps.host.cpu.arch == fields.Architecture.AARCH64: - drvr._has_uefi_support = mock.Mock(return_value=True) - instance_ref = objects.Instance(**self.test_instance) - image_meta = objects.ImageMeta.from_dict(self.test_image_meta) + drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True) + instance_ref = objects.Instance(**self.test_instance) + image_meta = objects.ImageMeta.from_dict(self.test_image_meta) - disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type, - instance_ref, - image_meta) - conf = drvr._get_guest_config(instance_ref, - _fake_network_info(self), - image_meta, disk_info) - self.assertIsInstance(conf.cpu, - vconfig.LibvirtConfigGuestCPU) - self.assertEqual(conf.cpu.mode, expect_mode) + disk_info = blockinfo.get_disk_info( + CONF.libvirt.virt_type, instance_ref, image_meta) + conf = drvr._get_guest_config( + instance_ref, _fake_network_info(self), image_meta, disk_info) + self.assertIsInstance(conf.cpu, vconfig.LibvirtConfigGuestCPU) + self.assertEqual(conf.cpu.mode, 'custom') @mock.patch.object(libvirt_driver.LOG, 'warning') def test_get_guest_cpu_config_custom_with_extra_flags(self, @@ -16885,10 +16804,8 @@ class LibvirtConnTestCase(test.NoDBTestCase, mock_get_domain.assert_called_once_with(instance) mock_get_error.assert_not_called() - @mock.patch.object(libvirt_driver.LibvirtDriver, "_has_uefi_support") @mock.patch.object(host.Host, "get_guest") - def test_undefine_domain_handles_libvirt_errors(self, mock_get, - mock_has_uefi): + def test_undefine_domain_handles_libvirt_errors(self, mock_get): drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) instance = objects.Instance(**self.test_instance) fake_guest = mock.Mock() diff --git a/nova/tests/unit/virt/libvirt/test_fakelibvirt.py b/nova/tests/unit/virt/libvirt/test_fakelibvirt.py index 126b42c4efcf..e2eaec00c3e6 100644 --- a/nova/tests/unit/virt/libvirt/test_fakelibvirt.py +++ b/nova/tests/unit/virt/libvirt/test_fakelibvirt.py @@ -13,6 +13,7 @@ # under the License. from lxml import etree +import mock from oslo_utils import uuidutils from nova.objects import fields as obj_fields @@ -274,7 +275,10 @@ class FakeLibvirtTests(test.NoDBTestCase): def test_getCapabilities(self): conn = self.get_openAuth_curry_func()('qemu:///system') - etree.fromstring(conn.getCapabilities()) + with mock.patch('os.uname') as mock_uname: + mock_uname.return_value = libvirt.os_uname( + 'Linux', '', '5.10.13-200-generic', '', 'x86_64') + etree.fromstring(conn.getCapabilities()) def test_getDomainCapabilities(self): conn = self.get_openAuth_curry_func()('qemu:///system') diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 37f7037490bb..4bd9ab8828ca 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -4703,16 +4703,23 @@ class LibvirtDriver(driver.ComputeDriver): return self.cpu_models_mapping.get(model.lower()) - def _get_guest_cpu_model_config(self, flavor=None): + # TODO(stephenfin): Libvirt exposes information about possible CPU models + # via 'getDomainCapabilities' and we should use it + def _get_guest_cpu_model_config(self, flavor=None, arch=None): mode = CONF.libvirt.cpu_mode models = [self._get_cpu_model_mapping(model) for model in CONF.libvirt.cpu_models] extra_flags = set([flag.lower() for flag in CONF.libvirt.cpu_model_extra_flags]) - if (CONF.libvirt.virt_type == "kvm" or - CONF.libvirt.virt_type == "qemu"): + if not arch: caps = self._host.get_capabilities() + arch = caps.host.cpu.arch + + if ( + CONF.libvirt.virt_type == "kvm" or + CONF.libvirt.virt_type == "qemu" + ): if mode is None: # AArch64 lacks 'host-model' support because neither libvirt # nor QEMU are able to tell what the host CPU model exactly is. @@ -4722,7 +4729,7 @@ class LibvirtDriver(driver.ComputeDriver): # Also worth noting: 'host-passthrough' mode will completely # break live migration, *unless* all the Compute nodes (running # libvirtd) have *identical* CPUs. - if caps.host.cpu.arch == fields.Architecture.AARCH64: + if arch == fields.Architecture.AARCH64: mode = "host-passthrough" LOG.info('CPU mode "host-passthrough" was chosen. Live ' 'migration can break unless all compute nodes ' @@ -4735,7 +4742,7 @@ class LibvirtDriver(driver.ComputeDriver): # On AArch64 platform the return of _get_cpu_model_mapping will not # return the default CPU model. if mode == "custom": - if caps.host.cpu.arch == fields.Architecture.AARCH64: + if arch == fields.Architecture.AARCH64: if not models: models = ['max'] @@ -4801,7 +4808,8 @@ class LibvirtDriver(driver.ComputeDriver): def _get_guest_cpu_config(self, flavor, image_meta, guest_cpu_numa_config, instance_numa_topology): - cpu = self._get_guest_cpu_model_config(flavor) + arch = libvirt_utils.get_arch(image_meta) + cpu = self._get_guest_cpu_model_config(flavor, arch) if cpu is None: return None @@ -5878,16 +5886,14 @@ class LibvirtDriver(driver.ComputeDriver): flavor: 'objects.Flavor', ) -> None: if CONF.libvirt.virt_type in ("kvm", "qemu"): - caps = self._host.get_capabilities() - if caps.host.cpu.arch in ( - fields.Architecture.I686, fields.Architecture.X86_64, - ): + arch = libvirt_utils.get_arch(image_meta) + if arch in (fields.Architecture.I686, fields.Architecture.X86_64): guest.sysinfo = self._get_guest_config_sysinfo(instance) guest.os_smbios = vconfig.LibvirtConfigGuestSMBIOS() hw_firmware_type = image_meta.properties.get('hw_firmware_type') - if caps.host.cpu.arch == fields.Architecture.AARCH64: + if arch == fields.Architecture.AARCH64: if not hw_firmware_type: hw_firmware_type = fields.FirmwareType.UEFI @@ -5899,7 +5905,7 @@ class LibvirtDriver(driver.ComputeDriver): "functional testing and therefore " "considered experimental.") uefi_logged = True - for lpath in DEFAULT_UEFI_LOADER_PATH[caps.host.cpu.arch]: + for lpath in DEFAULT_UEFI_LOADER_PATH[arch]: if os.path.exists(lpath): guest.os_loader = lpath guest.os_loader_type = "pflash"