[libvirt] [PATCH v2] esx: Simplify VI (vSphere) API and VMware product version handling

Matthias Bolte matthias.bolte at googlemail.com
Sat Oct 18 22:08:02 UTC 2014


Store version numbers in this format

version = 1000000 * major + 1000 * minor + micro

produced by virParseVersionString instead of dedicated enums.

Split the complex esxVI_ProductVersion enum into a simpler
esxVI_ProductLine enum and a product version number.

Relax API and product version number checks to accept everything that
is equal or greater than the supported minimum version. VMware ESX
went through 3 major versions and the vSphere API always stayed
backward compatible. This commit assumes that this will also be true
for future VMware ESX versions.

Also reword error messages in esxConnectTo* to say what was expected
and what was found instead (suggested by Richard W.M. Jones).
---

v2: - Fix copy&paste accident that replaced hostname with conn->uri->server
      in esxConnectToVCenter
    - Fix and improve commit message

 src/esx/esx_driver.c |  59 +++++---------
 src/esx/esx_vi.c     | 215 ++++++++++++++++++++++++++-------------------------
 src/esx/esx_vi.h     |  55 +++----------
 3 files changed, 140 insertions(+), 189 deletions(-)

diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index 39784b9..64265ed 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -646,9 +646,9 @@ esxConnectToHost(esxPrivate *priv,
     esxVI_String *propertyNameList = NULL;
     esxVI_ObjectContent *hostSystem = NULL;
     esxVI_Boolean inMaintenanceMode = esxVI_Boolean_Undefined;
-    esxVI_ProductVersion expectedProductVersion = STRCASEEQ(conn->uri->scheme, "esx")
-        ? esxVI_ProductVersion_ESX
-        : esxVI_ProductVersion_GSX;
+    esxVI_ProductLine expectedProductLine = STRCASEEQ(conn->uri->scheme, "esx")
+        ? esxVI_ProductLine_ESX
+        : esxVI_ProductLine_GSX;
 
     if (!vCenterIpAddress || *vCenterIpAddress) {
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
@@ -695,25 +695,13 @@ esxConnectToHost(esxPrivate *priv,
         goto cleanup;
     }
 
-    if (expectedProductVersion == esxVI_ProductVersion_ESX) {
-        if (priv->host->productVersion != esxVI_ProductVersion_ESX35 &&
-            priv->host->productVersion != esxVI_ProductVersion_ESX40 &&
-            priv->host->productVersion != esxVI_ProductVersion_ESX41 &&
-            priv->host->productVersion != esxVI_ProductVersion_ESX4x &&
-            priv->host->productVersion != esxVI_ProductVersion_ESX50 &&
-            priv->host->productVersion != esxVI_ProductVersion_ESX51 &&
-            priv->host->productVersion != esxVI_ProductVersion_ESX5x) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("%s is neither an ESX 3.5, 4.x nor 5.x host"),
-                           conn->uri->server);
-            goto cleanup;
-        }
-    } else { /* GSX */
-        if (priv->host->productVersion != esxVI_ProductVersion_GSX20) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("%s isn't a GSX 2.0 host"), conn->uri->server);
-            goto cleanup;
-        }
+    if (priv->host->productLine != expectedProductLine) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Expecting '%s' to be a %s host, but found a %s host"),
+                       conn->uri->server,
+                       esxVI_ProductLineToDisplayName(expectedProductLine),
+                       esxVI_ProductLineToDisplayName(priv->host->productLine));
+        goto cleanup;
     }
 
     /* Query the host for maintenance mode and vCenter IP address */
@@ -815,16 +803,12 @@ esxConnectToVCenter(esxPrivate *priv,
         goto cleanup;
     }
 
-    if (priv->vCenter->productVersion != esxVI_ProductVersion_VPX25 &&
-        priv->vCenter->productVersion != esxVI_ProductVersion_VPX40 &&
-        priv->vCenter->productVersion != esxVI_ProductVersion_VPX41 &&
-        priv->vCenter->productVersion != esxVI_ProductVersion_VPX4x &&
-        priv->vCenter->productVersion != esxVI_ProductVersion_VPX50 &&
-        priv->vCenter->productVersion != esxVI_ProductVersion_VPX51 &&
-        priv->vCenter->productVersion != esxVI_ProductVersion_VPX5x) {
+    if (priv->vCenter->productLine != esxVI_ProductLine_VPX) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("%s is neither a vCenter 2.5, 4.x nor 5.x server"),
-                       hostname);
+                       _("Expecting '%s' to be a %s host but found a %s host"),
+                       hostname,
+                       esxVI_ProductLineToDisplayName(esxVI_ProductLine_VPX),
+                       esxVI_ProductLineToDisplayName(priv->vCenter->productLine));
         goto cleanup;
     }
 
@@ -1217,14 +1201,7 @@ esxConnectGetVersion(virConnectPtr conn, unsigned long *version)
 {
     esxPrivate *priv = conn->privateData;
 
-    if (virParseVersionString(priv->primary->service->about->version,
-                              version, false) < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Could not parse version number from '%s'"),
-                       priv->primary->service->about->version);
-
-        return -1;
-    }
+    *version = priv->primary->productVersion;
 
     return 0;
 }
@@ -2934,7 +2911,7 @@ esxConnectDomainXMLToNative(virConnectPtr conn, const char *nativeFormat,
     }
 
     virtualHW_version = esxVI_ProductVersionToDefaultVirtualHWVersion
-                          (priv->primary->productVersion);
+                          (priv->primary->productLine, priv->primary->productVersion);
 
     if (virtualHW_version < 0) {
         return NULL;
@@ -3190,7 +3167,7 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml)
 
     /* Build VMX from domain XML */
     virtualHW_version = esxVI_ProductVersionToDefaultVirtualHWVersion
-                          (priv->primary->productVersion);
+                          (priv->primary->productLine, priv->primary->productVersion);
 
     if (virtualHW_version < 0) {
         goto cleanup;
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index b00d8e7..d28b8e0 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -1040,98 +1040,77 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
         return -1;
     }
 
-    if (STREQ(ctx->service->about->apiType, "HostAgent") ||
-        STREQ(ctx->service->about->apiType, "VirtualCenter")) {
-        if (STRPREFIX(ctx->service->about->apiVersion, "2.5")) {
-            ctx->apiVersion = esxVI_APIVersion_25;
-        } else if (STRPREFIX(ctx->service->about->apiVersion, "4.0")) {
-            ctx->apiVersion = esxVI_APIVersion_40;
-        } else if (STRPREFIX(ctx->service->about->apiVersion, "4.1")) {
-            ctx->apiVersion = esxVI_APIVersion_41;
-        } else if (STRPREFIX(ctx->service->about->apiVersion, "4.")) {
-            ctx->apiVersion = esxVI_APIVersion_4x;
-        } else if (STRPREFIX(ctx->service->about->apiVersion, "5.0")) {
-            ctx->apiVersion = esxVI_APIVersion_50;
-        } else if (STRPREFIX(ctx->service->about->apiVersion, "5.1")) {
-            ctx->apiVersion = esxVI_APIVersion_51;
-        } else if (STRPREFIX(ctx->service->about->apiVersion, "5.")) {
-            ctx->apiVersion = esxVI_APIVersion_5x;
-        } else {
+    if (STRNEQ(ctx->service->about->apiType, "HostAgent") &&
+        STRNEQ(ctx->service->about->apiType, "VirtualCenter")) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Expecting VI API type 'HostAgent' or 'VirtualCenter' "
+                         "but found '%s'"), ctx->service->about->apiType);
+        return -1;
+    }
+
+    if (virParseVersionString(ctx->service->about->apiVersion,
+                              &ctx->apiVersion, true) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Could not parse VI API version '%s'"),
+                       ctx->service->about->apiVersion);
+        return -1;
+    }
+
+    if (ctx->apiVersion < 1000000 * 2 + 1000 * 5 /* 2.5 */) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Minimum supported %s version is %s but found version '%s'"),
+                       "VI API", "2.5", ctx->service->about->apiVersion);
+        return -1;
+    }
+
+    if (virParseVersionString(ctx->service->about->version,
+                              &ctx->productVersion, true) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Could not parse product version '%s'"),
+                       ctx->service->about->version);
+        return -1;
+    }
+
+    if (STREQ(ctx->service->about->productLineId, "gsx")) {
+        if (ctx->productVersion < 1000000 * 2 + 1000 * 0 /* 2.0 */) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("Expecting VI API major/minor version '2.5', '4.x' or "
-                             "'5.x' but found '%s'"), ctx->service->about->apiVersion);
+                           _("Minimum supported %s version is %s but found version '%s'"),
+                           esxVI_ProductLineToDisplayName(esxVI_ProductLine_GSX),
+                           "2.0", ctx->service->about->version);
             return -1;
         }
 
-        if (STREQ(ctx->service->about->productLineId, "gsx")) {
-            if (STRPREFIX(ctx->service->about->version, "2.0")) {
-                ctx->productVersion = esxVI_ProductVersion_GSX20;
-            } else {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("Expecting GSX major/minor version '2.0' but "
-                                 "found '%s'"), ctx->service->about->version);
-                return -1;
-            }
-        } else if (STREQ(ctx->service->about->productLineId, "esx") ||
-                   STREQ(ctx->service->about->productLineId, "embeddedEsx")) {
-            if (STRPREFIX(ctx->service->about->version, "3.5")) {
-                ctx->productVersion = esxVI_ProductVersion_ESX35;
-            } else if (STRPREFIX(ctx->service->about->version, "4.0")) {
-                ctx->productVersion = esxVI_ProductVersion_ESX40;
-            } else if (STRPREFIX(ctx->service->about->version, "4.1")) {
-                ctx->productVersion = esxVI_ProductVersion_ESX41;
-            } else if (STRPREFIX(ctx->service->about->version, "4.")) {
-                ctx->productVersion = esxVI_ProductVersion_ESX4x;
-            } else if (STRPREFIX(ctx->service->about->version, "5.0")) {
-                ctx->productVersion = esxVI_ProductVersion_ESX50;
-            } else if (STRPREFIX(ctx->service->about->version, "5.1")) {
-                ctx->productVersion = esxVI_ProductVersion_ESX51;
-            } else if (STRPREFIX(ctx->service->about->version, "5.")) {
-                ctx->productVersion = esxVI_ProductVersion_ESX5x;
-            } else {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("Expecting ESX major/minor version '3.5', "
-                                 "'4.x' or '5.x' but found '%s'"),
-                               ctx->service->about->version);
-                return -1;
-            }
-        } else if (STREQ(ctx->service->about->productLineId, "vpx")) {
-            if (STRPREFIX(ctx->service->about->version, "2.5")) {
-                ctx->productVersion = esxVI_ProductVersion_VPX25;
-            } else if (STRPREFIX(ctx->service->about->version, "4.0")) {
-                ctx->productVersion = esxVI_ProductVersion_VPX40;
-            } else if (STRPREFIX(ctx->service->about->version, "4.1")) {
-                ctx->productVersion = esxVI_ProductVersion_VPX41;
-            } else if (STRPREFIX(ctx->service->about->version, "4.")) {
-                ctx->productVersion = esxVI_ProductVersion_VPX4x;
-            } else if (STRPREFIX(ctx->service->about->version, "5.0")) {
-                ctx->productVersion = esxVI_ProductVersion_VPX50;
-            } else if (STRPREFIX(ctx->service->about->version, "5.1")) {
-                ctx->productVersion = esxVI_ProductVersion_VPX51;
-            } else if (STRPREFIX(ctx->service->about->version, "5.")) {
-                ctx->productVersion = esxVI_ProductVersion_VPX5x;
-            } else {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("Expecting VPX major/minor version '2.5', '4.x' "
-                                 "or '5.x' but found '%s'"),
-                               ctx->service->about->version);
-                return -1;
-            }
-        } else {
+        ctx->productLine = esxVI_ProductLine_GSX;
+    } else if (STREQ(ctx->service->about->productLineId, "esx") ||
+               STREQ(ctx->service->about->productLineId, "embeddedEsx")) {
+        if (ctx->productVersion < 1000000 * 3 + 1000 * 5 /* 3.5 */) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Minimum supported %s version is %s but found version '%s'"),
+                           esxVI_ProductLineToDisplayName(esxVI_ProductLine_ESX),
+                           "3.5", ctx->service->about->version);
+            return -1;
+        }
+
+        ctx->productLine = esxVI_ProductLine_ESX;
+    } else if (STREQ(ctx->service->about->productLineId, "vpx")) {
+        if (ctx->productVersion < 1000000 * 2 + 1000 * 5 /* 2.5 */) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("Expecting product 'gsx' or 'esx' or 'embeddedEsx' "
-                             "or 'vpx' but found '%s'"),
-                           ctx->service->about->productLineId);
+                           _("Minimum supported %s version is %s but found version '%s'"),
+                           esxVI_ProductLineToDisplayName(esxVI_ProductLine_VPX),
+                           "2.5", ctx->service->about->version);
             return -1;
         }
+
+        ctx->productLine = esxVI_ProductLine_VPX;
     } else {
         virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Expecting VI API type 'HostAgent' or 'VirtualCenter' "
-                         "but found '%s'"), ctx->service->about->apiType);
+                       _("Expecting product 'gsx' or 'esx' or 'embeddedEsx' "
+                         "or 'vpx' but found '%s'"),
+                       ctx->service->about->productLineId);
         return -1;
     }
 
-    if (ctx->productVersion & esxVI_ProductVersion_ESX) {
+    if (ctx->productLine == esxVI_ProductLine_ESX) {
         /*
          * FIXME: Actually this should be detected by really calling
          * QueryVirtualDiskUuid and checking if a NotImplemented fault is
@@ -1142,7 +1121,7 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
         ctx->hasQueryVirtualDiskUuid = true;
     }
 
-    if (ctx->productVersion & esxVI_ProductVersion_VPX) {
+    if (ctx->productLine == esxVI_ProductLine_VPX) {
         ctx->hasSessionIsActive = true;
     }
 
@@ -4770,9 +4749,33 @@ esxVI_ParseHostCpuIdInfo(esxVI_ParsedHostCpuIdInfo *parsedHostCpuIdInfo,
 
 
 
+const char *
+esxVI_ProductLineToDisplayName(esxVI_ProductLine productLine)
+{
+    switch (productLine) {
+      case esxVI_ProductLine_GSX:
+        return "Server/GSX";
+
+      case esxVI_ProductLine_ESX:
+        return "ESX(i)";
+
+      case esxVI_ProductLine_VPX:
+        return "vCenter/VPX";
+
+      default:
+        return "<unknown>";
+    }
+}
+
+
+
 int
-esxVI_ProductVersionToDefaultVirtualHWVersion(esxVI_ProductVersion productVersion)
+esxVI_ProductVersionToDefaultVirtualHWVersion(esxVI_ProductLine productLine,
+                                              unsigned long productVersion)
 {
+    /* product version == 1000000 * major + 1000 * minor + micro */
+    int major = productVersion / 1000000;
+
     /*
      * virtualHW.version compatibility matrix:
      *
@@ -4785,35 +4788,39 @@ esxVI_ProductVersionToDefaultVirtualHWVersion(esxVI_ProductVersion productVersio
      *   ESX 5.5    + + + + +    5.5
      *   GSX 2.0    + +          2.5
      */
-    switch (productVersion) {
-      case esxVI_ProductVersion_ESX35:
-      case esxVI_ProductVersion_VPX25:
-        return 4;
-
-      case esxVI_ProductVersion_GSX20:
-      case esxVI_ProductVersion_ESX40:
-      case esxVI_ProductVersion_ESX41:
-      case esxVI_ProductVersion_VPX40:
-      case esxVI_ProductVersion_VPX41:
+    switch (productLine) {
+      case esxVI_ProductLine_GSX:
         return 7;
 
-      case esxVI_ProductVersion_ESX4x:
-      case esxVI_ProductVersion_VPX4x:
-        return 7;
+      case esxVI_ProductLine_ESX:
+        switch (major) {
+          case 3:
+            return 4;
 
-      case esxVI_ProductVersion_ESX50:
-      case esxVI_ProductVersion_VPX50:
-        return 8;
+          case 4:
+            return 7;
 
-      case esxVI_ProductVersion_ESX51:
-      case esxVI_ProductVersion_ESX5x:
-      case esxVI_ProductVersion_VPX51:
-      case esxVI_ProductVersion_VPX5x:
-        return 8;
+          case 5:
+          default:
+            return 8;
+        }
+
+      case esxVI_ProductLine_VPX:
+        switch (major) {
+          case 2:
+            return 4;
+
+          case 4:
+            return 7;
+
+          case 5:
+          default:
+            return 8;
+        }
 
       default:
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                       _("Unexpected product version"));
+                       _("Unexpected product line"));
         return -1;
     }
 }
diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h
index dac36cd..b7f0160 100644
--- a/src/esx/esx_vi.h
+++ b/src/esx/esx_vi.h
@@ -75,8 +75,7 @@
 
 
 
-typedef enum _esxVI_APIVersion esxVI_APIVersion;
-typedef enum _esxVI_ProductVersion esxVI_ProductVersion;
+typedef enum _esxVI_ProductLine esxVI_ProductLine;
 typedef enum _esxVI_Occurrence esxVI_Occurrence;
 typedef struct _esxVI_ParsedHostCpuIdInfo esxVI_ParsedHostCpuIdInfo;
 typedef struct _esxVI_CURL esxVI_CURL;
@@ -90,45 +89,10 @@ typedef struct _esxVI_List esxVI_List;
 
 
 
-enum _esxVI_APIVersion {
-    esxVI_APIVersion_Undefined = 0,
-    esxVI_APIVersion_Unknown,
-    esxVI_APIVersion_25,
-    esxVI_APIVersion_40,
-    esxVI_APIVersion_41,
-    esxVI_APIVersion_4x, /* > 4.1 */
-    esxVI_APIVersion_50,
-    esxVI_APIVersion_51,
-    esxVI_APIVersion_5x  /* > 5.1 */
-};
-
-/*
- * AAAABBBB: where AAAA0000 is the product and BBBB the version. this format
- * allows simple bitmask testing for a product independent of the version
- */
-enum _esxVI_ProductVersion {
-    esxVI_ProductVersion_Undefined = 0,
-
-    esxVI_ProductVersion_GSX   = (1 << 0) << 16,
-    esxVI_ProductVersion_GSX20 = esxVI_ProductVersion_GSX | 1,
-
-    esxVI_ProductVersion_ESX   = (1 << 1) << 16,
-    esxVI_ProductVersion_ESX35 = esxVI_ProductVersion_ESX | 1,
-    esxVI_ProductVersion_ESX40 = esxVI_ProductVersion_ESX | 2,
-    esxVI_ProductVersion_ESX41 = esxVI_ProductVersion_ESX | 3,
-    esxVI_ProductVersion_ESX4x = esxVI_ProductVersion_ESX | 4, /* > 4.1 */
-    esxVI_ProductVersion_ESX50 = esxVI_ProductVersion_ESX | 5,
-    esxVI_ProductVersion_ESX51 = esxVI_ProductVersion_ESX | 6,
-    esxVI_ProductVersion_ESX5x = esxVI_ProductVersion_ESX | 7, /* > 5.1 */
-
-    esxVI_ProductVersion_VPX   = (1 << 2) << 16,
-    esxVI_ProductVersion_VPX25 = esxVI_ProductVersion_VPX | 1,
-    esxVI_ProductVersion_VPX40 = esxVI_ProductVersion_VPX | 2,
-    esxVI_ProductVersion_VPX41 = esxVI_ProductVersion_VPX | 3,
-    esxVI_ProductVersion_VPX4x = esxVI_ProductVersion_VPX | 4, /* > 4.1 */
-    esxVI_ProductVersion_VPX50 = esxVI_ProductVersion_VPX | 5,
-    esxVI_ProductVersion_VPX51 = esxVI_ProductVersion_VPX | 6,
-    esxVI_ProductVersion_VPX5x = esxVI_ProductVersion_VPX | 7  /* > 5.1 */
+enum _esxVI_ProductLine {
+    esxVI_ProductLine_GSX = 0,
+    esxVI_ProductLine_ESX,
+    esxVI_ProductLine_VPX
 };
 
 enum _esxVI_Occurrence {
@@ -226,8 +190,9 @@ struct _esxVI_Context {
     char *username;
     char *password;
     esxVI_ServiceContent *service;
-    esxVI_APIVersion apiVersion;
-    esxVI_ProductVersion productVersion;
+    unsigned long apiVersion; /* = 1000000 * major + 1000 * minor + micro */
+    esxVI_ProductLine productLine;
+    unsigned long productVersion; /* = 1000000 * major + 1000 * minor + micro */
     esxVI_UserSession *session; /* ... except the session ... */
     virMutexPtr sessionLock; /* ... that is protected by this mutex */
     esxVI_Datacenter *datacenter;
@@ -536,8 +501,10 @@ int esxVI_WaitForTaskCompletion(esxVI_Context *ctx,
 int esxVI_ParseHostCpuIdInfo(esxVI_ParsedHostCpuIdInfo *parsedHostCpuIdInfo,
                              esxVI_HostCpuIdInfo *hostCpuIdInfo);
 
+const char *esxVI_ProductLineToDisplayName(esxVI_ProductLine productLine);
+
 int esxVI_ProductVersionToDefaultVirtualHWVersion
-      (esxVI_ProductVersion productVersion);
+      (esxVI_ProductLine productLine, unsigned long productVersion);
 
 int esxVI_LookupHostInternetScsiHbaStaticTargetByName
       (esxVI_Context *ctx, const char *name,
-- 
1.8.3.2




More information about the libvir-list mailing list