[libvirt] [PATCH v3] graphics: add support for action_if_connected in qemu

Michal Prívozník mprivozn at redhat.com
Thu Jun 9 11:31:59 UTC 2011


From: Michal Privoznik <mprivozn at redhat.com>

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 v2:
-fixed typo
-added test. However, functionality provided by this patch will show up
 only when talking to qemu monitor (set_password command).

diff to v1:
-Eric's review suggestions included
-update 'Since'
 
 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                            |   15 +++++-
 .../qemuxml2argv-graphics-spice-timeout.xml        |    2 +-
 7 files changed, 94 insertions(+), 9 deletions(-)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 98fb2b4..2ed16ff 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1801,7 +1801,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.5</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.3</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.
@@ -1820,7 +1824,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.5</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.3</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 0be0371..e71b683 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -1250,6 +1250,13 @@
               <data type="dateTime"/>
             </attribute>
           </optional>
+          <optional>
+            <attribute name="connected">
+              <choice>
+                <value>keep</value>
+              </choice>
+            </attribute>
+          </optional>
         </group>
         <group>
           <attribute name="type">
@@ -1293,6 +1300,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 0d9fef4..19f22e0 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -311,6 +311,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",
@@ -3892,9 +3899,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");
 
@@ -3935,6 +3945,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;
 }
 
@@ -4004,7 +4036,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");
@@ -4140,7 +4173,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;
@@ -9075,6 +9109,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 41c8136..6bfc337 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -640,12 +640,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 {
@@ -1546,6 +1556,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 9d4e163..c43da44 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -269,6 +269,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 d33fc87..da6629b 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1061,10 +1061,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",
@@ -1080,6 +1082,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;
         }
@@ -1112,6 +1115,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",
@@ -1127,6 +1131,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;
@@ -1812,16 +1817,20 @@ qemuDomainChangeGraphicsPasswords(struct qemud_driver *driver,
     qemuDomainObjPrivatePtr priv = vm->privateData;
     time_t now = time(NULL);
     char expire_time [64];
+    const char *connected = NULL;
     int ret;
 
     if (!auth->passwd && !driver->vncPassword)
         return 0;
 
+    if (auth->connected)
+        connected = virDomainGraphicsAuthConnectedTypeToString(auth->connected);
+
     qemuDomainObjEnterMonitorWithDriver(driver, vm);
     ret = qemuMonitorSetPassword(priv->mon,
                                  type,
                                  auth->passwd ? auth->passwd : defaultPasswd,
-                                 NULL);
+                                 connected);
 
     if (ret == -2) {
         if (type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-timeout.xml b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-timeout.xml
index 4c0c57e..6389de5 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-timeout.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-timeout.xml
@@ -71,7 +71,7 @@
     </console>
     <input type='tablet' bus='usb'/>
     <input type='mouse' bus='ps2'/>
-    <graphics type='spice' port='5900' autoport='no' passwd='sercet' passwdValidTo='2011-05-31T16:11:22'/>
+    <graphics type='spice' port='5900' autoport='no' passwd='sercet' passwdValidTo='2011-05-31T16:11:22' connected='disconnect'/>
     <sound model='ac97'>
       <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
     </sound>
-- 
1.7.5.rc3




More information about the libvir-list mailing list