mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-10-30 18:03:32 +00:00
esx: Implement virDomainScreenshot using libcurl stream driver
This implementation uses the https://esx-server/screen?id=<id> way to get a screenshot of a running domain. Compared to the CreateScreenshot_Task way this works since ESX 2.5 while CreateScreenshot_Task was added in version 4.0. The newly added libcurl stream driver is used to directly provide the downloaded data without saving it to a temporary file first.
This commit is contained in:
parent
125007d373
commit
a0f19e2f5b
@ -2,7 +2,7 @@
|
|||||||
* esx_driver.c: core driver functions for managing VMware ESX hosts
|
* esx_driver.c: core driver functions for managing VMware ESX hosts
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2014 Red Hat, Inc.
|
* Copyright (C) 2010-2014 Red Hat, Inc.
|
||||||
* Copyright (C) 2009-2013 Matthias Bolte <matthias.bolte@googlemail.com>
|
* Copyright (C) 2009-2014 Matthias Bolte <matthias.bolte@googlemail.com>
|
||||||
* Copyright (C) 2009 Maximilian Wilhelm <max@rfc2324.org>
|
* Copyright (C) 2009 Maximilian Wilhelm <max@rfc2324.org>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
@ -44,6 +44,7 @@
|
|||||||
#include "esx_vi.h"
|
#include "esx_vi.h"
|
||||||
#include "esx_vi_methods.h"
|
#include "esx_vi_methods.h"
|
||||||
#include "esx_util.h"
|
#include "esx_util.h"
|
||||||
|
#include "esx_stream.h"
|
||||||
#include "virstring.h"
|
#include "virstring.h"
|
||||||
#include "viruri.h"
|
#include "viruri.h"
|
||||||
|
|
||||||
@ -968,6 +969,7 @@ esxConnectOpen(virConnectPtr conn, virConnectAuthPtr auth,
|
|||||||
priv->maxVcpus = -1;
|
priv->maxVcpus = -1;
|
||||||
priv->supportsVMotion = esxVI_Boolean_Undefined;
|
priv->supportsVMotion = esxVI_Boolean_Undefined;
|
||||||
priv->supportsLongMode = esxVI_Boolean_Undefined;
|
priv->supportsLongMode = esxVI_Boolean_Undefined;
|
||||||
|
priv->supportsScreenshot = esxVI_Boolean_Undefined;
|
||||||
priv->usedCpuTimeCounterId = -1;
|
priv->usedCpuTimeCounterId = -1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1143,6 +1145,40 @@ esxSupportsVMotion(esxPrivate *priv)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static esxVI_Boolean
|
||||||
|
esxSupportsScreenshot(esxPrivate *priv)
|
||||||
|
{
|
||||||
|
esxVI_String *propertyNameList = NULL;
|
||||||
|
esxVI_ObjectContent *hostSystem = NULL;
|
||||||
|
|
||||||
|
if (priv->supportsScreenshot != esxVI_Boolean_Undefined)
|
||||||
|
return priv->supportsScreenshot;
|
||||||
|
|
||||||
|
if (esxVI_EnsureSession(priv->primary) < 0)
|
||||||
|
return esxVI_Boolean_Undefined;
|
||||||
|
|
||||||
|
if (esxVI_String_AppendValueToList(&propertyNameList,
|
||||||
|
"capability.screenshotSupported") < 0 ||
|
||||||
|
esxVI_LookupHostSystemProperties(priv->primary, propertyNameList,
|
||||||
|
&hostSystem) < 0 ||
|
||||||
|
esxVI_GetBoolean(hostSystem, "capability.screenshotSupported",
|
||||||
|
&priv->supportsScreenshot,
|
||||||
|
esxVI_Occurrence_RequiredItem) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
/*
|
||||||
|
* If we goto cleanup in case of an error then priv->supportsScreenshot is
|
||||||
|
* still esxVI_Boolean_Undefined, therefore we don't need to set it.
|
||||||
|
*/
|
||||||
|
esxVI_String_Free(&propertyNameList);
|
||||||
|
esxVI_ObjectContent_Free(&hostSystem);
|
||||||
|
|
||||||
|
return priv->supportsScreenshot;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
esxConnectSupportsFeature(virConnectPtr conn, int feature)
|
esxConnectSupportsFeature(virConnectPtr conn, int feature)
|
||||||
{
|
{
|
||||||
@ -2493,6 +2529,84 @@ esxDomainGetState(virDomainPtr domain,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static char *
|
||||||
|
esxDomainScreenshot(virDomainPtr domain, virStreamPtr stream,
|
||||||
|
unsigned int screen, unsigned int flags)
|
||||||
|
{
|
||||||
|
char *mimeType = NULL;
|
||||||
|
esxPrivate *priv = domain->conn->privateData;
|
||||||
|
esxVI_Boolean supportsScreenshot = esxVI_Boolean_Undefined;
|
||||||
|
esxVI_String *propertyNameList = NULL;
|
||||||
|
esxVI_ObjectContent *virtualMachine = NULL;
|
||||||
|
esxVI_VirtualMachinePowerState powerState;
|
||||||
|
virBuffer buffer = VIR_BUFFER_INITIALIZER;
|
||||||
|
char *url = NULL;
|
||||||
|
|
||||||
|
virCheckFlags(0, NULL);
|
||||||
|
|
||||||
|
if (screen != 0) {
|
||||||
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
||||||
|
_("Screen cannot be selected"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
supportsScreenshot = esxSupportsScreenshot(priv);
|
||||||
|
|
||||||
|
if (supportsScreenshot == esxVI_Boolean_Undefined)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (supportsScreenshot != esxVI_Boolean_True) {
|
||||||
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
||||||
|
_("Screenshot feature is unsupported"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (esxVI_EnsureSession(priv->primary) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (esxVI_String_AppendValueToList(&propertyNameList,
|
||||||
|
"runtime.powerState") < 0 ||
|
||||||
|
esxVI_LookupVirtualMachineByUuid(priv->primary, domain->uuid,
|
||||||
|
propertyNameList, &virtualMachine,
|
||||||
|
esxVI_Occurrence_RequiredItem) < 0 ||
|
||||||
|
esxVI_GetVirtualMachinePowerState(virtualMachine, &powerState) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (powerState != esxVI_VirtualMachinePowerState_PoweredOn) {
|
||||||
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
||||||
|
_("Domain is not powered on"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build URL */
|
||||||
|
virBufferAsprintf(&buffer, "%s://%s:%d/screen?id=", priv->parsedUri->transport,
|
||||||
|
domain->conn->uri->server, domain->conn->uri->port);
|
||||||
|
virBufferURIEncodeString(&buffer, virtualMachine->obj->value);
|
||||||
|
|
||||||
|
if (virBufferCheckError(&buffer))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
url = virBufferContentAndReset(&buffer);
|
||||||
|
|
||||||
|
if (VIR_STRDUP(mimeType, "image/png") < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (esxStreamOpenDownload(stream, priv, url, 0, 0) < 0) {
|
||||||
|
VIR_FREE(mimeType);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
virBufferFreeAndReset(&buffer);
|
||||||
|
|
||||||
|
esxVI_String_Free(&propertyNameList);
|
||||||
|
esxVI_ObjectContent_Free(&virtualMachine);
|
||||||
|
|
||||||
|
return mimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
esxDomainSetVcpusFlags(virDomainPtr domain, unsigned int nvcpus,
|
esxDomainSetVcpusFlags(virDomainPtr domain, unsigned int nvcpus,
|
||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
@ -5209,6 +5323,7 @@ static virDriver esxDriver = {
|
|||||||
.domainGetMemoryParameters = esxDomainGetMemoryParameters, /* 0.8.6 */
|
.domainGetMemoryParameters = esxDomainGetMemoryParameters, /* 0.8.6 */
|
||||||
.domainGetInfo = esxDomainGetInfo, /* 0.7.0 */
|
.domainGetInfo = esxDomainGetInfo, /* 0.7.0 */
|
||||||
.domainGetState = esxDomainGetState, /* 0.9.2 */
|
.domainGetState = esxDomainGetState, /* 0.9.2 */
|
||||||
|
.domainScreenshot = esxDomainScreenshot, /* 1.2.10 */
|
||||||
.domainSetVcpus = esxDomainSetVcpus, /* 0.7.0 */
|
.domainSetVcpus = esxDomainSetVcpus, /* 0.7.0 */
|
||||||
.domainSetVcpusFlags = esxDomainSetVcpusFlags, /* 0.8.5 */
|
.domainSetVcpusFlags = esxDomainSetVcpusFlags, /* 0.8.5 */
|
||||||
.domainGetVcpusFlags = esxDomainGetVcpusFlags, /* 0.8.5 */
|
.domainGetVcpusFlags = esxDomainGetVcpusFlags, /* 0.8.5 */
|
||||||
|
@ -38,6 +38,7 @@ typedef struct _esxPrivate {
|
|||||||
int32_t maxVcpus;
|
int32_t maxVcpus;
|
||||||
esxVI_Boolean supportsVMotion;
|
esxVI_Boolean supportsVMotion;
|
||||||
esxVI_Boolean supportsLongMode; /* aka x86_64 */
|
esxVI_Boolean supportsLongMode; /* aka x86_64 */
|
||||||
|
esxVI_Boolean supportsScreenshot;
|
||||||
int32_t usedCpuTimeCounterId;
|
int32_t usedCpuTimeCounterId;
|
||||||
} esxPrivate;
|
} esxPrivate;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user