]> xenbits.xensource.com Git - libvirt.git/commitdiff
vmx: Expose VMware Managed Object Reference (moref) in XML.
authorRichard W.M. Jones <rjones@redhat.com>
Fri, 25 Aug 2017 13:36:58 +0000 (14:36 +0100)
committerRichard W.M. Jones <rjones@redhat.com>
Mon, 4 Sep 2017 08:48:32 +0000 (09:48 +0100)
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.

Signed-off-by: Richard W.M. Jones <rjones@redhat.com>
src/esx/esx_driver.c
src/esx/esx_vi.c
src/esx/esx_vi.h
src/vmx/vmx.c
src/vmx/vmx.h

index 1f4f2c7a757b7ff66335a460609669d2ac4b5620..0cce0a41a3f983b5e5ead0b0b606e51d6aa22332 100644 (file)
@@ -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);
 
index 8586e3ff0af2871e432cd96bd59937d392dd3005..6d59bae9d885320cdd1c394cbece4c413856b02c 100644 (file)
@@ -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,
index 7c53f37816d9a9122f253fbb631ab0a1d5635ba3..47d518dd18e55a06a5274975b5b7c78d59e882f0 100644 (file)
@@ -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);
index d1d8184c566d52b9c62c47f961adbd7b2eeec977..8aae635c170383ce8ccc7ecf91e3435b56e972b4 100644 (file)
@@ -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,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,
index 08b62776596e1015b570726dbe44c3032de8e141..6b3d880d61b4871e7a4a7d584e602ace7fc7ed8e 100644 (file)
@@ -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;
 };