From 4c10c38275349805fac325b5c701c399cec0c9a3 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Fri, 25 Aug 2017 14:36:58 +0100 Subject: [PATCH] vmx: Expose VMware Managed Object Reference (moref) in XML. 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: Fedora ... ha-datacenter 2 Note that the moref can appear as either a simple ID (for esx:// connections) or as a "vm-" (for vpx:// connections). It should be treated by users as an opaque string. Signed-off-by: Richard W.M. Jones --- src/esx/esx_driver.c | 7 +++++++ src/esx/esx_vi.c | 13 +++++++++++++ src/esx/esx_vi.h | 4 ++++ src/vmx/vmx.c | 43 +++++++++++++++++++++++++++++++++---------- src/vmx/vmx.h | 2 ++ 5 files changed, 59 insertions(+), 10 deletions(-) diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index 1f4f2c7a75..0cce0a41a3 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 8586e3ff0a..6d59bae9d8 100644 --- a/src/esx/esx_vi.c +++ b/src/esx/esx_vi.c @@ -2390,6 +2390,19 @@ 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) { + return VIR_STRDUP(*moref, virtualMachine->obj->value); + } + } + 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 7c53f37816..47d518dd18 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 d1d8184c56..8aae635c17 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, ""); - virBufferEscapeString(buf, "%s", datacenterPath); - virBufferAddLit(buf, "\n"); + if (data->datacenterPath) { + virBufferAddLit(buf, ""); + virBufferEscapeString(buf, "%s", data->datacenterPath); + virBufferAddLit(buf, "\n"); + } + if (data->moref) { + virBufferAddLit(buf, ""); + virBufferEscapeString(buf, "%s", data->moref); + virBufferAddLit(buf, "\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,18 @@ 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 = NULL; + + if (VIR_ALLOC(nsdata) < 0 || + VIR_STRDUP(nsdata->datacenterPath, ctx->datacenterPath) < 0 || + VIR_STRDUP(nsdata->moref, ctx->moref) < 0) { + virVMXDomainDefNamespaceFree(nsdata); goto cleanup; + } def->ns = *virDomainXMLOptionGetNamespace(xmlopt); - def->namespaceData = namespaceData; + def->namespaceData = nsdata; } if (virDomainDefPostParse(def, caps, VIR_DOMAIN_DEF_PARSE_ABI_UPDATE, diff --git a/src/vmx/vmx.h b/src/vmx/vmx.h index 08b6277659..6b3d880d61 100644 --- a/src/vmx/vmx.h +++ b/src/vmx/vmx.h @@ -45,6 +45,7 @@ typedef int (*virVMXAutodetectSCSIControllerModel)(virDomainDiskDefPtr def, * formatFileName is only used by virVMXFormatConfig. * autodetectSCSIControllerModel is optionally used by virVMXFormatConfig. * datacenterPath is only used by virVMXFormatConfig. + * moref is only used by virVMXFormatConfig. */ struct _virVMXContext { void *opaque; @@ -52,6 +53,7 @@ struct _virVMXContext { virVMXFormatFileName formatFileName; virVMXAutodetectSCSIControllerModel autodetectSCSIControllerModel; const char *datacenterPath; /* including folders */ + const char *moref; };