If an ESX host is managed by a vCenter, it knows the IP address of the
vCenter. Setting the vCenter query parameter to * allows to connect to the
vCenter known to an ESX host without the need to specify its IP address
or hostname explicitly.
---
src/esx/esx_driver.c | 125 +++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 98 insertions(+), 27 deletions(-)
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index db379d7..d7e1ab5 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -234,7 +234,7 @@ esxCapsInit(virConnectPtr conn)
/*
- * URI format:
{esx|gsx}://[<user>@]<server>[:<port>][?transport={http|https}][&vcenter=<vcenter>][&no_verify={0|1}][&auto_answer={0|1}]
+ * URI format: {esx|gsx}://[<user>@]<server>[:<port>]/[<query
parameter> ...]
*
* If no port is specified the default port is set dependent on the scheme and
* transport parameter:
@@ -243,10 +243,19 @@ esxCapsInit(virConnectPtr conn)
* - gsx+http 8222
* - gsx+https 8333
*
+ * Optional query parameters:
+ * - transport={http|https}
+ * - vcenter={<vcenter>|*}
+ * - no_verify={0|1}
+ * - auto_answer={0|1}
+ *
* If no transport parameter is specified https is used.
*
* The vcenter parameter is only necessary for migration, because the vCenter
- * server is in charge to initiate a migration between two ESX hosts.
+ * server is in charge to initiate a migration between two ESX hosts. The
+ * vcenter parameter can be set to an explicity hostname or to *. If set to *,
+ * the driver will check if the ESX host is managed by a vCenter and connect to
+ * it. If the ESX host is not managed by a vCenter an error is reported.
*
* If the no_verify parameter is set to 1, this disables libcurl client checks
* of the server's certificate. The default value it 0.
@@ -258,6 +267,7 @@ esxCapsInit(virConnectPtr conn)
static virDrvOpenStatus
esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED)
{
+ virDrvOpenStatus result = VIR_DRV_OPEN_SUCCESS;
esxPrivate *priv = NULL;
char hostIpAddress[NI_MAXHOST] = "";
char vCenterIpAddress[NI_MAXHOST] = "";
@@ -267,6 +277,9 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags
ATTRIBUTE_UNUSED)
int autoAnswer = 0; // boolean
char *username = NULL;
char *password = NULL;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *hostSystem = NULL;
+ esxVI_DynamicProperty *dynamicProperty = NULL;
/* Decline if the URI is NULL or the scheme is neither 'esx' nor
'gsx' */
if (conn->uri == NULL || conn->uri->scheme == NULL ||
@@ -305,18 +318,6 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags
ATTRIBUTE_UNUSED)
priv->autoAnswer = esxVI_Boolean_True;
}
- /* Request credentials and login to host/vCenter */
- if (esxUtil_ResolveHostname(conn, conn->uri->server, hostIpAddress,
- NI_MAXHOST) < 0) {
- goto failure;
- }
-
- if (vCenter != NULL &&
- esxUtil_ResolveHostname(conn, vCenter, vCenterIpAddress,
- NI_MAXHOST) < 0) {
- goto failure;
- }
-
/*
* Set the port dependent on the transport protocol if no port is
* specified. This allows us to rely on the port parameter being
@@ -340,6 +341,11 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags
ATTRIBUTE_UNUSED)
}
/* Login to host */
+ if (esxUtil_ResolveHostname(conn, conn->uri->server, hostIpAddress,
+ NI_MAXHOST) < 0) {
+ goto failure;
+ }
+
if (virAsprintf(&url, "%s://%s:%d/sdk", priv->transport,
conn->uri->server, conn->uri->port) < 0) {
virReportOOMError(conn);
@@ -394,12 +400,77 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags
ATTRIBUTE_UNUSED)
}
}
- VIR_FREE(url);
- VIR_FREE(password);
- VIR_FREE(username);
-
/* Login to vCenter */
if (vCenter != NULL) {
+ VIR_FREE(url);
+ VIR_FREE(password);
+ VIR_FREE(username);
+
+ /* If a vCenter is specified resolve the hostname */
+ if (STRNEQ(vCenter, "*") &&
+ esxUtil_ResolveHostname(conn, vCenter, vCenterIpAddress,
+ NI_MAXHOST) < 0) {
+ goto failure;
+ }
+
+ /* Lookup the vCenter from the ESX host */
+ if (esxVI_String_AppendValueToList
+ (conn, &propertyNameList, "summary.managementServerIp") <
0 ||
+ esxVI_LookupHostSystemByIp(conn, priv->host, hostIpAddress,
+ propertyNameList, &hostSystem) < 0) {
+ goto failure;
+ }
+
+ for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL;
+ dynamicProperty = dynamicProperty->_next) {
+ if (STREQ(dynamicProperty->name,
+ "summary.managementServerIp")) {
+ if (esxVI_AnyType_ExpectType(conn, dynamicProperty->val,
+ esxVI_Type_String) < 0) {
+ goto failure;
+ }
+
+ /* Get the vCenter IP address or verify the specified one */
+ if (STREQ(vCenter, "*")) {
+ VIR_FREE(vCenter);
+
+ vCenter = strdup(dynamicProperty->val->string);
+
+ if (vCenter == NULL) {
+ virReportOOMError(conn);
+ goto failure;
+ }
+
+ if (virStrcpyStatic(vCenterIpAddress,
+ dynamicProperty->val->string) == NULL) {
+ ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+ "vCenter IP address %s too big for "
+ "destination",
dynamicProperty->val->string);
+ goto failure;
+ }
+ } else if (STRNEQ(vCenterIpAddress,
+ dynamicProperty->val->string)) {
+ ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+ "This host is managed by a vCenter with IP "
+ "address %s, but a mismachting vCenter '%s'
"
+ "(%s) has been specified",
+ dynamicProperty->val->string, vCenter,
+ vCenterIpAddress);
+ goto failure;
+ }
+
+ break;
+ } else {
+ VIR_WARN("Unexpected '%s' property",
dynamicProperty->name);
+ }
+ }
+
+ if (STREQ(vCenter, "*")) {
+ ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+ "This host is not managed by a vCenter");
+ goto failure;
+ }
+
if (virAsprintf(&url, "%s://%s/sdk", priv->transport,
vCenter) < 0) {
virReportOOMError(conn);
@@ -440,11 +511,6 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags
ATTRIBUTE_UNUSED)
conn->uri->server);
goto failure;
}
-
- VIR_FREE(url);
- VIR_FREE(vCenter);
- VIR_FREE(password);
- VIR_FREE(username);
}
conn->privateData = priv;
@@ -456,14 +522,17 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags
ATTRIBUTE_UNUSED)
goto failure;
}
- return VIR_DRV_OPEN_SUCCESS;
-
- failure:
+ cleanup:
VIR_FREE(url);
VIR_FREE(vCenter);
VIR_FREE(password);
VIR_FREE(username);
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&hostSystem);
+ return result;
+
+ failure:
if (priv != NULL) {
esxVI_Context_Free(&priv->host);
esxVI_Context_Free(&priv->vCenter);
@@ -474,7 +543,9 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags
ATTRIBUTE_UNUSED)
VIR_FREE(priv);
}
- return VIR_DRV_OPEN_ERROR;
+ result = VIR_DRV_OPEN_ERROR;
+
+ goto cleanup;
}
--
1.6.0.4