From c59084397401c690c6b23b5c8631138ec85e8f04 Mon Sep 17 00:00:00 2001 From: Kashyap Chamarthy Date: Fri, 21 May 2021 11:41:39 +0200 Subject: [PATCH] Allow 'bochs' as a display device option The 'bochs' display device is a recommended[1] safe option for UEFI guests. This is supported in libvirt from version 5.6.0; Nova's current MIN_LIBVIRT_VERSION (6.0.0) satisfies this requirement. Partially quoting the "bochs display device" section from a post written by a QEMU graphics maintainer[1]: [...] Main advantage over standard VGA is that this device is alot simpler. The code size and complexity needed to emulate this device is an order of magnitude smaller, resulting in a reduced attack surface. Another nice feature is that you can place this device in a PCI Express slot. For UEFI guests it is safe to use the bochs display device instead of the standard VGA device. The firmware will setup a linear framebuffer as GOP anyway and never use any legacy VGA features. For BIOS guests this device might be useable as well, depending on whenever they depend on direct VGA hardware access or not. There is a vgabios which supports text rendering on a linear framebuffer, so software which uses the vgabios services for text output will continue to work. Linux bootloaders typically fall into this category. The linux text mode console (vgacon) uses direct hardware access and does not work. The framebuffer console (fbcon running on vesafb or bochs-drm) works. [1] https://www.kraxel.org/blog/2019/09/display-devices-in-qemu/ Implements: blueprint add-bochs-display-device Change-Id: Id194028f5d2cbaac1c5e699b71fd9751f87f5da5 Signed-off-by: Kashyap Chamarthy --- .../ImageMetaPropsPayload.json | 2 +- nova/notifications/objects/image.py | 3 ++- nova/objects/fields.py | 3 ++- nova/objects/image_meta.py | 10 ++++++++- .../test_instance.py | 4 ++-- .../objects/test_notification.py | 2 +- nova/tests/unit/objects/test_image_meta.py | 22 +++++++++++++++++++ nova/tests/unit/objects/test_objects.py | 2 +- .../notes/bochs-ffaa289da97d08c8.yaml | 7 ++++++ 9 files changed, 47 insertions(+), 8 deletions(-) create mode 100644 releasenotes/notes/releasenotes/notes/bochs-ffaa289da97d08c8.yaml diff --git a/doc/notification_samples/common_payloads/ImageMetaPropsPayload.json b/doc/notification_samples/common_payloads/ImageMetaPropsPayload.json index c970a4c45df8..ef9d49647db7 100644 --- a/doc/notification_samples/common_payloads/ImageMetaPropsPayload.json +++ b/doc/notification_samples/common_payloads/ImageMetaPropsPayload.json @@ -4,5 +4,5 @@ "hw_architecture": "x86_64" }, "nova_object.name": "ImageMetaPropsPayload", - "nova_object.version": "1.7" + "nova_object.version": "1.8" } diff --git a/nova/notifications/objects/image.py b/nova/notifications/objects/image.py index d35627eb3d2b..0240d00105ea 100644 --- a/nova/notifications/objects/image.py +++ b/nova/notifications/objects/image.py @@ -124,7 +124,8 @@ class ImageMetaPropsPayload(base.NotificationPayloadBase): # Version 1.5: Added 'hw_tpm_model' and 'hw_tpm_version' fields # Version 1.6: Added 'socket' to hw_pci_numa_affinity_policy # Version 1.7: Added 'hw_input_bus' field - VERSION = '1.7' + # Version 1.8: Added 'bochs' as an option to 'hw_video_model' + VERSION = '1.8' SCHEMA = { k: ('image_meta_props', k) for k in image_meta.ImageMetaProps.fields} diff --git a/nova/objects/fields.py b/nova/objects/fields.py index 960fcc849641..d8cb10f70058 100644 --- a/nova/objects/fields.py +++ b/nova/objects/fields.py @@ -577,8 +577,9 @@ class VideoModel(BaseNovaEnum): VIRTIO = 'virtio' GOP = 'gop' NONE = 'none' + BOCHS = 'bochs' - ALL = (CIRRUS, QXL, VGA, VMVGA, XEN, VIRTIO, GOP, NONE) + ALL = (CIRRUS, QXL, VGA, VMVGA, XEN, VIRTIO, GOP, NONE, BOCHS) class VIFModel(BaseNovaEnum): diff --git a/nova/objects/image_meta.py b/nova/objects/image_meta.py index c07b358647c4..4d18631302cd 100644 --- a/nova/objects/image_meta.py +++ b/nova/objects/image_meta.py @@ -178,14 +178,22 @@ class ImageMetaProps(base.NovaObject): # Version 1.27: Added 'hw_tpm_model' and 'hw_tpm_version' fields # Version 1.28: Added 'socket' to 'hw_pci_numa_affinity_policy' # Version 1.29: Added 'hw_input_bus' field + # Version 1.30: Added 'bochs' as an option to 'hw_video_model' # NOTE(efried): When bumping this version, the version of # ImageMetaPropsPayload must also be bumped. See its docstring for details. - VERSION = '1.29' + VERSION = '1.30' def obj_make_compatible(self, primitive, target_version): super(ImageMetaProps, self).obj_make_compatible(primitive, target_version) target_version = versionutils.convert_version_to_tuple(target_version) + if target_version < (1, 30): + video = primitive.get('hw_video_model', None) + if video == fields.VideoModel.BOCHS: + raise exception.ObjectActionError( + action='obj_make_compatible', + reason='hw_video_model=%s not supported in version %s' % + (video, target_version)) if target_version < (1, 29): primitive.pop('hw_input_bus', None) if target_version < (1, 28): diff --git a/nova/tests/functional/notification_sample_tests/test_instance.py b/nova/tests/functional/notification_sample_tests/test_instance.py index a263e5129348..2fa298ffa0de 100644 --- a/nova/tests/functional/notification_sample_tests/test_instance.py +++ b/nova/tests/functional/notification_sample_tests/test_instance.py @@ -1236,7 +1236,7 @@ class TestInstanceNotificationSample( 'nova_object.data': {}, 'nova_object.name': 'ImageMetaPropsPayload', 'nova_object.namespace': 'nova', - 'nova_object.version': '1.7', + 'nova_object.version': '1.8', }, 'image.size': 58145823, 'image.tags': [], @@ -1332,7 +1332,7 @@ class TestInstanceNotificationSample( 'nova_object.data': {}, 'nova_object.name': 'ImageMetaPropsPayload', 'nova_object.namespace': 'nova', - 'nova_object.version': '1.7', + 'nova_object.version': '1.8', }, 'image.size': 58145823, 'image.tags': [], diff --git a/nova/tests/unit/notifications/objects/test_notification.py b/nova/tests/unit/notifications/objects/test_notification.py index a55bbc0b9eb1..66c9b533f3be 100644 --- a/nova/tests/unit/notifications/objects/test_notification.py +++ b/nova/tests/unit/notifications/objects/test_notification.py @@ -387,7 +387,7 @@ notification_object_data = { # ImageMetaProps, so when you see a fail here for that reason, you must # *also* bump the version of ImageMetaPropsPayload. See its docstring for # more information. - 'ImageMetaPropsPayload': '1.7-652a6048036c0d0cb8740ea62521c459', + 'ImageMetaPropsPayload': '1.8-080bdcba9b96122eab57bf39d47348f7', 'InstanceActionNotification': '1.0-a73147b93b520ff0061865849d3dfa56', 'InstanceActionPayload': '1.8-4fa3da9cbf0761f1f700ae578f36dc2f', 'InstanceActionRebuildNotification': diff --git a/nova/tests/unit/objects/test_image_meta.py b/nova/tests/unit/objects/test_image_meta.py index a4b7a33fa826..1750caba01b4 100644 --- a/nova/tests/unit/objects/test_image_meta.py +++ b/nova/tests/unit/objects/test_image_meta.py @@ -390,6 +390,28 @@ class TestImageMetaProps(test.NoDBTestCase): obj.obj_to_primitive, '1.21') self.assertIn('hw_video_model', str(ex)) + def test_obj_bochs_model_positive(self): + """Test "bochs" support from Nova object version 1.30 onwards + """ + obj = objects.ImageMetaProps( + hw_video_model=objects.fields.VideoModel.BOCHS, + ) + primitive = obj.obj_to_primitive('1.30') + self.assertEqual( + objects.fields.VideoModel.BOCHS, + primitive['nova_object.data']['hw_video_model']) + + def test_obj_bochs_model_negative(self): + """Make sure an exception is raised for Nova object version < + 1.30 + """ + obj = objects.ImageMetaProps( + hw_video_model=objects.fields.VideoModel.BOCHS, + ) + ex = self.assertRaises(exception.ObjectActionError, + obj.obj_to_primitive, '1.29') + self.assertIn('hw_video_model=bochs not supported', str(ex)) + def test_obj_make_compatible_watchdog_action_not_disabled(self): """Tests that we don't pop the hw_watchdog_action if the value is not 'disabled'. diff --git a/nova/tests/unit/objects/test_objects.py b/nova/tests/unit/objects/test_objects.py index b2f4f0616d01..650b3fe4733e 100644 --- a/nova/tests/unit/objects/test_objects.py +++ b/nova/tests/unit/objects/test_objects.py @@ -1074,7 +1074,7 @@ object_data = { 'HyperVLiveMigrateData': '1.4-e265780e6acfa631476c8170e8d6fce0', 'IDEDeviceBus': '1.0-29d4c9f27ac44197f01b6ac1b7e16502', 'ImageMeta': '1.8-642d1b2eb3e880a367f37d72dd76162d', - 'ImageMetaProps': '1.29-5c02bd7b1e050ef39513d3fca728e543', + 'ImageMetaProps': '1.30-5bfc3dd01bbfdbb28cb3a096c0b2f383', 'Instance': '2.7-d187aec68cad2e4d8b8a03a68e4739ce', 'InstanceAction': '1.2-9a5abc87fdd3af46f45731960651efb5', 'InstanceActionEvent': '1.4-5b1f361bd81989f8bb2c20bb7e8a4cb4', diff --git a/releasenotes/notes/releasenotes/notes/bochs-ffaa289da97d08c8.yaml b/releasenotes/notes/releasenotes/notes/bochs-ffaa289da97d08c8.yaml new file mode 100644 index 000000000000..4b5e310c8d15 --- /dev/null +++ b/releasenotes/notes/releasenotes/notes/bochs-ffaa289da97d08c8.yaml @@ -0,0 +1,7 @@ +--- +features: + - | + Add support for the ``bochs`` libvirt video model. This is a + legacy-free video model that is best suited for UEFI guests. In + limited cases (e.g. if the guest does not depend on direct VGA + hardware access), it can be useable for BIOS guests as well.