Merge "libvirt: Add configuration options to set SPICE compression settings"
This commit is contained in:
commit
5c32d5efe1
|
@ -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
|
||||
------
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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):
|
||||
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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).
|
Loading…
Reference in New Issue