Merge "libvirt: Add configuration options to set SPICE compression settings"

This commit is contained in:
Zuul 2023-02-17 01:45:41 +00:00 committed by Gerrit Code Review
commit 5c32d5efe1
7 changed files with 204 additions and 1 deletions

View File

@ -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
------

View File

@ -84,6 +84,59 @@ Agent. With the Spice agent installed the following features are enabled:
* Better mouse integration - The mouse can be captured and released without
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',

View File

@ -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):

View File

@ -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')

View File

@ -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

View File

@ -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

View File

@ -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).