[libvirt] [PATCH] vmx: Expose VMware Managed Object Reference (moref) in XML.
Michal Privoznik
mprivozn at redhat.com
Fri Sep 1 09:23:56 UTC 2017
On 08/25/2017 04:04 PM, Richard W.M. Jones wrote:
> If you use the VDDK library to access virtual machines remotely, you
> really need to know the Managed Object Reference ("moref") of the VM.
> This must be passed each time you connect to the API.
>
> For example nbdkit's VDDK plugin requires a moref to be passed to
> mount up a VM's disk remotely:
>
> nbdkit vddk user=root password=+/tmp/rootpw \
> server=esxi.example.com thumbprint=xx:xx:xx:... \
> vm=moref=2 \
> file="[datastore1] Fedora/Fedora.vmdk"
>
> Getting the moref is a huge pain. To get some idea of what it is, why
> it is needed, and how much trouble it is to get it, see:
> https://blogs.vmware.com/vsphere/2012/02/uniquely-identifying-virtual-machines-in-vsphere-and-vcloud-part-1-overview.html
> https://blogs.vmware.com/vsphere/2012/02/uniquely-identifying-virtual-machines-in-vsphere-and-vcloud-part-2-technical.html
>
> However the moref is available conveniently in the internals of the
> libvirt VMX driver. This patch exposes it as a custom XML element
> using the same "vmware:" namespace which was previously used for the
> datacenterpath (see libvirt commit 636a99058758a044).
>
> It appears in the XML like this:
>
> <domain type='vmware' xmlns:vmware='http://libvirt.org/schemas/domain/vmware/1.0'>
> <name>Fedora</name>
> ...
> <vmware:datacenterpath>ha-datacenter</vmware:datacenterpath>
> <vmware:moref>2</vmware:moref>
> </domain>
>
> Note that the moref can appear as either a simple ID (for esx://
> connections) or as a "vm-<ID>" (for vpx:// connections). It should be
> treated by users as an opaque string.
> ---
> src/esx/esx_driver.c | 7 +++++++
> src/esx/esx_vi.c | 15 +++++++++++++++
> src/esx/esx_vi.h | 4 ++++
> src/vmx/vmx.c | 51 +++++++++++++++++++++++++++++++++++++++++----------
> src/vmx/vmx.h | 2 ++
> 5 files changed, 69 insertions(+), 10 deletions(-)
>
> diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
> index 1f4f2c7a7..0cce0a41a 100644
> --- a/src/esx/esx_driver.c
> +++ b/src/esx/esx_driver.c
> @@ -2645,6 +2645,7 @@ esxDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
> esxVI_ObjectContent *virtualMachine = NULL;
> esxVI_VirtualMachinePowerState powerState;
> int id;
> + char *moref = NULL;
> char *vmPathName = NULL;
> char *datastoreName = NULL;
> char *directoryName = NULL;
> @@ -2670,6 +2671,7 @@ esxDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
> esxVI_LookupVirtualMachineByUuid(priv->primary, domain->uuid,
> propertyNameList, &virtualMachine,
> esxVI_Occurrence_RequiredItem) < 0 ||
> + esxVI_GetVirtualMachineMORef(virtualMachine, &moref) < 0 ||
> esxVI_GetVirtualMachinePowerState(virtualMachine, &powerState) < 0 ||
> esxVI_GetVirtualMachineIdentity(virtualMachine, &id, NULL, NULL) < 0 ||
> esxVI_GetStringValue(virtualMachine, "config.files.vmPathName",
> @@ -2715,6 +2717,7 @@ esxDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
> ctx.formatFileName = NULL;
> ctx.autodetectSCSIControllerModel = NULL;
> ctx.datacenterPath = priv->primary->datacenterPath;
> + ctx.moref = moref;
>
> def = virVMXParseConfig(&ctx, priv->xmlopt, priv->caps, vmx);
>
> @@ -2732,6 +2735,7 @@ esxDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
>
> esxVI_String_Free(&propertyNameList);
> esxVI_ObjectContent_Free(&virtualMachine);
> + VIR_FREE(moref);
> VIR_FREE(datastoreName);
> VIR_FREE(directoryName);
> VIR_FREE(directoryAndFileName);
> @@ -2774,6 +2778,7 @@ esxConnectDomainXMLFromNative(virConnectPtr conn, const char *nativeFormat,
> ctx.formatFileName = NULL;
> ctx.autodetectSCSIControllerModel = NULL;
> ctx.datacenterPath = NULL;
> + ctx.moref = NULL;
>
> def = virVMXParseConfig(&ctx, priv->xmlopt, priv->caps, nativeConfig);
>
> @@ -2830,6 +2835,7 @@ esxConnectDomainXMLToNative(virConnectPtr conn, const char *nativeFormat,
> ctx.formatFileName = esxFormatVMXFileName;
> ctx.autodetectSCSIControllerModel = esxAutodetectSCSIControllerModel;
> ctx.datacenterPath = NULL;
> + ctx.moref = NULL;
>
> vmx = virVMXFormatConfig(&ctx, priv->xmlopt, def, virtualHW_version);
>
> @@ -3077,6 +3083,7 @@ esxDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags)
> ctx.formatFileName = esxFormatVMXFileName;
> ctx.autodetectSCSIControllerModel = esxAutodetectSCSIControllerModel;
> ctx.datacenterPath = NULL;
> + ctx.moref = NULL;
>
> vmx = virVMXFormatConfig(&ctx, priv->xmlopt, def, virtualHW_version);
>
> diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
> index 8586e3ff0..77bcfd9b6 100644
> --- a/src/esx/esx_vi.c
> +++ b/src/esx/esx_vi.c
> @@ -2390,6 +2390,21 @@ esxVI_GetVirtualMachineQuestionInfo
> }
>
>
> +int
> +esxVI_GetVirtualMachineMORef(esxVI_ObjectContent *virtualMachine,
> + char **moref)
> +{
> + for (; virtualMachine != NULL; virtualMachine = virtualMachine->_next) {
> + if (virtualMachine->obj &&
> + STREQ(virtualMachine->obj->type, "VirtualMachine") &&
> + virtualMachine->obj->value) {
> + if (VIR_STRDUP(*moref, virtualMachine->obj->value) < 0)
> + return -1;
> + return 0;
Or return VIR_STRDUP() for short.
> + }
> + }
> + return -1;
> +}
>
> int
> esxVI_GetBoolean(esxVI_ObjectContent *objectContent, const char *propertyName,
> diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h
> index 7c53f3781..47d518dd1 100644
> --- a/src/esx/esx_vi.h
> +++ b/src/esx/esx_vi.h
> @@ -334,6 +334,10 @@ int esxVI_GetVirtualMachineQuestionInfo
> (esxVI_ObjectContent *virtualMachine,
> esxVI_VirtualMachineQuestionInfo **questionInfo);
>
> +int esxVI_GetVirtualMachineMORef
> + (esxVI_ObjectContent *virtualMachine,
> + char **moref);
> +
> int esxVI_GetBoolean(esxVI_ObjectContent *objectContent,
> const char *propertyName,
> esxVI_Boolean *value, esxVI_Occurrence occurrence);
> diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c
> index d1d8184c5..6f96f4cbf 100644
> --- a/src/vmx/vmx.c
> +++ b/src/vmx/vmx.c
> @@ -553,23 +553,41 @@ static virDomainDefParserConfig virVMXDomainDefParserConfig = {
> VIR_DOMAIN_DEF_FEATURE_NAME_SLASH),
> };
>
> +struct virVMXDomainDefNamespaceData {
> + char *datacenterPath;
> + char *moref;
> +};
> +
> static void
> virVMXDomainDefNamespaceFree(void *nsdata)
> {
> - VIR_FREE(nsdata);
> + struct virVMXDomainDefNamespaceData *data = nsdata;
> +
> + if (data) {
> + VIR_FREE(data->datacenterPath);
> + VIR_FREE(data->moref);
> + }
> + VIR_FREE(data);
> }
>
> static int
> virVMXDomainDefNamespaceFormatXML(virBufferPtr buf, void *nsdata)
> {
> - const char *datacenterPath = nsdata;
> + struct virVMXDomainDefNamespaceData *data = nsdata;
>
> - if (!datacenterPath)
> + if (!data)
> return 0;
>
> - virBufferAddLit(buf, "<vmware:datacenterpath>");
> - virBufferEscapeString(buf, "%s", datacenterPath);
> - virBufferAddLit(buf, "</vmware:datacenterpath>\n");
> + if (data->datacenterPath) {
> + virBufferAddLit(buf, "<vmware:datacenterpath>");
> + virBufferEscapeString(buf, "%s", data->datacenterPath);
> + virBufferAddLit(buf, "</vmware:datacenterpath>\n");
> + }
> + if (data->moref) {
> + virBufferAddLit(buf, "<vmware:moref>");
> + virBufferEscapeString(buf, "%s", data->moref);
> + virBufferAddLit(buf, "</vmware:moref>\n");
> + }
>
> return 0;
> }
> @@ -1304,7 +1322,6 @@ virVMXParseConfig(virVMXContext *ctx,
> bool hgfs_disabled = true;
> long long sharedFolder_maxNum = 0;
> int cpumasklen;
> - char *namespaceData;
>
> if (ctx->parseFileName == NULL) {
> virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> @@ -1802,12 +1819,26 @@ virVMXParseConfig(virVMXContext *ctx,
> }
>
> /* ctx:datacenterPath -> def:namespaceData */
> - if (ctx->datacenterPath) {
> - if (VIR_STRDUP(namespaceData, ctx->datacenterPath) < 0)
> + if (ctx->datacenterPath || ctx->moref) {
> + struct virVMXDomainDefNamespaceData *nsdata;
> +
> + if (VIR_ALLOC(nsdata) < 0)
> goto cleanup;
> + nsdata->datacenterPath = NULL;
> + nsdata->moref = NULL;
This explicit set to NULL is not necessary. VIR_ALLOC uses calloc()
under the hood so the memory is zeroed out.
> +
> + if (ctx->datacenterPath) {
> + if (VIR_STRDUP(nsdata->datacenterPath, ctx->datacenterPath) < 0)
VIR_STRDUP() accepts NULL as source (in which case success is returned).
So this can be just:
if (VIR_STRDUP() < 0) ..
> + goto cleanup;
Almost, @nsdata is leaked here. These lines can be then written as:
if (VIR_ALLOC(nsdata) < 0 ||
VIR_STRDUP(nsdata->datacenterPath, ctx->datacenterPath) < 0 ||
VIR_STRDUP(nsdata->moref, ctx->moref) < 0) {
virVMXDomainDefNamespaceFree(nsdata);
goto cleanup;
}
> + }
> +
> + if (ctx->moref) {
> + if (VIR_STRDUP(nsdata->moref, ctx->moref) < 0)
> + goto cleanup;
> + }
>
> def->ns = *virDomainXMLOptionGetNamespace(xmlopt);
> - def->namespaceData = namespaceData;
> + def->namespaceData = nsdata;
> }
>
> if (virDomainDefPostParse(def, caps, VIR_DOMAIN_DEF_PARSE_ABI_UPDATE,
Oh, not testcase? :( I'll write one.
ACK with those small nits fixed.
Michal
More information about the libvir-list
mailing list