aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/drvesx.html.in10
-rw-r--r--src/esx/esx_driver.c30
-rw-r--r--src/esx/esx_util.c22
-rw-r--r--src/esx/esx_util.h4
-rw-r--r--src/esx/esx_vi.c267
-rw-r--r--src/esx/esx_vi.h11
-rw-r--r--src/esx/esx_vi_generator.input4
7 files changed, 280 insertions, 68 deletions
diff --git a/docs/drvesx.html.in b/docs/drvesx.html.in
index da9d2a1ba..7d323b352 100644
--- a/docs/drvesx.html.in
+++ b/docs/drvesx.html.in
@@ -56,7 +56,7 @@ esx://example-esx.com/?no_verify=1 (ESX over HTTPS, but doesn't verify the s
URIs have this general form (<code>[...]</code> marks an optional part).
</p>
<pre>
-type://[username@]hostname[:port]/[datacenter[/cluster]/server][?extraparameters]
+type://[username@]hostname[:port]/[[folder/...]datacenter/[folder/...][cluster/]server][?extraparameters]
</pre>
<p>
The <code>type://</code> is either <code>esx://</code> or
@@ -80,6 +80,14 @@ type://[username@]hostname[:port]/[datacenter[/cluster]/server][?extraparameters
<pre>
vpx://example-vcenter.com/dc1/cluster1/example-esx.com
</pre>
+ <p>
+ Datacenters and clusters can be organized in folders, those have to be
+ specified as well. The driver can handle folders
+ <span class="since">since 0.9.7</span>.
+ </p>
+<pre>
+vpx://example-vcenter.com/folder1/dc1/folder2/example-esx.com
+</pre>
<h4><a name="extraparams">Extra parameters</a></h4>
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index 5d0b6dbd5..dfeef8533 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -722,7 +722,7 @@ esxConnectToHost(esxPrivate *priv, virConnectAuthPtr auth,
if (esxVI_Context_Alloc(&priv->host) < 0 ||
esxVI_Context_Connect(priv->host, url, ipAddress, username, password,
priv->parsedUri) < 0 ||
- esxVI_Context_LookupObjectsByPath(priv->host, priv->parsedUri) < 0) {
+ esxVI_Context_LookupManagedObjects(priv->host) < 0) {
goto cleanup;
}
@@ -804,8 +804,7 @@ esxConnectToVCenter(esxPrivate *priv, virConnectAuthPtr auth,
char *url = NULL;
if (hostSystemIpAddress == NULL &&
- (priv->parsedUri->path_datacenter == NULL ||
- priv->parsedUri->path_computeResource == NULL)) {
+ (priv->parsedUri->path == NULL || STREQ(priv->parsedUri->path, "/"))) {
ESX_ERROR(VIR_ERR_INVALID_ARG, "%s",
_("Path has to specify the datacenter and compute resource"));
return -1;
@@ -869,13 +868,13 @@ esxConnectToVCenter(esxPrivate *priv, virConnectAuthPtr auth,
}
if (hostSystemIpAddress != NULL) {
- if (esxVI_Context_LookupObjectsByHostSystemIp(priv->vCenter,
- hostSystemIpAddress) < 0) {
+ if (esxVI_Context_LookupManagedObjectsByHostSystemIp
+ (priv->vCenter, hostSystemIpAddress) < 0) {
goto cleanup;
}
} else {
- if (esxVI_Context_LookupObjectsByPath(priv->vCenter,
- priv->parsedUri) < 0) {
+ if (esxVI_Context_LookupManagedObjectsByPath(priv->vCenter,
+ priv->parsedUri->path) < 0) {
goto cleanup;
}
}
@@ -894,8 +893,8 @@ esxConnectToVCenter(esxPrivate *priv, virConnectAuthPtr auth,
/*
- * URI format: {vpx|esx|gsx}://[<username>@]<hostname>[:<port>]/[<path>][?<query parameter> ...]
- * <path> = <datacenter>/<computeresource>[/<hostsystem>]
+ * URI format: {vpx|esx|gsx}://[<username>@]<hostname>[:<port>]/[<path>][?<query parameter>...]
+ * <path> = [<folder>/...]<datacenter>/[<folder>/...]<computeresource>[/<hostsystem>]
*
* If no port is specified the default port is set dependent on the scheme and
* transport parameter:
@@ -909,7 +908,8 @@ esxConnectToVCenter(esxPrivate *priv, virConnectAuthPtr auth,
* For a vpx:// connection <path> references a host managed by the vCenter.
* In case the host is part of a cluster then <computeresource> is the cluster
* name. Otherwise <computeresource> and <hostsystem> are equal and the later
- * can be omitted.
+ * can be omitted. As datacenters and computeresources can be organized in
+ * folders those have to be included in <path>.
*
* Optional query parameters:
* - transport={http|https}
@@ -977,6 +977,12 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth,
return VIR_DRV_OPEN_ERROR;
}
+ if (STRCASENEQ(conn->uri->scheme, "vpx") &&
+ conn->uri->path != NULL && STRNEQ(conn->uri->path, "/")) {
+ VIR_WARN("Ignoring unexpected path '%s' for non-vpx scheme '%s'",
+ conn->uri->path, conn->uri->scheme);
+ }
+
/* Require server part */
if (conn->uri->server == NULL) {
ESX_ERROR(VIR_ERR_INVALID_ARG, "%s",
@@ -2769,7 +2775,7 @@ esxDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
domain->conn->uri->server, domain->conn->uri->port);
virBufferURIEncodeString(&buffer, directoryAndFileName);
virBufferAddLit(&buffer, "?dcPath=");
- virBufferURIEncodeString(&buffer, priv->primary->datacenter->name);
+ virBufferURIEncodeString(&buffer, priv->primary->datacenterPath);
virBufferAddLit(&buffer, "&dsName=");
virBufferURIEncodeString(&buffer, datastoreName);
@@ -3237,7 +3243,7 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml)
virBufferURIEncodeString(&buffer, escapedName);
virBufferAddLit(&buffer, ".vmx?dcPath=");
- virBufferURIEncodeString(&buffer, priv->primary->datacenter->name);
+ virBufferURIEncodeString(&buffer, priv->primary->datacenterPath);
virBufferAddLit(&buffer, "&dsName=");
virBufferURIEncodeString(&buffer, datastoreName);
diff --git a/src/esx/esx_util.c b/src/esx/esx_util.c
index c14179d7f..1925802f4 100644
--- a/src/esx/esx_util.c
+++ b/src/esx/esx_util.c
@@ -51,7 +51,6 @@ esxUtil_ParseUri(esxUtil_ParsedUri **parsedUri, xmlURIPtr uri)
int noVerify;
int autoAnswer;
char *tmp;
- char *saveptr;
if (parsedUri == NULL || *parsedUri != NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
@@ -184,26 +183,13 @@ esxUtil_ParseUri(esxUtil_ParsedUri **parsedUri, xmlURIPtr uri)
}
}
- /* Expected format: [/]<datacenter>/<computeresource>[/<hostsystem>] */
if (uri->path != NULL) {
- tmp = strdup(uri->path);
+ (*parsedUri)->path = strdup(uri->path);
- if (tmp == NULL) {
+ if ((*parsedUri)->path == NULL) {
virReportOOMError();
goto cleanup;
}
-
- if (esxVI_String_DeepCopyValue(&(*parsedUri)->path_datacenter,
- strtok_r(tmp, "/", &saveptr)) < 0 ||
- esxVI_String_DeepCopyValue(&(*parsedUri)->path_computeResource,
- strtok_r(NULL, "/", &saveptr)) < 0 ||
- esxVI_String_DeepCopyValue(&(*parsedUri)->path_hostSystem,
- strtok_r(NULL, "", &saveptr)) < 0) {
- VIR_FREE(tmp);
- goto cleanup;
- }
-
- VIR_FREE(tmp);
}
if ((*parsedUri)->transport == NULL) {
@@ -242,9 +228,7 @@ esxUtil_FreeParsedUri(esxUtil_ParsedUri **parsedUri)
VIR_FREE((*parsedUri)->transport);
VIR_FREE((*parsedUri)->vCenter);
VIR_FREE((*parsedUri)->proxy_hostname);
- VIR_FREE((*parsedUri)->path_datacenter);
- VIR_FREE((*parsedUri)->path_computeResource);
- VIR_FREE((*parsedUri)->path_hostSystem);
+ VIR_FREE((*parsedUri)->path);
VIR_FREE(*parsedUri);
}
diff --git a/src/esx/esx_util.h b/src/esx/esx_util.h
index 39fdb6db4..8d172e10a 100644
--- a/src/esx/esx_util.h
+++ b/src/esx/esx_util.h
@@ -37,9 +37,7 @@ struct _esxUtil_ParsedUri {
int proxy_type;
char *proxy_hostname;
int proxy_port;
- char *path_datacenter;
- char *path_computeResource;
- char *path_hostSystem;
+ char *path;
};
int esxUtil_ParseUri(esxUtil_ParsedUri **parsedUri, xmlURIPtr uri);
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index 86e5739a3..21892a011 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -616,8 +616,11 @@ ESX_VI__TEMPLATE__FREE(Context,
esxVI_UserSession_Free(&item->session);
VIR_FREE(item->sessionLock);
esxVI_Datacenter_Free(&item->datacenter);
+ VIR_FREE(item->datacenterPath);
esxVI_ComputeResource_Free(&item->computeResource);
+ VIR_FREE(item->computeResourcePath);
esxVI_HostSystem_Free(&item->hostSystem);
+ VIR_FREE(item->hostSystemName);
esxVI_SelectionSpec_Free(&item->selectSet_folderToChildEntity);
esxVI_SelectionSpec_Free(&item->selectSet_hostSystemToParent);
esxVI_SelectionSpec_Free(&item->selectSet_hostSystemToVm);
@@ -789,21 +792,25 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
}
int
-esxVI_Context_LookupObjectsByPath(esxVI_Context *ctx,
- esxUtil_ParsedUri *parsedUri)
+esxVI_Context_LookupManagedObjects(esxVI_Context *ctx)
{
- char *hostSystemName = NULL;
/* Lookup Datacenter */
- if (esxVI_LookupDatacenter(ctx, parsedUri->path_datacenter,
- ctx->service->rootFolder, NULL, &ctx->datacenter,
+ if (esxVI_LookupDatacenter(ctx, NULL, ctx->service->rootFolder, NULL,
+ &ctx->datacenter,
esxVI_Occurrence_RequiredItem) < 0) {
return -1;
}
+ ctx->datacenterPath = strdup(ctx->datacenter->name);
+
+ if (ctx->datacenterPath == NULL) {
+ virReportOOMError();
+ return -1;
+ }
+
/* Lookup (Cluster)ComputeResource */
- if (esxVI_LookupComputeResource(ctx, parsedUri->path_computeResource,
- ctx->datacenter->hostFolder, NULL,
- &ctx->computeResource,
+ if (esxVI_LookupComputeResource(ctx, NULL, ctx->datacenter->hostFolder,
+ NULL, &ctx->computeResource,
esxVI_Occurrence_RequiredItem) < 0) {
return -1;
}
@@ -814,38 +821,240 @@ esxVI_Context_LookupObjectsByPath(esxVI_Context *ctx,
return -1;
}
+ ctx->computeResourcePath = strdup(ctx->computeResource->name);
+
+ if (ctx->computeResourcePath == NULL) {
+ virReportOOMError();
+ return -1;
+ }
+
/* Lookup HostSystem */
- if (parsedUri->path_hostSystem == NULL &&
- STREQ(ctx->computeResource->_reference->type,
- "ClusterComputeResource")) {
- ESX_VI_ERROR(VIR_ERR_INVALID_ARG, "%s",
- _("Path has to specify the host system"));
+ if (esxVI_LookupHostSystem(ctx, NULL, ctx->computeResource->_reference,
+ NULL, &ctx->hostSystem,
+ esxVI_Occurrence_RequiredItem) < 0) {
return -1;
}
- if (parsedUri->path_hostSystem != NULL ||
- (parsedUri->path_computeResource != NULL &&
- parsedUri->path_hostSystem == NULL)) {
- if (parsedUri->path_hostSystem != NULL) {
- hostSystemName = parsedUri->path_hostSystem;
+ ctx->hostSystemName = strdup(ctx->hostSystem->name);
+
+ if (ctx->hostSystemName == NULL) {
+ virReportOOMError();
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+esxVI_Context_LookupManagedObjectsByPath(esxVI_Context *ctx, const char *path)
+{
+ int result = -1;
+ char *tmp = NULL;
+ char *saveptr = NULL;
+ char *previousItem = NULL;
+ char *item = NULL;
+ virBuffer buffer = VIR_BUFFER_INITIALIZER;
+ esxVI_ManagedObjectReference *root = NULL;
+ esxVI_Folder *folder = NULL;
+
+ tmp = strdup(path);
+
+ if (tmp == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ /* Lookup Datacenter */
+ item = strtok_r(tmp, "/", &saveptr);
+
+ if (item == NULL) {
+ ESX_VI_ERROR(VIR_ERR_INVALID_ARG,
+ _("Path '%s' does not specify a datacenter"), path);
+ goto cleanup;
+ }
+
+ root = ctx->service->rootFolder;
+
+ while (ctx->datacenter == NULL && item != NULL) {
+ esxVI_Folder_Free(&folder);
+
+ /* Try to lookup item as a folder */
+ if (esxVI_LookupFolder(ctx, item, root, NULL, &folder,
+ esxVI_Occurrence_OptionalItem) < 0) {
+ goto cleanup;
+ }
+
+ if (folder != NULL) {
+ /* It's a folder, use it as new lookup root */
+ if (root != ctx->service->rootFolder) {
+ esxVI_ManagedObjectReference_Free(&root);
+ }
+
+ root = folder->_reference;
+ folder->_reference = NULL;
+ } else {
+ /* Try to lookup item as a datacenter */
+ if (esxVI_LookupDatacenter(ctx, item, root, NULL, &ctx->datacenter,
+ esxVI_Occurrence_OptionalItem) < 0) {
+ goto cleanup;
+ }
+ }
+
+ /* Build datacenter path */
+ if (virBufferUse(&buffer) > 0) {
+ virBufferAddChar(&buffer, '/');
+ }
+
+ virBufferAdd(&buffer, item, -1);
+
+ previousItem = item;
+ item = strtok_r(NULL, "/", &saveptr);
+ }
+
+ if (ctx->datacenter == NULL) {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Could not find datacenter specified in '%s'"), path);
+ goto cleanup;
+ }
+
+ if (virBufferError(&buffer)) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ ctx->datacenterPath = virBufferContentAndReset(&buffer);
+
+ /* Lookup (Cluster)ComputeResource */
+ if (item == NULL) {
+ ESX_VI_ERROR(VIR_ERR_INVALID_ARG,
+ _("Path '%s' does not specify a compute resource"), path);
+ goto cleanup;
+ }
+
+ if (root != ctx->service->rootFolder) {
+ esxVI_ManagedObjectReference_Free(&root);
+ }
+
+ root = ctx->datacenter->hostFolder;
+
+ while (ctx->computeResource == NULL && item != NULL) {
+ esxVI_Folder_Free(&folder);
+
+ /* Try to lookup item as a folder */
+ if (esxVI_LookupFolder(ctx, item, root, NULL, &folder,
+ esxVI_Occurrence_OptionalItem) < 0) {
+ goto cleanup;
+ }
+
+ if (folder != NULL) {
+ /* It's a folder, use it as new lookup root */
+ if (root != ctx->datacenter->hostFolder) {
+ esxVI_ManagedObjectReference_Free(&root);
+ }
+
+ root = folder->_reference;
+ folder->_reference = NULL;
} else {
- hostSystemName = parsedUri->path_computeResource;
+ /* Try to lookup item as a compute resource */
+ if (esxVI_LookupComputeResource(ctx, item, root, NULL,
+ &ctx->computeResource,
+ esxVI_Occurrence_OptionalItem) < 0) {
+ goto cleanup;
+ }
+ }
+
+ /* Build compute resource path */
+ if (virBufferUse(&buffer) > 0) {
+ virBufferAddChar(&buffer, '/');
+ }
+
+ virBufferAdd(&buffer, item, -1);
+
+ previousItem = item;
+ item = strtok_r(NULL, "/", &saveptr);
+ }
+
+ if (ctx->computeResource == NULL) {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Could not find compute resource specified in '%s'"),
+ path);
+ goto cleanup;
+ }
+
+ if (ctx->computeResource->resourcePool == NULL) {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not retrieve resource pool"));
+ goto cleanup;
+ }
+
+ if (virBufferError(&buffer)) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ ctx->computeResourcePath = virBufferContentAndReset(&buffer);
+
+ /* Lookup HostSystem */
+ if (STREQ(ctx->computeResource->_reference->type,
+ "ClusterComputeResource")) {
+ if (item == NULL) {
+ ESX_VI_ERROR(VIR_ERR_INVALID_ARG,
+ _("Path '%s' does not specify a host system"), path);
+ goto cleanup;
}
+
+ /* The path specified a cluster, it has to specify a host system too */
+ previousItem = item;
+ item = strtok_r(NULL, "/", &saveptr);
+ }
+
+ if (item != NULL) {
+ ESX_VI_ERROR(VIR_ERR_INVALID_ARG,
+ _("Path '%s' ends with an excess item"), path);
+ goto cleanup;
}
- if (esxVI_LookupHostSystem(ctx, hostSystemName,
+ ctx->hostSystemName = strdup(previousItem);
+
+ if (ctx->hostSystemName == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (esxVI_LookupHostSystem(ctx, ctx->hostSystemName,
ctx->computeResource->_reference, NULL,
&ctx->hostSystem,
- esxVI_Occurrence_RequiredItem) < 0) {
- return -1;
+ esxVI_Occurrence_OptionalItem) < 0) {
+ goto cleanup;
}
- return 0;
+ if (ctx->hostSystem == NULL) {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Could not find host system specified in '%s'"), path);
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ if (result < 0) {
+ virBufferFreeAndReset(&buffer);
+ }
+
+ if (root != ctx->service->rootFolder &&
+ (ctx->datacenter == NULL || root != ctx->datacenter->hostFolder)) {
+ esxVI_ManagedObjectReference_Free(&root);
+ }
+
+ VIR_FREE(tmp);
+ esxVI_Folder_Free(&folder);
+
+ return result;
}
int
-esxVI_Context_LookupObjectsByHostSystemIp(esxVI_Context *ctx,
- const char *hostSystemIpAddress)
+esxVI_Context_LookupManagedObjectsByHostSystemIp(esxVI_Context *ctx,
+ const char *hostSystemIpAddress)
{
int result = -1;
esxVI_ManagedObjectReference *managedObjectReference = NULL;
@@ -1491,8 +1700,7 @@ esxVI_BuildSelectSetCollection(esxVI_Context *ctx)
/* Folder -> childEntity (ManagedEntity) */
if (esxVI_BuildSelectSet(&ctx->selectSet_folderToChildEntity,
"folderToChildEntity",
- "Folder", "childEntity",
- "folderToChildEntity\0") < 0) {
+ "Folder", "childEntity", NULL) < 0) {
return -1;
}
@@ -1689,9 +1897,10 @@ esxVI_LookupObjectContentByType(esxVI_Context *ctx,
objectSpec->obj = root;
objectSpec->skip = esxVI_Boolean_False;
- if (STRNEQ(root->type, type)) {
+ if (STRNEQ(root->type, type) || STREQ(root->type, "Folder")) {
if (STREQ(root->type, "Folder")) {
- if (STREQ(type, "Datacenter") || STREQ(type, "ComputeResource") ||
+ if (STREQ(type, "Folder") || STREQ(type, "Datacenter") ||
+ STREQ(type, "ComputeResource") ||
STREQ(type, "ClusterComputeResource")) {
objectSpec->selectSet = ctx->selectSet_folderToChildEntity;
} else {
diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h
index 0b3f889b5..78d398609 100644
--- a/src/esx/esx_vi.h
+++ b/src/esx/esx_vi.h
@@ -204,8 +204,11 @@ struct _esxVI_Context {
esxVI_UserSession *session; /* ... except the session ... */
virMutexPtr sessionLock; /* ... that is protected by this mutex */
esxVI_Datacenter *datacenter;
+ char *datacenterPath; /* including folders */
esxVI_ComputeResource *computeResource;
+ char *computeResourcePath; /* including folders */
esxVI_HostSystem *hostSystem;
+ char *hostSystemName;
esxVI_SelectionSpec *selectSet_folderToChildEntity;
esxVI_SelectionSpec *selectSet_hostSystemToParent;
esxVI_SelectionSpec *selectSet_hostSystemToVm;
@@ -221,10 +224,10 @@ void esxVI_Context_Free(esxVI_Context **ctx);
int esxVI_Context_Connect(esxVI_Context *ctx, const char *ipAddress,
const char *url, const char *username,
const char *password, esxUtil_ParsedUri *parsedUri);
-int esxVI_Context_LookupObjectsByPath(esxVI_Context *ctx,
- esxUtil_ParsedUri *parsedUri);
-int esxVI_Context_LookupObjectsByHostSystemIp(esxVI_Context *ctx,
- const char *hostSystemIpAddress);
+int esxVI_Context_LookupManagedObjects(esxVI_Context *ctx);
+int esxVI_Context_LookupManagedObjectsByPath(esxVI_Context *ctx, const char *path);
+int esxVI_Context_LookupManagedObjectsByHostSystemIp(esxVI_Context *ctx,
+ const char *hostSystemIpAddress);
int esxVI_Context_Execute(esxVI_Context *ctx, const char *methodName,
const char *request, esxVI_Response **response,
esxVI_Occurrence occurrence);
diff --git a/src/esx/esx_vi_generator.input b/src/esx/esx_vi_generator.input
index 361a6e704..1a67a8cad 100644
--- a/src/esx/esx_vi_generator.input
+++ b/src/esx/esx_vi_generator.input
@@ -755,6 +755,10 @@ managed object Datacenter extends ManagedEntity
end
+managed object Folder extends ManagedEntity
+end
+
+
managed object HostSystem extends ManagedEntity
HostConfigManager configManager r
end