Skip to content

Commit 85a0711

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "driver/secheduler/docs for Adds Pick guest CPU architecture based on host arch in libvirt driver support"
2 parents 4062bb8 + 31ff7ce commit 85a0711

File tree

10 files changed

+319
-18
lines changed

10 files changed

+319
-18
lines changed
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
..
2+
Licensed under the Apache License, Version 2.0 (the "License"); you may
3+
not use this file except in compliance with the License. You may obtain
4+
a copy of the License at
5+
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
8+
Unless required by applicable law or agreed to in writing, software
9+
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10+
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11+
License for the specific language governing permissions and limitations
12+
under the License.
13+
14+
============================================================================
15+
hw_emulation_architecture - Configuring QEMU instance emulation architecture
16+
============================================================================
17+
18+
.. versionadded:: 25.0.0 (Yoga)
19+
20+
The libvirt driver now allows for handling of specific cpu architectures
21+
when defined within the image metadata properties, to be emulated through
22+
QEMU.
23+
24+
Added ``hw_emulation_architecture`` as an available image_meta property.
25+
26+
.. note::
27+
28+
The following only applies to environments using libvirt compute hosts.
29+
and should be considered experimental in its entirety, during its first
30+
release as a feature.
31+
32+
Introduction
33+
------------
34+
35+
This capability is to fill a need with environments that do not have the
36+
capability to support the various cpu architectures that are present today
37+
with physical hardware. A small subset of architectures that are supported
38+
both within libvirt and QEMU have been selected as prime candidates for
39+
emulation support.
40+
41+
While support has been added for the below base architectures, this does
42+
not guarantee that every subset or custom operating system that leverages
43+
one of these architectures will function.
44+
45+
Configure
46+
---------
47+
48+
-------------------
49+
QEMU Binary Support
50+
-------------------
51+
52+
To ensure that libvirt and QEMU can properly handle the level of cpu
53+
emulation desired by the end-user, you are required to install the specific
54+
``qemu-system-XXX``, ``qemu-efi-arm``, ``qemu-efi-aarch64`` binaries on the
55+
compute nodes that will be providing support.
56+
57+
---------------
58+
Console Support
59+
---------------
60+
61+
Consideration need to be made in regards to which architectures you want to
62+
support, as there are limitations on support through spice, novnc, and
63+
serial. All testing and validation has been done to ensure that spice and
64+
serial connections function as expected.
65+
66+
- ``AARCH64`` - Spice & Serial
67+
- ``S390X`` - Serial
68+
- ``PPC64LE`` - Spice & Serial
69+
- ``MIPSEL`` - untested
70+
71+
--------------------------------
72+
Supported Emulated Architectures
73+
--------------------------------
74+
75+
The supported emulated architectures require specific image meta
76+
properties to be set in order to trigger the proper settings to be
77+
configured by libvirtd.
78+
79+
For end users the emulation architecture of an instance is controlled by the
80+
selection of an image with the ``hw_emulation_architecture`` image metadata
81+
property set.
82+
83+
84+
AARCH64
85+
~~~~~~~
86+
87+
``Tested and Validated as functional``
88+
89+
.. code-block:: shell
90+
91+
$ openstack image set --property hw_emulation_architecture=aarch64 $IMAGE
92+
$ openstack image set --property hw_machine_type=virt $IMAGE
93+
$ openstack image set --property hw_firmware_type=uefi $IMAGE
94+
95+
S390x
96+
~~~~~
97+
98+
``Tested and Validated as functional``
99+
100+
.. code-block:: shell
101+
102+
$ openstack image set --property hw_emulation_architecture=s390x $IMAGE
103+
$ openstack image set --property hw_machine_type=s390-ccw-virtio $IMAGE
104+
$ openstack image set --property hw_video_model=virtio $IMAGE
105+
106+
PPC64LE
107+
~~~~~~~
108+
109+
``Tested and Validated as functional``
110+
111+
.. code-block:: shell
112+
113+
$ openstack image set --property hw_emulation_architecture=ppc64le $IMAGE
114+
$ openstack image set --property hw_machine_type=pseries $IMAGE
115+
116+
117+
MIPSEL
118+
~~~~~~
119+
120+
``Testing and validation is ongoing to overcome PCI issues``
121+
122+
.. note::
123+
124+
Support is currently impacted, one current method for support is manually
125+
patching and compiling as defined in libvirt bug
126+
`XML error: No PCI buses available`_.
127+
128+
.. _`XML error: No PCI buses available`: https://bugzilla.redhat.com/show_bug.cgi?id=1432101
129+
130+
.. code-block:: shell
131+
132+
$ openstack image set --property hw_emulation_architecture=mipsel $IMAGE
133+
$ openstack image set --property hw_machine_type=virt $IMAGE

doc/source/admin/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,4 @@ Once you are running nova, the following information is extremely useful.
227227
upgrades
228228
node-down
229229
hw-machine-type
230+
hw-emulation-architecture

nova/scheduler/request_filter.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@ def transform_image_metadata(ctxt, request_spec):
212212
'hw_disk_bus': 'COMPUTE_STORAGE_BUS',
213213
'hw_video_model': 'COMPUTE_GRAPHICS_MODEL',
214214
'hw_vif_model': 'COMPUTE_NET_VIF_MODEL',
215+
'hw_architecture': 'HW_ARCH',
216+
'hw_emulation_architecture': 'COMPUTE_ARCH',
215217
}
216218

217219
trait_names = []

nova/tests/functional/libvirt/test_uefi.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
# under the License.
1515

1616
import datetime
17+
import re
1718

1819
from lxml import etree
1920
from oslo_log import log as logging
@@ -47,6 +48,8 @@ def test_create_server(self):
4748
orig_create = nova.virt.libvirt.guest.Guest.create
4849

4950
def fake_create(cls, xml, host):
51+
xml = re.sub('type arch.*machine',
52+
'type machine', xml)
5053
tree = etree.fromstring(xml)
5154
self.assertXmlEqual(
5255
"""

nova/tests/unit/scheduler/test_request_filter.py

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -406,13 +406,15 @@ def test_compute_status_filter(self, mock_log):
406406
self.assertIn('took %.1f seconds', log_lines[1])
407407

408408
@mock.patch.object(request_filter, 'LOG', new=mock.Mock())
409-
def test_transform_image_metadata(self):
409+
def test_transform_image_metadata_x86(self):
410410
self.flags(image_metadata_prefilter=True, group='scheduler')
411411
properties = objects.ImageMetaProps(
412412
hw_disk_bus=objects.fields.DiskBus.SATA,
413413
hw_cdrom_bus=objects.fields.DiskBus.IDE,
414414
hw_video_model=objects.fields.VideoModel.QXL,
415-
hw_vif_model=network_model.VIF_MODEL_VIRTIO
415+
hw_vif_model=network_model.VIF_MODEL_VIRTIO,
416+
hw_architecture=objects.fields.Architecture.X86_64,
417+
hw_emulation_architecture=objects.fields.Architecture.AARCH64
416418
)
417419
reqspec = objects.RequestSpec(
418420
image=objects.ImageMeta(properties=properties),
@@ -426,6 +428,36 @@ def test_transform_image_metadata(self):
426428
'COMPUTE_NET_VIF_MODEL_VIRTIO',
427429
'COMPUTE_STORAGE_BUS_IDE',
428430
'COMPUTE_STORAGE_BUS_SATA',
431+
'HW_ARCH_X86_64',
432+
'COMPUTE_ARCH_AARCH64',
433+
}
434+
self.assertEqual(expected, reqspec.root_required)
435+
436+
@mock.patch.object(request_filter, 'LOG', new=mock.Mock())
437+
def test_transform_image_metadata_aarch64(self):
438+
self.flags(image_metadata_prefilter=True, group='scheduler')
439+
properties = objects.ImageMetaProps(
440+
hw_disk_bus=objects.fields.DiskBus.SATA,
441+
hw_cdrom_bus=objects.fields.DiskBus.IDE,
442+
hw_video_model=objects.fields.VideoModel.QXL,
443+
hw_vif_model=network_model.VIF_MODEL_VIRTIO,
444+
hw_architecture=objects.fields.Architecture.AARCH64,
445+
hw_emulation_architecture=objects.fields.Architecture.X86_64
446+
)
447+
reqspec = objects.RequestSpec(
448+
image=objects.ImageMeta(properties=properties),
449+
flavor=objects.Flavor(extra_specs={}),
450+
)
451+
self.assertTrue(
452+
request_filter.transform_image_metadata(None, reqspec)
453+
)
454+
expected = {
455+
'COMPUTE_GRAPHICS_MODEL_QXL',
456+
'COMPUTE_NET_VIF_MODEL_VIRTIO',
457+
'COMPUTE_STORAGE_BUS_IDE',
458+
'COMPUTE_STORAGE_BUS_SATA',
459+
'HW_ARCH_AARCH64',
460+
'COMPUTE_ARCH_X86_64',
429461
}
430462
self.assertEqual(expected, reqspec.root_required)
431463

nova/tests/unit/virt/libvirt/test_driver.py

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5218,7 +5218,8 @@ def test_check_uefi_support_aarch64(self):
52185218
self.mock_uname.return_value = fakelibvirt.os_uname(
52195219
'Linux', '', '5.4.0-0-generic', '', fields.Architecture.AARCH64)
52205220
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
5221-
self.assertTrue(drvr._check_uefi_support(None))
5221+
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
5222+
self.assertTrue(drvr._check_uefi_support(image_meta))
52225223

52235224
def test_get_guest_config_with_block_device(self):
52245225
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
@@ -5769,6 +5770,7 @@ def test_create_serial_console_devices_based_on_arch(
57695770
self.flags(enabled=True, group='serial_console')
57705771
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
57715772
instance = objects.Instance(**self.test_instance)
5773+
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
57725774

57735775
expected = {
57745776
fields.Architecture.X86_64: vconfig.LibvirtConfigGuestSerial,
@@ -5781,7 +5783,10 @@ def test_create_serial_console_devices_based_on_arch(
57815783

57825784
guest = vconfig.LibvirtConfigGuest()
57835785
drvr._create_consoles(
5784-
guest_cfg=guest, instance=instance, flavor={}, image_meta={})
5786+
guest_cfg=guest,
5787+
instance=instance,
5788+
flavor={},
5789+
image_meta=image_meta)
57855790
self.assertEqual(1, len(guest.devices))
57865791
console_device = guest.devices[0]
57875792
self.assertIsInstance(console_device, device_type)
@@ -5993,9 +5998,13 @@ def _test_consoles(arch_to_mock, serial_enabled,
59935998
self.flags(enabled=serial_enabled, group='serial_console')
59945999
guest_cfg = vconfig.LibvirtConfigGuest()
59956000
instance = objects.Instance(**self.test_instance)
6001+
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
59966002

59976003
drvr._create_consoles(
5998-
guest_cfg, instance=instance, flavor=None, image_meta=None)
6004+
guest_cfg,
6005+
instance=instance,
6006+
flavor=None,
6007+
image_meta=image_meta)
59996008

60006009
self.assertEqual(1, len(guest_cfg.devices))
60016010
device = guest_cfg.devices[0]
@@ -7975,6 +7984,33 @@ def test_get_guest_cpu_config_qemu_custom_aarch64(self):
79757984
self.assertIsInstance(conf.cpu, vconfig.LibvirtConfigGuestCPU)
79767985
self.assertEqual(conf.cpu.mode, 'custom')
79777986

7987+
def test_get_x86_64_hw_emulated_architecture_aarch64(self):
7988+
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
7989+
image_meta = objects.ImageMeta.from_dict({
7990+
"disk_format": "raw",
7991+
'properties': {
7992+
'hw_architecture': 'x86_64',
7993+
'hw_emulation_architecture': 'aarch64',
7994+
'hw_machine_type': 'virt',
7995+
'hw_firmware_type': 'uefi',
7996+
}})
7997+
7998+
self.assertEqual(drvr._check_emulation_arch(image_meta),
7999+
'aarch64')
8000+
8001+
def test_get_x86_64_hw_emulated_architecture_ppc64(self):
8002+
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
8003+
image_meta = objects.ImageMeta.from_dict({
8004+
"disk_format": "raw",
8005+
'properties': {
8006+
'hw_architecture': 'x86_64',
8007+
'hw_emulation_architecture': 'ppc64le',
8008+
'hw_machine_type': 'pseries',
8009+
}})
8010+
8011+
self.assertEqual(drvr._check_emulation_arch(image_meta),
8012+
'ppc64le')
8013+
79788014
@mock.patch.object(libvirt_driver.LOG, 'warning')
79798015
def test_get_guest_cpu_config_custom_with_extra_flags(self,
79808016
mock_warn):

nova/virt/libvirt/config.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2823,6 +2823,7 @@ def __init__(self, **kwargs):
28232823
self.os_init_path = None
28242824
self.os_boot_dev = []
28252825
self.os_smbios = None
2826+
self.os_arch = None
28262827
self.os_mach_type = None
28272828
self.os_bootmenu = False
28282829
self.devices = []
@@ -2865,6 +2866,8 @@ def _format_os(self, root):
28652866
os.set("firmware", self.os_firmware)
28662867

28672868
type_node = self._text_node("type", self.os_type)
2869+
if self.os_arch is not None:
2870+
type_node.set("arch", self.os_arch)
28682871
if self.os_mach_type is not None:
28692872
type_node.set("machine", self.os_mach_type)
28702873
os.append(type_node)

0 commit comments

Comments
 (0)