This option accepts 3 values: -keep, to keep current client connected (Spice+VNC) -disconnect, to disconnect client (Spice) -fail, to fail setting password if there is a client connected (Spice) --- diff to v1: -doc added docs/formatdomain.html.in | 13 +++++++++++-- docs/schemas/domain.rng | 16 ++++++++++++++++ src/conf/domain_conf.c | 44 +++++++++++++++++++++++++++++++++++++++++--- src/conf/domain_conf.h | 11 +++++++++++ src/libvirt_private.syms | 2 ++ src/qemu/qemu_hotplug.c | 11 ++++++++--- 6 files changed, 89 insertions(+), 8 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index f8baffd..25e97a5 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1762,7 +1762,11 @@ qemu-kvm -net nic,model=? /dev/null in clear text. The <code>keymap</code> attribute specifies the keymap to use. It is possible to set a limit on the validity of the password be giving an timestamp <code>passwdValidTo='2010-04-09T15:51:00'</code> - assumed to be in UTC. NB, this may not be supported by all hypervisors.<br/> + assumed to be in UTC. <span class="since">Since 0.8.6</span> + The <code>connected</code> attribute allows control of connected client + during password changes. VNC accepts <code>keep</code> value only. + <span class="since">since 0.9.2</span> + NB, this may not be supported by all hypervisors.<br/> <br/> Rather than using listen/port, QEMU supports a <code>socket</code> attribute for listening on a unix domain socket path. @@ -1781,7 +1785,12 @@ qemu-kvm -net nic,model=? /dev/null in clear text. The <code>keymap</code> attribute specifies the keymap to use. It is possible to set a limit on the validity of the password be giving an timestamp <code>passwdValidTo='2010-04-09T15:51:00'</code> - assumed to be in UTC. NB, this may not be supported by all hypervisors. + assumed to be in UTC.<span class="since">Since 0.8.6</span> + The <code>connected</code> attribute allows control of connected client + during password changes. SPICE accepts <code>keep</code> to keep client + connected, <code>disconnect</code> to disconnect client and + <code>fail</code> to fail changing password. <span class="since">Since 0.9.2</span> + NB, this may not be supported by all hypervisors. <span class="since">"spice" since 0.8.6</span>. </p> <p> diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index c270815..f0efe60 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -1227,6 +1227,13 @@ <data type="dateTime"/> </attribute> </optional> + <optional> + <attribute name="connected"> + <choice> + <value>keep</value> + </choice> + </attribute> + </optional> </group> <group> <attribute name="type"> @@ -1270,6 +1277,15 @@ <data type="dateTime"/> </attribute> </optional> + <optional> + <attribute name="connected"> + <choice> + <value>fail</value> + <value>disconnect</value> + <value>keep</value> + </choice> + </attribute> + </optional> <interleave> <zeroOrMore> <element name="channel"> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index fbef61e..571fcf4 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -313,6 +313,13 @@ VIR_ENUM_IMPL(virDomainGraphics, VIR_DOMAIN_GRAPHICS_TYPE_LAST, "desktop", "spice") +VIR_ENUM_IMPL(virDomainGraphicsAuthConnected, + VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_LAST, + "default", + "fail", + "disconnect", + "keep") + VIR_ENUM_IMPL(virDomainGraphicsSpiceChannelName, VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_LAST, "main", @@ -3803,9 +3810,12 @@ error: static int -virDomainGraphicsAuthDefParseXML(xmlNodePtr node, virDomainGraphicsAuthDefPtr def) +virDomainGraphicsAuthDefParseXML(xmlNodePtr node, + virDomainGraphicsAuthDefPtr def, + int type) { char *validTo = NULL; + char *connected = virXMLPropString(node, "connected"); def->passwd = virXMLPropString(node, "passwd"); @@ -3846,6 +3856,28 @@ virDomainGraphicsAuthDefParseXML(xmlNodePtr node, virDomainGraphicsAuthDefPtr de def->expires = 1; } + if (connected) { + int action = virDomainGraphicsAuthConnectedTypeFromString(connected); + if (action < 0) { + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown connected value %s"), + connected); + VIR_FREE(connected); + return -1; + } + VIR_FREE(connected); + + /* VNC supports connected='keep' only */ + if (type == VIR_DOMAIN_GRAPHICS_TYPE_VNC && + action != VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_KEEP) { + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("VNC supports connected='keep' only")); + return -1; + } + + def->connected = action; + } + return 0; } @@ -3915,7 +3947,8 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) { !def->data.vnc.listenAddr[0]) VIR_FREE(def->data.vnc.listenAddr); - if (virDomainGraphicsAuthDefParseXML(node, &def->data.vnc.auth) < 0) + if (virDomainGraphicsAuthDefParseXML(node, &def->data.vnc.auth, + def->type) < 0) goto error; } else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) { char *fullscreen = virXMLPropString(node, "fullscreen"); @@ -4051,7 +4084,8 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) { !def->data.spice.listenAddr[0]) VIR_FREE(def->data.spice.listenAddr); - if (virDomainGraphicsAuthDefParseXML(node, &def->data.spice.auth) < 0) + if (virDomainGraphicsAuthDefParseXML(node, &def->data.spice.auth, + def->type) < 0) goto error; cur = node->children; @@ -7995,6 +8029,10 @@ virDomainGraphicsAuthDefFormatAttr(virBufferPtr buf, strftime(strbuf, sizeof(strbuf), "%Y-%m-%dT%H:%M:%S", tm); virBufferAsprintf(buf, " passwdValidTo='%s'", strbuf); } + + if (def->connected) + virBufferEscapeString(buf, " connected='%s'", + virDomainGraphicsAuthConnectedTypeToString(def->connected)); } static int diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 8c94d4d..d090b9a 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -631,12 +631,22 @@ enum virDomainGraphicsType { VIR_DOMAIN_GRAPHICS_TYPE_LAST, }; +enum virDomainGraphicsAuthConnectedType { + VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_DEFAULT = 0, + VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_FAIL, + VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_DISCONNECT, + VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_KEEP, + + VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_LAST +}; + typedef struct _virDomainGraphicsAuthDef virDomainGraphicsAuthDef; typedef virDomainGraphicsAuthDef *virDomainGraphicsAuthDefPtr; struct _virDomainGraphicsAuthDef { char *passwd; unsigned int expires: 1; /* Whether there is an expiry time set */ time_t validTo; /* seconds since epoch */ + int connected; /* action if connected */ }; enum virDomainGraphicsSpiceChannelName { @@ -1514,6 +1524,7 @@ VIR_ENUM_DECL(virDomainHostdevSubsys) VIR_ENUM_DECL(virDomainInput) VIR_ENUM_DECL(virDomainInputBus) VIR_ENUM_DECL(virDomainGraphics) +VIR_ENUM_DECL(virDomainGraphicsAuthConnected) 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 321df2a..bb331a3 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -263,6 +263,8 @@ virDomainFindByID; virDomainFindByName; virDomainFindByUUID; virDomainGetRootFilesystem; +virDomainGraphicsAuthConnectedTypeFromString; +virDomainGraphicsAuthConnectedTypeToString; virDomainGraphicsDefFree; virDomainGraphicsSpiceChannelModeTypeFromString; virDomainGraphicsSpiceChannelModeTypeToString; diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 3cf7d35..c0c4a15 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1017,10 +1017,12 @@ qemuDomainChangeGraphics(struct qemud_driver *driver, return -1; } - /* If a password lifetime was, or is set, then we must always run, - * even if new password matches old password */ + /* If a password lifetime was, or is set, or action if connected has + * changed, then we must always run, even if new password matches + * old password */ if (olddev->data.vnc.auth.expires || dev->data.vnc.auth.expires || + olddev->data.vnc.auth.connected != dev->data.vnc.auth.connected || STRNEQ_NULLABLE(olddev->data.vnc.auth.passwd, dev->data.vnc.auth.passwd)) { VIR_DEBUG("Updating password on VNC server %p %p", dev->data.vnc.auth.passwd, driver->vncPassword); ret = qemuDomainChangeGraphicsPasswords(driver, vm, VIR_DOMAIN_GRAPHICS_TYPE_VNC, @@ -1032,6 +1034,7 @@ qemuDomainChangeGraphics(struct qemud_driver *driver, dev->data.vnc.auth.passwd = NULL; olddev->data.vnc.auth.validTo = dev->data.vnc.auth.validTo; olddev->data.vnc.auth.expires = dev->data.vnc.auth.expires; + olddev->data.vnc.auth.connected = dev->data.vnc.auth.connected; } else { ret = 0; } @@ -1060,6 +1063,7 @@ qemuDomainChangeGraphics(struct qemud_driver *driver, * even if new password matches old password */ if (olddev->data.spice.auth.expires || dev->data.spice.auth.expires || + olddev->data.spice.auth.connected != dev->data.spice.auth.connected || STRNEQ_NULLABLE(olddev->data.spice.auth.passwd, dev->data.spice.auth.passwd)) { VIR_DEBUG("Updating password on SPICE server %p %p", dev->data.spice.auth.passwd, driver->spicePassword); ret = qemuDomainChangeGraphicsPasswords(driver, vm, VIR_DOMAIN_GRAPHICS_TYPE_SPICE, @@ -1071,6 +1075,7 @@ qemuDomainChangeGraphics(struct qemud_driver *driver, dev->data.spice.auth.passwd = NULL; olddev->data.spice.auth.validTo = dev->data.spice.auth.validTo; olddev->data.spice.auth.expires = dev->data.spice.auth.expires; + olddev->data.spice.auth.connected = dev->data.spice.auth.connected; } else { VIR_DEBUG("Not updating since password didn't change"); ret = 0; @@ -1755,7 +1760,7 @@ qemuDomainChangeGraphicsPasswords(struct qemud_driver *driver, ret = qemuMonitorSetPassword(priv->mon, type, auth->passwd ? auth->passwd : defaultPasswd, - NULL); + auth->connected ? virDomainGraphicsAuthConnectedTypeToString(auth->connected) : NULL); if (ret == -2) { if (type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) { -- 1.7.5.rc3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list