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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list