[libvirt] [PATCH] esx: Rework datastore path parsing and handling
by Matthias Bolte
Instead of splitting the path part of a datastore path into
directory and file name, keep this in one piece. An example:
"[datastore] directory/file"
was split into this before:
datastoreName = "datastore"
directoryName = "directory"
fileName = "file"
Now it's split into this:
datastoreName = "datastore"
directoryName = "directory"
directoryAndFileName = "directory/file"
This simplifies code using esxUtil_ParseDatastorePath, because
directoryAndFileName is used more often than fileName. Also the
old approach expected the datastore path to reference a actual
file, but this isn't always correct, especially when listing
volume. In that case esxUtil_ParseDatastorePath is used to parse
a path that references a directory. This fails for a vpx://
connection because the vCenter returns directory paths with a
trailing '/'. The new approach is robust against this and the
actual decision if the datastore path should reference a file or
a directory is up to the caller of esxUtil_ParseDatastorePath.
Update the tests accordingly.
---
src/esx/esx_driver.c | 90 +++++++++++++++++++-----------------------
src/esx/esx_storage_driver.c | 70 +++++++++-----------------------
src/esx/esx_util.c | 71 +++++++++++++++++++--------------
src/esx/esx_util.h | 2 +-
src/esx/esx_vi.c | 30 +++++++++++++-
tests/esxutilstest.c | 32 ++++++++------
tests/xml2vmxtest.c | 19 +++------
7 files changed, 155 insertions(+), 159 deletions(-)
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index 50d5bc0..eda3fc2 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -52,8 +52,7 @@ typedef struct _esxVMX_Data esxVMX_Data;
struct _esxVMX_Data {
esxVI_Context *ctx;
- const char *datastoreName;
- const char *directoryName;
+ char *datastorePathWithoutFileName;
};
@@ -117,8 +116,8 @@ esxParseVMXFileName(const char *fileName, void *opaque)
if (strchr(fileName, '/') == NULL && strchr(fileName, '\\') == NULL) {
/* Plain file name, use same directory as for the .vmx file */
- if (virAsprintf(&datastorePath, "[%s] %s/%s", data->datastoreName,
- data->directoryName, fileName) < 0) {
+ if (virAsprintf(&datastorePath, "%s/%s",
+ data->datastorePathWithoutFileName, fileName) < 0) {
virReportOOMError();
goto cleanup;
}
@@ -254,8 +253,7 @@ esxFormatVMXFileName(const char *datastorePath, void *opaque)
bool success = false;
esxVMX_Data *data = opaque;
char *datastoreName = NULL;
- char *directoryName = NULL;
- char *fileName = NULL;
+ char *directoryAndFileName = NULL;
esxVI_ObjectContent *datastore = NULL;
esxVI_DatastoreHostMount *hostMount = NULL;
char separator = '/';
@@ -265,13 +263,12 @@ esxFormatVMXFileName(const char *datastorePath, void *opaque)
char *absolutePath = NULL;
/* Parse datastore path and lookup datastore */
- if (esxUtil_ParseDatastorePath(datastorePath, &datastoreName,
- &directoryName, &fileName) < 0) {
+ if (esxUtil_ParseDatastorePath(datastorePath, &datastoreName, NULL,
+ &directoryAndFileName) < 0) {
goto cleanup;
}
- if (esxVI_LookupDatastoreByName(data->ctx, datastoreName,
- NULL, &datastore,
+ if (esxVI_LookupDatastoreByName(data->ctx, datastoreName, NULL, &datastore,
esxVI_Occurrence_RequiredItem) < 0 ||
esxVI_LookupDatastoreHostMount(data->ctx, datastore->obj,
&hostMount) < 0) {
@@ -290,29 +287,23 @@ esxFormatVMXFileName(const char *datastorePath, void *opaque)
--length;
}
- /* Format as <mount>[/<directory>]/<file> */
+ /* Format as <mount>[/<directory>]/<file>, convert / to \ when necessary */
virBufferAdd(&buffer, hostMount->mountInfo->path, length);
- if (directoryName != NULL) {
- /* Convert / to \ when necessary */
- if (separator != '/') {
- tmp = directoryName;
-
- while (*tmp != '\0') {
- if (*tmp == '/') {
- *tmp = separator;
- }
+ if (separator != '/') {
+ tmp = directoryAndFileName;
- ++tmp;
+ while (*tmp != '\0') {
+ if (*tmp == '/') {
+ *tmp = separator;
}
- }
- virBufferAddChar(&buffer, separator);
- virBufferAdd(&buffer, directoryName, -1);
+ ++tmp;
+ }
}
virBufferAddChar(&buffer, separator);
- virBufferAdd(&buffer, fileName, -1);
+ virBufferAdd(&buffer, directoryAndFileName, -1);
if (virBufferError(&buffer)) {
virReportOOMError();
@@ -332,8 +323,7 @@ esxFormatVMXFileName(const char *datastorePath, void *opaque)
}
VIR_FREE(datastoreName);
- VIR_FREE(directoryName);
- VIR_FREE(fileName);
+ VIR_FREE(directoryAndFileName);
esxVI_ObjectContent_Free(&datastore);
esxVI_DatastoreHostMount_Free(&hostMount);
@@ -2527,7 +2517,7 @@ esxDomainDumpXML(virDomainPtr domain, int flags)
char *vmPathName = NULL;
char *datastoreName = NULL;
char *directoryName = NULL;
- char *fileName = NULL;
+ char *directoryAndFileName = NULL;
virBuffer buffer = VIR_BUFFER_INITIALIZER;
char *url = NULL;
char *vmx = NULL;
@@ -2554,19 +2544,13 @@ esxDomainDumpXML(virDomainPtr domain, int flags)
}
if (esxUtil_ParseDatastorePath(vmPathName, &datastoreName, &directoryName,
- &fileName) < 0) {
+ &directoryAndFileName) < 0) {
goto cleanup;
}
virBufferVSprintf(&buffer, "%s://%s:%d/folder/", priv->transport,
domain->conn->uri->server, domain->conn->uri->port);
-
- if (directoryName != NULL) {
- virBufferURIEncodeString(&buffer, directoryName);
- virBufferAddChar(&buffer, '/');
- }
-
- virBufferURIEncodeString(&buffer, fileName);
+ virBufferURIEncodeString(&buffer, directoryAndFileName);
virBufferAddLit(&buffer, "?dcPath=");
virBufferURIEncodeString(&buffer, priv->primary->datacenter->name);
virBufferAddLit(&buffer, "&dsName=");
@@ -2584,8 +2568,20 @@ esxDomainDumpXML(virDomainPtr domain, int flags)
}
data.ctx = priv->primary;
- data.datastoreName = datastoreName;
- data.directoryName = directoryName;
+
+ if (directoryName == NULL) {
+ if (virAsprintf(&data.datastorePathWithoutFileName, "[%s]",
+ datastoreName) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ } else {
+ if (virAsprintf(&data.datastorePathWithoutFileName, "[%s] %s",
+ datastoreName, directoryName) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ }
ctx.opaque = &data;
ctx.parseFileName = esxParseVMXFileName;
@@ -2612,8 +2608,9 @@ esxDomainDumpXML(virDomainPtr domain, int flags)
esxVI_ObjectContent_Free(&virtualMachine);
VIR_FREE(datastoreName);
VIR_FREE(directoryName);
- VIR_FREE(fileName);
+ VIR_FREE(directoryAndFileName);
VIR_FREE(url);
+ VIR_FREE(data.datastorePathWithoutFileName);
VIR_FREE(vmx);
virDomainDefFree(def);
@@ -2640,8 +2637,7 @@ esxDomainXMLFromNative(virConnectPtr conn, const char *nativeFormat,
}
data.ctx = priv->primary;
- data.datastoreName = "?";
- data.directoryName = "?";
+ data.datastorePathWithoutFileName = (char *)"[?] ?";
ctx.opaque = &data;
ctx.parseFileName = esxParseVMXFileName;
@@ -2686,8 +2682,7 @@ esxDomainXMLToNative(virConnectPtr conn, const char *nativeFormat,
}
data.ctx = priv->primary;
- data.datastoreName = NULL;
- data.directoryName = NULL;
+ data.datastorePathWithoutFileName = NULL;
ctx.opaque = &data;
ctx.parseFileName = NULL;
@@ -2887,7 +2882,6 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml ATTRIBUTE_UNUSED)
esxVMX_Data data;
char *datastoreName = NULL;
char *directoryName = NULL;
- char *fileName = NULL;
virBuffer buffer = VIR_BUFFER_INITIALIZER;
char *url = NULL;
char *datastoreRelatedPath = NULL;
@@ -2927,8 +2921,7 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml ATTRIBUTE_UNUSED)
/* Build VMX from domain XML */
data.ctx = priv->primary;
- data.datastoreName = NULL;
- data.directoryName = NULL;
+ data.datastorePathWithoutFileName = NULL;
ctx.opaque = &data;
ctx.parseFileName = NULL;
@@ -2979,11 +2972,11 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml ATTRIBUTE_UNUSED)
}
if (esxUtil_ParseDatastorePath(disk->src, &datastoreName, &directoryName,
- &fileName) < 0) {
+ NULL) < 0) {
goto cleanup;
}
- if (! virFileHasSuffix(fileName, ".vmdk")) {
+ if (! virFileHasSuffix(disk->src, ".vmdk")) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting source '%s' of first file-based harddisk to "
"be a VMDK image"), disk->src);
@@ -3067,7 +3060,6 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml ATTRIBUTE_UNUSED)
VIR_FREE(vmx);
VIR_FREE(datastoreName);
VIR_FREE(directoryName);
- VIR_FREE(fileName);
VIR_FREE(url);
VIR_FREE(datastoreRelatedPath);
esxVI_ObjectContent_Free(&virtualMachine);
diff --git a/src/esx/esx_storage_driver.c b/src/esx/esx_storage_driver.c
index af8876a..d2d8f22 100644
--- a/src/esx/esx_storage_driver.c
+++ b/src/esx/esx_storage_driver.c
@@ -611,10 +611,8 @@ esxStoragePoolListStorageVolumes(virStoragePoolPtr pool, char **const names,
esxVI_HostDatastoreBrowserSearchResults *searchResultsList = NULL;
esxVI_HostDatastoreBrowserSearchResults *searchResults = NULL;
esxVI_FileInfo *fileInfo = NULL;
- char *datastoreName = NULL;
- char *directoryName = NULL;
- char *fileName = NULL;
- char *prefix = NULL;
+ char *directoryAndFileName = NULL;
+ int length;
int count = 0;
int i;
@@ -639,40 +637,32 @@ esxStoragePoolListStorageVolumes(virStoragePoolPtr pool, char **const names,
/* Interpret search result */
for (searchResults = searchResultsList; searchResults != NULL;
searchResults = searchResults->_next) {
- VIR_FREE(datastoreName);
- VIR_FREE(directoryName);
- VIR_FREE(fileName);
- VIR_FREE(prefix);
+ VIR_FREE(directoryAndFileName);
- if (esxUtil_ParseDatastorePath(searchResults->folderPath, &datastoreName,
- &directoryName, &fileName) < 0) {
+ if (esxUtil_ParseDatastorePath(searchResults->folderPath, NULL, NULL,
+ &directoryAndFileName) < 0) {
goto cleanup;
}
- if (directoryName != NULL) {
- if (virAsprintf(&prefix, "%s/%s", directoryName, fileName) < 0) {
- virReportOOMError();
- goto cleanup;
- }
- } else {
- prefix = strdup(fileName);
+ /* Strip trailing separators */
+ length = strlen(directoryAndFileName);
- if (prefix == NULL) {
- virReportOOMError();
- goto cleanup;
- }
+ while (length > 0 && directoryAndFileName[length - 1] == '/') {
+ directoryAndFileName[length - 1] = '\0';
+ --length;
}
+ /* Build volume names */
for (fileInfo = searchResults->file; fileInfo != NULL;
fileInfo = fileInfo->_next) {
- if (*prefix == '\0') {
+ if (length < 1) {
names[count] = strdup(fileInfo->path);
if (names[count] == NULL) {
virReportOOMError();
goto cleanup;
}
- } else if (virAsprintf(&names[count], "%s/%s", prefix,
+ } else if (virAsprintf(&names[count], "%s/%s", directoryAndFileName,
fileInfo->path) < 0) {
virReportOOMError();
goto cleanup;
@@ -694,10 +684,7 @@ esxStoragePoolListStorageVolumes(virStoragePoolPtr pool, char **const names,
}
esxVI_HostDatastoreBrowserSearchResults_Free(&searchResultsList);
- VIR_FREE(datastoreName);
- VIR_FREE(directoryName);
- VIR_FREE(fileName);
- VIR_FREE(prefix);
+ VIR_FREE(directoryAndFileName);
return count;
}
@@ -744,46 +731,29 @@ esxStorageVolumeLookupByKeyOrPath(virConnectPtr conn, const char *keyOrPath)
virStorageVolPtr volume = NULL;
esxPrivate *priv = conn->storagePrivateData;
char *datastoreName = NULL;
- char *directoryName = NULL;
- char *fileName = NULL;
- char *volumeName = NULL;
+ char *directoryAndFileName = NULL;
esxVI_FileInfo *fileInfo = NULL;
if (esxVI_EnsureSession(priv->primary) < 0) {
return NULL;
}
- if (esxUtil_ParseDatastorePath(keyOrPath, &datastoreName, &directoryName,
- &fileName) < 0) {
+ if (esxUtil_ParseDatastorePath(keyOrPath, &datastoreName, NULL,
+ &directoryAndFileName) < 0) {
goto cleanup;
}
- if (directoryName != NULL) {
- if (virAsprintf(&volumeName, "%s/%s", directoryName, fileName) < 0) {
- virReportOOMError();
- goto cleanup;
- }
- } else {
- volumeName = strdup(fileName);
-
- if (volumeName == NULL) {
- virReportOOMError();
- goto cleanup;
- }
- }
-
if (esxVI_LookupFileInfoByDatastorePath(priv->primary, keyOrPath, &fileInfo,
esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
- volume = virGetStorageVol(conn, datastoreName, volumeName, keyOrPath);
+ volume = virGetStorageVol(conn, datastoreName, directoryAndFileName,
+ keyOrPath);
cleanup:
VIR_FREE(datastoreName);
- VIR_FREE(directoryName);
- VIR_FREE(fileName);
- VIR_FREE(volumeName);
+ VIR_FREE(directoryAndFileName);
esxVI_FileInfo_Free(&fileInfo);
return volume;
diff --git a/src/esx/esx_util.c b/src/esx/esx_util.c
index 7c7c841..08c6c46 100644
--- a/src/esx/esx_util.c
+++ b/src/esx/esx_util.c
@@ -275,19 +275,19 @@ esxUtil_ParseVirtualMachineIDString(const char *id_string, int *id)
int
esxUtil_ParseDatastorePath(const char *datastorePath, char **datastoreName,
- char **directoryName, char **fileName)
+ char **directoryName, char **directoryAndFileName)
{
int result = -1;
char *copyOfDatastorePath = NULL;
char *tmp = NULL;
char *saveptr = NULL;
char *preliminaryDatastoreName = NULL;
- char *directoryAndFileName = NULL;
- char *separator = NULL;
+ char *preliminaryDirectoryAndFileName = NULL;
+ char *preliminaryFileName = NULL;
- if (datastoreName == NULL || *datastoreName != NULL ||
- directoryName == NULL || *directoryName != NULL ||
- fileName == NULL || *fileName != NULL) {
+ if ((datastoreName != NULL && *datastoreName != NULL) ||
+ (directoryName != NULL && *directoryName != NULL) ||
+ (directoryAndFileName != NULL && *directoryAndFileName != NULL)) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
return -1;
}
@@ -296,43 +296,46 @@ esxUtil_ParseDatastorePath(const char *datastorePath, char **datastoreName,
goto cleanup;
}
- /* Expected format: '[<datastore>] <path>' */
- if ((tmp = STRSKIP(copyOfDatastorePath, "[")) == NULL ||
- (preliminaryDatastoreName = strtok_r(tmp, "]", &saveptr)) == NULL ||
- (directoryAndFileName = strtok_r(NULL, "", &saveptr)) == NULL) {
+ /* Expected format: '[<datastore>] <path>' where <path> is optional */
+ if ((tmp = STRSKIP(copyOfDatastorePath, "[")) == NULL || *tmp == ']' ||
+ (preliminaryDatastoreName = strtok_r(tmp, "]", &saveptr)) == NULL) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Datastore path '%s' doesn't have expected format "
"'[<datastore>] <path>'"), datastorePath);
goto cleanup;
}
- if (esxVI_String_DeepCopyValue(datastoreName,
+ if (datastoreName != NULL &&
+ esxVI_String_DeepCopyValue(datastoreName,
preliminaryDatastoreName) < 0) {
goto cleanup;
}
- directoryAndFileName += strspn(directoryAndFileName, " ");
+ preliminaryDirectoryAndFileName = strtok_r(NULL, "", &saveptr);
- /* Split <path> into <directory>/<file>, where <directory> is optional */
- separator = strrchr(directoryAndFileName, '/');
+ if (preliminaryDirectoryAndFileName == NULL) {
+ preliminaryDirectoryAndFileName = (char *)"";
+ } else {
+ preliminaryDirectoryAndFileName +=
+ strspn(preliminaryDirectoryAndFileName, " ");
+ }
+
+ if (directoryAndFileName != NULL &&
+ esxVI_String_DeepCopyValue(directoryAndFileName,
+ preliminaryDirectoryAndFileName) < 0) {
+ goto cleanup;
+ }
- if (separator != NULL) {
- *separator++ = '\0';
+ if (directoryName != NULL) {
+ /* Split <path> into <directory>/<file> */
+ preliminaryFileName = strrchr(preliminaryDirectoryAndFileName, '/');
- if (*separator == '\0') {
- ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
- _("Datastore path '%s' doesn't reference a file"),
- datastorePath);
- goto cleanup;
+ if (preliminaryFileName != NULL) {
+ *preliminaryFileName++ = '\0';
}
if (esxVI_String_DeepCopyValue(directoryName,
- directoryAndFileName) < 0 ||
- esxVI_String_DeepCopyValue(fileName, separator) < 0) {
- goto cleanup;
- }
- } else {
- if (esxVI_String_DeepCopyValue(fileName, directoryAndFileName) < 0) {
+ preliminaryDirectoryAndFileName) < 0) {
goto cleanup;
}
}
@@ -341,9 +344,17 @@ esxUtil_ParseDatastorePath(const char *datastorePath, char **datastoreName,
cleanup:
if (result < 0) {
- VIR_FREE(*datastoreName);
- VIR_FREE(*directoryName);
- VIR_FREE(*fileName);
+ if (datastoreName != NULL) {
+ VIR_FREE(*datastoreName);
+ }
+
+ if (directoryName != NULL) {
+ VIR_FREE(*directoryName);
+ }
+
+ if (directoryAndFileName != NULL) {
+ VIR_FREE(*directoryAndFileName);
+ }
}
VIR_FREE(copyOfDatastorePath);
diff --git a/src/esx/esx_util.h b/src/esx/esx_util.h
index 5799730..4d92333 100644
--- a/src/esx/esx_util.h
+++ b/src/esx/esx_util.h
@@ -52,7 +52,7 @@ void esxUtil_FreeParsedUri(esxUtil_ParsedUri **parsedUri);
int esxUtil_ParseVirtualMachineIDString(const char *id_string, int *id);
int esxUtil_ParseDatastorePath(const char *datastorePath, char **datastoreName,
- char **directoryName, char **fileName);
+ char **directoryName, char **directoryAndFileName);
int esxUtil_ResolveHostname(const char *hostname,
char *ipAddress, size_t ipAddress_length);
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index 2359e8f..a6950fd 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -2946,7 +2946,9 @@ esxVI_LookupFileInfoByDatastorePath(esxVI_Context *ctx,
int result = -1;
char *datastoreName = NULL;
char *directoryName = NULL;
+ char *directoryAndFileName = NULL;
char *fileName = NULL;
+ int length;
char *datastorePathWithoutFileName = NULL;
esxVI_String *propertyNameList = NULL;
esxVI_ObjectContent *datastore = NULL;
@@ -2966,22 +2968,45 @@ esxVI_LookupFileInfoByDatastorePath(esxVI_Context *ctx,
}
if (esxUtil_ParseDatastorePath(datastorePath, &datastoreName,
- &directoryName, &fileName) < 0) {
+ &directoryName, &directoryAndFileName) < 0) {
goto cleanup;
}
- if (directoryName == NULL) {
+ if (STREQ(directoryName, directoryAndFileName)) {
+ /*
+ * The <path> part of the datatore path didn't contain a '/', assume
+ * that the <path> part is actually the file name.
+ */
if (virAsprintf(&datastorePathWithoutFileName, "[%s]",
datastoreName) < 0) {
virReportOOMError();
goto cleanup;
}
+
+ if (esxVI_String_DeepCopyValue(&fileName, directoryAndFileName) < 0) {
+ goto cleanup;
+ }
} else {
if (virAsprintf(&datastorePathWithoutFileName, "[%s] %s",
datastoreName, directoryName) < 0) {
virReportOOMError();
goto cleanup;
}
+
+ length = strlen(directoryName);
+
+ if (directoryAndFileName[length] != '/' ||
+ directoryAndFileName[length + 1] == '\0') {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Datastore path '%s' doesn't reference a file"),
+ datastorePath);
+ goto cleanup;
+ }
+
+ if (esxVI_String_DeepCopyValue(&fileName,
+ directoryAndFileName + length + 1) < 0) {
+ goto cleanup;
+ }
}
/* Lookup HostDatastoreBrowser */
@@ -3087,6 +3112,7 @@ esxVI_LookupFileInfoByDatastorePath(esxVI_Context *ctx,
VIR_FREE(datastoreName);
VIR_FREE(directoryName);
+ VIR_FREE(directoryAndFileName);
VIR_FREE(fileName);
VIR_FREE(datastorePathWithoutFileName);
esxVI_String_Free(&propertyNameList);
diff --git a/tests/esxutilstest.c b/tests/esxutilstest.c
index 09470ed..4906ad4 100644
--- a/tests/esxutilstest.c
+++ b/tests/esxutilstest.c
@@ -99,14 +99,18 @@ struct testPath {
int result;
const char *datastoreName;
const char *directoryName;
- const char *fileName;
+ const char *directoryAndFileName;
};
static struct testPath paths[] = {
- { "[datastore] directory/file", 0, "datastore", "directory", "file" },
- { "[datastore] file", 0, "datastore", NULL, "file" },
+ { "[datastore] directory/file", 0, "datastore", "directory",
+ "directory/file" },
+ { "[datastore] directory1/directory2/file", 0, "datastore",
+ "directory1/directory2", "directory1/directory2/file" },
+ { "[datastore] file", 0, "datastore", "file", "file" },
+ { "[datastore] directory/", 0, "datastore", "directory", "directory/" },
+ { "[datastore]", 0, "datastore", "", "" },
{ "[] directory/file", -1, NULL, NULL, NULL },
- { "[datastore] directory/", -1, NULL, NULL, NULL },
{ "directory/file", -1, NULL, NULL, NULL },
};
@@ -116,16 +120,16 @@ testParseDatastorePath(const void *data ATTRIBUTE_UNUSED)
int i, result = 0;
char *datastoreName = NULL;
char *directoryName = NULL;
- char *fileName = NULL;
+ char *directoryAndFileName = NULL;
for (i = 0; i < ARRAY_CARDINALITY(paths); ++i) {
VIR_FREE(datastoreName);
VIR_FREE(directoryName);
- VIR_FREE(fileName);
+ VIR_FREE(directoryAndFileName);
- if (esxUtil_ParseDatastorePath(paths[i].datastorePath,
- &datastoreName, &directoryName,
- &fileName) != paths[i].result) {
+ if (esxUtil_ParseDatastorePath
+ (paths[i].datastorePath, &datastoreName, &directoryName,
+ &directoryAndFileName) != paths[i].result) {
goto failure;
}
@@ -138,14 +142,14 @@ testParseDatastorePath(const void *data ATTRIBUTE_UNUSED)
goto failure;
}
- if (paths[i].directoryName != NULL &&
- STRNEQ(paths[i].directoryName, directoryName)) {
+ if (STRNEQ(paths[i].directoryName, directoryName)) {
virtTestDifference(stderr, paths[i].directoryName, directoryName);
goto failure;
}
- if (STRNEQ(paths[i].fileName, fileName)) {
- virtTestDifference(stderr, paths[i].fileName, fileName);
+ if (STRNEQ(paths[i].directoryAndFileName, directoryAndFileName)) {
+ virtTestDifference(stderr, paths[i].directoryAndFileName,
+ directoryAndFileName);
goto failure;
}
}
@@ -153,7 +157,7 @@ testParseDatastorePath(const void *data ATTRIBUTE_UNUSED)
cleanup:
VIR_FREE(datastoreName);
VIR_FREE(directoryName);
- VIR_FREE(fileName);
+ VIR_FREE(directoryAndFileName);
return result;
diff --git a/tests/xml2vmxtest.c b/tests/xml2vmxtest.c
index eed3ac0..71ce14a 100644
--- a/tests/xml2vmxtest.c
+++ b/tests/xml2vmxtest.c
@@ -148,24 +148,18 @@ testFormatVMXFileName(const char *src, void *opaque ATTRIBUTE_UNUSED)
{
bool success = false;
char *datastoreName = NULL;
- char *directoryName = NULL;
- char *fileName = NULL;
+ char *directoryAndFileName = NULL;
char *absolutePath = NULL;
if (STRPREFIX(src, "[")) {
/* Found potential datastore path */
- if (esxUtil_ParseDatastorePath(src, &datastoreName, &directoryName,
- &fileName) < 0) {
+ if (esxUtil_ParseDatastorePath(src, &datastoreName, NULL,
+ &directoryAndFileName) < 0) {
goto cleanup;
}
- if (directoryName == NULL) {
- virAsprintf(&absolutePath, "/vmfs/volumes/%s/%s", datastoreName,
- fileName);
- } else {
- virAsprintf(&absolutePath, "/vmfs/volumes/%s/%s/%s", datastoreName,
- directoryName, fileName);
- }
+ virAsprintf(&absolutePath, "/vmfs/volumes/%s/%s", datastoreName,
+ directoryAndFileName);
} else if (STRPREFIX(src, "/")) {
/* Found absolute path */
absolutePath = strdup(src);
@@ -182,8 +176,7 @@ testFormatVMXFileName(const char *src, void *opaque ATTRIBUTE_UNUSED)
}
VIR_FREE(datastoreName);
- VIR_FREE(directoryName);
- VIR_FREE(fileName);
+ VIR_FREE(directoryAndFileName);
return absolutePath;
}
--
1.7.0.4
14 years, 7 months
[libvirt] [PATCH] esx: Fix generator for string return values
by Matthias Bolte
Distinguish between strings as parameters (const char *)
and strings as return values (char **).
---
src/esx/esx_vi_generator.py | 19 +++++++++++++------
src/esx/esx_vi_methods.c | 22 ++++++++++++----------
2 files changed, 25 insertions(+), 16 deletions(-)
diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py
index be96a03..f9e8e11 100755
--- a/src/esx/esx_vi_generator.py
+++ b/src/esx/esx_vi_generator.py
@@ -52,9 +52,10 @@ class Parameter:
"SessionManager" : "sessionManager",
"VirtualDiskManager" : "virtualDiskManager" }
- def __init__(self, type, name, occurrence):
+ def __init__(self, type, name, occurrence, is_return_value = False):
self.type = type
self.occurrence = occurrence
+ self.is_return_value = is_return_value
if ':' in name and name.startswith("_this"):
self.name, self.autobind_type = name.split(":")
@@ -96,7 +97,7 @@ class Parameter:
def generate_return(self, offset = 0, end_of_line = ";"):
if self.occurrence == OCCURRENCE__IGNORED:
- raise ValueError("invalid function parameteroccurrence value '%s'" % self.occurrence)
+ raise ValueError("invalid function parameter occurrence value '%s'" % self.occurrence)
else:
string = " "
string += " " * offset
@@ -130,7 +131,10 @@ class Parameter:
if self.type == "String" and \
self.occurrence not in [OCCURRENCE__REQUIRED_LIST,
OCCURRENCE__OPTIONAL_LIST]:
- return "const char *"
+ if self.is_return_value:
+ return "char *"
+ else:
+ return "const char *"
elif self.is_enum():
return "esxVI_%s " % self.type
else:
@@ -227,9 +231,11 @@ class Method:
source += "),\n"
if self.returns is None:
- source += " void, None,\n"
+ source += " void, /* nothing */, None,\n"
+ elif self.returns.type == "String":
+ source += " String, Value, %s,\n" % self.returns.get_occurrence_short_enum()
else:
- source += " %s, %s,\n" % (self.returns.type, self.returns.get_occurrence_short_enum())
+ source += " %s, /* nothing */, %s,\n" % (self.returns.type, self.returns.get_occurrence_short_enum())
source += "{\n"
@@ -1054,7 +1060,8 @@ def parse_method(block):
report_error("line %d: invalid block header" % (number))
else:
returns = Parameter(type = header_items[3], name = "output",
- occurrence = header_items[4])
+ occurrence = header_items[4],
+ is_return_value = True)
parameters = []
diff --git a/src/esx/esx_vi_methods.c b/src/esx/esx_vi_methods.c
index a00561f..5967088 100644
--- a/src/esx/esx_vi_methods.c
+++ b/src/esx/esx_vi_methods.c
@@ -67,34 +67,34 @@
-#define ESX_VI__METHOD__DESERIALIZE_OUTPUT__None(_type) \
+#define ESX_VI__METHOD__DESERIALIZE_OUTPUT__None(_type, _suffix) \
/* nothing */
-#define ESX_VI__METHOD__DESERIALIZE_OUTPUT__RequiredItem(_type) \
- if (esxVI_##_type##_Deserialize(response->node, output) < 0) { \
+#define ESX_VI__METHOD__DESERIALIZE_OUTPUT__RequiredItem(_type, _suffix) \
+ if (esxVI_##_type##_Deserialize##_suffix(response->node, output) < 0) { \
goto cleanup; \
}
-#define ESX_VI__METHOD__DESERIALIZE_OUTPUT__RequiredList(_type) \
+#define ESX_VI__METHOD__DESERIALIZE_OUTPUT__RequiredList(_type, _suffix) \
if (esxVI_##_type##_DeserializeList(response->node, output) < 0) { \
goto cleanup; \
}
-#define ESX_VI__METHOD__DESERIALIZE_OUTPUT__OptionalItem(_type) \
+#define ESX_VI__METHOD__DESERIALIZE_OUTPUT__OptionalItem(_type, _suffix) \
if (response->node != NULL && \
- esxVI_##_type##_Deserialize(response->node, output) < 0) { \
+ esxVI_##_type##_Deserialize##_suffix(response->node, output) < 0) { \
goto cleanup; \
}
-#define ESX_VI__METHOD__DESERIALIZE_OUTPUT__OptionalList(_type) \
+#define ESX_VI__METHOD__DESERIALIZE_OUTPUT__OptionalList(_type, _suffix) \
if (response->node != NULL && \
esxVI_##_type##_DeserializeList(response->node, output) < 0) { \
goto cleanup; \
@@ -103,7 +103,8 @@
#define ESX_VI__METHOD(_name, _this_from_service, _parameters, _output_type, \
- _occurrence, _validate, _serialize) \
+ _deserialize_suffix, _occurrence, _validate, \
+ _serialize) \
int \
esxVI_##_name _parameters \
{ \
@@ -139,7 +140,8 @@
goto cleanup; \
} \
\
- ESX_VI__METHOD__DESERIALIZE_OUTPUT__##_occurrence(_output_type) \
+ ESX_VI__METHOD__DESERIALIZE_OUTPUT__##_occurrence \
+ (_output_type, _deserialize_suffix) \
\
result = 0; \
\
@@ -296,7 +298,7 @@ ESX_VI__METHOD(ValidateMigration, /* special _this */,
esxVI_ManagedObjectReference *pool, /* optional */
esxVI_ManagedObjectReference *host, /* optional */
esxVI_Event **output), /* optional, list */
- Event, OptionalList,
+ Event, /* nothing */, OptionalList,
{
ESX_VI__METHOD__PARAMETER__REQUIRE(vm)
},
--
1.7.0.4
14 years, 7 months
[libvirt] Need help, how can I access to qemu-monitor with libvirt 0.8.1
by Lai Jiangshan
Hi, all
I encounter this problem when I try to send NMI to guest.
I don't know how. I think if I can access to the qemu-monitor, I can
just do this command in the qemu-monitor: "nmi <cpu#>".
But I don't know how to access to qemu-monitor, I think I can
get help here.
I noticed that the guest is started by libvirt with these parameters:
-chardev socket,id=monitor,path=/var/lib/libvirt/qemu/vm~laijs.monitor,server,nowait \
-mon chardev=monitor,mode=control
So I wrote a simple program and tried to access qemu-monitor by accessing the socket
/var/lib/libvirt/qemu/vm~laijs.monitor. It failed, because I don't know how
to send commands with "mode=control", I don't know the protocol for exchanging
data with this file.
(If I start guest with the same parameters as libvirt but using "mode=readline",
I successfully sent commands to qemu-monitor by my simple program, I just
send text commands)
I noticed that libvirt 0.8.3 supports remote protocol and arbitrary qemu commands,
but I did not found any document, how can I use it?
Thanks, Lai,
(I'm not in this email-list:libvir-list@redhat.com, please ensure my email address
in your cc-list when you reply, thanks)
14 years, 7 months
[libvirt] [PATCH] virsh: remove driver check from attach-disk command
by Ryan Harper
Virsh shouldn't check for driver support but rather let the backend handled this.
After removing the check, I can successfully attach file-based images to a qemu
VM with attach-disk.
% virsh attach-disk vm2 /images/test02.img vdc --driver qemu --type disk --subdriver raw
Disk attached successfully
This command generates the following XML:
<disk type='block' device='disk'>
<driver name='qemu' type='raw'/>
<source dev='/images/test02.img'/>
<target dev='vdc' bus='virtio'/>
<alias name='virtio-disk2'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/>
</disk>
Signed-off-by: Ryan Harper <ryanh(a)us.ibm.com>
diff --git a/tools/virsh.c b/tools/virsh.c
index c0ee3ee..7bc33d8 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -8146,13 +8146,8 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
mode = vshCommandOptString(cmd, "mode", NULL);
if (driver) {
- if (STREQ(driver, "file") || STREQ(driver, "tap")) {
+ if (STREQ(driver, "file") || STREQ(driver, "tap"))
isFile = 1;
- } else if (STRNEQ(driver, "phy")) {
- vshError(ctl, _("No support for %s in command 'attach-disk'"),
- driver);
- goto cleanup;
- }
}
if (mode) {
--
Ryan Harper
Software Engineer; Linux Technology Center
IBM Corp., Austin, Tx
ryanh(a)us.ibm.com
14 years, 7 months
[libvirt] [PATCH] Explicitly pass uml_dir argument to user-mode-linux
by Soren Hansen
uml_dir overrides user-mode-linux's default of ~/.uml. This is needed
for a couple of different reasons:
libvirt expects this to default to virGetUserDirectory(geteuid()) +
'/.uml'. However, user-mode-linux actually uses the HOME environment
variable to determine where to look for the uml sockets, but if running
libvirtd under sudo (which I routinely do during development), $HOME is
pointing at my user's homedir, while my euid is 0, so libvirt looks in
/root.
Also (and this was my actual motivation for this patch), if HOME isn't
set at all, user-mode-linux utterly fails. Looking at the code, it seems
it's meant to emit a warning, but alas, it doesn't for some reason.
If running libvirtd from upstart, HOME is not set, so any system using
upstart will need this change.
Signed-off-by: Soren Hansen <soren(a)linux2go.dk>
---
src/uml/uml_conf.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/uml/uml_conf.c b/src/uml/uml_conf.c
index 65b06c5..4906192 100644
--- a/src/uml/uml_conf.c
+++ b/src/uml/uml_conf.c
@@ -409,7 +409,7 @@ static char *umlNextArg(char *args)
* for a given virtual machine.
*/
int umlBuildCommandLine(virConnectPtr conn,
- struct uml_driver *driver ATTRIBUTE_UNUSED,
+ struct uml_driver *driver,
virDomainObjPtr vm,
fd_set *keepfd,
const char ***retargv,
@@ -499,7 +499,6 @@ int umlBuildCommandLine(virConnectPtr conn,
ADD_ENV_COPY("LD_PRELOAD");
ADD_ENV_COPY("LD_LIBRARY_PATH");
ADD_ENV_COPY("PATH");
- ADD_ENV_COPY("HOME");
ADD_ENV_COPY("USER");
ADD_ENV_COPY("LOGNAME");
ADD_ENV_COPY("TMPDIR");
@@ -508,6 +507,7 @@ int umlBuildCommandLine(virConnectPtr conn,
//ADD_ARG_PAIR("con0", "fd:0,fd:1");
ADD_ARG_PAIR("mem", memory);
ADD_ARG_PAIR("umid", vm->def->name);
+ ADD_ARG_PAIR("uml_dir", driver->monitorDir);
if (vm->def->os.root)
ADD_ARG_PAIR("root", vm->def->os.root);
--
1.7.0.4
14 years, 7 months
[libvirt] virsh create and virsh dumpxml certain code location
by benian
Hi all,
My libivrt is libvirt-0.8.3
I would like to add "tap2" recognition when using virsh create and dumpxml,
but i could not find the certain function part that the logic of "create"
and "dumpxml" are defined,
Would anyone please give me some hints?
Thanks Very Much
Regards,
Ben
14 years, 7 months
[libvirt] [PATCH] maint: track moved file
by Eric Blake
* daemon/.gitignore: Move libvirt-guests.init...
* tools/.gitignore: ...to its new location.
---
Pushing under the obvious rule, as fallout from 2c090a555.
daemon/.gitignore | 1 -
tools/.gitignore | 1 +
2 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/daemon/.gitignore b/daemon/.gitignore
index 4475b6d..8ed7784 100644
--- a/daemon/.gitignore
+++ b/daemon/.gitignore
@@ -7,7 +7,6 @@ Makefile.in
libvirt_qemud
libvirtd
libvirtd.init
-libvirt-guests.init
libvirtd*.logrotate
libvirtd.pod
libvirtd.8
diff --git a/tools/.gitignore b/tools/.gitignore
index 51f1f66..3e34ea8 100644
--- a/tools/.gitignore
+++ b/tools/.gitignore
@@ -1,3 +1,4 @@
+libvirt-guests.init
virt-xml-validate
virt-pki-validate
*.1
--
1.7.2.2
14 years, 7 months
[libvirt] Decent How-To now on the wiki for setting up Transport Layer Security
by Justin Clift
Hi all,
For anyone that's interested in setting up TLS with libvirt, but hasn't
gotten around to it yet, there's a decent guide on the wiki now:
http://wiki.libvirt.org/page/TLSSetup
It's user focused (ie SysAdmin's), and has lots of pics explaining
concepts, plus shows what needs to be done, and shows how to do it.
Please note, it doesn't cover SASL, it's just plain host based TLS.
Very much open to feedback on it, if people have suggestions for
improvement.
Hope that helps. :)
Regards and best wishes,
Justin Clift
14 years, 7 months