From 0396394f027edb5fa70514a0d11fa62ea7281bd9 Mon Sep 17 00:00:00 2001 From: Matthias Bolte Date: Sun, 19 Oct 2014 00:11:13 +0200 Subject: [PATCH] esx: Simplify VI (vSphere) API and VMware product version handling 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). --- src/esx/esx_driver.c | 59 ++++------- src/esx/esx_vi.c | 229 ++++++++++++++++++++++--------------------- src/esx/esx_vi.h | 55 +++-------- 3 files changed, 147 insertions(+), 196 deletions(-) diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index 0770e89200..af567d2006 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 b00d8e738a..d28b8e030d 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 { - 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); - 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 { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Expecting product 'gsx' or 'esx' or 'embeddedEsx' " - "or 'vpx' but found '%s'"), - ctx->service->about->productLineId); - return -1; - } - } 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 (ctx->productVersion & esxVI_ProductVersion_ESX) { + 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, + _("Minimum supported %s version is %s but found version '%s'"), + esxVI_ProductLineToDisplayName(esxVI_ProductLine_GSX), + "2.0", ctx->service->about->version); + return -1; + } + + 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, + _("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 product 'gsx' or 'esx' or 'embeddedEsx' " + "or 'vpx' but found '%s'"), + ctx->service->about->productLineId); + return -1; + } + + 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, -int -esxVI_ProductVersionToDefaultVirtualHWVersion(esxVI_ProductVersion productVersion) +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 ""; + } +} + + + +int +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 dac36cddcc..b7f0160936 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,