Add support for configuring SPICE graphics with libvirt

Add support to the libvirt driver to configure SPICE graphics
and the SPICE guest agent. It allows for enablement of both
VNC and SPICE at the same time, since some recent libvirt/KVM
versions support this concurrent mode.

The USB tablet will now only be enabled if VNC is requested,
or SPICE is requested without the agent

Blueprint: libvirt-spice
Change-Id: Ic7fbfd636455aba5bf881b6a1925fd4561edfd15
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrange 2012-12-18 12:06:15 +00:00
parent a41f4c96ca
commit c215b5ec79
2 changed files with 181 additions and 6 deletions

View File

@ -769,6 +769,150 @@ class LibvirtConnTestCase(test.TestCase):
vconfig.LibvirtConfigGuestDisk)
self.assertEquals(cfg.devices[3].target_dev, 'vdd')
def test_get_guest_config_with_vnc(self):
self.flags(libvirt_type='kvm',
vnc_enabled=True,
use_usb_tablet=False)
self.flags(enabled=False, group='spice')
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
instance_ref = db.instance_create(self.context, self.test_instance)
cfg = conn.get_guest_config(instance_ref, [], None, None)
self.assertEquals(len(cfg.devices), 5)
self.assertEquals(type(cfg.devices[0]),
vconfig.LibvirtConfigGuestDisk)
self.assertEquals(type(cfg.devices[1]),
vconfig.LibvirtConfigGuestDisk)
self.assertEquals(type(cfg.devices[2]),
vconfig.LibvirtConfigGuestSerial)
self.assertEquals(type(cfg.devices[3]),
vconfig.LibvirtConfigGuestSerial)
self.assertEquals(type(cfg.devices[4]),
vconfig.LibvirtConfigGuestGraphics)
self.assertEquals(cfg.devices[4].type, "vnc")
def test_get_guest_config_with_vnc_and_tablet(self):
self.flags(libvirt_type='kvm',
vnc_enabled=True,
use_usb_tablet=True)
self.flags(enabled=False, group='spice')
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
instance_ref = db.instance_create(self.context, self.test_instance)
cfg = conn.get_guest_config(instance_ref, [], None, None)
self.assertEquals(len(cfg.devices), 6)
self.assertEquals(type(cfg.devices[0]),
vconfig.LibvirtConfigGuestDisk)
self.assertEquals(type(cfg.devices[1]),
vconfig.LibvirtConfigGuestDisk)
self.assertEquals(type(cfg.devices[2]),
vconfig.LibvirtConfigGuestSerial)
self.assertEquals(type(cfg.devices[3]),
vconfig.LibvirtConfigGuestSerial)
self.assertEquals(type(cfg.devices[4]),
vconfig.LibvirtConfigGuestInput)
self.assertEquals(type(cfg.devices[5]),
vconfig.LibvirtConfigGuestGraphics)
self.assertEquals(cfg.devices[4].type, "tablet")
self.assertEquals(cfg.devices[5].type, "vnc")
def test_get_guest_config_with_spice_and_tablet(self):
self.flags(libvirt_type='kvm',
vnc_enabled=False,
use_usb_tablet=True)
self.flags(enabled=True,
agent_enabled=False,
group='spice')
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
instance_ref = db.instance_create(self.context, self.test_instance)
cfg = conn.get_guest_config(instance_ref, [], None, None)
self.assertEquals(len(cfg.devices), 6)
self.assertEquals(type(cfg.devices[0]),
vconfig.LibvirtConfigGuestDisk)
self.assertEquals(type(cfg.devices[1]),
vconfig.LibvirtConfigGuestDisk)
self.assertEquals(type(cfg.devices[2]),
vconfig.LibvirtConfigGuestSerial)
self.assertEquals(type(cfg.devices[3]),
vconfig.LibvirtConfigGuestSerial)
self.assertEquals(type(cfg.devices[4]),
vconfig.LibvirtConfigGuestInput)
self.assertEquals(type(cfg.devices[5]),
vconfig.LibvirtConfigGuestGraphics)
self.assertEquals(cfg.devices[4].type, "tablet")
self.assertEquals(cfg.devices[5].type, "spice")
def test_get_guest_config_with_spice_and_agent(self):
self.flags(libvirt_type='kvm',
vnc_enabled=False,
use_usb_tablet=True)
self.flags(enabled=True,
agent_enabled=True,
group='spice')
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
instance_ref = db.instance_create(self.context, self.test_instance)
cfg = conn.get_guest_config(instance_ref, [], None, None)
self.assertEquals(len(cfg.devices), 6)
self.assertEquals(type(cfg.devices[0]),
vconfig.LibvirtConfigGuestDisk)
self.assertEquals(type(cfg.devices[1]),
vconfig.LibvirtConfigGuestDisk)
self.assertEquals(type(cfg.devices[2]),
vconfig.LibvirtConfigGuestSerial)
self.assertEquals(type(cfg.devices[3]),
vconfig.LibvirtConfigGuestSerial)
self.assertEquals(type(cfg.devices[4]),
vconfig.LibvirtConfigGuestChannel)
self.assertEquals(type(cfg.devices[5]),
vconfig.LibvirtConfigGuestGraphics)
self.assertEquals(cfg.devices[4].target_name, "com.redhat.spice.0")
self.assertEquals(cfg.devices[5].type, "spice")
def test_get_guest_config_with_vnc_and_spice(self):
self.flags(libvirt_type='kvm',
vnc_enabled=True,
use_usb_tablet=True)
self.flags(enabled=True,
agent_enabled=True,
group='spice')
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
instance_ref = db.instance_create(self.context, self.test_instance)
cfg = conn.get_guest_config(instance_ref, [], None, None)
self.assertEquals(len(cfg.devices), 8)
self.assertEquals(type(cfg.devices[0]),
vconfig.LibvirtConfigGuestDisk)
self.assertEquals(type(cfg.devices[1]),
vconfig.LibvirtConfigGuestDisk)
self.assertEquals(type(cfg.devices[2]),
vconfig.LibvirtConfigGuestSerial)
self.assertEquals(type(cfg.devices[3]),
vconfig.LibvirtConfigGuestSerial)
self.assertEquals(type(cfg.devices[4]),
vconfig.LibvirtConfigGuestInput)
self.assertEquals(type(cfg.devices[5]),
vconfig.LibvirtConfigGuestChannel)
self.assertEquals(type(cfg.devices[6]),
vconfig.LibvirtConfigGuestGraphics)
self.assertEquals(type(cfg.devices[7]),
vconfig.LibvirtConfigGuestGraphics)
self.assertEquals(cfg.devices[4].type, "tablet")
self.assertEquals(cfg.devices[5].target_name, "com.redhat.spice.0")
self.assertEquals(cfg.devices[6].type, "vnc")
self.assertEquals(cfg.devices[7].type, "spice")
def test_get_guest_cpu_config_none(self):
self.flags(libvirt_cpu_mode="none")
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)

View File

@ -196,6 +196,7 @@ CONF.import_opt('default_ephemeral_format', 'nova.virt.driver')
CONF.import_opt('use_cow_images', 'nova.virt.driver')
CONF.import_opt('live_migration_retry_count', 'nova.compute.manager')
CONF.import_opt('vncserver_proxyclient_address', 'nova.vnc')
CONF.import_opt('server_proxyclient_address', 'nova.spice', group='spice')
DEFAULT_FIREWALL_DRIVER = "%s.%s" % (
libvirt_firewall.__name__,
@ -1786,19 +1787,49 @@ class LibvirtDriver(driver.ComputeDriver):
consolepty.type = "pty"
guest.add_device(consolepty)
if CONF.vnc_enabled and CONF.libvirt_type not in ('lxc', 'uml'):
if CONF.use_usb_tablet and guest.os_type == vm_mode.HVM:
tablet = vconfig.LibvirtConfigGuestInput()
tablet.type = "tablet"
tablet.bus = "usb"
guest.add_device(tablet)
# We want a tablet if VNC is enabled,
# or SPICE is enabled and the SPICE agent is disabled
# NB: this implies that if both SPICE + VNC are enabled
# at the same time, we'll get the tablet whether the
# SPICE agent is used or not.
need_usb_tablet = False
if CONF.vnc_enabled:
need_usb_tablet = CONF.use_usb_tablet
elif CONF.spice.enabled and not CONF.spice.agent_enabled:
need_usb_tablet = CONF.use_usb_tablet
if need_usb_tablet and guest.os_type == vm_mode.HVM:
tablet = vconfig.LibvirtConfigGuestInput()
tablet.type = "tablet"
tablet.bus = "usb"
guest.add_device(tablet)
if CONF.spice.enabled and CONF.spice.agent_enabled and \
CONF.libvirt_type not in ('lxc', 'uml', 'xen'):
channel = vconfig.LibvirtConfigGuestChannel()
channel.target_name = "com.redhat.spice.0"
guest.add_device(channel)
# NB some versions of libvirt support both SPICE and VNC
# at the same time. We're not trying to second guess which
# those versions are. We'll just let libvirt report the
# errors appropriately if the user enables both.
if CONF.vnc_enabled and CONF.libvirt_type not in ('lxc', 'uml'):
graphics = vconfig.LibvirtConfigGuestGraphics()
graphics.type = "vnc"
graphics.keymap = CONF.vnc_keymap
graphics.listen = CONF.vncserver_listen
guest.add_device(graphics)
if CONF.spice.enabled and \
CONF.libvirt_type not in ('lxc', 'uml', 'xen'):
graphics = vconfig.LibvirtConfigGuestGraphics()
graphics.type = "spice"
graphics.keymap = CONF.spice.keymap
graphics.listen = CONF.spice.server_listen
guest.add_device(graphics)
return guest
def to_xml(self, instance, network_info, image_meta=None, rescue=None,