提交 72f92bce 编写于 作者: T Taowei 提交者: Michal Privoznik

vbox: Rewrite vboxDomainScreenshot

上级 4fab8d3f
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <config.h> #include <config.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h>
#include "internal.h" #include "internal.h"
#include "datatypes.h" #include "datatypes.h"
...@@ -32,6 +33,8 @@ ...@@ -32,6 +33,8 @@
#include "virtime.h" #include "virtime.h"
#include "snapshot_conf.h" #include "snapshot_conf.h"
#include "vbox_snapshot_conf.h" #include "vbox_snapshot_conf.h"
#include "fdstream.h"
#include "configmake.h"
#include "vbox_common.h" #include "vbox_common.h"
#include "vbox_uniformed_api.h" #include "vbox_uniformed_api.h"
...@@ -7121,3 +7124,130 @@ int vboxDomainSnapshotDelete(virDomainSnapshotPtr snapshot, ...@@ -7121,3 +7124,130 @@ int vboxDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
gVBoxAPI.UISession.Close(data->vboxSession); gVBoxAPI.UISession.Close(data->vboxSession);
return ret; return ret;
} }
char *
vboxDomainScreenshot(virDomainPtr dom,
virStreamPtr st,
unsigned int screen,
unsigned int flags)
{
VBOX_OBJECT_CHECK(dom->conn, char *, NULL);
IConsole *console = NULL;
vboxIIDUnion iid;
IMachine *machine = NULL;
nsresult rc;
char *tmp;
int tmp_fd = -1;
unsigned int max_screen;
if (!gVBoxAPI.supportScreenshot) {
virReportError(VIR_ERR_NO_SUPPORT, "%s",
_("virDomainScreenshot don't support for current vbox version"));
return NULL;
}
virCheckFlags(0, NULL);
if (openSessionForMachine(data, dom->uuid, &iid, &machine, false) < 0)
return NULL;
rc = gVBoxAPI.UIMachine.GetMonitorCount(machine, &max_screen);
if (NS_FAILED(rc)) {
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
_("unable to get monitor count"));
VBOX_RELEASE(machine);
return NULL;
}
if (screen >= max_screen) {
virReportError(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) {
VBOX_RELEASE(machine);
return NULL;
}
if ((tmp_fd = mkostemp(tmp, O_CLOEXEC)) == -1) {
virReportSystemError(errno, _("mkostemp(\"%s\") failed"), tmp);
VIR_FREE(tmp);
VBOX_RELEASE(machine);
return NULL;
}
rc = gVBoxAPI.UISession.OpenExisting(data, &iid, machine);
if (NS_SUCCEEDED(rc)) {
rc = gVBoxAPI.UISession.GetConsole(data->vboxSession, &console);
if (NS_SUCCEEDED(rc) && console) {
IDisplay *display = NULL;
gVBoxAPI.UIConsole.GetDisplay(console, &display);
if (display) {
PRUint32 width, height, bitsPerPixel;
PRUint32 screenDataSize;
PRUint8 *screenData;
PRInt32 xOrigin, yOrigin;
rc = gVBoxAPI.UIDisplay.GetScreenResolution(display, screen,
&width, &height,
&bitsPerPixel,
&xOrigin, &yOrigin);
if (NS_FAILED(rc) || !width || !height) {
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
_("unable to get screen resolution"));
goto endjob;
}
rc = gVBoxAPI.UIDisplay.TakeScreenShotPNGToArray(display, screen,
width, height,
&screenDataSize,
&screenData);
if (NS_FAILED(rc)) {
virReportError(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 (VIR_STRDUP(ret, "image/png") < 0)
goto endjob;
if (virFDStreamOpenFile(st, tmp, 0, 0, O_RDONLY) < 0) {
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
_("unable to open stream"));
VIR_FREE(ret);
}
endjob:
VIR_FREE(screenData);
VBOX_RELEASE(display);
}
VBOX_RELEASE(console);
}
gVBoxAPI.UISession.Close(data->vboxSession);
}
VIR_FORCE_CLOSE(tmp_fd);
unlink(tmp);
VIR_FREE(tmp);
VBOX_RELEASE(machine);
vboxIIDUnalloc(&iid);
return ret;
}
...@@ -301,5 +301,6 @@ typedef nsISupports IMediumAttachment; ...@@ -301,5 +301,6 @@ typedef nsISupports IMediumAttachment;
typedef nsISupports IStorageController; typedef nsISupports IStorageController;
typedef nsISupports ISharedFolder; typedef nsISupports ISharedFolder;
typedef nsISupports ISnapshot; typedef nsISupports ISnapshot;
typedef nsISupports IDisplay;
#endif /* VBOX_COMMON_H */ #endif /* VBOX_COMMON_H */
...@@ -3733,141 +3733,6 @@ static char *vboxStorageVolGetPath(virStorageVolPtr vol) { ...@@ -3733,141 +3733,6 @@ static char *vboxStorageVolGetPath(virStorageVolPtr vol) {
return ret; return ret;
} }
#if VBOX_API_VERSION >= 4000000
static char *
vboxDomainScreenshot(virDomainPtr dom,
virStreamPtr st,
unsigned int screen,
unsigned int flags)
{
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;
virCheckFlags(0, NULL);
vboxIIDFromUUID(&iid, dom->uuid);
rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
if (NS_FAILED(rc)) {
virReportError(VIR_ERR_NO_DOMAIN, "%s",
_("no domain with matching uuid"));
return NULL;
}
rc = machine->vtbl->GetMonitorCount(machine, &max_screen);
if (NS_FAILED(rc)) {
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
_("unable to get monitor count"));
VBOX_RELEASE(machine);
return NULL;
}
if (screen >= max_screen) {
virReportError(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) {
VBOX_RELEASE(machine);
return NULL;
}
if ((tmp_fd = mkostemp(tmp, O_CLOEXEC)) == -1) {
virReportSystemError(errno, _("mkostemp(\"%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;
# if VBOX_API_VERSION >= 4003000
PRInt32 xOrigin, yOrigin;
# endif
rc = display->vtbl->GetScreenResolution(display, screen,
&width, &height,
# if VBOX_API_VERSION < 4003000
&bitsPerPixel);
# else
&bitsPerPixel,
&xOrigin, &yOrigin);
# endif
if (NS_FAILED(rc) || !width || !height) {
virReportError(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)) {
virReportError(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 (VIR_STRDUP(ret, "image/png") < 0)
goto endjob;
if (virFDStreamOpenFile(st, tmp, 0, 0, O_RDONLY) < 0) {
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
_("unable to open stream"));
VIR_FREE(ret);
}
endjob:
VIR_FREE(screenData);
VBOX_RELEASE(display);
}
VBOX_RELEASE(console);
}
VBOX_SESSION_CLOSE();
}
VIR_FORCE_CLOSE(tmp_fd);
unlink(tmp);
VIR_FREE(tmp);
VBOX_RELEASE(machine);
vboxIIDUnalloc(&iid);
return ret;
}
#endif /* VBOX_API_VERSION >= 4000000 */
#define MATCH(FLAG) (flags & (FLAG)) #define MATCH(FLAG) (flags & (FLAG))
static int static int
vboxConnectListAllDomains(virConnectPtr conn, vboxConnectListAllDomains(virConnectPtr conn,
...@@ -5474,6 +5339,12 @@ _consoleDeleteSnapshot(IConsole *console, vboxIIDUnion *iidu, IProgress **progre ...@@ -5474,6 +5339,12 @@ _consoleDeleteSnapshot(IConsole *console, vboxIIDUnion *iidu, IProgress **progre
#endif /* VBOX_API_VERSION >= 3001000 */ #endif /* VBOX_API_VERSION >= 3001000 */
} }
static nsresult
_consoleGetDisplay(IConsole *console, IDisplay **display)
{
return console->vtbl->GetDisplay(console, display);
}
static nsresult static nsresult
_progressWaitForCompletion(IProgress *progress, PRInt32 timeout) _progressWaitForCompletion(IProgress *progress, PRInt32 timeout)
{ {
...@@ -6340,6 +6211,46 @@ _snapshotGetOnline(ISnapshot *snapshot, PRBool *online) ...@@ -6340,6 +6211,46 @@ _snapshotGetOnline(ISnapshot *snapshot, PRBool *online)
return snapshot->vtbl->GetOnline(snapshot, online); return snapshot->vtbl->GetOnline(snapshot, online);
} }
static nsresult
_displayGetScreenResolution(IDisplay *display ATTRIBUTE_UNUSED,
PRUint32 screenId ATTRIBUTE_UNUSED,
PRUint32 *width ATTRIBUTE_UNUSED,
PRUint32 *height ATTRIBUTE_UNUSED,
PRUint32 *bitsPerPixel ATTRIBUTE_UNUSED,
PRInt32 *xOrigin ATTRIBUTE_UNUSED,
PRInt32 *yOrigin ATTRIBUTE_UNUSED)
{
#if VBOX_API_VERSION < 3002000
vboxUnsupported();
return 0;
#elif VBOX_API_VERSION < 4003000
return display->vtbl->GetScreenResolution(display, screenId, width,
height, bitsPerPixel);
#else /* VBOX_API_VERSION >= 4003000 */
return display->vtbl->GetScreenResolution(display, screenId, width,
height, bitsPerPixel,
xOrigin, yOrigin);
#endif /* VBOX_API_VERSION >= 4003000 */
}
static nsresult
_displayTakeScreenShotPNGToArray(IDisplay *display ATTRIBUTE_UNUSED,
PRUint32 screenId ATTRIBUTE_UNUSED,
PRUint32 width ATTRIBUTE_UNUSED,
PRUint32 height ATTRIBUTE_UNUSED,
PRUint32 *screenDataSize ATTRIBUTE_UNUSED,
PRUint8** screenData ATTRIBUTE_UNUSED)
{
#if VBOX_API_VERSION < 4000000
vboxUnsupported();
return 0;
#else /* VBOX_API_VERSION >= 4000000 */
return display->vtbl->TakeScreenShotPNGToArray(display, screenId, width,
height, screenDataSize,
screenData);
#endif /* VBOX_API_VERSION >= 4000000 */
}
static bool _machineStateOnline(PRUint32 state) static bool _machineStateOnline(PRUint32 state)
{ {
return ((state >= MachineState_FirstOnline) && return ((state >= MachineState_FirstOnline) &&
...@@ -6487,6 +6398,7 @@ static vboxUniformedIConsole _UIConsole = { ...@@ -6487,6 +6398,7 @@ static vboxUniformedIConsole _UIConsole = {
.Reset = _consoleReset, .Reset = _consoleReset,
.TakeSnapshot = _consoleTakeSnapshot, .TakeSnapshot = _consoleTakeSnapshot,
.DeleteSnapshot = _consoleDeleteSnapshot, .DeleteSnapshot = _consoleDeleteSnapshot,
.GetDisplay = _consoleGetDisplay,
}; };
static vboxUniformedIProgress _UIProgress = { static vboxUniformedIProgress _UIProgress = {
...@@ -6635,6 +6547,11 @@ static vboxUniformedISnapshot _UISnapshot = { ...@@ -6635,6 +6547,11 @@ static vboxUniformedISnapshot _UISnapshot = {
.GetOnline = _snapshotGetOnline, .GetOnline = _snapshotGetOnline,
}; };
static vboxUniformedIDisplay _UIDisplay = {
.GetScreenResolution = _displayGetScreenResolution,
.TakeScreenShotPNGToArray = _displayTakeScreenShotPNGToArray,
};
static uniformedMachineStateChecker _machineStateChecker = { static uniformedMachineStateChecker _machineStateChecker = {
.Online = _machineStateOnline, .Online = _machineStateOnline,
.Inactive = _machineStateInactive, .Inactive = _machineStateInactive,
...@@ -6686,6 +6603,7 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) ...@@ -6686,6 +6603,7 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI)
pVBoxAPI->UIStorageController = _UIStorageController; pVBoxAPI->UIStorageController = _UIStorageController;
pVBoxAPI->UISharedFolder = _UISharedFolder; pVBoxAPI->UISharedFolder = _UISharedFolder;
pVBoxAPI->UISnapshot = _UISnapshot; pVBoxAPI->UISnapshot = _UISnapshot;
pVBoxAPI->UIDisplay = _UIDisplay;
pVBoxAPI->machineStateChecker = _machineStateChecker; pVBoxAPI->machineStateChecker = _machineStateChecker;
#if VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000 #if VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000
...@@ -6705,10 +6623,12 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) ...@@ -6705,10 +6623,12 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI)
pVBoxAPI->getMachineForSession = 1; pVBoxAPI->getMachineForSession = 1;
pVBoxAPI->detachDevicesExplicitly = 0; pVBoxAPI->detachDevicesExplicitly = 0;
pVBoxAPI->vboxAttachDrivesUseOld = 0; pVBoxAPI->vboxAttachDrivesUseOld = 0;
pVBoxAPI->supportScreenshot = 1;
#else /* VBOX_API_VERSION < 4000000 */ #else /* VBOX_API_VERSION < 4000000 */
pVBoxAPI->getMachineForSession = 0; pVBoxAPI->getMachineForSession = 0;
pVBoxAPI->detachDevicesExplicitly = 1; pVBoxAPI->detachDevicesExplicitly = 1;
pVBoxAPI->vboxAttachDrivesUseOld = 1; pVBoxAPI->vboxAttachDrivesUseOld = 1;
pVBoxAPI->supportScreenshot = 0;
#endif /* VBOX_API_VERSION < 4000000 */ #endif /* VBOX_API_VERSION < 4000000 */
#if VBOX_API_VERSION >= 4001000 #if VBOX_API_VERSION >= 4001000
......
...@@ -273,6 +273,7 @@ typedef struct { ...@@ -273,6 +273,7 @@ typedef struct {
nsresult (*TakeSnapshot)(IConsole *console, PRUnichar *name, nsresult (*TakeSnapshot)(IConsole *console, PRUnichar *name,
PRUnichar *description, IProgress **progress); PRUnichar *description, IProgress **progress);
nsresult (*DeleteSnapshot)(IConsole *console, vboxIIDUnion *iidu, IProgress **progress); nsresult (*DeleteSnapshot)(IConsole *console, vboxIIDUnion *iidu, IProgress **progress);
nsresult (*GetDisplay)(IConsole *console, IDisplay **display);
} vboxUniformedIConsole; } vboxUniformedIConsole;
/* Functions for IProgress */ /* Functions for IProgress */
...@@ -446,6 +447,23 @@ typedef struct { ...@@ -446,6 +447,23 @@ typedef struct {
nsresult (*GetOnline)(ISnapshot *snapshot, PRBool *online); nsresult (*GetOnline)(ISnapshot *snapshot, PRBool *online);
} vboxUniformedISnapshot; } vboxUniformedISnapshot;
/* Functions for IDisplay */
typedef struct {
nsresult (*GetScreenResolution)(IDisplay *display,
PRUint32 screenId,
PRUint32 *width,
PRUint32 *height,
PRUint32 *bitsPerPixel,
PRInt32 *xOrigin,
PRInt32 *yOrigin);
nsresult (*TakeScreenShotPNGToArray)(IDisplay *display,
PRUint32 screenId,
PRUint32 width,
PRUint32 height,
PRUint32 *screenDataSize,
PRUint8** screenData);
} vboxUniformedIDisplay;
typedef struct { typedef struct {
bool (*Online)(PRUint32 state); bool (*Online)(PRUint32 state);
bool (*Inactive)(PRUint32 state); bool (*Inactive)(PRUint32 state);
...@@ -498,6 +516,7 @@ typedef struct { ...@@ -498,6 +516,7 @@ typedef struct {
vboxUniformedIStorageController UIStorageController; vboxUniformedIStorageController UIStorageController;
vboxUniformedISharedFolder UISharedFolder; vboxUniformedISharedFolder UISharedFolder;
vboxUniformedISnapshot UISnapshot; vboxUniformedISnapshot UISnapshot;
vboxUniformedIDisplay UIDisplay;
uniformedMachineStateChecker machineStateChecker; uniformedMachineStateChecker machineStateChecker;
/* vbox API features */ /* vbox API features */
bool domainEventCallbacks; bool domainEventCallbacks;
...@@ -509,6 +528,7 @@ typedef struct { ...@@ -509,6 +528,7 @@ typedef struct {
bool vboxAttachDrivesUseOld; bool vboxAttachDrivesUseOld;
bool oldMediumInterface; bool oldMediumInterface;
bool vboxSnapshotRedefine; bool vboxSnapshotRedefine;
bool supportScreenshot;
} vboxUniformedAPI; } vboxUniformedAPI;
/* libvirt API /* libvirt API
...@@ -599,7 +619,8 @@ int vboxDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, ...@@ -599,7 +619,8 @@ int vboxDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
unsigned int flags); unsigned int flags);
int vboxDomainSnapshotDelete(virDomainSnapshotPtr snapshot, int vboxDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
unsigned int flags); unsigned int flags);
char *vboxDomainScreenshot(virDomainPtr dom, virStreamPtr st,
unsigned int screen, unsigned int flags);
/* Version specified functions for installing uniformed API */ /* Version specified functions for installing uniformed API */
void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册