]> xenbits.xensource.com Git - libvirt.git/commitdiff
graphics: add support for action_if_connected in qemu
authorMichal Privoznik <mprivozn@redhat.com>
Thu, 26 May 2011 14:15:54 +0000 (16:15 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Fri, 8 Jul 2011 15:00:43 +0000 (17:00 +0200)
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)

docs/formatdomain.html.in
docs/schemas/domain.rng
src/conf/domain_conf.c
src/conf/domain_conf.h
src/libvirt_private.syms
src/qemu/qemu_hotplug.c
tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-timeout.xml

index 10d87a9bb6f62794042f3272db263ca13b774847..fa4e0c23b71f165ffa33906b218cb43b4fc9190f 100644 (file)
@@ -1896,11 +1896,14 @@ qemu-kvm -net nic,model=? /dev/null
             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/>  <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>
+            assumed to be in UTC. 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.<span class="since">Since 0.8.8</span>
           </dd>
           <dt><code>"spice"</code></dt>
           <dd>
@@ -1918,8 +1921,14 @@ qemu-kvm -net nic,model=? /dev/null
               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.<span class="since">"spice" since 0.8.6</span>.
+              assumed to be in UTC. 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>
               When SPICE has both a normal and TLS secured TCP port
index 3c8414eef06e753fe369d5e9ba22164cc15e4bbd..c01801e4cdfb5b3da376b57161231d1d031168d4 100644 (file)
               <data type="dateTime"/>
             </attribute>
           </optional>
+          <optional>
+            <attribute name="connected">
+              <choice>
+                <value>keep</value>
+              </choice>
+            </attribute>
+          </optional>
         </group>
         <group>
           <attribute name="type">
               <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">
index 2275d3ae5b3c725b114e5c67284aa856f13bda75..a680b114e8151dd7857d55dc80140484d63e038a 100644 (file)
@@ -317,6 +317,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",
@@ -3945,9 +3952,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");
 
@@ -3988,6 +3998,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;
 }
 
@@ -4058,7 +4090,8 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, unsigned 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");
@@ -4194,7 +4227,8 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, unsigned 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;
@@ -9280,6 +9314,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
index ddfe18e3d90c2569f86c25bedfc7f2591b4f3e0a..15adc70b88b606643ec190f58a05dd3333e38c14 100644 (file)
@@ -639,12 +639,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 {
@@ -1582,6 +1592,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)
index 28a34045f7ed6727fbc18f81374a87267dc23992..11123986422c7c98ff735ef148e1f819a0419bc1 100644 (file)
@@ -270,6 +270,8 @@ virDomainFindByID;
 virDomainFindByName;
 virDomainFindByUUID;
 virDomainGetRootFilesystem;
+virDomainGraphicsAuthConnectedTypeFromString;
+virDomainGraphicsAuthConnectedTypeToString;
 virDomainGraphicsDefFree;
 virDomainGraphicsSpiceChannelModeTypeFromString;
 virDomainGraphicsSpiceChannelModeTypeToString;
index a7f11ab4363f202a5381d8cb9f7aff92da1f958e..58689f688a88dfd5b9789da3783024975209fd5a 100644 (file)
@@ -1065,10 +1065,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",
@@ -1084,6 +1086,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;
         }
@@ -1116,6 +1119,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",
@@ -1131,6 +1135,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;
@@ -1874,16 +1879,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) {
index 4c0c57edf2af6724c605687a5c520463dc54eb16..6389de54ad4fb0c97a92c4dd76a34f8cd90480b8 100644 (file)
@@ -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>