libvirt: Move some host arch checks to guest checks
We have a load of tests to enable specific behavior depending on the guest architecture, but in many cases we're actually testing the host architecture. This is wrong and breaks our ability to create guests with non-host architectures plus our ability to rely on mocking of these APIs by 'FakeLibvirt'. We fix this by switching checks against the CPU architecture reported by libvirt's host capabilities, to checks against the guest image metadata (via 'nova.virt.libvirt.utils.get_arch') with a fallback to the host architecture (via 'os.uname'). This seemingly simple change subsequently highlights *a lot* of gaps in the mocking done by 'FakeLibvirtFixture'. Pretty much all of these stem from the fact that by previously extracting the CPU host architecture from host capabilities, we were in practice almost always checking against x86-64. Now that we're doing checks against image metadata with a fallback to 'os.uname()', we suddenly need to be able to provide host and domain capabilities for other architectures and doing additional mocks for some of these architecture-specific code paths. Note that this change effectively removes test coverage for the 'LibvirtDriver._has_uefi_support' helper because we now mock it in the 'FakeLibvirtFixture' to avoid checks in AArch64 tests (AArch64 defaults to a UEFI bootloader). This is okay since we're going to remove this helper entirely in a future change. Also note that this _still_ isn't as complete as I'd like it to be, owing to time constraints and the sheer depth of the problem here. The remaining issues will be addressed in follow-ups, potentially alongside patches to drop support for legacy architectures like MIPS and I686 (the former has been EOL'd in favour of RISC-V as of March 2021 and both Intel and AMD stopped manufacturing products using the latter ISA for anything other than embedded use cases many moons ago). Change-Id: I158dd70076ecdbef422ef08c11ce6a140c991537 Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
parent
faad45b632
commit
452d2fb3a0
|
@ -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)))
|
||||
|
|
|
@ -249,8 +249,7 @@ FAKE_KVM_GUEST = """
|
|||
</launchSecurity>
|
||||
</domain>"""
|
||||
|
||||
|
||||
CAPABILITIES_HOST_TEMPLATE = '''
|
||||
CAPABILITIES_HOST_X86_64_TEMPLATE = """
|
||||
<host>
|
||||
<uuid>cef19ce0-0ca2-11df-855d-b19fbce37686</uuid>
|
||||
<cpu>
|
||||
|
@ -271,6 +270,9 @@ CAPABILITIES_HOST_TEMPLATE = '''
|
|||
<feature name='acpi'/>
|
||||
<feature name='ds'/>
|
||||
<feature name='vme'/>
|
||||
<pages unit='KiB' size='4'/>
|
||||
<pages unit='KiB' size='2048'/>
|
||||
<pages unit='KiB' size='1048576'/>
|
||||
</cpu>
|
||||
<migration_features>
|
||||
<live/>
|
||||
|
@ -283,7 +285,114 @@ CAPABILITIES_HOST_TEMPLATE = '''
|
|||
<model>apparmor</model>
|
||||
<doi>0</doi>
|
||||
</secmodel>
|
||||
</host>'''
|
||||
</host>"""
|
||||
|
||||
# NOTE(stephenfin): This is incomplete
|
||||
CAPABILITIES_HOST_I686_TEMPLATE = """
|
||||
<host>
|
||||
<uuid>cef19ce0-0ca2-11df-855d-b19fbce37686</uuid>
|
||||
<cpu>
|
||||
<arch>i686</arch>
|
||||
</cpu>
|
||||
<power_management/>
|
||||
<iommu support='no'/>
|
||||
</host>"""
|
||||
|
||||
CAPABILITIES_HOST_AARCH64_TEMPLATE = """
|
||||
<host>
|
||||
<uuid>cef19ce0-0ca2-11df-855d-b19fbce37686</uuid>
|
||||
<cpu>
|
||||
<arch>aarch64</arch>
|
||||
<model>host</model>
|
||||
<topology sockets='1' cores='48' threads='1'/>
|
||||
<pages unit='KiB' size='4'/>
|
||||
<pages unit='KiB' size='2048'/>
|
||||
</cpu>
|
||||
<power_management/>
|
||||
<migration_features>
|
||||
<live/>
|
||||
<uri_transports>
|
||||
<uri_transport>tcp</uri_transport>
|
||||
<uri_transport>rdma</uri_transport>
|
||||
</uri_transports>
|
||||
</migration_features>
|
||||
%(topology)s
|
||||
<secmodel>
|
||||
<model>apparmor</model>
|
||||
<doi>0</doi>
|
||||
</secmodel>
|
||||
<secmodel>
|
||||
<model>dac</model>
|
||||
<doi>0</doi>
|
||||
<baselabel type='kvm'>+0:+0</baselabel>
|
||||
<baselabel type='qemu'>+0:+0</baselabel>
|
||||
</secmodel>
|
||||
</host>"""
|
||||
|
||||
# NOTE(stephenfin): This is incomplete
|
||||
CAPABILITIES_HOST_ARMV7_TEMPLATE = """
|
||||
<host>
|
||||
<cpu>
|
||||
<arch>armv7l</arch>
|
||||
</cpu>
|
||||
<power_management/>
|
||||
<iommu support='no'/>
|
||||
</host>"""
|
||||
|
||||
# NOTE(stephenfin): This is incomplete
|
||||
CAPABILITIES_HOST_PPC_TEMPLATE = """
|
||||
<host>
|
||||
<uuid>cef19ce0-0ca2-11df-855d-b19fbce37686</uuid>
|
||||
<cpu>
|
||||
<arch>ppc</arch>
|
||||
</cpu>
|
||||
<power_management/>
|
||||
<iommu support='no'/>
|
||||
</host>"""
|
||||
|
||||
# NOTE(stephenfin): This is incomplete
|
||||
CAPABILITIES_HOST_PPC64_TEMPLATE = """
|
||||
<host>
|
||||
<uuid>cef19ce0-0ca2-11df-855d-b19fbce37686</uuid>
|
||||
<cpu>
|
||||
<arch>ppc64</arch>
|
||||
</cpu>
|
||||
<power_management/>
|
||||
<iommu support='no'/>
|
||||
</host>"""
|
||||
|
||||
# NOTE(stephenfin): This is incomplete
|
||||
CAPABILITIES_HOST_PPC64LE_TEMPLATE = """
|
||||
<host>
|
||||
<uuid>cef19ce0-0ca2-11df-855d-b19fbce37686</uuid>
|
||||
<cpu>
|
||||
<arch>ppc64le</arch>
|
||||
</cpu>
|
||||
<power_management/>
|
||||
<iommu support='no'/>
|
||||
</host>"""
|
||||
|
||||
# NOTE(stephenfin): This is incomplete
|
||||
CAPABILITIES_HOST_S390X_TEMPLATE = """
|
||||
<host>
|
||||
<uuid>cef19ce0-0ca2-11df-855d-b19fbce37686</uuid>
|
||||
<cpu>
|
||||
<arch>s390x</arch>
|
||||
</cpu>
|
||||
<power_management/>
|
||||
<iommu support='no'/>
|
||||
</host>"""
|
||||
|
||||
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 = {
|
|||
</features>
|
||||
</guest>''',
|
||||
|
||||
'aarch64': '''
|
||||
<guest>
|
||||
<os_type>hvm</os_type>
|
||||
<arch name='aarch64'>
|
||||
<wordsize>64</wordsize>
|
||||
<emulator>/usr/bin/qemu-system-aarch64</emulator>
|
||||
<machine maxCpus='1'>integratorcp</machine>
|
||||
<machine maxCpus='2'>ast2600-evb</machine>
|
||||
<machine maxCpus='1'>borzoi</machine>
|
||||
<machine maxCpus='1'>spitz</machine>
|
||||
<machine maxCpus='255'>virt-2.7</machine>
|
||||
<machine maxCpus='2'>nuri</machine>
|
||||
<machine maxCpus='2'>mcimx7d-sabre</machine>
|
||||
<machine maxCpus='1'>romulus-bmc</machine>
|
||||
<machine maxCpus='512'>virt-3.0</machine>
|
||||
<machine maxCpus='512'>virt-5.0</machine>
|
||||
<machine maxCpus='255'>virt-2.10</machine>
|
||||
<machine maxCpus='255'>virt-2.8</machine>
|
||||
<machine maxCpus='2'>musca-b1</machine>
|
||||
<machine maxCpus='4'>realview-pbx-a9</machine>
|
||||
<machine maxCpus='1'>versatileab</machine>
|
||||
<machine maxCpus='1'>kzm</machine>
|
||||
<machine maxCpus='2'>musca-a</machine>
|
||||
<machine maxCpus='512'>virt-3.1</machine>
|
||||
<machine maxCpus='1'>mcimx6ul-evk</machine>
|
||||
<machine maxCpus='512'>virt-5.1</machine>
|
||||
<machine canonical='virt-5.1' maxCpus='512'>virt</machine>
|
||||
<machine maxCpus='2'>smdkc210</machine>
|
||||
<machine maxCpus='1'>sx1</machine>
|
||||
<machine maxCpus='4'>raspi2</machine>
|
||||
<machine maxCpus='255'>virt-2.11</machine>
|
||||
<machine maxCpus='1'>imx25-pdk</machine>
|
||||
<machine maxCpus='255'>virt-2.9</machine>
|
||||
<machine maxCpus='4'>orangepi-pc</machine>
|
||||
<machine maxCpus='1'>z2</machine>
|
||||
<machine maxCpus='1'>xilinx-zynq-a9</machine>
|
||||
<machine maxCpus='6'>xlnx-zcu102</machine>
|
||||
<machine maxCpus='4'>raspi3</machine>
|
||||
<machine maxCpus='1'>tosa</machine>
|
||||
<machine maxCpus='255'>virt-2.12</machine>
|
||||
<machine maxCpus='2'>mps2-an521</machine>
|
||||
<machine maxCpus='4'>sabrelite</machine>
|
||||
<machine maxCpus='1'>mps2-an511</machine>
|
||||
<machine maxCpus='1'>canon-a1100</machine>
|
||||
<machine maxCpus='1'>realview-eb</machine>
|
||||
<machine maxCpus='1'>emcraft-sf2</machine>
|
||||
<machine maxCpus='1'>realview-pb-a8</machine>
|
||||
<machine maxCpus='512'>sbsa-ref</machine>
|
||||
<machine maxCpus='512'>virt-4.0</machine>
|
||||
<machine maxCpus='1'>palmetto-bmc</machine>
|
||||
<machine maxCpus='1'>sx1-v1</machine>
|
||||
<machine maxCpus='1'>n810</machine>
|
||||
<machine maxCpus='2'>tacoma-bmc</machine>
|
||||
<machine maxCpus='1'>n800</machine>
|
||||
<machine maxCpus='512'>virt-4.1</machine>
|
||||
<machine maxCpus='1'>versatilepb</machine>
|
||||
<machine maxCpus='1'>terrier</machine>
|
||||
<machine maxCpus='1'>mainstone</machine>
|
||||
<machine maxCpus='4'>realview-eb-mpcore</machine>
|
||||
<machine maxCpus='512'>virt-4.2</machine>
|
||||
<machine maxCpus='1'>witherspoon-bmc</machine>
|
||||
<machine maxCpus='1'>swift-bmc</machine>
|
||||
<machine maxCpus='4'>vexpress-a9</machine>
|
||||
<machine maxCpus='4'>midway</machine>
|
||||
<machine maxCpus='1'>musicpal</machine>
|
||||
<machine maxCpus='1'>lm3s811evb</machine>
|
||||
<machine maxCpus='1'>lm3s6965evb</machine>
|
||||
<machine maxCpus='1'>microbit</machine>
|
||||
<machine maxCpus='1'>mps2-an505</machine>
|
||||
<machine maxCpus='1'>mps2-an385</machine>
|
||||
<machine maxCpus='1'>cubieboard</machine>
|
||||
<machine maxCpus='1'>verdex</machine>
|
||||
<machine maxCpus='1'>netduino2</machine>
|
||||
<machine maxCpus='2'>xlnx-versal-virt</machine>
|
||||
<machine maxCpus='4'>vexpress-a15</machine>
|
||||
<machine maxCpus='1'>sonorapass-bmc</machine>
|
||||
<machine maxCpus='1'>cheetah</machine>
|
||||
<machine maxCpus='255'>virt-2.6</machine>
|
||||
<machine maxCpus='1'>ast2500-evb</machine>
|
||||
<machine maxCpus='4'>highbank</machine>
|
||||
<machine maxCpus='1'>akita</machine>
|
||||
<machine maxCpus='1'>connex</machine>
|
||||
<machine maxCpus='1'>netduinoplus2</machine>
|
||||
<machine maxCpus='1'>collie</machine>
|
||||
<domain type='qemu'/>
|
||||
</arch>
|
||||
<features>
|
||||
<acpi default='on' toggle='yes'/>
|
||||
<cpuselection/>
|
||||
<deviceboot/>
|
||||
<disksnapshot default='on' toggle='no'/>
|
||||
</features>
|
||||
</guest>''',
|
||||
|
||||
'armv7l': '''
|
||||
<guest>
|
||||
<os_type>hvm</os_type>
|
||||
|
@ -628,20 +831,6 @@ CAPABILITIES_GUEST = {
|
|||
</guest>'''
|
||||
}
|
||||
|
||||
CAPABILITIES_TEMPLATE = (
|
||||
"<capabilities>\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'] +
|
||||
"</capabilities>\n"
|
||||
)
|
||||
|
||||
|
||||
DOMCAPABILITIES_SPARC = """
|
||||
<domainCapabilities>
|
||||
<path>/usr/bin/qemu-system-sparc</path>
|
||||
|
@ -719,7 +908,7 @@ DOMCAPABILITIES_SPARC = """
|
|||
</domainCapabilities>
|
||||
"""
|
||||
|
||||
DOMCAPABILITIES_ARMV7L = """
|
||||
DOMCAPABILITIES_ARMV7 = """
|
||||
<domainCapabilities>
|
||||
<path>/usr/bin/qemu-system-arm</path>
|
||||
<domain>qemu</domain>
|
||||
|
@ -836,6 +1025,164 @@ DOMCAPABILITIES_ARMV7L = """
|
|||
</domainCapabilities>
|
||||
"""
|
||||
|
||||
DOMCAPABILITIES_AARCH64 = """
|
||||
<domainCapabilities>
|
||||
<path>/usr/bin/qemu-system-aarch64</path>
|
||||
<domain>qemu</domain>
|
||||
<machine>virt-5.1</machine>
|
||||
<arch>aarch64</arch>
|
||||
<vcpu max='512'/>
|
||||
<iothreads supported='yes'/>
|
||||
<os supported='yes'>
|
||||
<enum name='firmware'>
|
||||
<value>efi</value>
|
||||
</enum>
|
||||
<loader supported='yes'>
|
||||
<value>/usr/share/AAVMF/AAVMF_CODE.fd</value>
|
||||
<enum name='type'>
|
||||
<value>rom</value>
|
||||
<value>pflash</value>
|
||||
</enum>
|
||||
<enum name='readonly'>
|
||||
<value>yes</value>
|
||||
<value>no</value>
|
||||
</enum>
|
||||
<enum name='secure'>
|
||||
<value>no</value>
|
||||
<value>yes</value>
|
||||
</enum>
|
||||
</loader>
|
||||
</os>
|
||||
<cpu>
|
||||
<mode name='host-passthrough' supported='no'/>
|
||||
<mode name='host-model' supported='no'/>
|
||||
<mode name='custom' supported='yes'>
|
||||
<model usable='unknown'>pxa270-c0</model>
|
||||
<model usable='unknown'>cortex-a15</model>
|
||||
<model usable='unknown'>pxa270-b0</model>
|
||||
<model usable='unknown'>cortex-a57</model>
|
||||
<model usable='unknown'>cortex-m4</model>
|
||||
<model usable='unknown'>pxa270-a0</model>
|
||||
<model usable='unknown'>arm1176</model>
|
||||
<model usable='unknown'>pxa270-b1</model>
|
||||
<model usable='unknown'>cortex-a7</model>
|
||||
<model usable='unknown'>pxa270-a1</model>
|
||||
<model usable='unknown'>cortex-a8</model>
|
||||
<model usable='unknown'>cortex-r5</model>
|
||||
<model usable='unknown'>ti925t</model>
|
||||
<model usable='unknown'>cortex-r5f</model>
|
||||
<model usable='unknown'>arm1026</model>
|
||||
<model usable='unknown'>cortex-a9</model>
|
||||
<model usable='unknown'>cortex-m7</model>
|
||||
<model usable='unknown'>pxa270</model>
|
||||
<model usable='unknown'>pxa260</model>
|
||||
<model usable='unknown'>pxa250</model>
|
||||
<model usable='unknown'>pxa270-c5</model>
|
||||
<model usable='unknown'>pxa261</model>
|
||||
<model usable='unknown'>pxa262</model>
|
||||
<model usable='unknown'>sa1110</model>
|
||||
<model usable='unknown'>sa1100</model>
|
||||
<model usable='unknown'>max</model>
|
||||
<model usable='unknown'>cortex-a53</model>
|
||||
<model usable='unknown'>cortex-m0</model>
|
||||
<model usable='unknown'>cortex-m33</model>
|
||||
<model usable='unknown'>cortex-a72</model>
|
||||
<model usable='unknown'>arm946</model>
|
||||
<model usable='unknown'>pxa255</model>
|
||||
<model usable='unknown'>arm11mpcore</model>
|
||||
<model usable='unknown'>arm926</model>
|
||||
<model usable='unknown'>arm1136</model>
|
||||
<model usable='unknown'>arm1136-r2</model>
|
||||
<model usable='unknown'>cortex-m3</model>
|
||||
</mode>
|
||||
</cpu>
|
||||
<devices>
|
||||
<disk supported='yes'>
|
||||
<enum name='diskDevice'>
|
||||
<value>disk</value>
|
||||
<value>cdrom</value>
|
||||
<value>floppy</value>
|
||||
<value>lun</value>
|
||||
</enum>
|
||||
<enum name='bus'>
|
||||
<value>fdc</value>
|
||||
<value>scsi</value>
|
||||
<value>virtio</value>
|
||||
<value>usb</value>
|
||||
<value>sata</value>
|
||||
</enum>
|
||||
<enum name='model'>
|
||||
<value>virtio</value>
|
||||
<value>virtio-transitional</value>
|
||||
<value>virtio-non-transitional</value>
|
||||
</enum>
|
||||
</disk>
|
||||
<graphics supported='yes'>
|
||||
<enum name='type'>
|
||||
<value>sdl</value>
|
||||
<value>vnc</value>
|
||||
<value>spice</value>
|
||||
</enum>
|
||||
</graphics>
|
||||
<video supported='yes'>
|
||||
<enum name='modelType'>
|
||||
<value>vga</value>
|
||||
<value>cirrus</value>
|
||||
<value>vmvga</value>
|
||||
<value>qxl</value>
|
||||
<value>virtio</value>
|
||||
<value>none</value>
|
||||
<value>bochs</value>
|
||||
<value>ramfb</value>
|
||||
</enum>
|
||||
</video>
|
||||
<hostdev supported='yes'>
|
||||
<enum name='mode'>
|
||||
<value>subsystem</value>
|
||||
</enum>
|
||||
<enum name='startupPolicy'>
|
||||
<value>default</value>
|
||||
<value>mandatory</value>
|
||||
<value>requisite</value>
|
||||
<value>optional</value>
|
||||
</enum>
|
||||
<enum name='subsysType'>
|
||||
<value>usb</value>
|
||||
<value>pci</value>
|
||||
<value>scsi</value>
|
||||
</enum>
|
||||
<enum name='capsType'/>
|
||||
<enum name='pciBackend'/>
|
||||
</hostdev>
|
||||
<rng supported='yes'>
|
||||
<enum name='model'>
|
||||
<value>virtio</value>
|
||||
<value>virtio-transitional</value>
|
||||
<value>virtio-non-transitional</value>
|
||||
</enum>
|
||||
<enum name='backendModel'>
|
||||
<value>random</value>
|
||||
<value>egd</value>
|
||||
<value>builtin</value>
|
||||
</enum>
|
||||
</rng>
|
||||
</devices>
|
||||
<features>
|
||||
<gic supported='yes'>
|
||||
<enum name='version'>
|
||||
<value>2</value>
|
||||
<value>3</value>
|
||||
</enum>
|
||||
</gic>
|
||||
<vmcoreinfo supported='yes'/>
|
||||
<genid supported='no'/>
|
||||
<backingStoreInput supported='yes'/>
|
||||
<backup supported='no'/>
|
||||
<sev supported='no'/>
|
||||
</features>
|
||||
</domainCapabilities>
|
||||
"""
|
||||
|
||||
DOMCAPABILITIES_PPC = """
|
||||
<domainCapabilities>
|
||||
<path>/usr/bin/qemu-system-ppc</path>
|
||||
|
@ -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,
|
||||
|
|
|
@ -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 = [
|
||||
'<capabilities>\n',
|
||||
fake_libvirt_data.CAPABILITIES_HOST_TEMPLATES[os.uname().machine],
|
||||
] + list(fake_libvirt_data.CAPABILITIES_GUEST.values()) + [
|
||||
'</capabilities>',
|
||||
]
|
||||
|
||||
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:
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue