[libvirt] [PATCH v4 8/8] vbox: Implement the driver methods

Michal Privoznik mprivozn at redhat.com
Thu May 12 16:29:15 UTC 2011


* src/vbox/vbox_tmpl.c: New vboxDomainScreenshot() function
---
 src/vbox/vbox_tmpl.c |  133 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 133 insertions(+), 0 deletions(-)

diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index dc91240..d598bcf 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -36,6 +36,9 @@
 
 #include <sys/utsname.h>
 #include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 
 #include "internal.h"
 #include "datatypes.h"
@@ -51,6 +54,9 @@
 #include "nodeinfo.h"
 #include "logging.h"
 #include "vbox_driver.h"
+#include "configmake.h"
+#include "files.h"
+#include "fdstream.h"
 
 /* This one changes from version to version. */
 #if VBOX_API_VERSION == 2002
@@ -8527,6 +8533,129 @@ static char *vboxStorageVolGetPath(virStorageVolPtr vol) {
     return ret;
 }
 
+#if VBOX_API_VERSION == 4000
+static char *
+vboxDomainScreenshot(virDomainPtr dom,
+                     virStreamPtr st,
+                     unsigned int screen,
+                     unsigned int flags ATTRIBUTE_UNUSED)
+{
+    VBOX_OBJECT_CHECK(dom->conn, char *, NULL);
+    IConsole *console = NULL;
+    vboxIID iid = VBOX_IID_INITIALIZER;
+    IMachine *machine = NULL;
+    nsresult rc;
+    char *tmp;
+    int tmp_fd = -1;
+    unsigned int max_screen;
+
+    vboxIIDFromUUID(&iid, dom->uuid);
+    rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
+    if (NS_FAILED(rc)) {
+        vboxError(VIR_ERR_NO_DOMAIN, "%s",
+                  _("no domain with matching uuid"));
+        return NULL;
+    }
+
+    rc = machine->vtbl->GetMonitorCount(machine, &max_screen);
+    if (NS_FAILED(rc)) {
+        vboxError(VIR_ERR_OPERATION_FAILED, "%s",
+                  _("unable to get monitor count"));
+        VBOX_RELEASE(machine);
+        return NULL;
+    }
+
+    if (screen >= max_screen) {
+        vboxError(VIR_ERR_INVALID_ARG, _("screen ID higher than monitor "
+                  "count (%d)"), max_screen);
+        VBOX_RELEASE(machine);
+        return NULL;
+    }
+
+    if (virAsprintf(&tmp, "%s/cache/libvirt/vbox.screendump.XXXXXX", LOCALSTATEDIR) < 0) {
+        virReportOOMError();
+        VBOX_RELEASE(machine);
+        return NULL;
+    }
+
+    if ((tmp_fd = mkstemp(tmp)) == -1) {
+        virReportSystemError(errno, _("mkstemp(\"%s\") failed"), tmp);
+        VIR_FREE(tmp);
+        VBOX_RELEASE(machine);
+        return NULL;
+    }
+
+
+    rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine);
+    if (NS_SUCCEEDED(rc)) {
+        rc = data->vboxSession->vtbl->GetConsole(data->vboxSession, &console);
+        if (NS_SUCCEEDED(rc) && console) {
+            IDisplay *display = NULL;
+
+            console->vtbl->GetDisplay(console, &display);
+
+            if (display) {
+                PRUint32 width, height, bitsPerPixel;
+                PRUint32 screenDataSize;
+                PRUint8 *screenData;
+
+                rc = display->vtbl->GetScreenResolution(display, screen,
+                                                        &width, &height,
+                                                        &bitsPerPixel);
+
+                if (NS_FAILED(rc) || !width || !height) {
+                    vboxError(VIR_ERR_OPERATION_FAILED, "%s",
+                              _("unable to get screen resolution"));
+                    goto endjob;
+                }
+
+                rc = display->vtbl->TakeScreenShotPNGToArray(display, screen,
+                                                             width, height,
+                                                             &screenDataSize,
+                                                             &screenData);
+                if (NS_FAILED(rc)) {
+                    vboxError(VIR_ERR_OPERATION_FAILED, "%s",
+                              _("failed to take screenshot"));
+                    goto endjob;
+                }
+
+                if (safewrite(tmp_fd, (char *) screenData,
+                              screenDataSize) < 0) {
+                    virReportSystemError(errno, _("unable to write data "
+                                                  "to '%s'"), tmp);
+                    goto endjob;
+                }
+
+                if (VIR_CLOSE(tmp_fd) < 0) {
+                    virReportSystemError(errno, _("unable to close %s"), tmp);
+                    goto endjob;
+                }
+
+                if (virFDStreamOpenFile(st, tmp, 0, 0, O_RDONLY, true) < 0) {
+                    vboxError(VIR_ERR_OPERATION_FAILED, "%s",
+                              _("unable to open stream"));
+                    goto endjob;
+                }
+
+                ret = strdup("image/png; charset=binary");
+
+endjob:
+                VIR_FREE(screenData);
+                VBOX_RELEASE(display);
+            }
+            VBOX_RELEASE(console);
+        }
+        VBOX_SESSION_CLOSE();
+    }
+
+    VIR_FORCE_CLOSE(tmp_fd);
+    VIR_FREE(tmp);
+    VBOX_RELEASE(machine);
+    vboxIIDUnalloc(&iid);
+    return ret;
+}
+#endif /* VBOX_API_VERSION == 4000 */
+
 /**
  * Function Tables
  */
@@ -8569,7 +8698,11 @@ virDriver NAME(Driver) = {
     vboxDomainSave, /* domainSave */
     NULL, /* domainRestore */
     NULL, /* domainCoreDump */
+#if VBOX_API_VERSION == 4000
+    vboxDomainScreenshot, /* domainScreenshot */
+#else
     NULL, /* domainScreenshot */
+#endif
     vboxDomainSetVcpus, /* domainSetVcpus */
     vboxDomainSetVcpusFlags, /* domainSetVcpusFlags */
     vboxDomainGetVcpusFlags, /* domainGetVcpusFlags */
-- 
1.7.5.rc3




More information about the libvir-list mailing list