aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel P. Berrange <berrange@redhat.com>2011-10-21 09:00:13 +0100
committerDaniel P. Berrange <berrange@redhat.com>2011-10-28 10:23:53 +0100
commitf877fed36f90985c909cc444c670a1aa66909dd5 (patch)
treebd47b6fb2b7dc832387accbc927694b275692d30
parentExtend graphics event to include UNIX socket (diff)
downloadlibvirt-f877fed36f90985c909cc444c670a1aa66909dd5.tar.gz
libvirt-f877fed36f90985c909cc444c670a1aa66909dd5.tar.bz2
libvirt-f877fed36f90985c909cc444c670a1aa66909dd5.zip
Wire up QEMU implementation for virDomainOpenGraphics
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
-rw-r--r--src/qemu/qemu_driver.c72
-rw-r--r--src/qemu/qemu_monitor.c33
-rw-r--r--src/qemu/qemu_monitor.h6
-rw-r--r--src/qemu/qemu_monitor_json.c27
-rw-r--r--src/qemu/qemu_monitor_json.h5
-rw-r--r--src/qemu/qemu_monitor_text.c32
-rw-r--r--src/qemu/qemu_monitor_text.h5
7 files changed, 180 insertions, 0 deletions
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index e053a9745..049abe1a2 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -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 */
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 2b004b7cc..73e5ea986 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -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;
+}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 90e7b4590..883e0aaf1 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -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
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 15360988c..56a62dbf4 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -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;
+}
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index a638b41ca..f10d7d20c 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -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 */
diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c
index c652321f7..5de4d24be 100644
--- a/src/qemu/qemu_monitor_text.c
+++ b/src/qemu/qemu_monitor_text.c
@@ -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;
+}
diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h
index cc2a25205..f32fce023 100644
--- a/src/qemu/qemu_monitor_text.h
+++ b/src/qemu/qemu_monitor_text.h
@@ -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 */