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