diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index b6978380708c68e54f34a266476a7098cf7da3e0..e61af23870d97643a08b6dc9847dce60a2ba766d 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3999,6 +3999,8 @@ qemuDomainScreenshot(virDomainPtr dom, qemuDomainObjPrivatePtr priv; char *tmp = NULL; int tmp_fd = -1; + size_t i; + const char *videoAlias = NULL; char *ret = NULL; bool unlink_tmp = false; virQEMUDriverConfigPtr cfg = NULL; @@ -4020,15 +4022,37 @@ qemuDomainScreenshot(virDomainPtr dom, if (virDomainObjCheckActive(vm) < 0) goto endjob; - /* Well, even if qemu allows multiple graphic cards, heads, whatever, - * screenshot command does not */ - if (screen) { - virReportError(VIR_ERR_INVALID_ARG, - "%s", _("currently is supported only taking " - "screenshots of screen ID 0")); + if (!vm->def->nvideos) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("no screens to take screenshot from")); goto endjob; } + if (screen) { + if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SCREENDUMP_DEVICE)) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("qemu does not allow specifying screen ID")); + goto endjob; + } + + for (i = 0; i < vm->def->nvideos; i++) { + const virDomainVideoDef *video = vm->def->videos[i]; + + if (screen < video->heads) { + videoAlias = video->info.alias; + break; + } + + screen -= video->heads; + } + + if (i == vm->def->nvideos) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("no such screen ID")); + goto endjob; + } + } + if (virAsprintf(&tmp, "%s/qemu.screendump.XXXXXX", cfg->cacheDir) < 0) goto endjob; @@ -4041,7 +4065,7 @@ qemuDomainScreenshot(virDomainPtr dom, qemuSecuritySetSavedStateLabel(driver->securityManager, vm->def, tmp); qemuDomainObjEnterMonitor(driver, vm); - if (qemuMonitorScreendump(priv->mon, tmp) < 0) { + if (qemuMonitorScreendump(priv->mon, videoAlias, screen, tmp) < 0) { ignore_value(qemuDomainObjExitMonitor(driver, vm)); goto endjob; } diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 3d7ca3ccfc5bb4af662de16009d8fb445cf07dc2..f21bf7000d770802c3f0d215377acbd2ce24e9c0 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3477,6 +3477,8 @@ qemuMonitorSendKey(qemuMonitorPtr mon, int qemuMonitorScreendump(qemuMonitorPtr mon, + const char *device, + unsigned int head, const char *file) { VIR_DEBUG("file=%s", file); @@ -3484,7 +3486,7 @@ qemuMonitorScreendump(qemuMonitorPtr mon, QEMU_CHECK_MONITOR(mon); if (mon->json) - return qemuMonitorJSONScreendump(mon, file); + return qemuMonitorJSONScreendump(mon, device, head, file); else return qemuMonitorTextScreendump(mon, file); } diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 33dc521e83fee1479a057446f6c9cbe67f7763b5..6cba37c2816cc556f98e8b6f45754e6e99271213 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -886,6 +886,8 @@ int qemuMonitorArbitraryCommand(qemuMonitorPtr mon, int qemuMonitorInjectNMI(qemuMonitorPtr mon); int qemuMonitorScreendump(qemuMonitorPtr mon, + const char *device, + unsigned int head, const char *file); int qemuMonitorSendKey(qemuMonitorPtr mon, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index e2e0004e4dbd72134f30dab9fc30b0309760e7df..6dcded93691e617a3d7e309a123ffc3700a87944 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -4483,6 +4483,8 @@ int qemuMonitorJSONSendKey(qemuMonitorPtr mon, } int qemuMonitorJSONScreendump(qemuMonitorPtr mon, + const char *device, + unsigned int head, const char *file) { int ret = -1; @@ -4490,6 +4492,8 @@ int qemuMonitorJSONScreendump(qemuMonitorPtr mon, cmd = qemuMonitorJSONMakeCommand("screendump", "s:filename", file, + "S:device", device, + "p:head", head, NULL); if (!cmd) diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index e86b58f7ea73fb221c52e125c1c5d9d7794b93f8..8461932cac52e17c002fd60168577a0225e1fcc8 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -296,6 +296,8 @@ int qemuMonitorJSONSendKey(qemuMonitorPtr mon, unsigned int nkeycodes); int qemuMonitorJSONScreendump(qemuMonitorPtr mon, + const char *device, + unsigned int head, const char *file); int qemuMonitorJSONBlockStream(qemuMonitorPtr mon, diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index edd57067bd553a30ad5f819e1c9d80b261b12f03..add5ff0f19fe17860e32438daf4adb9e3a92770b 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -1348,7 +1348,7 @@ GEN_TEST_FUNC(qemuMonitorJSONDriveMirror, "vdb", "/foo/bar", NULL, 1024, 0, 0, VIR_DOMAIN_BLOCK_REBASE_SHALLOW | VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT) GEN_TEST_FUNC(qemuMonitorJSONBlockCommit, "vdb", "/foo/bar1", "/foo/bar2", NULL, 1024) GEN_TEST_FUNC(qemuMonitorJSONDrivePivot, "vdb") -GEN_TEST_FUNC(qemuMonitorJSONScreendump, "/foo/bar") +GEN_TEST_FUNC(qemuMonitorJSONScreendump, NULL, 0, "/foo/bar") GEN_TEST_FUNC(qemuMonitorJSONOpenGraphics, "spice", "spicefd", false) GEN_TEST_FUNC(qemuMonitorJSONNBDServerStart, "localhost", 12345, "test-alias") GEN_TEST_FUNC(qemuMonitorJSONNBDServerAdd, "vda", true)