From: Marc-André Lureau <[email protected]>

When both a D-Bus display and a VNC graphics device are configured
and the qemu-vnc binary is available, use the standalone VNC server
instead of QEMU's built-in VNC.

During domain preparation, detect whether the standalone VNC path
applies and allocate the qemuVnc context. Skip the built-in -vnc
command line argument when standalone VNC is active. Start and stop
the qemu-vnc process through the external device hooks.

Signed-off-by: Marc-André Lureau <[email protected]>
---
 src/qemu/qemu_command.c   |  2 ++
 src/qemu/qemu_domain.c    |  1 +
 src/qemu/qemu_domain.h    |  2 ++
 src/qemu/qemu_extdevice.c | 13 +++++++++++--
 src/qemu/qemu_process.c   | 40 ++++++++++++++++++++++++++++++++++++++-
 5 files changed, 55 insertions(+), 3 deletions(-)

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 5b7423e354..a35205bd25 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -8806,6 +8806,8 @@ qemuBuildGraphicsCommandLine(virQEMUDriverConfig *cfg,
 
             break;
         case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
+            if (QEMU_DOMAIN_GRAPHICS_PRIVATE(graphics)->vnc)
+                break;
             if (qemuBuildGraphicsVNCCommandLine(cfg, def, cmd,
                                                 graphics) < 0)
                 return -1;
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 91d57ee60b..dc6282d811 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -1040,6 +1040,7 @@ qemuDomainGraphicsPrivateDispose(void *obj)
     g_free(priv->tlsAlias);
     g_clear_pointer(&priv->secinfo, qemuDomainSecretInfoFree);
     g_clear_pointer(&priv->rdp, qemuRdpFree);
+    g_clear_pointer(&priv->vnc, qemuVncFree);
 }
 
 
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index b321a64e96..24e62dd2e7 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -36,6 +36,7 @@
 #include "qemu_migration_params.h"
 #include "qemu_nbdkit.h"
 #include "qemu_rdp.h"
+#include "qemu_vnc.h"
 #include "qemu_slirp.h"
 #include "qemu_fd.h"
 #include "virchrdev.h"
@@ -417,6 +418,7 @@ struct _qemuDomainGraphicsPrivate {
     char *tlsAlias;
     qemuDomainSecretInfo *secinfo;
     qemuRdp *rdp;
+    qemuVnc *vnc;
 };
 
 
diff --git a/src/qemu/qemu_extdevice.c b/src/qemu/qemu_extdevice.c
index 6e16c6be29..93a070f892 100644
--- a/src/qemu/qemu_extdevice.c
+++ b/src/qemu/qemu_extdevice.c
@@ -247,8 +247,14 @@ qemuExtDevicesStart(virQEMUDriver *driver,
                 return -1;
             continue;
         }
+        case VIR_DOMAIN_GRAPHICS_TYPE_VNC: {
+            if (QEMU_DOMAIN_GRAPHICS_PRIVATE(graphics)->vnc) {
+                if (qemuVncStart(vm, graphics) < 0)
+                    return -1;
+            }
+            continue;
+        }
         case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
-        case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
         case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
         case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
         case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
@@ -327,9 +333,12 @@ qemuExtDevicesStop(virQEMUDriver *driver,
             qemuRdpStop(vm, graphics);
             continue;
         }
+        case VIR_DOMAIN_GRAPHICS_TYPE_VNC: {
+            qemuVncStop(vm, graphics);
+            continue;
+        }
         case VIR_DOMAIN_GRAPHICS_TYPE_DBUS:
         case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
-        case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
         case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
         case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
         case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 7ebc038e54..40db4fabbd 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -5589,6 +5589,41 @@ qemuProcessGraphicsSetupRenderNode(virDomainGraphicsDef 
*graphics,
 }
 
 
+static bool
+qemuHasNonP2PDbusGraphics(virDomainDef *def)
+{
+    size_t i;
+
+    for (i = 0; i < def->ngraphics; i++) {
+        virDomainGraphicsDef *g = def->graphics[i];
+
+        if (g->type == VIR_DOMAIN_GRAPHICS_TYPE_DBUS && !g->data.dbus.p2p)
+            return true;
+    }
+
+    return false;
+}
+
+
+static int
+qemuPrepareGraphicsVnc(virQEMUDriver *driver,
+                       virDomainDef *def,
+                       virDomainGraphicsDef *gfx)
+{
+    g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
+
+    if (!qemuHasNonP2PDbusGraphics(def))
+        return 0;
+
+    if (!qemuVncAvailable(cfg->qemuVncName))
+        return 0;
+
+    QEMU_DOMAIN_GRAPHICS_PRIVATE(gfx)->vnc = qemuVncNew();
+
+    return 0;
+}
+
+
 static int
 qemuProcessSetupGraphics(virQEMUDriver *driver,
                          virDomainObj *vm,
@@ -5610,6 +5645,10 @@ qemuProcessSetupGraphics(virQEMUDriver *driver,
 
         if (qemuProcessGraphicsSetupDBus(driver, graphics, vm) < 0)
             return -1;
+
+        if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
+            qemuPrepareGraphicsVnc(driver, vm->def, graphics) < 0)
+            return -1;
     }
 
     if (allocate) {
@@ -6174,7 +6213,6 @@ qemuProcessPrepareGraphics(virDomainObj *vm)
         if (gfx->type == VIR_DOMAIN_GRAPHICS_TYPE_RDP &&
             qemuPrepareGraphicsRdp(priv->driver, gfx) < 0)
             return -1;
-
     }
 
     return 0;
-- 
2.53.0

Reply via email to