[libvirt] [PATCH 2/2] esx: Implement virDomainScreenshot using libcurl stream driver
Michal Privoznik
mprivozn at redhat.com
Mon Mar 31 13:46:42 UTC 2014
On 30.03.2014 21:03, Matthias Bolte wrote:
> 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.
> ---
> src/esx/esx_driver.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++++-
> src/esx/esx_private.h | 1 +
> 2 files changed, 120 insertions(+), 1 deletion(-)
>
> diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
> index ff44881..7b6b1a0 100644
> --- a/src/esx/esx_driver.c
> +++ b/src/esx/esx_driver.c
> @@ -2,7 +2,7 @@
> * esx_driver.c: core driver functions for managing VMware ESX hosts
> *
> * Copyright (C) 2010-2014 Red Hat, Inc.
> - * Copyright (C) 2009-2013 Matthias Bolte <matthias.bolte at googlemail.com>
> + * Copyright (C) 2009-2014 Matthias Bolte <matthias.bolte at googlemail.com>
> * Copyright (C) 2009 Maximilian Wilhelm <max at rfc2324.org>
> *
> * This library is free software; you can redistribute it and/or
> @@ -44,6 +44,7 @@
> #include "esx_vi.h"
> #include "esx_vi_methods.h"
> #include "esx_util.h"
> +#include "esx_stream.h"
> #include "virstring.h"
> #include "viruri.h"
>
> @@ -970,6 +971,7 @@ esxConnectOpen(virConnectPtr conn, virConnectAuthPtr auth,
> priv->maxVcpus = -1;
> priv->supportsVMotion = esxVI_Boolean_Undefined;
> priv->supportsLongMode = esxVI_Boolean_Undefined;
> + priv->supportsScreenshot = esxVI_Boolean_Undefined;
> priv->usedCpuTimeCounterId = -1;
>
> /*
> @@ -1145,6 +1147,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
> esxConnectSupportsFeature(virConnectPtr conn, int feature)
> {
> @@ -2501,6 +2537,87 @@ 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 (virBufferError(&buffer)) {
> + virReportOOMError();
> + 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:
> + if (!url)
> + virBufferFreeAndReset(&buffer);
The 'if' is redundant. Ether we get here with partially allocated
buffer, or buffer is already reset.
> +
> + esxVI_String_Free(&propertyNameList);
> + esxVI_ObjectContent_Free(&virtualMachine);
> +
> + return mimeType;
> +}
> +
> +
> +
> static int
> esxDomainSetVcpusFlags(virDomainPtr domain, unsigned int nvcpus,
> unsigned int flags)
> @@ -5221,6 +5338,7 @@ static virDriver esxDriver = {
> .domainGetMemoryParameters = esxDomainGetMemoryParameters, /* 0.8.6 */
> .domainGetInfo = esxDomainGetInfo, /* 0.7.0 */
> .domainGetState = esxDomainGetState, /* 0.9.2 */
> + .domainScreenshot = esxDomainScreenshot, /* 1.2.4 */
> .domainSetVcpus = esxDomainSetVcpus, /* 0.7.0 */
> .domainSetVcpusFlags = esxDomainSetVcpusFlags, /* 0.8.5 */
> .domainGetVcpusFlags = esxDomainGetVcpusFlags, /* 0.8.5 */
> diff --git a/src/esx/esx_private.h b/src/esx/esx_private.h
> index 05ee1d6..f2766eb 100644
> --- a/src/esx/esx_private.h
> +++ b/src/esx/esx_private.h
> @@ -38,6 +38,7 @@ typedef struct _esxPrivate {
> int32_t maxVcpus;
> esxVI_Boolean supportsVMotion;
> esxVI_Boolean supportsLongMode; /* aka x86_64 */
> + esxVI_Boolean supportsScreenshot;
> int32_t usedCpuTimeCounterId;
> } esxPrivate;
>
>
ACK
Michal
More information about the libvir-list
mailing list