[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

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



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/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 ++++++++---
 5 files changed, 78 insertions(+), 6 deletions(-)

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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]