[libvirt] [PATCH v2 0/3]add 'sharePolicy' attribute for qemu vnc sharing policy

v1->v2: changed attribute name from 'policy' to 'sharePolicy' renamed caps flag name: QEMU_CAPS_VNC_SHARE_POLICY fixed issues pointed out in v1 review have to keep hard-coded version probe after checking qemu -help and qmp command. These patches try to add a new attribute 'sharePolicy' to element graphics of vnc type. This attribute has three values: libvirt XML: <graphics type='vnc' port='5900' sharePolicy='allow-exclusive'> QEMU commandline -vnc :5900,share=allow-exclusive Allows clients to ask for exclusive access which is implemented by dropping other connections Connecting multiple clients in parallel requires all clients asking for a shared session (vncviewer: -shared switch) libvirt XML: <graphics type='vnc' port='5900' sharePolicy='force-shared'> QEMU commandline -vnc :5900,share=force-shared Disables exclusive client access. Useful for shared desktop sessions, where you don't want someone forgetting specify -shared disconnect everybody else. libvirt XML: <graphics type='vnc' port='5900' sharePolicy='ignore'> QEMU commandline -vnc :5900,share=ignore Dompletely ignores the shared flag and allows everybody connect unconditionally Guannan Ren(3) [PATCH v2 1/3] qemu: new vnc display sharing policy caps flag [PATCH v2 2/3] conf: add 'sharePolicy' attribute to graphics element for vnc [PATCH v2 3/3] qemu: support share attribute and its values to -vnc docs/formatdomain.html.in | 13 +++++++++++-- docs/schemas/domaincommon.rng | 9 +++++++++ src/conf/domain_conf.c | 28 ++++++++++++++++++++++++++++ src/conf/domain_conf.h | 11 +++++++++++ src/libvirt_private.syms | 2 ++ src/qemu/qemu_capabilities.c | 12 ++++++++---- src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 13 +++++++++++++ tests/qemuhelptest.c | 9 ++++++--- tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc-policy.args | 4 ++++ tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc-policy.xml | 35 +++++++++++++++++++++++++++++++++++ tests/qemuxml2argvtest.c | 1 + 12 files changed, 129 insertions(+), 9 deletions(-)

QEMU_CAPS_VNC_SHARE_POLICY (qemu >= 1.1) --- src/qemu/qemu_capabilities.c | 12 ++++++++---- src/qemu/qemu_capabilities.h | 1 + tests/qemuhelptest.c | 9 ++++++--- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 71059c6..d6479a3 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -221,9 +221,10 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "tpm-tis", "nvram", /* 140 */ - "pci-bridge", /* 141 */ - "vfio-pci", /* 142 */ - "vfio-pci.bootindex", /* 143 */ + "pci-bridge", + "vfio-pci", + "vfio-pci.bootindex", + "vnc-share-policy", ); struct _virQEMUCaps { @@ -1181,8 +1182,10 @@ virQEMUCapsComputeCmdFlags(const char *help, if (version >= 11000) virQEMUCapsSet(qemuCaps, QEMU_CAPS_CPU_HOST); - if (version >= 1001000) + if (version >= 1001000) { virQEMUCapsSet(qemuCaps, QEMU_CAPS_IPV6_MIGRATION); + virQEMUCapsSet(qemuCaps, QEMU_CAPS_VNC_SHARE_POLICY); + } if (version >= 1002000) virQEMUCapsSet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY); @@ -2382,6 +2385,7 @@ virQEMUCapsInitQMPBasic(virQEMUCapsPtr qemuCaps) virQEMUCapsSet(qemuCaps, QEMU_CAPS_IPV6_MIGRATION); virQEMUCapsSet(qemuCaps, QEMU_CAPS_MACHINE_OPT); virQEMUCapsSet(qemuCaps, QEMU_CAPS_DUMP_GUEST_CORE); + virQEMUCapsSet(qemuCaps, QEMU_CAPS_VNC_SHARE_POLICY); } /* Capabilities that are architecture depending diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 213f63c..fea4a8b 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -182,6 +182,7 @@ enum virQEMUCapsFlags { QEMU_CAPS_DEVICE_PCI_BRIDGE = 141, /* -device pci-bridge */ QEMU_CAPS_DEVICE_VFIO_PCI = 142, /* -device vfio-pci */ QEMU_CAPS_VFIO_PCI_BOOTINDEX = 143, /* bootindex param for vfio-pci device */ + QEMU_CAPS_VNC_SHARE_POLICY = 144, /* set display sharing policy */ QEMU_CAPS_LAST, /* this must always be the last item */ }; diff --git a/tests/qemuhelptest.c b/tests/qemuhelptest.c index fa56406..853db89 100644 --- a/tests/qemuhelptest.c +++ b/tests/qemuhelptest.c @@ -822,7 +822,8 @@ mymain(void) QEMU_CAPS_DEVICE_USB_NET, QEMU_CAPS_DTB, QEMU_CAPS_IPV6_MIGRATION, - QEMU_CAPS_DEVICE_PCI_BRIDGE); + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_VNC_SHARE_POLICY); DO_TEST("qemu-1.2.0", 1002000, 0, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -926,7 +927,8 @@ mymain(void) QEMU_CAPS_DTB, QEMU_CAPS_SCSI_MEGASAS, QEMU_CAPS_IPV6_MIGRATION, - QEMU_CAPS_DEVICE_PCI_BRIDGE); + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_VNC_SHARE_POLICY); DO_TEST("qemu-kvm-1.2.0", 1002000, 1, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -1035,7 +1037,8 @@ mymain(void) QEMU_CAPS_DTB, QEMU_CAPS_SCSI_MEGASAS, QEMU_CAPS_IPV6_MIGRATION, - QEMU_CAPS_DEVICE_PCI_BRIDGE); + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_VNC_SHARE_POLICY); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } -- 1.8.1.4

-vnc :5900,share=allow-exclusive allows clients to ask for exclusive access which is implemented by dropping other connections Connecting multiple clients in parallel requires all clients asking for a shared session (vncviewer: -shared switch) -vnc :5900,share=force-shared disables exclusive client access. Useful for shared desktop sessions, where you don't want someone forgetting specify -shared disconnect everybody else. -vnc :5900,share=ignore completely ignores the shared flag and allows everybody connect unconditionally --- docs/formatdomain.html.in | 13 +++++++++++-- docs/schemas/domaincommon.rng | 9 +++++++++ src/conf/domain_conf.c | 28 ++++++++++++++++++++++++++++ src/conf/domain_conf.h | 11 +++++++++++ src/libvirt_private.syms | 2 ++ 5 files changed, 61 insertions(+), 2 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 572d7ee..fee2a1c 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -3493,7 +3493,7 @@ qemu-kvm -net nic,model=? /dev/null ... <devices> <graphics type='sdl' display=':0.0'/> - <graphics type='vnc' port='5904'> + <graphics type='vnc' port='5904' sharePolicy='allow-exclusive'> <listen type='address' address='1.2.3.4'/> </graphics> <graphics type='rdp' autoport='yes' multiUser='yes' /> @@ -3536,7 +3536,16 @@ qemu-kvm -net nic,model=? /dev/null allows control of connected client during password changes. VNC accepts <code>keep</code> value only. <span class="since">since 0.9.3</span> - NB, this may not be supported by all hypervisors.<br/> <br/> + NB, this may not be supported by all hypervisors.<br/> + The optional <code>sharePolicy</code> attribute specifies vnc server + display sharing policy. "allow-exclusive" allows clients to ask + for exclusive access by dropping other connections. Connecting + multiple clients in parallel requires all clients asking for a + shared session (vncviewer: -Shared switch). This is the default + value. "force-shared" disables exclusive client access, every + connection has to specify -Shared switch for vncviewer. "ignore" + welcomes every connection unconditionally + <span class="since">since 1.0.6</span>. <br/> <br/> Rather than using listen/port, QEMU supports a <code>socket</code> attribute for listening on a unix domain socket path.<span class="since">Since 0.8.8</span> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 10596dc..26779e7 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2075,6 +2075,15 @@ <ref name="addrIPorName"/> </attribute> </optional> + <optional> + <attribute name='sharePolicy'> + <choice> + <value>allow-exclusive</value> + <value>force-shared</value> + <value>ignore</value> + </choice> + </attribute> + </optional> </group> <group> <optional> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 59badf8..1b4a7ae 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -513,6 +513,13 @@ VIR_ENUM_IMPL(virDomainGraphicsAuthConnected, "disconnect", "keep") +VIR_ENUM_IMPL(virDomainGraphicsVNCSharePolicy, + VIR_DOMAIN_GRAPHICS_VNC_SHARE_LAST, + "default", + "allow-exclusive", + "force-shared", + "ignore") + VIR_ENUM_IMPL(virDomainGraphicsSpiceChannelName, VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_LAST, "main", @@ -7545,6 +7552,7 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) { char *port = virXMLPropString(node, "port"); char *autoport; + char *policy; if (port) { if (virStrToLong_i(port, NULL, 10, &def->data.vnc.port) < 0) { @@ -7574,6 +7582,21 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, VIR_FREE(autoport); } + if ((policy = virXMLPropString(node, "sharePolicy")) != NULL) { + int sharePolicy = + virDomainGraphicsVNCSharePolicyTypeFromString(policy); + + if (sharePolicy < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown vnc display sharing policy '%s'"), policy); + VIR_FREE(policy); + goto error; + } else { + def->data.vnc.sharePolicy = sharePolicy; + } + VIR_FREE(policy); + } + def->data.vnc.socket = virXMLPropString(node, "socket"); def->data.vnc.keymap = virXMLPropString(node, "keymap"); @@ -14986,6 +15009,11 @@ virDomainGraphicsDefFormat(virBufferPtr buf, virBufferEscapeString(buf, " keymap='%s'", def->data.vnc.keymap); + if (def->data.vnc.sharePolicy) + virBufferAsprintf(buf, " sharePolicy='%s'", + virDomainGraphicsVNCSharePolicyTypeToString( + def->data.vnc.sharePolicy)); + virDomainGraphicsAuthDefFormatAttr(buf, &def->data.vnc.auth, flags); break; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 21f7ce2..20eb0cb 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1284,6 +1284,15 @@ struct _virDomainGraphicsAuthDef { int connected; /* action if connected */ }; +enum virDomainGraphicsVNCSharePolicy { + VIR_DOMAIN_GRAPHICS_VNC_SHARE_DEFAULT = 0, + VIR_DOMAIN_GRAPHICS_VNC_SHARE_ALLOW_EXCLUSIVE, + VIR_DOMAIN_GRAPHICS_VNC_SHARE_FORCE_SHARED, + VIR_DOMAIN_GRAPHICS_VNC_SHARE_IGNORE, + + VIR_DOMAIN_GRAPHICS_VNC_SHARE_LAST +}; + enum virDomainGraphicsSpiceChannelName { VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MAIN, VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_DISPLAY, @@ -1404,6 +1413,7 @@ struct _virDomainGraphicsDef { char *keymap; char *socket; virDomainGraphicsAuthDef auth; + int sharePolicy; } vnc; struct { char *display; @@ -2493,6 +2503,7 @@ VIR_ENUM_DECL(virDomainInputBus) VIR_ENUM_DECL(virDomainGraphics) VIR_ENUM_DECL(virDomainGraphicsListen) VIR_ENUM_DECL(virDomainGraphicsAuthConnected) +VIR_ENUM_DECL(virDomainGraphicsVNCSharePolicy) VIR_ENUM_DECL(virDomainGraphicsSpiceChannelName) VIR_ENUM_DECL(virDomainGraphicsSpiceChannelMode) VIR_ENUM_DECL(virDomainGraphicsSpiceImageCompression) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d4cb4a3..1540f27 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -201,6 +201,8 @@ virDomainGraphicsSpiceZlibCompressionTypeFromString; virDomainGraphicsSpiceZlibCompressionTypeToString; virDomainGraphicsTypeFromString; virDomainGraphicsTypeToString; +virDomainGraphicsVNCSharePolicyTypeFromString; +virDomainGraphicsVNCSharePolicyTypeToString; virDomainHasDiskMirror; virDomainHostdevCapsTypeToString; virDomainHostdevDefAlloc; -- 1.8.1.4

Hey, On Wed, May 08, 2013 at 01:22:47PM +0800, Guannan Ren wrote:
-vnc :5900,share=allow-exclusive allows clients to ask for exclusive access which is implemented by dropping other connections Connecting multiple clients in parallel requires all clients asking for a shared session (vncviewer: -shared switch)
-vnc :5900,share=force-shared disables exclusive client access. Useful for shared desktop sessions, where you don't want someone forgetting specify -shared disconnect everybody else.
-vnc :5900,share=ignore completely ignores the shared flag and allows everybody connect unconditionally
rdp seems to support some similar (though they don't look identical) features through replaceUser/multiUser. « The replaceUser attribute is a boolean deciding whether multiple simultaneous connections to the VM are permitted. The multiUser attribute is a boolean deciding whether the existing connection must be dropped and a new connection must be established by the VRDP server, when a new client connects in single connection mode. » I'm wondering if we should try to use similar attributes for both rdp and vnc for more consistency? Christophe

On 05/14/2013 05:17 PM, Christophe Fergeau wrote:
Hey,
On Wed, May 08, 2013 at 01:22:47PM +0800, Guannan Ren wrote:
-vnc :5900,share=allow-exclusive allows clients to ask for exclusive access which is implemented by dropping other connections Connecting multiple clients in parallel requires all clients asking for a shared session (vncviewer: -shared switch)
-vnc :5900,share=force-shared disables exclusive client access. Useful for shared desktop sessions, where you don't want someone forgetting specify -shared disconnect everybody else.
-vnc :5900,share=ignore completely ignores the shared flag and allows everybody connect unconditionally rdp seems to support some similar (though they don't look identical) features through replaceUser/multiUser.
« The replaceUser attribute is a boolean deciding whether multiple simultaneous connections to the VM are permitted. The multiUser attribute is a boolean deciding whether the existing connection must be dropped and a new connection must be established by the VRDP server, when a new client connects in single connection mode. »
I'm wondering if we should try to use similar attributes for both rdp and vnc for more consistency?
These vnc server flags need to work together with vnc client flag (like: -Shared for vncviewer) for a certain behaviour, and these flags focus on how to share more than whether to share or not. I don't know more about RDP, it seems that their common behaviours are not quite same according to above docs. Guannan

--- src/qemu/qemu_command.c | 13 ++++++++ .../qemuxml2argv-graphics-vnc-policy.args | 4 +++ .../qemuxml2argv-graphics-vnc-policy.xml | 35 ++++++++++++++++++++++ tests/qemuxml2argvtest.c | 1 + 4 files changed, 53 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc-policy.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc-policy.xml diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index fe70133..31087cf 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -5952,6 +5952,19 @@ qemuBuildGraphicsVNCCommandLine(virQEMUDriverConfigPtr cfg, /* TODO: Support ACLs later */ } + + if (graphics->data.vnc.sharePolicy) { + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VNC_SHARE_POLICY)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("vnc display sharing policy is not " + "supported with this QEMU")); + goto error; + } + + virBufferAsprintf(&opt, ",share=%s", + virDomainGraphicsVNCSharePolicyTypeToString( + graphics->data.vnc.sharePolicy)); + } } virCommandAddArg(cmd, "-vnc"); diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc-policy.args b/tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc-policy.args new file mode 100644 index 0000000..1b61fcf --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc-policy.args @@ -0,0 +1,4 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \ +/usr/bin/qemu -S -M pc -m 214 -smp 1 -monitor unix:/tmp/test-monitor,server,nowait \ +-no-acpi -boot c -usb -hda /dev/HostVG/QEMUGuest1 \ +-net none -serial none -parallel none -vnc 127.0.0.1:0,share=allow-exclusive diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc-policy.xml b/tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc-policy.xml new file mode 100644 index 0000000..6c95c8a --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc-policy.xml @@ -0,0 +1,35 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <driver name='qemu' type='raw'/> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='usb' index='0'/> + <controller type='ide' index='0'/> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <graphics type='vnc' port='5900' autoport='no' listen='127.0.0.1' sharePolicy='allow-exclusive'> + <listen type='address' address='127.0.0.1'/> + </graphics> + <video> + <model type='cirrus' vram='9216' heads='1'/> + </video> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 1286273..4ccc536 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -597,6 +597,7 @@ mymain(void) QEMU_CAPS_SCSI_LSI, QEMU_CAPS_VIRTIO_SCSI); DO_TEST("graphics-vnc", QEMU_CAPS_VNC); + DO_TEST("graphics-vnc-policy", QEMU_CAPS_VNC, QEMU_CAPS_VNC_SHARE_POLICY); DO_TEST("graphics-vnc-socket", QEMU_CAPS_VNC); driver.config->vncSASL = 1; -- 1.8.1.4
participants (2)
-
Christophe Fergeau
-
Guannan Ren