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

v3->v4 add missing .args, .xml files (I raw it in git Untracked files this morning and thought about it for a while, then git-cleaned them...) rebase work. v2->v3 rebase work. 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. As there were some vnc patches recently, I chose do rebase work a little later. These patches try to add a new attribute 'sharePolicy' to element graphics of vnc type. This attribute has three values: allow-exclusive,force-shared and ignore.

QEMU_CAPS_VNC_SHARE_POLICY (qemu >= 1.1) --- src/qemu/qemu_capabilities.c | 7 ++++++- src/qemu/qemu_capabilities.h | 1 + tests/qemuhelptest.c | 9 ++++++--- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 82129a2..b13a5ab 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -231,6 +231,8 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "vnc-websocket", "drive-discard", "mlock", + + "vnc-share-policy", /* 150 */ ); struct _virQEMUCaps { @@ -1188,8 +1190,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); @@ -2433,6 +2437,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 117bf8a..90d08c6 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -188,6 +188,7 @@ enum virQEMUCapsFlags { QEMU_CAPS_VNC_WEBSOCKET = 147, /* -vnc x:y,websocket */ QEMU_CAPS_DRIVE_DISCARD = 148, /* -drive discard=off(ignore)|on(unmap) */ QEMU_CAPS_MLOCK = 149, /* -realtime mlock=on|off */ + QEMU_CAPS_VNC_SHARE_POLICY = 150, /* 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 f7f88d0..f6bf7dd 100644 --- a/tests/qemuhelptest.c +++ b/tests/qemuhelptest.c @@ -827,7 +827,8 @@ mymain(void) QEMU_CAPS_IPV6_MIGRATION, QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_DEVICE_SCSI_GENERIC, - QEMU_CAPS_DEVICE_SCSI_GENERIC_BOOTINDEX); + QEMU_CAPS_DEVICE_SCSI_GENERIC_BOOTINDEX, + QEMU_CAPS_VNC_SHARE_POLICY); DO_TEST("qemu-1.2.0", 1002000, 0, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -933,7 +934,8 @@ mymain(void) QEMU_CAPS_IPV6_MIGRATION, QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_DEVICE_SCSI_GENERIC, - QEMU_CAPS_DEVICE_SCSI_GENERIC_BOOTINDEX); + QEMU_CAPS_DEVICE_SCSI_GENERIC_BOOTINDEX, + QEMU_CAPS_VNC_SHARE_POLICY); DO_TEST("qemu-kvm-1.2.0", 1002000, 1, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -1044,7 +1046,8 @@ mymain(void) QEMU_CAPS_IPV6_MIGRATION, QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_DEVICE_SCSI_GENERIC, - QEMU_CAPS_DEVICE_SCSI_GENERIC_BOOTINDEX); + QEMU_CAPS_DEVICE_SCSI_GENERIC_BOOTINDEX, + 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 d9814dd..8c12690 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -3621,7 +3621,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' /> @@ -3664,7 +3664,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 b53099b..939654f 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2135,6 +2135,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 e7a0381..812a0d6 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -515,6 +515,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", @@ -7703,6 +7710,7 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) { char *port = virXMLPropString(node, "port"); char *websocket = virXMLPropString(node, "websocket"); + char *sharePolicy = virXMLPropString(node, "sharePolicy"); char *autoport; if (port) { @@ -7745,6 +7753,21 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, VIR_FREE(websocket); } + if (sharePolicy) { + int policy = + virDomainGraphicsVNCSharePolicyTypeFromString(sharePolicy); + + if (policy < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown vnc display sharing policy '%s'"), sharePolicy); + VIR_FREE(sharePolicy); + goto error; + } else { + def->data.vnc.sharePolicy = policy; + } + VIR_FREE(sharePolicy); + } + def->data.vnc.socket = virXMLPropString(node, "socket"); def->data.vnc.keymap = virXMLPropString(node, "keymap"); @@ -15280,6 +15303,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 e74da1c..3f98647 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1288,6 +1288,15 @@ enum virDomainGraphicsType { VIR_DOMAIN_GRAPHICS_TYPE_LAST }; +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 virDomainGraphicsAuthConnectedType { VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_DEFAULT = 0, VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_FAIL, @@ -1427,6 +1436,7 @@ struct _virDomainGraphicsDef { char *keymap; char *socket; virDomainGraphicsAuthDef auth; + int sharePolicy; } vnc; struct { char *display; @@ -2528,6 +2538,7 @@ VIR_ENUM_DECL(virDomainGraphicsSpicePlaybackCompression) VIR_ENUM_DECL(virDomainGraphicsSpiceStreamingMode) VIR_ENUM_DECL(virDomainGraphicsSpiceClipboardCopypaste) VIR_ENUM_DECL(virDomainGraphicsSpiceMouseMode) +VIR_ENUM_DECL(virDomainGraphicsVNCSharePolicy) VIR_ENUM_DECL(virDomainHyperv) VIR_ENUM_DECL(virDomainRNGModel) VIR_ENUM_DECL(virDomainRNGBackend) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 392357f..0fa2277 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -202,6 +202,8 @@ virDomainGraphicsSpiceZlibCompressionTypeFromString; virDomainGraphicsSpiceZlibCompressionTypeToString; virDomainGraphicsTypeFromString; virDomainGraphicsTypeToString; +virDomainGraphicsVNCSharePolicyTypeFromString; +virDomainGraphicsVNCSharePolicyTypeToString; virDomainHasDiskMirror; virDomainHostdevCapsTypeToString; virDomainHostdevDefAlloc; -- 1.8.1.4

example: qemu ${otherargs} \ -vnc 127.0.0.1:0,share=allow-exclusive --- src/qemu/qemu_command.c | 36 ++++++++++++++++++++++ tests/qemuargv2xmltest.c | 1 + .../qemuxml2argv-graphics-vnc-policy.args | 4 +++ .../qemuxml2argv-graphics-vnc-policy.xml | 35 +++++++++++++++++++++ tests/qemuxml2argvtest.c | 1 + 5 files changed, 77 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 33a1910..1f7e717 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6099,6 +6099,19 @@ qemuBuildGraphicsVNCCommandLine(virQEMUDriverConfigPtr cfg, virBufferAsprintf(&opt, ",websocket=%d", graphics->data.vnc.websocket); } + 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)); + } + if (graphics->data.vnc.auth.passwd || cfg->vncPassword) virBufferAddLit(&opt, ",password"); @@ -10030,6 +10043,29 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr qemuCaps, vnc->data.vnc.websocket = vnc->data.vnc.port + 5700; } + } else if (STRPREFIX(opts, "share=")) { + char *sharePolicy = opts + strlen("share="); + if (sharePolicy && *sharePolicy) { + int policy = + virDomainGraphicsVNCSharePolicyTypeFromString(sharePolicy); + + if (policy < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown vnc display sharing policy '%s'"), + sharePolicy); + virDomainGraphicsDefFree(vnc); + VIR_FREE(orig_opts); + goto error; + } else { + vnc->data.vnc.sharePolicy = policy; + } + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("missing vnc sharing policy")); + virDomainGraphicsDefFree(vnc); + VIR_FREE(orig_opts); + goto error; + } } opts = nextopt; diff --git a/tests/qemuargv2xmltest.c b/tests/qemuargv2xmltest.c index 58fabdb..652cd09 100644 --- a/tests/qemuargv2xmltest.c +++ b/tests/qemuargv2xmltest.c @@ -201,6 +201,7 @@ mymain(void) DO_TEST("graphics-vnc"); DO_TEST("graphics-vnc-socket"); DO_TEST("graphics-vnc-websocket"); + DO_TEST("graphics-vnc-policy"); DO_TEST("graphics-vnc-sasl"); DO_TEST("graphics-vnc-tls"); 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 fb61017..b18436b 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -610,6 +610,7 @@ mymain(void) DO_TEST("graphics-vnc", QEMU_CAPS_VNC); DO_TEST("graphics-vnc-socket", QEMU_CAPS_VNC); DO_TEST("graphics-vnc-websocket", QEMU_CAPS_VNC, QEMU_CAPS_VNC_WEBSOCKET); + DO_TEST("graphics-vnc-policy", QEMU_CAPS_VNC, QEMU_CAPS_VNC_SHARE_POLICY); driver.config->vncSASL = 1; VIR_FREE(driver.config->vncSASLdir); -- 1.8.1.4

On 05/21/2013 04:31 PM, Guannan Ren wrote:
v3->v4 add missing .args, .xml files (I raw it in git Untracked files this morning and thought about it for a while, then git-cleaned them...) rebase work.
v2->v3 rebase work.
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.
As there were some vnc patches recently, I chose do rebase work a little later.
These patches try to add a new attribute 'sharePolicy' to element graphics of vnc type. This attribute has three values: allow-exclusive,force-shared and ignore.
ACK series. Jan

On 05/22/2013 01:50 PM, Ján Tomko wrote:
On 05/21/2013 04:31 PM, Guannan Ren wrote:
v3->v4 add missing .args, .xml files (I raw it in git Untracked files this morning and thought about it for a while, then git-cleaned them...) rebase work.
v2->v3 rebase work.
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.
As there were some vnc patches recently, I chose do rebase work a little later.
These patches try to add a new attribute 'sharePolicy' to element graphics of vnc type. This attribute has three values: allow-exclusive,force-shared and ignore.
ACK series.
Thanks for the review. pushed. Guannan
participants (2)
-
Guannan Ren
-
Ján Tomko