| From 2a16bf474e9b151de24c4bf56f40e179e1045547 Mon Sep 17 00:00:00 2001 |
| Message-Id: <2a16bf474e9b151de24c4bf56f40e179e1045547.1386932212.git.jdenemar@redhat.com> |
| From: Michal Privoznik <mprivozn@redhat.com> |
| Date: Fri, 26 Aug 2011 16:41:17 +0800 |
| Subject: [PATCH] screenshot: Implement multiple screen support |
| |
| For https://bugzilla.redhat.com/show_bug.cgi?id=1026966 |
| https://bugzilla.redhat.com/show_bug.cgi?id=710489 |
| RHEL only, requires __com.redhat_qxl_screendump |
| |
| As RHEL qemu supports taking screenshot of other monitors than the |
| first one, we can allow libvirt to support this feature too. |
| |
| Although this command allows screen specification via ID, there is |
| not a way to assign one to the primary monitor. Therefore, we must |
| stick to upstream command in case of primary monitor, and use this |
| new command in other cases. |
| |
| (cherry picked from commit 800c9b2c1e0347585213ba6895db7cf064cda21c in |
| rhel-6.5 branch) |
| |
| Signed-off-by: Jiri Denemark <jdenemar@redhat.com> |
| |
| Conflicts: |
| src/qemu/qemu_driver.c - context |
| src/qemu/qemu_monitor.c - don't return -1 without reporting an |
| error |
| |
| src/qemu/qemu_driver.c | 22 +++++++++++++++------- |
| src/qemu/qemu_monitor.c | 23 +++++++++++++++++------ |
| src/qemu/qemu_monitor.h | 3 ++- |
| src/qemu/qemu_monitor_json.c | 24 ++++++++++++++++++++++++ |
| src/qemu/qemu_monitor_json.h | 4 ++++ |
| 5 files changed, 62 insertions(+), 14 deletions(-) |
| |
| diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c |
| index 8b34010..d79bd02 100644 |
| |
| |
| @@ -3629,6 +3629,8 @@ qemuDomainScreenshot(virDomainPtr dom, |
| char *ret = NULL; |
| bool unlink_tmp = false; |
| virQEMUDriverConfigPtr cfg = NULL; |
| + int video_index = 0; |
| + const char *video_id = NULL; |
| |
| virCheckFlags(0, NULL); |
| |
| @@ -3650,12 +3652,15 @@ qemuDomainScreenshot(virDomainPtr dom, |
| 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")); |
| + while (video_index < vm->def->nvideos) { |
| + if (screen < vm->def->videos[video_index]->heads) |
| + break; |
| + screen -= vm->def->videos[video_index]->heads; |
| + video_index++; |
| + } |
| + |
| + if (video_index == vm->def->nvideos) { |
| + virReportError(VIR_ERR_INVALID_ARG, "%s", _("no such screen")); |
| goto endjob; |
| } |
| |
| @@ -3670,8 +3675,11 @@ qemuDomainScreenshot(virDomainPtr dom, |
| |
| virSecurityManagerSetSavedStateLabel(qemu_driver->securityManager, vm->def, tmp); |
| |
| + if (video_index) |
| + video_id = vm->def->videos[video_index]->info.alias; |
| + |
| qemuDomainObjEnterMonitor(driver, vm); |
| - if (qemuMonitorScreendump(priv->mon, tmp) < 0) { |
| + if (qemuMonitorScreendump(priv->mon, tmp, video_id) < 0) { |
| qemuDomainObjExitMonitor(driver, vm); |
| goto endjob; |
| } |
| diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c |
| index adc9cca..c780786 100644 |
| |
| |
| @@ -3264,11 +3264,12 @@ int qemuMonitorSendKey(qemuMonitorPtr mon, |
| } |
| |
| int qemuMonitorScreendump(qemuMonitorPtr mon, |
| - const char *file) |
| + const char *file, |
| + const char *id) |
| { |
| int ret; |
| |
| - VIR_DEBUG("mon=%p, file=%s", mon, file); |
| + VIR_DEBUG("mon=%p, file=%s, id=%s", mon, file, id); |
| |
| if (!mon) { |
| virReportError(VIR_ERR_INVALID_ARG,"%s", |
| @@ -3276,10 +3277,20 @@ int qemuMonitorScreendump(qemuMonitorPtr mon, |
| return -1; |
| } |
| |
| - if (mon->json) |
| - ret = qemuMonitorJSONScreendump(mon, file); |
| - else |
| - ret = qemuMonitorTextScreendump(mon, file); |
| + if (id) { |
| + if (mon->json) { |
| + ret = qemuMonitorJSONScreendumpRH(mon, file, id); |
| + } else { |
| + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", |
| + _("non-zero screen IDs require JSON monitor")); |
| + ret = -1; |
| + } |
| + } else { |
| + if (mon->json) |
| + ret = qemuMonitorJSONScreendump(mon, file); |
| + else |
| + ret = qemuMonitorTextScreendump(mon, file); |
| + } |
| return ret; |
| } |
| |
| diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h |
| index 3e113f3..c694e1c 100644 |
| |
| |
| @@ -612,7 +612,8 @@ int qemuMonitorArbitraryCommand(qemuMonitorPtr mon, |
| int qemuMonitorInjectNMI(qemuMonitorPtr mon); |
| |
| int qemuMonitorScreendump(qemuMonitorPtr mon, |
| - const char *file); |
| + const char *file, |
| + const char *id); |
| |
| int qemuMonitorSendKey(qemuMonitorPtr mon, |
| unsigned int holdtime, |
| diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c |
| index ef5c08a..def3296 100644 |
| |
| |
| @@ -3474,6 +3474,30 @@ cleanup: |
| return ret; |
| } |
| |
| +int qemuMonitorJSONScreendumpRH(qemuMonitorPtr mon, |
| + const char *file, |
| + const char *id) |
| +{ |
| + int ret = -1; |
| + virJSONValuePtr cmd, reply = NULL; |
| + |
| + cmd = qemuMonitorJSONMakeCommand("__com.redhat_qxl_screendump", |
| + "s:filename", file, |
| + "s:id", id, |
| + NULL); |
| + if (!cmd) |
| + return -1; |
| + |
| + ret = qemuMonitorJSONCommand(mon, cmd, &reply); |
| + |
| + if (ret == 0) |
| + ret = qemuMonitorJSONCheckError(cmd, reply); |
| + |
| + virJSONValueFree(cmd); |
| + virJSONValueFree(reply); |
| + return ret; |
| +} |
| + |
| int qemuMonitorJSONScreendump(qemuMonitorPtr mon, |
| const char *file) |
| { |
| diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h |
| index 2fdc28f..0f2e9c8 100644 |
| |
| |
| @@ -272,6 +272,10 @@ int qemuMonitorJSONSendKey(qemuMonitorPtr mon, |
| unsigned int *keycodes, |
| unsigned int nkeycodes); |
| |
| +int qemuMonitorJSONScreendumpRH(qemuMonitorPtr mon, |
| + const char *file, |
| + const char *id); |
| + |
| int qemuMonitorJSONScreendump(qemuMonitorPtr mon, |
| const char *file); |
| |
| -- |
| 1.8.5.1 |
| |