diff options
author | Zuul <zuul@review.opendev.org> | 2023-02-17 01:45:41 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2023-02-17 01:45:41 +0000 |
commit | 5c32d5efe1e1aece48b680474617113c61a248d5 (patch) | |
tree | 94fa220d00611e040e634c31f4d43e5159fc42ea | |
parent | 59ac94158179fc53a87cc3c717dcacff33f2781e (diff) | |
parent | b5e0ed248fe0f3250d7f1648f23147d175096fe2 (diff) | |
download | nova-5c32d5efe1e1aece48b680474617113c61a248d5.tar.gz |
Merge "libvirt: Add configuration options to set SPICE compression settings"
-rw-r--r-- | doc/source/admin/remote-console-access.rst | 10 | ||||
-rw-r--r-- | nova/conf/spice.py | 53 | ||||
-rw-r--r-- | nova/tests/unit/virt/libvirt/test_config.py | 26 | ||||
-rw-r--r-- | nova/tests/unit/virt/libvirt/test_driver.py | 64 | ||||
-rw-r--r-- | nova/virt/libvirt/config.py | 24 | ||||
-rw-r--r-- | nova/virt/libvirt/driver.py | 5 | ||||
-rw-r--r-- | releasenotes/notes/add-spice-compression-support-e41676f445544e8d.yaml | 23 |
7 files changed, 204 insertions, 1 deletions
diff --git a/doc/source/admin/remote-console-access.rst b/doc/source/admin/remote-console-access.rst index 015c6522d0..9b28646d27 100644 --- a/doc/source/admin/remote-console-access.rst +++ b/doc/source/admin/remote-console-access.rst @@ -366,6 +366,16 @@ Replace ``IP_ADDRESS`` with the IP address from which the proxy is accessible by the outside world. For example, this may be the management interface IP address of the controller or the VIP. +Optionally, the :program:`nova-compute` service supports the following +additional options to configure compression settings (algorithms and modes) +for SPICE consoles. + +- :oslo.config:option:`spice.image_compression` +- :oslo.config:option:`spice.jpeg_compression` +- :oslo.config:option:`spice.zlib_compression` +- :oslo.config:option:`spice.playback_compression` +- :oslo.config:option:`spice.streaming_mode` + Serial ------ diff --git a/nova/conf/spice.py b/nova/conf/spice.py index 59ed4e80a0..e5854946f1 100644 --- a/nova/conf/spice.py +++ b/nova/conf/spice.py @@ -85,6 +85,59 @@ Agent. With the Spice agent installed the following features are enabled: needing to click inside the console or press keys to release it. The performance of mouse movement is also improved. """), + cfg.StrOpt('image_compression', + advanced=True, + choices=[ + ('auto_glz', 'enable image compression mode to choose between glz ' + 'and quic algorithm, based on image properties'), + ('auto_lz', 'enable image compression mode to choose between lz ' + 'and quic algorithm, based on image properties'), + ('quic', 'enable image compression based on the SFALIC algorithm'), + ('glz', 'enable image compression using lz with history based ' + 'global dictionary'), + ('lz', 'enable image compression with the Lempel-Ziv algorithm'), + ('off', 'disable image compression') + ], + help=""" +Configure the SPICE image compression (lossless). +"""), + cfg.StrOpt('jpeg_compression', + advanced=True, + choices=[ + ('auto', 'enable JPEG image compression automatically'), + ('never', 'disable JPEG image compression'), + ('always', 'enable JPEG image compression') + ], + help=""" +Configure the SPICE wan image compression (lossy for slow links). +"""), + cfg.StrOpt('zlib_compression', + advanced=True, + choices=[ + ('auto', 'enable zlib image compression automatically'), + ('never', 'disable zlib image compression'), + ('always', 'enable zlib image compression') + ], + help=""" +Configure the SPICE wan image compression (lossless for slow links). +"""), + cfg.BoolOpt('playback_compression', + advanced=True, + help=""" +Enable the SPICE audio stream compression (using celt). +"""), + cfg.StrOpt('streaming_mode', + advanced=True, + choices=[ + ('filter', 'SPICE server adds additional filters to decide if ' + 'video streaming should be activated'), + ('all', 'any fast-refreshing window can be encoded into a video ' + 'stream'), + ('off', 'no video detection and (lossy) compression is performed') + ], + help=""" +Configure the SPICE video stream detection and (lossy) compression. +"""), cfg.URIOpt('html5proxy_base_url', default='http://127.0.0.1:6082/spice_auto.html', help=""" diff --git a/nova/tests/unit/virt/libvirt/test_config.py b/nova/tests/unit/virt/libvirt/test_config.py index 8f840e8859..3d0b5ae685 100644 --- a/nova/tests/unit/virt/libvirt/test_config.py +++ b/nova/tests/unit/virt/libvirt/test_config.py @@ -1537,7 +1537,7 @@ class LibvirtConfigGuestInputTest(LibvirtConfigBaseTest): class LibvirtConfigGuestGraphicsTest(LibvirtConfigBaseTest): - def test_config_graphics(self): + def test_config_graphics_vnc(self): obj = config.LibvirtConfigGuestGraphics() obj.type = "vnc" obj.autoport = True @@ -1549,6 +1549,30 @@ class LibvirtConfigGuestGraphicsTest(LibvirtConfigBaseTest): <graphics type="vnc" autoport="yes" keymap="en_US" listen="127.0.0.1"/> """) + def test_config_graphics_spice(self): + obj = config.LibvirtConfigGuestGraphics() + obj.type = "spice" + obj.autoport = False + obj.keymap = "en_US" + obj.listen = "127.0.0.1" + + obj.image_compression = "auto_glz" + obj.jpeg_compression = "auto" + obj.zlib_compression = "always" + obj.playback_compression = True + obj.streaming_mode = "filter" + + xml = obj.to_xml() + self.assertXmlEqual(xml, """ + <graphics type="spice" autoport="no" keymap="en_US" listen="127.0.0.1"> + <image compression="auto_glz"/> + <jpeg compression="auto"/> + <zlib compression="always"/> + <playback compression="on"/> + <streaming mode="filter"/> + </graphics> + """) + class LibvirtConfigGuestHostdev(LibvirtConfigBaseTest): diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index e9b7a2133e..139299e1fa 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -5839,6 +5839,11 @@ class LibvirtConnTestCase(test.NoDBTestCase, self.assertEqual(cfg.devices[3].type, 'vnc') self.assertEqual(cfg.devices[3].listen, '10.0.0.1') self.assertIsNone(cfg.devices[3].keymap) + self.assertIsNone(cfg.devices[3].image_compression) + self.assertIsNone(cfg.devices[3].jpeg_compression) + self.assertIsNone(cfg.devices[3].zlib_compression) + self.assertIsNone(cfg.devices[3].playback_compression) + self.assertIsNone(cfg.devices[3].streaming_mode) def test_get_guest_config_with_vnc_and_tablet(self): self.flags(enabled=True, group='vnc') @@ -5869,6 +5874,11 @@ class LibvirtConnTestCase(test.NoDBTestCase, vconfig.LibvirtConfigMemoryBalloon) self.assertEqual(cfg.devices[3].type, 'vnc') + self.assertIsNone(cfg.devices[3].image_compression) + self.assertIsNone(cfg.devices[3].jpeg_compression) + self.assertIsNone(cfg.devices[3].zlib_compression) + self.assertIsNone(cfg.devices[3].playback_compression) + self.assertIsNone(cfg.devices[3].streaming_mode) self.assertEqual(cfg.devices[5].type, 'tablet') def test_get_guest_config_with_spice_and_tablet(self): @@ -5905,6 +5915,11 @@ class LibvirtConnTestCase(test.NoDBTestCase, self.assertEqual(cfg.devices[3].type, 'spice') self.assertEqual(cfg.devices[3].listen, '10.0.0.1') self.assertIsNone(cfg.devices[3].keymap) + self.assertIsNone(cfg.devices[3].image_compression) + self.assertIsNone(cfg.devices[3].jpeg_compression) + self.assertIsNone(cfg.devices[3].zlib_compression) + self.assertIsNone(cfg.devices[3].playback_compression) + self.assertIsNone(cfg.devices[3].streaming_mode) self.assertEqual(cfg.devices[5].type, 'tablet') @mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock()) @@ -5964,8 +5979,57 @@ class LibvirtConnTestCase(test.NoDBTestCase, self.assertEqual(cfg.devices[3].target_name, "com.redhat.spice.0") self.assertEqual(cfg.devices[3].type, 'spicevmc') self.assertEqual(cfg.devices[4].type, "spice") + self.assertIsNone(cfg.devices[4].image_compression) + self.assertIsNone(cfg.devices[4].jpeg_compression) + self.assertIsNone(cfg.devices[4].zlib_compression) + self.assertIsNone(cfg.devices[4].playback_compression) + self.assertIsNone(cfg.devices[4].streaming_mode) self.assertEqual(cfg.devices[5].type, video_type) + def test_get_guest_config_with_spice_compression(self): + self.flags(enabled=False, group='vnc') + self.flags(virt_type='kvm', group='libvirt') + self.flags(enabled=True, + agent_enabled=False, + image_compression='auto_lz', + jpeg_compression='never', + zlib_compression='always', + playback_compression=False, + streaming_mode='all', + server_listen='10.0.0.1', + group='spice') + self.flags(pointer_model='usbtablet') + + cfg = self._get_guest_config_with_graphics() + + self.assertEqual(len(cfg.devices), 9) + self.assertIsInstance(cfg.devices[0], + vconfig.LibvirtConfigGuestDisk) + self.assertIsInstance(cfg.devices[1], + vconfig.LibvirtConfigGuestDisk) + self.assertIsInstance(cfg.devices[2], + vconfig.LibvirtConfigGuestSerial) + self.assertIsInstance(cfg.devices[3], + vconfig.LibvirtConfigGuestGraphics) + self.assertIsInstance(cfg.devices[4], + vconfig.LibvirtConfigGuestVideo) + self.assertIsInstance(cfg.devices[5], + vconfig.LibvirtConfigGuestInput) + self.assertIsInstance(cfg.devices[6], + vconfig.LibvirtConfigGuestRng) + self.assertIsInstance(cfg.devices[7], + vconfig.LibvirtConfigGuestUSBHostController) + self.assertIsInstance(cfg.devices[8], + vconfig.LibvirtConfigMemoryBalloon) + + self.assertEqual(cfg.devices[3].type, 'spice') + self.assertEqual(cfg.devices[3].listen, '10.0.0.1') + self.assertEqual(cfg.devices[3].image_compression, 'auto_lz') + self.assertEqual(cfg.devices[3].jpeg_compression, 'never') + self.assertEqual(cfg.devices[3].zlib_compression, 'always') + self.assertFalse(cfg.devices[3].playback_compression) + self.assertEqual(cfg.devices[3].streaming_mode, 'all') + @mock.patch.object(host.Host, 'get_guest') @mock.patch.object(libvirt_driver.LibvirtDriver, '_get_serial_ports_from_guest') diff --git a/nova/virt/libvirt/config.py b/nova/virt/libvirt/config.py index 0db2dc6b67..231283b8dd 100644 --- a/nova/virt/libvirt/config.py +++ b/nova/virt/libvirt/config.py @@ -2047,6 +2047,12 @@ class LibvirtConfigGuestGraphics(LibvirtConfigGuestDevice): self.keymap = None self.listen = None + self.image_compression = None + self.jpeg_compression = None + self.zlib_compression = None + self.playback_compression = None + self.streaming_mode = None + def format_dom(self): dev = super(LibvirtConfigGuestGraphics, self).format_dom() @@ -2057,6 +2063,24 @@ class LibvirtConfigGuestGraphics(LibvirtConfigGuestDevice): if self.listen: dev.set("listen", self.listen) + if self.type == "spice": + if self.image_compression is not None: + dev.append(etree.Element( + 'image', compression=self.image_compression)) + if self.jpeg_compression is not None: + dev.append(etree.Element( + 'jpeg', compression=self.jpeg_compression)) + if self.zlib_compression is not None: + dev.append(etree.Element( + 'zlib', compression=self.zlib_compression)) + if self.playback_compression is not None: + dev.append(etree.Element( + 'playback', compression=self.get_on_off_str( + self.playback_compression))) + if self.streaming_mode is not None: + dev.append(etree.Element( + 'streaming', mode=self.streaming_mode)) + return dev diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 5b0fa799c3..b9a389910d 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -7300,6 +7300,11 @@ class LibvirtDriver(driver.ComputeDriver): graphics = vconfig.LibvirtConfigGuestGraphics() graphics.type = "spice" graphics.listen = CONF.spice.server_listen + graphics.image_compression = CONF.spice.image_compression + graphics.jpeg_compression = CONF.spice.jpeg_compression + graphics.zlib_compression = CONF.spice.zlib_compression + graphics.playback_compression = CONF.spice.playback_compression + graphics.streaming_mode = CONF.spice.streaming_mode guest.add_device(graphics) add_video_driver = True diff --git a/releasenotes/notes/add-spice-compression-support-e41676f445544e8d.yaml b/releasenotes/notes/add-spice-compression-support-e41676f445544e8d.yaml new file mode 100644 index 0000000000..b370889171 --- /dev/null +++ b/releasenotes/notes/add-spice-compression-support-e41676f445544e8d.yaml @@ -0,0 +1,23 @@ +--- +features: + - | + The following SPICE-related options are added to the ``spice`` + configuration group of a Nova configuration: + + - ``image_compression`` + - ``jpeg_compression`` + - ``zlib_compression`` + - ``playback_compression`` + - ``streaming_mode`` + + These configuration options can be used to enable and set the + SPICE compression settings for libvirt (QEMU/KVM) provisioned + instances. Each configuration option is optional and can be set + explictly to configure the associated SPICE compression setting + for libvirt. If all configuration options are not set, then none + of the SPICE compression settings will be configured for libvirt, + which corresponds to the behavior before this change. In this case, + the built-in defaults from the libvirt backend (e.g. QEMU) are used. + + Note that those options are only taken into account if SPICE support + is enabled (and the VNC support is disabled). |