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"