]> xenbits.xensource.com Git - libvirt.git/commitdiff
Wire up QEMU implementation for virDomainOpenGraphics
authorDaniel P. Berrange <berrange@redhat.com>
Fri, 21 Oct 2011 08:00:13 +0000 (09:00 +0100)
committerDaniel P. Berrange <berrange@redhat.com>
Fri, 28 Oct 2011 09:23:53 +0000 (10:23 +0100)
The QEMU monitor command 'add_client' can be used to connect to
a VNC or SPICE graphics display. This allows for implementation
of the virDomainOpenGraphics API

* src/qemu/qemu_driver.c: Implement virDomainOpenGraphics
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
  src/qemu/qemu_monitor_json.c, src/qemu/qemu_monitor_json.h,
  src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
  Add binding for 'add_client' command

src/qemu/qemu_driver.c
src/qemu/qemu_monitor.c
src/qemu/qemu_monitor.h
src/qemu/qemu_monitor_json.c
src/qemu/qemu_monitor_json.h
src/qemu/qemu_monitor_text.c
src/qemu/qemu_monitor_text.h

index e053a97457e9380e67cde2702b42968efd0f8cb7..049abe1a25873b34b2ad1712437813cb1eafeb3f 100644 (file)
@@ -919,6 +919,7 @@ qemudSupportsFeature (virConnectPtr conn ATTRIBUTE_UNUSED, int feature)
     case VIR_DRV_FEATURE_MIGRATION_V3:
     case VIR_DRV_FEATURE_MIGRATION_P2P:
     case VIR_DRV_FEATURE_MIGRATE_CHANGE_PROTECTION:
+    case VIR_DRV_FEATURE_FD_PASSING:
         return 1;
     default:
         return 0;
@@ -10660,6 +10661,76 @@ qemuDomainBlockPull(virDomainPtr dom, const char *path, unsigned long bandwidth,
     return ret;
 }
 
+static int
+qemuDomainOpenGraphics(virDomainPtr dom,
+                       unsigned int idx,
+                       int fd,
+                       unsigned int flags)
+{
+    struct qemud_driver *driver = dom->conn->privateData;
+    virDomainObjPtr vm = NULL;
+    char uuidstr[VIR_UUID_STRING_BUFLEN];
+    int ret = -1;
+    qemuDomainObjPrivatePtr priv;
+    const char *protocol;
+
+    virCheckFlags(VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH, -1);
+
+    qemuDriverLock(driver);
+    virUUIDFormat(dom->uuid, uuidstr);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    if (!vm) {
+        qemuReportError(VIR_ERR_NO_DOMAIN,
+                        _("no domain with matching uuid '%s'"), uuidstr);
+        goto cleanup;
+    }
+
+    if (!virDomainObjIsActive(vm)) {
+        qemuReportError(VIR_ERR_OPERATION_INVALID,
+                        "%s", _("domain is not running"));
+        goto cleanup;
+    }
+
+    priv = vm->privateData;
+
+    if (idx >= vm->def->ngraphics) {
+        qemuReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("No graphics backend with index %d"), idx);
+        goto cleanup;
+    }
+    switch (vm->def->graphics[idx]->type) {
+    case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
+        protocol = "vnc";
+        break;
+    case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
+        protocol = "spice";
+        break;
+    default:
+        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                        _("Can only open VNC or SPICE graphics backends, not %s"),
+                        virDomainGraphicsTypeToString(vm->def->graphics[idx]->type));
+        goto cleanup;
+    }
+
+    if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
+        goto cleanup;
+    qemuDomainObjEnterMonitorWithDriver(driver, vm);
+    ret = qemuMonitorOpenGraphics(priv->mon, protocol, fd, "graphicsfd",
+                                  (flags & VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH) != 0);
+    qemuDomainObjExitMonitorWithDriver(driver, vm);
+    if (qemuDomainObjEndJob(driver, vm) == 0) {
+        vm = NULL;
+        goto cleanup;
+    }
+
+cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
+    return ret;
+}
+
+
 static virDriver qemuDriver = {
     .no = VIR_DRV_QEMU,
     .name = "QEMU",
@@ -10790,6 +10861,7 @@ static virDriver qemuDriver = {
     .qemuDomainMonitorCommand = qemuDomainMonitorCommand, /* 0.8.3 */
     .qemuDomainAttach = qemuDomainAttach, /* 0.9.4 */
     .domainOpenConsole = qemuDomainOpenConsole, /* 0.8.6 */
+    .domainOpenGraphics = qemuDomainOpenGraphics, /* 0.9.7 */
     .domainInjectNMI = qemuDomainInjectNMI, /* 0.9.2 */
     .domainMigrateBegin3 = qemuDomainMigrateBegin3, /* 0.9.2 */
     .domainMigratePrepare3 = qemuDomainMigratePrepare3, /* 0.9.2 */
index 2b004b7ccbf81f64d1e258d82590670ef01b6242..73e5ea986795f77f78277f7cc609006ab4f50e23 100644 (file)
@@ -2616,3 +2616,36 @@ int qemuMonitorVMStatusToPausedReason(const char *status)
     }
     return VIR_DOMAIN_PAUSED_UNKNOWN;
 }
+
+
+int qemuMonitorOpenGraphics(qemuMonitorPtr mon,
+                            const char *protocol,
+                            int fd,
+                            const char *fdname,
+                            bool skipauth)
+{
+    VIR_DEBUG("mon=%p protocol=%s fd=%d fdname=%s skipauth=%d",
+              mon, protocol, fd, NULLSTR(fdname), skipauth);
+    int ret;
+
+    if (!mon) {
+        qemuReportError(VIR_ERR_INVALID_ARG, "%s",
+                        _("monitor must not be NULL"));
+        return -1;
+    }
+
+    if (qemuMonitorSendFileHandle(mon, fdname, fd) < 0)
+        return -1;
+
+    if (mon->json)
+        ret = qemuMonitorJSONOpenGraphics(mon, protocol, fdname, skipauth);
+    else
+        ret = qemuMonitorTextOpenGraphics(mon, protocol, fdname, skipauth);
+
+    if (ret < 0) {
+        if (qemuMonitorCloseFileHandle(mon, fdname) < 0)
+            VIR_WARN("failed to close device handle '%s'", fdname);
+    }
+
+    return ret;
+}
index 90e7b4590188e9ed3ec4ae3cb07c91631e436b53..883e0aaf1e47555531b282dee3561014e917692a 100644 (file)
@@ -515,6 +515,12 @@ int qemuMonitorBlockJob(qemuMonitorPtr mon,
                         virDomainBlockJobInfoPtr info,
                         int mode);
 
+int qemuMonitorOpenGraphics(qemuMonitorPtr mon,
+                            const char *protocol,
+                            int fd,
+                            const char *fdname,
+                            bool skipauth);
+
 /**
  * When running two dd process and using <> redirection, we need a
  * shell that will not truncate files.  These two strings serve that
index 15360988ca38b218080efc726fea0581d9c13523..56a62dbf416c1c1de2ab0049304588a3c3610c2a 100644 (file)
@@ -3249,3 +3249,30 @@ int qemuMonitorJSONBlockJob(qemuMonitorPtr mon,
     virJSONValueFree(reply);
     return ret;
 }
+
+int qemuMonitorJSONOpenGraphics(qemuMonitorPtr mon,
+                                const char *protocol,
+                                const char *fdname,
+                                bool skipauth)
+{
+    int ret;
+    virJSONValuePtr cmd, reply = NULL;
+
+    cmd = qemuMonitorJSONMakeCommand("add_client",
+                                     "s:protocol", protocol,
+                                     "s:fdname", fdname,
+                                     "b:skipauth", skipauth,
+                                     NULL);
+
+    if (!cmd)
+        return -1;
+
+    ret = qemuMonitorJSONCommand(mon, cmd, &reply);
+
+    if (ret == 0)
+        ret = qemuMonitorJSONCheckError(cmd, reply);
+
+    virJSONValueFree(cmd);
+    virJSONValueFree(reply);
+    return ret;
+}
index a638b41ca89df13aa139795afec505173b7cadb4..f10d7d20ce2952816cf917ab455e2f711b74abc7 100644 (file)
@@ -250,4 +250,9 @@ int qemuMonitorJSONSetLink(qemuMonitorPtr mon,
                            const char *name,
                            enum virDomainNetInterfaceLinkState state);
 
+int qemuMonitorJSONOpenGraphics(qemuMonitorPtr mon,
+                                const char *protocol,
+                                const char *fdname,
+                                bool skipauth);
+
 #endif /* QEMU_MONITOR_JSON_H */
index c652321f76082bf7503321f4082731a2dce2a20b..5de4d24be86a43ff3b48f993a3f9448f7e9a0d3b 100644 (file)
@@ -3397,3 +3397,35 @@ cleanup:
     VIR_FREE(reply);
     return ret;
 }
+
+
+int qemuMonitorTextOpenGraphics(qemuMonitorPtr mon,
+                                const char *protocol,
+                                const char *fdname,
+                                bool skipauth)
+{
+    char *cmd = NULL;
+    char *reply = NULL;
+    int ret = -1;
+
+    if (virAsprintf(&cmd, "add_client %s %s %d", protocol, fdname, skipauth ? 0 : 1) < 0){
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0) {
+        qemuReportError(VIR_ERR_OPERATION_FAILED,
+                        "%s", _("adding graphics client failed"));
+        goto cleanup;
+    }
+
+    if (STRNEQ(reply, ""))
+        goto cleanup;
+
+    ret = 0;
+
+cleanup:
+    VIR_FREE(reply);
+    VIR_FREE(cmd);
+    return ret;
+}
index cc2a252051a91200536c6a372f4fa8c5bb6c381f..f32fce0235eb2aa975e5ca8e5743c6f67c2b5d40 100644 (file)
@@ -243,4 +243,9 @@ int qemuMonitorTextSetLink(qemuMonitorPtr mon,
                            const char *name,
                            enum virDomainNetInterfaceLinkState state);
 
+int qemuMonitorTextOpenGraphics(qemuMonitorPtr mon,
+                                const char *protocol,
+                                const char *fdname,
+                                bool skipauth);
+
 #endif /* QEMU_MONITOR_TEXT_H */