[libvirt] [PATCH] Fix tunnelled migration with qemu running as qemu:qemu.
by Chris Lalancette
The problem is that on the source of the migration, libvirtd
is responsible for creating the unix socket over which the data
will flow. Since libvirtd is running as root, this file will
be created as root. When the qemu process running as qemu:qemu
goes to access the unix file to write data to it, it will get
permission denied and fail. Make sure to change the owner
of the unix file to qemu:qemu.
Thanks to Justin Clift for testing this patch out for me.
Signed-off-by: Chris Lalancette <clalance(a)redhat.com>
---
src/qemu/qemu_driver.c | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 3dfd1ae..b6b6633 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -10975,6 +10975,13 @@ static int doTunnelMigrate(virDomainPtr dom,
goto cleanup;
}
+ if (chown(unixfile, qemu_driver->user, qemu_driver->group) < 0) {
+ virReportSystemError(errno,
+ _("Cannot change unix socket '%s' owner"),
+ unixfile);
+ goto cleanup;
+ }
+
/* check that this qemu version supports the unix migration */
if (qemudExtractVersionInfo(vm->def->emulator, NULL, &qemuCmdFlags) < 0) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
--
1.7.2.1
14 years, 3 months
[libvirt] [PATCH] Fix valgrind complaints when using kill -SIGHUP on libvirtd
by Stefan Berger
This patch fixes a couple of complaints from valgrind when tickling
libvirtd with SIGHUP.
The first two files contain fixes for memory leaks. The 3rd one
initializes an uninitialized variable. The 4th one is another memory leak.
Here are some example valgrind outputs (not in order of patch addressing
it):
==5261== 43 bytes in 1 blocks are definitely lost in loss record 347 of 573
==5261== at 0x4A0515D: malloc (vg_replace_malloc.c:195)
==5261== by 0x327607FD51: strdup (in /lib64/libc-2.12.so)
==5261== by 0x4E865DF: virStoragePoolLoadAllConfigs (storage_conf.c:1413)
==5261== by 0x48A759: storageDriverStartup (storage_driver.c:168)
==5261== by 0x4EA4D2F: virStateInitialize (libvirt.c:978)
==5261== by 0x41E190: main (libvirtd.c:3241)
==5261==
==5261== 43 bytes in 1 blocks are definitely lost in loss record 348 of 573
==5261== at 0x4A0515D: malloc (vg_replace_malloc.c:195)
==5261== by 0x327607FD51: strdup (in /lib64/libc-2.12.so)
==5261== by 0x4E865DF: virStoragePoolLoadAllConfigs (storage_conf.c:1413)
==5261== by 0x48A551: storageDriverReload (storage_driver.c:198)
==5261== by 0x4E9566D: virStateReload (libvirt.c:1017)
==5261== by 0x418870: qemudDispatchSignalEvent (libvirtd.c:388)
==5261== by 0x418538: virEventRunOnce (event.c:479)
==5261== by 0x41A1D5: qemudOneLoop (libvirtd.c:2215)
==5261== by 0x41A4A2: qemudRunLoop (libvirtd.c:2324)
==5261== by 0x3276807760: start_thread (in /lib64/libpthread-2.12.so)
==5261== by 0x32760E14EC: clone (in /lib64/libc-2.12.so)
[...]
==5261== Conditional jump or move depends on uninitialised value(s)
==5261== at 0x437E66: virPipeReadUntilEOF (util.c:966)
==5261== by 0x439467: virRunWithHook (util.c:829)
==5261== by 0x4A821F: ebiptablesExecCLI
(nwfilter_ebiptables_driver.c:2312)
==5261== by 0x4A8728: ebiptablesTearOldRules
(nwfilter_ebiptables_driver.c:3218)
[...]
==21871== 841 bytes in 20 blocks are definitely lost in loss record 552
of 577
==21871== at 0x4A0515D: malloc (vg_replace_malloc.c:195)
==21871== by 0x327607FD51: strdup (in /lib64/libc-2.12.so)
==21871== by 0x4E7FD34: virNWFilterPoolLoadAllConfigs
(nwfilter_conf.c:2242)
==21871== by 0x4A5406: nwfilterDriverStartup (nwfilter_driver.c:111)
==21871== by 0x4EA4D5F: virStateInitialize (libvirt.c:978)
==21871== by 0x41E190: main (libvirtd.c:3241)
[...]
==12889== at 0x4A04481: calloc (vg_replace_malloc.c:418)
==12889== by 0x434D2D: virAlloc (memory.c:100)
==12889== by 0x4E8E0A1: x86MapLoadCallback (cpu_x86.c:473)
==12889== by 0x4E90ED0: cpuMapLoad (cpu_map.c:58)
==12889== by 0x4E8DACE: x86LoadMap (cpu_x86.c:1131)
==12889== by 0x4E901DB: x86Decode (cpu_x86.c:1313)
==12889== by 0x45F4F8: qemudCapsInit (qemu_conf.c:1056)
==12889== by 0x440FBF: qemuCreateCapabilities (qemu_driver.c:1553)
==12889== by 0x44165F: qemudStartup (qemu_driver.c:1856)
==12889== by 0x4EA4D3F: virStateInitialize (libvirt.c:978)
==12889== by 0x41E190: main (libvirtd.c:3241)
Signed-off-by: Stefan Berger <stefanb(a)us.ibm.com>
---
src/conf/nwfilter_conf.c | 1 +
src/conf/storage_conf.c | 2 ++
src/util/util.c | 2 ++
3 files changed, 5 insertions(+)
Index: libvirt-acl/src/conf/nwfilter_conf.c
===================================================================
--- libvirt-acl.orig/src/conf/nwfilter_conf.c
+++ libvirt-acl/src/conf/nwfilter_conf.c
@@ -2239,6 +2239,7 @@ virNWFilterPoolObjLoad(virConnectPtr con
return NULL;
}
+ VIR_FREE(pool->configFile); // for driver reload
pool->configFile = strdup(path);
if (pool->configFile == NULL) {
virReportOOMError();
Index: libvirt-acl/src/conf/storage_conf.c
===================================================================
--- libvirt-acl.orig/src/conf/storage_conf.c
+++ libvirt-acl/src/conf/storage_conf.c
@@ -1403,12 +1403,14 @@ virStoragePoolObjLoad(virStoragePoolObjL
return NULL;
}
+ VIR_FREE(pool->configFile); // for driver reload
pool->configFile = strdup(path);
if (pool->configFile == NULL) {
virReportOOMError();
virStoragePoolDefFree(def);
return NULL;
}
+ VIR_FREE(pool->autostartLink); // for driver reload
pool->autostartLink = strdup(autostartLink);
if (pool->autostartLink == NULL) {
virReportOOMError();
Index: libvirt-acl/src/util/util.c
===================================================================
--- libvirt-acl.orig/src/util/util.c
+++ libvirt-acl/src/util/util.c
@@ -941,9 +941,11 @@ virPipeReadUntilEOF(int outfd, int errfd
fds[0].fd = outfd;
fds[0].events = POLLIN;
+ fds[0].revents = 0;
finished[0] = 0;
fds[1].fd = errfd;
fds[1].events = POLLIN;
+ fds[1].revents = 0;
finished[1] = 0;
while(!(finished[0] && finished[1])) {
Index: libvirt-acl/src/cpu/cpu_x86.c
===================================================================
--- libvirt-acl.orig/src/cpu/cpu_x86.c
+++ libvirt-acl/src/cpu/cpu_x86.c
@@ -1092,6 +1092,12 @@ x86MapFree(struct x86_map *map)
x86ModelFree(model);
}
+ while (map->vendors != NULL) {
+ struct x86_vendor *vendor = map->vendors;
+ map->vendors = vendor->next;
+ x86VendorFree(vendor);
+ }
+
VIR_FREE(map);
}
14 years, 3 months
[libvirt] [PATCH] qemu: do not ask for balloon information if not used
by Daniel Veillard
Basically a followup of the previous patch about balloon desactivation
if desactivated, to not ask for balloon information to qemu as we will
just get an error back.
This can make a huge difference in the time needed for domain
information or list when a machine is loaded, and balloon has been
desactivated in the guests.
Note that the patch does a check in the GetDomainInfo function, to avoid
checking for job, getting a job, getting the monitor lock and cleaning
back which would be added operations if I had done this one level
down in qemuMonitorGetBalloonInfo()
The qemudDomainDumpXML() function also call qemuMonitorGetBalloonInfo()
so maybe the check should be duplicated there, I left that out of the
patch for now as this is an operation which sounds less time critical.
Or maybe the test should be added to qemuMonitorGetBalloonInfo() too
since it's exported from src/qemu/qemu_monitor.h and may end up being
used from other places in the future,
opinions ?
Daniel
--
Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
daniel(a)veillard.com | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library http://libvirt.org/
14 years, 3 months
[libvirt] [PATCH] bridge: Add --dhcp-no-override option to dnsmasq
by Jiri Denemark
--dhcp-no-override description from dnsmasq man page:
Disable re-use of the DHCP servername and filename fields as
extra option space. If it can, dnsmasq moves the boot server and
filename information (from dhcp-boot) out of their dedicated
fields into DHCP options. This make extra space available in the
DHCP packet for options but can, rarely, confuse old or broken
clients. This flag forces "simple and safe" behaviour to avoid
problems in such a case.
It seems some virtual network card ROMs are this old/buggy so let's add
--dhcp-no-override as a workaround for them. We don't use extra DHCP
options so this should be safe.
---
src/network/bridge_driver.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index f247a0f..d6d3068 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -427,6 +427,8 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network,
(2 * network->def->nranges) + /* --dhcp-range 10.0.0.2,10.0.0.254 */
/* --dhcp-lease-max=xxx if needed */
(network->def->nranges ? 1 : 0) +
+ /* --dhcp-no-override if needed */
+ (network->def->nranges ? 1 : 0) +
/* --dhcp-hostsfile=/var/lib/dnsmasq/$NAME.hostsfile */
(network->def->nhosts > 0 ? 1 : 0) +
/* --enable-tftp --tftp-root /srv/tftp */
@@ -497,6 +499,7 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network,
if (network->def->nranges > 0) {
snprintf(buf, sizeof(buf), "--dhcp-lease-max=%d", nbleases);
APPEND_ARG(*argv, i++, buf);
+ APPEND_ARG(*argv, i++, "--dhcp-no-override");
}
if (network->def->nhosts > 0) {
--
1.7.2
14 years, 3 months
[libvirt] [PATCH 0/3] A couple of UML-related fixes
by Soren Hansen
I've been trying to get UML working for the last couple of days. As it stands,
at least bridged networking doesn't work for me. I've got a fix, but I'm not
sure I'm doing it right.
I can get it to fail in three distinct ways:
* With the current code, it seems that the tap device disappears almost
immediately. This happens becuase the call to brAddTap includes an
(int *)tapfd argument, so the tap device isn't persistent. A few
lines after brAddTap, close(tapfd) is called and the tap device goes
missing.
* Passing a NULL tapfd argument to brAddTap and removing the call to
close(tapfd) makes the tapfd persist, but when the uml domain
attempts to bring up the interface, it fails with EBUSY. This turns
out to be because brAddTap marks the tap device persistent, but
doesn't close the fd, so both libvirt and uml have the fd open and
that's doesn't work out well.
* Finally, I tried passing the tapfd result back up the call chain so
that I have a list of them that I could tell virExecDaemonize to keep
open and then close them in libvirt after the fork. I think this is
when I got EPERM when trying to bring the interface up in UML domain,
but I'm not sure right now.
Also, I've had problems connecting to the domain's console.
These three patches seem to fix everything for me.
Soren Hansen (3):
Close fd's of persistent tap devices
Make umlConnectTapDevice ask brAddTap for a persistent tap device.
Remove wrong check for uml monitor response size
src/uml/uml_conf.c | 6 +-----
src/uml/uml_driver.c | 4 ----
src/util/bridge.c | 2 ++
3 files changed, 3 insertions(+), 9 deletions(-)
14 years, 3 months
[libvirt] [PATCH] esx: Improve VMX file name parsing and formatting
by Matthias Bolte
For parsing try to match by datastore mount path first, if that
fails fallback to /vmfs/volumes/<datastore>/<path> parsing. This
also fixes problems with GSX on Windows. Because GSX on Windows
doesn't use /vmfs/volumes/ style file names.
For formatting use the datastore mount path too, instead of using
/vmfs/volumes/<datastore>/<path> as fixed format.
---
src/esx/esx_driver.c | 372 +++++++++++++++++++++++++++++++------------------
1 files changed, 235 insertions(+), 137 deletions(-)
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index b0ef704..322c588 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -24,8 +24,6 @@
#include <config.h>
-#include <netdb.h>
-
#include "internal.h"
#include "domain_conf.h"
#include "authhelper.h"
@@ -60,190 +58,290 @@ struct _esxVMX_Data {
-static char *
-esxAbsolutePathToDatastorePath(esxVI_Context *ctx, const char *absolutePath)
-{
- bool success = false;
- char *copyOfAbsolutePath = NULL;
- char *tmp = NULL;
- char *saveptr = NULL;
- esxVI_String *propertyNameList = NULL;
- esxVI_ObjectContent *datastore = NULL;
-
- char *datastorePath = NULL;
- char *preliminaryDatastoreName = NULL;
- char *directoryAndFileName = NULL;
- char *datastoreName = NULL;
-
- if (esxVI_String_DeepCopyValue(©OfAbsolutePath, absolutePath) < 0) {
- return NULL;
- }
-
- /* Expected format: '/vmfs/volumes/<datastore>/<path>' */
- if ((tmp = STRSKIP(copyOfAbsolutePath, "/vmfs/volumes/")) == NULL ||
- (preliminaryDatastoreName = strtok_r(tmp, "/", &saveptr)) == NULL ||
- (directoryAndFileName = strtok_r(NULL, "", &saveptr)) == NULL) {
- ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
- _("Absolute path '%s' doesn't have expected format "
- "'/vmfs/volumes/<datastore>/<path>'"), absolutePath);
- goto cleanup;
- }
-
- if (esxVI_String_AppendValueToList(&propertyNameList,
- "summary.name") < 0 ||
- esxVI_LookupDatastoreByAbsolutePath(ctx, absolutePath,
- propertyNameList, &datastore,
- esxVI_Occurrence_OptionalItem) < 0) {
- goto cleanup;
- }
-
- if (datastore == NULL) {
- if (esxVI_LookupDatastoreByName(ctx, preliminaryDatastoreName,
- propertyNameList, &datastore,
- esxVI_Occurrence_OptionalItem) < 0) {
- goto cleanup;
- }
- }
-
- if (datastore != NULL) {
- if (esxVI_GetStringValue(datastore, "summary.name", &datastoreName,
- esxVI_Occurrence_RequiredItem)) {
- goto cleanup;
- }
- }
-
- if (datastoreName == NULL) {
- VIR_WARN("Could not retrieve datastore name for absolute "
- "path '%s', falling back to preliminary name '%s'",
- absolutePath, preliminaryDatastoreName);
-
- datastoreName = preliminaryDatastoreName;
- }
-
- if (virAsprintf(&datastorePath, "[%s] %s", datastoreName,
- directoryAndFileName) < 0) {
- virReportOOMError();
- goto cleanup;
- }
-
- /* FIXME: Check if referenced path/file really exists */
-
- success = true;
-
- cleanup:
- if (! success) {
- VIR_FREE(datastorePath);
- }
-
- VIR_FREE(copyOfAbsolutePath);
- esxVI_String_Free(&propertyNameList);
- esxVI_ObjectContent_Free(&datastore);
-
- return datastorePath;
-}
-
-
-
+/*
+ * Parse a file name from a .vmx file and convert it to datastore path format.
+ * A .vmx file can contain file names in various formats:
+ *
+ * - A single name referencing a file in the same directory as the .vmx file:
+ *
+ * test1.vmdk
+ *
+ * - An absolute file name referencing a file in a datastore that is mounted at
+ * /vmfs/volumes/<datastore>:
+ *
+ * /vmfs/volumes/b24b7a78-9d82b4f5/test1/test1.vmdk
+ * /vmfs/volumes/datastore1/test1/test1.vmdk
+ *
+ * The actual mount directory is /vmfs/volumes/b24b7a78-9d82b4f5, the second
+ * form is a symlink to it using the datastore name. This is the typical
+ * setup on an ESX(i) server.
+ *
+ * - With GSX installed on Windows there are also Windows style file names
+ * including UNC file names:
+ *
+ * C:\Virtual Machines\test1\test1.vmdk
+ * \\nas1\storage1\test1\test1.vmdk
+ *
+ * The datastore path format typically looks like this:
+ *
+ * [datastore1] test1/test1.vmdk
+ *
+ * Firstly this functions checks if the given file name contains a separator.
+ * If it doesn't then the referenced file is in the same directory as the .vmx
+ * file. The datastore name and directory of the .vmx file are passed to this
+ * function via the opaque paramater by the caller of esxVMX_ParseConfig.
+ *
+ * Otherwise query for all known datastores and their mount directories. Then
+ * try to find a datastore with a mount directory that is a prefix to the given
+ * file name. This mechanism covers the Windows style file names too.
+ *
+ * The symlinks using the datastore name (/vmfs/volumes/datastore1) are an
+ * exception and need special handling. Parse the datastore name and use it
+ * to lookup the datastore by name to verify that it exists.
+ */
static char *
esxParseVMXFileName(const char *fileName, void *opaque)
{
- char *src = NULL;
+ char *datastorePath = NULL;
esxVMX_Data *data = opaque;
-
- if (STRPREFIX(fileName, "/vmfs/volumes/")) {
- /* Found absolute path referencing a file inside a datastore */
- return esxAbsolutePathToDatastorePath(data->ctx, fileName);
- } else if (STRPREFIX(fileName, "/")) {
- /* Found absolute path referencing a file outside a datastore */
- src = strdup(fileName);
-
- if (src == NULL) {
- virReportOOMError();
- return NULL;
- }
-
- /* FIXME: Check if referenced path/file really exists */
-
- return src;
- } else if (strchr(fileName, '/') != NULL) {
- /* Found relative path, this is not supported */
- ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
- _("Found relative path '%s' in VMX file, this is not "
- "supported"), fileName);
- return NULL;
- } else {
- /* Found single file name referencing a file inside a datastore */
- if (virAsprintf(&src, "[%s] %s/%s", data->datastoreName,
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *datastoreList = NULL;
+ esxVI_ObjectContent *datastore = NULL;
+ esxVI_DatastoreHostMount *hostMount = NULL;
+ char *datastoreName;
+ char *tmp;
+ char *saveptr;
+ char *strippedFileName = NULL;
+ char *copyOfFileName = NULL;
+ char *directoryAndFileName;
+
+ 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) {
virReportOOMError();
+ goto cleanup;
+ }
+ } else {
+ if (esxVI_String_AppendValueToList(&propertyNameList,
+ "summary.name") < 0 ||
+ esxVI_LookupDatastoreList(data->ctx, propertyNameList,
+ &datastoreList) < 0) {
return NULL;
}
- /* FIXME: Check if referenced path/file really exists */
+ /* Search for datastore by mount path */
+ for (datastore = datastoreList; datastore != NULL;
+ datastore = datastore->_next) {
+ esxVI_DatastoreHostMount_Free(&hostMount);
+ datastoreName = NULL;
- return src;
+ if (esxVI_LookupDatastoreHostMount(data->ctx, datastore->obj,
+ &hostMount) < 0 ||
+ esxVI_GetStringValue(datastore, "summary.name", &datastoreName,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ tmp = (char *)STRSKIP(fileName, hostMount->mountInfo->path);
+
+ if (tmp == NULL) {
+ continue;
+ }
+
+ /* Found a match. Strip leading separators */
+ while (*tmp == '/' || *tmp == '\\') {
+ ++tmp;
+ }
+
+ if (esxVI_String_DeepCopyValue(&strippedFileName, tmp) < 0) {
+ goto cleanup;
+ }
+
+ tmp = strippedFileName;
+
+ /* Convert \ to / */
+ while (*tmp != '\0') {
+ if (*tmp == '\\') {
+ *tmp = '/';
+ }
+
+ ++tmp;
+ }
+
+ if (virAsprintf(&datastorePath, "[%s] %s", datastoreName,
+ strippedFileName) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ break;
+ }
+
+ /* Fallback to direct datastore name match */
+ if (datastorePath == NULL && STRPREFIX(fileName, "/vmfs/volumes/")) {
+ if (esxVI_String_DeepCopyValue(©OfFileName, fileName) < 0) {
+ goto cleanup;
+ }
+
+ /* Expected format: '/vmfs/volumes/<datastore>/<path>' */
+ if ((tmp = STRSKIP(copyOfFileName, "/vmfs/volumes/")) == NULL ||
+ (datastoreName = strtok_r(tmp, "/", &saveptr)) == NULL ||
+ (directoryAndFileName = strtok_r(NULL, "", &saveptr)) == NULL) {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("File name '%s' doesn't have expected format "
+ "'/vmfs/volumes/<datastore>/<path>'"), fileName);
+ goto cleanup;
+ }
+
+ esxVI_ObjectContent_Free(&datastoreList);
+
+ if (esxVI_LookupDatastoreByName(data->ctx, datastoreName,
+ NULL, &datastoreList,
+ esxVI_Occurrence_OptionalItem) < 0) {
+ goto cleanup;
+ }
+
+ if (datastoreList == NULL) {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("File name '%s' refers to non-existing datastore '%s'"),
+ fileName, datastoreName);
+ goto cleanup;
+ }
+
+ if (virAsprintf(&datastorePath, "[%s] %s", datastoreName,
+ directoryAndFileName) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ }
+
+ if (datastorePath == NULL) {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Could not find datastore for '%s'"), fileName);
+ goto cleanup;
+ }
}
+
+ cleanup:
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&datastoreList);
+ esxVI_DatastoreHostMount_Free(&hostMount);
+ VIR_FREE(strippedFileName);
+ VIR_FREE(copyOfFileName);
+
+ return datastorePath;
}
+/*
+ * This function does the inverse of esxParseVMXFileName. It takes an file name
+ * in datastore path format and converts it to a file name that can be used in
+ * a .vmx file.
+ *
+ * The datastore path format and the formats found in a .vmx file are described
+ * in the documentation of esxParseVMXFileName.
+ *
+ * Firstly parse the datastore path. Then use the datastore name to lookup the
+ * datastore and it's mount path. Finally concatenate the mount path, directory
+ * and file name to an absolute path and return it. Detect the seperator type
+ * based on the mount path.
+ */
static char *
-esxFormatVMXFileName(const char *src, void *opaque ATTRIBUTE_UNUSED)
+esxFormatVMXFileName(const char *datastorePath, void *opaque)
{
bool success = false;
+ esxVMX_Data *data = opaque;
char *datastoreName = NULL;
char *directoryName = NULL;
char *fileName = NULL;
+ esxVI_ObjectContent *datastore = NULL;
+ esxVI_DatastoreHostMount *hostMount = NULL;
+ char separator = '/';
+ virBuffer buffer = VIR_BUFFER_INITIALIZER;
+ char *tmp;
+ int length;
char *absolutePath = NULL;
- if (STRPREFIX(src, "[")) {
- /* Found potential datastore path */
- if (esxUtil_ParseDatastorePath(src, &datastoreName, &directoryName,
- &fileName) < 0) {
- goto cleanup;
+ /* Parse datastore path and lookup datastore */
+ if (esxUtil_ParseDatastorePath(datastorePath, &datastoreName,
+ &directoryName, &fileName) < 0) {
+ goto cleanup;
+ }
+
+ if (esxVI_LookupDatastoreByName(data->ctx, datastoreName,
+ NULL, &datastore,
+ esxVI_Occurrence_RequiredItem) < 0 ||
+ esxVI_LookupDatastoreHostMount(data->ctx, datastore->obj,
+ &hostMount) < 0) {
+ goto cleanup;
+ }
+
+ /* Detect separator type */
+ if (strchr(hostMount->mountInfo->path, '\\') != NULL) {
+ separator = '\\';
+ }
+
+ /* Strip trailing separators */
+ length = strlen(hostMount->mountInfo->path);
+
+ if (length > 0) {
+ tmp = hostMount->mountInfo->path + length - 1;
+
+ while (*tmp == separator && tmp > hostMount->mountInfo->path) {
+ --tmp;
}
- if (directoryName == NULL) {
- if (virAsprintf(&absolutePath, "/vmfs/volumes/%s/%s",
- datastoreName, fileName) < 0) {
- virReportOOMError();
- goto cleanup;
- }
- } else {
- if (virAsprintf(&absolutePath, "/vmfs/volumes/%s/%s/%s",
- datastoreName, directoryName, fileName) < 0) {
- virReportOOMError();
- goto cleanup;
+ length = tmp - hostMount->mountInfo->path;
+ }
+
+ /* Format as <mount>[/<directory>]/<file> */
+ virBufferAdd(&buffer, hostMount->mountInfo->path, length);
+
+ if (directoryName != NULL) {
+ /* Convert / to \ when necessary */
+ if (separator != '/') {
+ tmp = directoryName;
+
+ while (*tmp != '\0') {
+ if (*tmp == '/') {
+ *tmp = separator;
+ }
+
+ ++tmp;
}
}
- } else if (STRPREFIX(src, "/")) {
- /* Found absolute path */
- absolutePath = strdup(src);
- if (absolutePath == NULL) {
- virReportOOMError();
- goto cleanup;
- }
- } else {
- /* Found relative path, this is not supported */
- ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
- _("Found relative path '%s' in domain XML, this is not "
- "supported"), src);
+ virBufferAddChar(&buffer, separator);
+ virBufferAdd(&buffer, directoryName, -1);
+ }
+
+ virBufferAddChar(&buffer, separator);
+ virBufferAdd(&buffer, fileName, -1);
+
+ if (virBufferError(&buffer)) {
+ virReportOOMError();
goto cleanup;
}
+ absolutePath = virBufferContentAndReset(&buffer);
+
/* FIXME: Check if referenced path/file really exists */
success = true;
cleanup:
if (! success) {
+ virBufferFreeAndReset(&buffer);
VIR_FREE(absolutePath);
}
VIR_FREE(datastoreName);
VIR_FREE(directoryName);
VIR_FREE(fileName);
+ esxVI_ObjectContent_Free(&datastore);
+ esxVI_DatastoreHostMount_Free(&hostMount);
return absolutePath;
}
--
1.7.0.4
14 years, 3 months
[libvirt] [PATCH] esx: Explicitly disable unused floppy0 device for GSX
by Matthias Bolte
floppy0.present defaults to true for GSX. Therefore, it needs to be
explicitly disabled for GSX.
---
src/esx/esx_vmx.c | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/src/esx/esx_vmx.c b/src/esx/esx_vmx.c
index d5d9ff0..61aaf10 100644
--- a/src/esx/esx_vmx.c
+++ b/src/esx/esx_vmx.c
@@ -216,6 +216,7 @@ def->disks[0]...
## disks: floppy from .flp image ###############################################
floppy0.present = "true" # defaults to "false"
+ # defaults to "true" for GSX
floppy0.startConnected = "true" # defaults to "true"
floppy0.clientDevice = "false" # defaults to "false"
@@ -236,6 +237,7 @@ def->disks[0]...
## disks: floppy from host device ##############################################
floppy0.present = "true" # defaults to "false"
+ # defaults to "true" for GSX
floppy0.startConnected = "true" # defaults to "true"
floppy0.clientDevice = "false" # defaults to "false"
@@ -2320,6 +2322,7 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
virBuffer buffer = VIR_BUFFER_INITIALIZER;
bool scsi_present[4] = { false, false, false, false };
int scsi_virtualDev[4] = { -1, -1, -1, -1 };
+ bool hasFloppyDevice = false;
if (ctx->formatFileName == NULL) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -2525,6 +2528,8 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
break;
case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
+ hasFloppyDevice = true;
+
if (esxVMX_FormatFloppy(ctx, def->disks[i], &buffer) < 0) {
goto failure;
}
@@ -2539,6 +2544,11 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
}
}
+ if (!hasFloppyDevice && productVersion & esxVI_ProductVersion_GSX) {
+ /* floppy0.present defaults to true for GSX, disable it explicitly */
+ virBufferAddLit(&buffer, "floppy0.present = \"false\"\n");
+ }
+
/* def:fss */
/* FIXME */
--
1.7.0.4
14 years, 3 months
[libvirt] [PATCH] bridge: Fix potential segfault when preparing dnsmasq arguments
by Jiri Denemark
We add --dhcp-lease-max=xxx argument when network->def->nranges > 0 but
we only allocate space for in the opposite case :-) I guess we are lucky
enough to miscount somewhere else so that we actually allocate more
space than we need since no-one has hit this bug so far.
---
src/network/bridge_driver.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 59e02b1..f247a0f 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -426,7 +426,7 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network,
2 + /* --listen-address 10.0.0.1 */
(2 * network->def->nranges) + /* --dhcp-range 10.0.0.2,10.0.0.254 */
/* --dhcp-lease-max=xxx if needed */
- (network->def->nranges ? 0 : 1) +
+ (network->def->nranges ? 1 : 0) +
/* --dhcp-hostsfile=/var/lib/dnsmasq/$NAME.hostsfile */
(network->def->nhosts > 0 ? 1 : 0) +
/* --enable-tftp --tftp-root /srv/tftp */
--
1.7.2
14 years, 3 months
[libvirt] [PATCH 2/2] Add a detailed message when tap device add fails
by Doug Goldstein
Added a more detailed error message when adding a tap devices fails and
the kernel is missing tun support.
Signed-off-by: Doug Goldstein <cardoe(a)gentoo.org>
---
src/uml/uml_conf.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/src/uml/uml_conf.c b/src/uml/uml_conf.c
index 025169f..4b1df84 100644
--- a/src/uml/uml_conf.c
+++ b/src/uml/uml_conf.c
@@ -146,6 +146,11 @@ umlConnectTapDevice(virDomainNetDefPtr net,
umlReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to add tap interface to bridge. "
"%s is not a bridge device"), bridge);
+ } else if (err == ENOENT) {
+ virReportSystemError(err, "%s",
+ _("Failed to add tap interface to bridge. Your kernel "
+ "is missing the 'tun' module or CONFIG_TUN or you need "
+ "to add the /dev/net/tun device node."));
} else if (template_ifname) {
virReportSystemError(err,
_("Failed to add tap interface to
bridge '%s'"),
--
1.7.2
14 years, 3 months
[libvirt] [PATCH] esx: Split VMX code into a general and an ESX specific part
by Matthias Bolte
Introduce esxVMX_Context containing functions pointers to
glue both parts together in an generic way.
Move the ESX specific part to esx_driver.c.
This is a step towards making the VMX code reusable in a
potential VMware Workstation and VMware Player driver.
---
src/esx/esx_driver.c | 417 ++++++++++++++++++++++++++++++++++++++++++++++-
src/esx/esx_vmx.c | 448 +++++---------------------------------------------
src/esx/esx_vmx.h | 71 +++++----
tests/vmx2xmltest.c | 52 ++++++-
tests/xml2vmxtest.c | 64 +++++++-
5 files changed, 611 insertions(+), 441 deletions(-)
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index d824371..b0ef704 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -50,6 +50,369 @@
static int esxDomainGetMaxVcpus(virDomainPtr domain);
+typedef struct _esxVMX_Data esxVMX_Data;
+
+struct _esxVMX_Data {
+ esxVI_Context *ctx;
+ const char *datastoreName;
+ const char *directoryName;
+};
+
+
+
+static char *
+esxAbsolutePathToDatastorePath(esxVI_Context *ctx, const char *absolutePath)
+{
+ bool success = false;
+ char *copyOfAbsolutePath = NULL;
+ char *tmp = NULL;
+ char *saveptr = NULL;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *datastore = NULL;
+
+ char *datastorePath = NULL;
+ char *preliminaryDatastoreName = NULL;
+ char *directoryAndFileName = NULL;
+ char *datastoreName = NULL;
+
+ if (esxVI_String_DeepCopyValue(©OfAbsolutePath, absolutePath) < 0) {
+ return NULL;
+ }
+
+ /* Expected format: '/vmfs/volumes/<datastore>/<path>' */
+ if ((tmp = STRSKIP(copyOfAbsolutePath, "/vmfs/volumes/")) == NULL ||
+ (preliminaryDatastoreName = strtok_r(tmp, "/", &saveptr)) == NULL ||
+ (directoryAndFileName = strtok_r(NULL, "", &saveptr)) == NULL) {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Absolute path '%s' doesn't have expected format "
+ "'/vmfs/volumes/<datastore>/<path>'"), absolutePath);
+ goto cleanup;
+ }
+
+ if (esxVI_String_AppendValueToList(&propertyNameList,
+ "summary.name") < 0 ||
+ esxVI_LookupDatastoreByAbsolutePath(ctx, absolutePath,
+ propertyNameList, &datastore,
+ esxVI_Occurrence_OptionalItem) < 0) {
+ goto cleanup;
+ }
+
+ if (datastore == NULL) {
+ if (esxVI_LookupDatastoreByName(ctx, preliminaryDatastoreName,
+ propertyNameList, &datastore,
+ esxVI_Occurrence_OptionalItem) < 0) {
+ goto cleanup;
+ }
+ }
+
+ if (datastore != NULL) {
+ if (esxVI_GetStringValue(datastore, "summary.name", &datastoreName,
+ esxVI_Occurrence_RequiredItem)) {
+ goto cleanup;
+ }
+ }
+
+ if (datastoreName == NULL) {
+ VIR_WARN("Could not retrieve datastore name for absolute "
+ "path '%s', falling back to preliminary name '%s'",
+ absolutePath, preliminaryDatastoreName);
+
+ datastoreName = preliminaryDatastoreName;
+ }
+
+ if (virAsprintf(&datastorePath, "[%s] %s", datastoreName,
+ directoryAndFileName) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ /* FIXME: Check if referenced path/file really exists */
+
+ success = true;
+
+ cleanup:
+ if (! success) {
+ VIR_FREE(datastorePath);
+ }
+
+ VIR_FREE(copyOfAbsolutePath);
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&datastore);
+
+ return datastorePath;
+}
+
+
+
+static char *
+esxParseVMXFileName(const char *fileName, void *opaque)
+{
+ char *src = NULL;
+ esxVMX_Data *data = opaque;
+
+ if (STRPREFIX(fileName, "/vmfs/volumes/")) {
+ /* Found absolute path referencing a file inside a datastore */
+ return esxAbsolutePathToDatastorePath(data->ctx, fileName);
+ } else if (STRPREFIX(fileName, "/")) {
+ /* Found absolute path referencing a file outside a datastore */
+ src = strdup(fileName);
+
+ if (src == NULL) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ /* FIXME: Check if referenced path/file really exists */
+
+ return src;
+ } else if (strchr(fileName, '/') != NULL) {
+ /* Found relative path, this is not supported */
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Found relative path '%s' in VMX file, this is not "
+ "supported"), fileName);
+ return NULL;
+ } else {
+ /* Found single file name referencing a file inside a datastore */
+ if (virAsprintf(&src, "[%s] %s/%s", data->datastoreName,
+ data->directoryName, fileName) < 0) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ /* FIXME: Check if referenced path/file really exists */
+
+ return src;
+ }
+}
+
+
+
+static char *
+esxFormatVMXFileName(const char *src, void *opaque ATTRIBUTE_UNUSED)
+{
+ bool success = false;
+ char *datastoreName = NULL;
+ char *directoryName = NULL;
+ char *fileName = NULL;
+ char *absolutePath = NULL;
+
+ if (STRPREFIX(src, "[")) {
+ /* Found potential datastore path */
+ if (esxUtil_ParseDatastorePath(src, &datastoreName, &directoryName,
+ &fileName) < 0) {
+ goto cleanup;
+ }
+
+ if (directoryName == NULL) {
+ if (virAsprintf(&absolutePath, "/vmfs/volumes/%s/%s",
+ datastoreName, fileName) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ } else {
+ if (virAsprintf(&absolutePath, "/vmfs/volumes/%s/%s/%s",
+ datastoreName, directoryName, fileName) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ }
+ } else if (STRPREFIX(src, "/")) {
+ /* Found absolute path */
+ absolutePath = strdup(src);
+
+ if (absolutePath == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ } else {
+ /* Found relative path, this is not supported */
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Found relative path '%s' in domain XML, this is not "
+ "supported"), src);
+ goto cleanup;
+ }
+
+ /* FIXME: Check if referenced path/file really exists */
+
+ success = true;
+
+ cleanup:
+ if (! success) {
+ VIR_FREE(absolutePath);
+ }
+
+ VIR_FREE(datastoreName);
+ VIR_FREE(directoryName);
+ VIR_FREE(fileName);
+
+ return absolutePath;
+}
+
+
+
+static int
+esxAutodetectSCSIControllerModel(virDomainDiskDefPtr def, int *model,
+ void *opaque)
+{
+ int result = -1;
+ esxVMX_Data *data = opaque;
+ char *datastoreName = NULL;
+ char *directoryName = NULL;
+ char *fileName = NULL;
+ char *datastorePath = NULL;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *datastore = NULL;
+ esxVI_ManagedObjectReference *hostDatastoreBrowser = NULL;
+ esxVI_HostDatastoreBrowserSearchSpec *searchSpec = NULL;
+ esxVI_VmDiskFileQuery *vmDiskFileQuery = NULL;
+ esxVI_ManagedObjectReference *task = NULL;
+ esxVI_TaskInfoState taskInfoState;
+ esxVI_TaskInfo *taskInfo = NULL;
+ esxVI_HostDatastoreBrowserSearchResults *searchResults = NULL;
+ esxVI_VmDiskFileInfo *vmDiskFileInfo = NULL;
+
+ if (def->device != VIR_DOMAIN_DISK_DEVICE_DISK ||
+ def->bus != VIR_DOMAIN_DISK_BUS_SCSI ||
+ def->type != VIR_DOMAIN_DISK_TYPE_FILE ||
+ def->src == NULL ||
+ ! STRPREFIX(def->src, "[")) {
+ /*
+ * This isn't a file-based SCSI disk device with a datastore related
+ * source path => do nothing.
+ */
+ return 0;
+ }
+
+ if (esxUtil_ParseDatastorePath(def->src, &datastoreName, &directoryName,
+ &fileName) < 0) {
+ goto cleanup;
+ }
+
+ if (directoryName == NULL) {
+ if (virAsprintf(&datastorePath, "[%s]", datastoreName) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ } else {
+ if (virAsprintf(&datastorePath, "[%s] %s", datastoreName,
+ directoryName) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ }
+
+ /* Lookup HostDatastoreBrowser */
+ if (esxVI_String_AppendValueToList(&propertyNameList, "browser") < 0 ||
+ esxVI_LookupDatastoreByName(data->ctx, datastoreName, propertyNameList,
+ &datastore,
+ esxVI_Occurrence_RequiredItem) < 0 ||
+ esxVI_GetManagedObjectReference(datastore, "browser",
+ &hostDatastoreBrowser,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ /* Build HostDatastoreBrowserSearchSpec */
+ if (esxVI_HostDatastoreBrowserSearchSpec_Alloc(&searchSpec) < 0 ||
+ esxVI_FileQueryFlags_Alloc(&searchSpec->details) < 0) {
+ goto cleanup;
+ }
+
+ searchSpec->details->fileType = esxVI_Boolean_True;
+ searchSpec->details->fileSize = esxVI_Boolean_False;
+ searchSpec->details->modification = esxVI_Boolean_False;
+
+ if (esxVI_VmDiskFileQuery_Alloc(&vmDiskFileQuery) < 0 ||
+ esxVI_VmDiskFileQueryFlags_Alloc(&vmDiskFileQuery->details) < 0 ||
+ esxVI_FileQuery_AppendToList
+ (&searchSpec->query,
+ esxVI_FileQuery_DynamicCast(vmDiskFileQuery)) < 0) {
+ goto cleanup;
+ }
+
+ vmDiskFileQuery->details->diskType = esxVI_Boolean_False;
+ vmDiskFileQuery->details->capacityKb = esxVI_Boolean_False;
+ vmDiskFileQuery->details->hardwareVersion = esxVI_Boolean_False;
+ vmDiskFileQuery->details->controllerType = esxVI_Boolean_True;
+ vmDiskFileQuery->details->diskExtents = esxVI_Boolean_False;
+
+ if (esxVI_String_Alloc(&searchSpec->matchPattern) < 0) {
+ goto cleanup;
+ }
+
+ searchSpec->matchPattern->value = fileName;
+
+ /* Search datastore for file */
+ if (esxVI_SearchDatastore_Task(data->ctx, hostDatastoreBrowser,
+ datastorePath, searchSpec, &task) < 0 ||
+ esxVI_WaitForTaskCompletion(data->ctx, task, NULL, esxVI_Occurrence_None,
+ esxVI_Boolean_False, &taskInfoState) < 0) {
+ goto cleanup;
+ }
+
+ if (taskInfoState != esxVI_TaskInfoState_Success) {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Could not serach in datastore '%s'"), datastoreName);
+ goto cleanup;
+ }
+
+ if (esxVI_LookupTaskInfoByTask(data->ctx, task, &taskInfo) < 0 ||
+ esxVI_HostDatastoreBrowserSearchResults_CastFromAnyType
+ (taskInfo->result, &searchResults) < 0) {
+ goto cleanup;
+ }
+
+ /* Interpret search result */
+ vmDiskFileInfo = esxVI_VmDiskFileInfo_DynamicCast(searchResults->file);
+
+ if (vmDiskFileInfo == NULL || vmDiskFileInfo->controllerType == NULL) {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Could not lookup controller model for '%s'"), def->src);
+ goto cleanup;
+ }
+
+ if (STRCASEEQ(vmDiskFileInfo->controllerType,
+ "VirtualBusLogicController")) {
+ *model = VIR_DOMAIN_CONTROLLER_MODEL_BUSLOGIC;
+ } else if (STRCASEEQ(vmDiskFileInfo->controllerType,
+ "VirtualLsiLogicController")) {
+ *model = VIR_DOMAIN_CONTROLLER_MODEL_LSILOGIC;
+ } else if (STRCASEEQ(vmDiskFileInfo->controllerType,
+ "VirtualLsiLogicSASController")) {
+ *model = VIR_DOMAIN_CONTROLLER_MODEL_LSISAS1068;
+ } else if (STRCASEEQ(vmDiskFileInfo->controllerType,
+ "ParaVirtualSCSIController")) {
+ *model = VIR_DOMAIN_CONTROLLER_MODEL_VMPVSCSI;
+ } else {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Found unexpected controller model '%s' for disk '%s'"),
+ vmDiskFileInfo->controllerType, def->src);
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ /* Don't double free fileName */
+ if (searchSpec != NULL && searchSpec->matchPattern != NULL) {
+ searchSpec->matchPattern->value = NULL;
+ }
+
+ VIR_FREE(datastoreName);
+ VIR_FREE(directoryName);
+ VIR_FREE(fileName);
+ VIR_FREE(datastorePath);
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&datastore);
+ esxVI_ManagedObjectReference_Free(&hostDatastoreBrowser);
+ esxVI_HostDatastoreBrowserSearchSpec_Free(&searchSpec);
+ esxVI_ManagedObjectReference_Free(&task);
+ esxVI_TaskInfo_Free(&taskInfo);
+ esxVI_HostDatastoreBrowserSearchResults_Free(&searchResults);
+
+ return result;
+}
+
static esxVI_Boolean
@@ -2176,6 +2539,8 @@ esxDomainDumpXML(virDomainPtr domain, int flags)
virBuffer buffer = VIR_BUFFER_INITIALIZER;
char *url = NULL;
char *vmx = NULL;
+ esxVMX_Context ctx;
+ esxVMX_Data data;
virDomainDefPtr def = NULL;
char *xml = NULL;
@@ -2223,8 +2588,17 @@ esxDomainDumpXML(virDomainPtr domain, int flags)
goto cleanup;
}
- def = esxVMX_ParseConfig(priv->primary, priv->caps, vmx, datastoreName,
- directoryName, priv->primary->productVersion);
+ data.ctx = priv->primary;
+ data.datastoreName = datastoreName;
+ data.directoryName = directoryName;
+
+ ctx.opaque = &data;
+ ctx.parseFileName = esxParseVMXFileName;
+ ctx.formatFileName = NULL;
+ ctx.autodetectSCSIControllerModel = NULL;
+
+ def = esxVMX_ParseConfig(&ctx, priv->caps, vmx,
+ priv->primary->productVersion);
if (def != NULL) {
xml = virDomainDefFormat(def, flags);
@@ -2255,6 +2629,8 @@ esxDomainXMLFromNative(virConnectPtr conn, const char *nativeFormat,
unsigned int flags ATTRIBUTE_UNUSED)
{
esxPrivate *priv = conn->privateData;
+ esxVMX_Context ctx;
+ esxVMX_Data data;
virDomainDefPtr def = NULL;
char *xml = NULL;
@@ -2264,7 +2640,16 @@ esxDomainXMLFromNative(virConnectPtr conn, const char *nativeFormat,
return NULL;
}
- def = esxVMX_ParseConfig(priv->primary, priv->caps, nativeConfig, "?", "?",
+ data.ctx = priv->primary;
+ data.datastoreName = "?";
+ data.directoryName = "?";
+
+ ctx.opaque = &data;
+ ctx.parseFileName = esxParseVMXFileName;
+ ctx.formatFileName = NULL;
+ ctx.autodetectSCSIControllerModel = NULL;
+
+ def = esxVMX_ParseConfig(&ctx, priv->caps, nativeConfig,
priv->primary->productVersion);
if (def != NULL) {
@@ -2284,6 +2669,8 @@ esxDomainXMLToNative(virConnectPtr conn, const char *nativeFormat,
unsigned int flags ATTRIBUTE_UNUSED)
{
esxPrivate *priv = conn->privateData;
+ esxVMX_Context ctx;
+ esxVMX_Data data;
virDomainDefPtr def = NULL;
char *vmx = NULL;
@@ -2299,7 +2686,16 @@ esxDomainXMLToNative(virConnectPtr conn, const char *nativeFormat,
return NULL;
}
- vmx = esxVMX_FormatConfig(priv->primary, priv->caps, def,
+ data.ctx = priv->primary;
+ data.datastoreName = NULL;
+ data.directoryName = NULL;
+
+ ctx.opaque = &data;
+ ctx.parseFileName = NULL;
+ ctx.formatFileName = esxFormatVMXFileName;
+ ctx.autodetectSCSIControllerModel = esxAutodetectSCSIControllerModel;
+
+ vmx = esxVMX_FormatConfig(&ctx, priv->caps, def,
priv->primary->productVersion);
virDomainDefFree(def);
@@ -2488,6 +2884,8 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml ATTRIBUTE_UNUSED)
int i;
virDomainDiskDefPtr disk = NULL;
esxVI_ObjectContent *virtualMachine = NULL;
+ esxVMX_Context ctx;
+ esxVMX_Data data;
char *datastoreName = NULL;
char *directoryName = NULL;
char *fileName = NULL;
@@ -2529,7 +2927,16 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml ATTRIBUTE_UNUSED)
}
/* Build VMX from domain XML */
- vmx = esxVMX_FormatConfig(priv->primary, priv->caps, def,
+ data.ctx = priv->primary;
+ data.datastoreName = NULL;
+ data.directoryName = NULL;
+
+ ctx.opaque = &data;
+ ctx.parseFileName = NULL;
+ ctx.formatFileName = esxFormatVMXFileName;
+ ctx.autodetectSCSIControllerModel = esxAutodetectSCSIControllerModel;
+
+ vmx = esxVMX_FormatConfig(&ctx, priv->caps, def,
priv->primary->productVersion);
if (vmx == NULL) {
diff --git a/src/esx/esx_vmx.c b/src/esx/esx_vmx.c
index 1a5e8d3..d5d9ff0 100644
--- a/src/esx/esx_vmx.c
+++ b/src/esx/esx_vmx.c
@@ -29,9 +29,7 @@
#include "virterror_internal.h"
#include "memory.h"
#include "logging.h"
-#include "esx_vi_methods.h"
#include "esx_private.h"
-#include "esx_util.h"
#include "esx_vmx.h"
/*
@@ -441,6 +439,11 @@ VIR_ENUM_IMPL(esxVMX_SCSIControllerModel, VIR_DOMAIN_CONTROLLER_MODEL_LAST,
"pvscsi");
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Helpers
+ */
+
int
esxVMX_SCSIDiskNameToControllerAndUnit(const char *name, int *controller, int *unit)
{
@@ -718,171 +721,7 @@ esxVMX_HandleLegacySCSIDiskDriverName(virDomainDefPtr def,
int
-esxVMX_AutodetectSCSIControllerModel(esxVI_Context *ctx,
- virDomainDiskDefPtr def, int *model)
-{
- int result = -1;
- char *datastoreName = NULL;
- char *directoryName = NULL;
- char *fileName = NULL;
- char *datastorePath = NULL;
- esxVI_String *propertyNameList = NULL;
- esxVI_ObjectContent *datastore = NULL;
- esxVI_ManagedObjectReference *hostDatastoreBrowser = NULL;
- esxVI_HostDatastoreBrowserSearchSpec *searchSpec = NULL;
- esxVI_VmDiskFileQuery *vmDiskFileQuery = NULL;
- esxVI_ManagedObjectReference *task = NULL;
- esxVI_TaskInfoState taskInfoState;
- esxVI_TaskInfo *taskInfo = NULL;
- esxVI_HostDatastoreBrowserSearchResults *searchResults = NULL;
- esxVI_VmDiskFileInfo *vmDiskFileInfo = NULL;
-
- if (def->device != VIR_DOMAIN_DISK_DEVICE_DISK ||
- def->bus != VIR_DOMAIN_DISK_BUS_SCSI ||
- def->type != VIR_DOMAIN_DISK_TYPE_FILE ||
- def->src == NULL ||
- ! STRPREFIX(def->src, "[")) {
- /*
- * This isn't a file-based SCSI disk device with a datastore related
- * source path => do nothing.
- */
- return 0;
- }
-
- if (esxUtil_ParseDatastorePath(def->src, &datastoreName, &directoryName,
- &fileName) < 0) {
- goto cleanup;
- }
-
- if (directoryName == NULL) {
- if (virAsprintf(&datastorePath, "[%s]", datastoreName) < 0) {
- virReportOOMError();
- goto cleanup;
- }
- } else {
- if (virAsprintf(&datastorePath, "[%s] %s", datastoreName,
- directoryName) < 0) {
- virReportOOMError();
- goto cleanup;
- }
- }
-
- /* Lookup HostDatastoreBrowser */
- if (esxVI_String_AppendValueToList(&propertyNameList, "browser") < 0 ||
- esxVI_LookupDatastoreByName(ctx, datastoreName, propertyNameList,
- &datastore,
- esxVI_Occurrence_RequiredItem) < 0 ||
- esxVI_GetManagedObjectReference(datastore, "browser",
- &hostDatastoreBrowser,
- esxVI_Occurrence_RequiredItem) < 0) {
- goto cleanup;
- }
-
- /* Build HostDatastoreBrowserSearchSpec */
- if (esxVI_HostDatastoreBrowserSearchSpec_Alloc(&searchSpec) < 0 ||
- esxVI_FileQueryFlags_Alloc(&searchSpec->details) < 0) {
- goto cleanup;
- }
-
- searchSpec->details->fileType = esxVI_Boolean_True;
- searchSpec->details->fileSize = esxVI_Boolean_False;
- searchSpec->details->modification = esxVI_Boolean_False;
-
- if (esxVI_VmDiskFileQuery_Alloc(&vmDiskFileQuery) < 0 ||
- esxVI_VmDiskFileQueryFlags_Alloc(&vmDiskFileQuery->details) < 0 ||
- esxVI_FileQuery_AppendToList
- (&searchSpec->query,
- esxVI_FileQuery_DynamicCast(vmDiskFileQuery)) < 0) {
- goto cleanup;
- }
-
- vmDiskFileQuery->details->diskType = esxVI_Boolean_False;
- vmDiskFileQuery->details->capacityKb = esxVI_Boolean_False;
- vmDiskFileQuery->details->hardwareVersion = esxVI_Boolean_False;
- vmDiskFileQuery->details->controllerType = esxVI_Boolean_True;
- vmDiskFileQuery->details->diskExtents = esxVI_Boolean_False;
-
- if (esxVI_String_Alloc(&searchSpec->matchPattern) < 0) {
- goto cleanup;
- }
-
- searchSpec->matchPattern->value = fileName;
-
- /* Search datastore for file */
- if (esxVI_SearchDatastore_Task(ctx, hostDatastoreBrowser, datastorePath,
- searchSpec, &task) < 0 ||
- esxVI_WaitForTaskCompletion(ctx, task, NULL, esxVI_Occurrence_None,
- esxVI_Boolean_False, &taskInfoState) < 0) {
- goto cleanup;
- }
-
- if (taskInfoState != esxVI_TaskInfoState_Success) {
- ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
- _("Could not serach in datastore '%s'"), datastoreName);
- goto cleanup;
- }
-
- if (esxVI_LookupTaskInfoByTask(ctx, task, &taskInfo) < 0 ||
- esxVI_HostDatastoreBrowserSearchResults_CastFromAnyType
- (taskInfo->result, &searchResults) < 0) {
- goto cleanup;
- }
-
- /* Interpret search result */
- vmDiskFileInfo = esxVI_VmDiskFileInfo_DynamicCast(searchResults->file);
-
- if (vmDiskFileInfo == NULL || vmDiskFileInfo->controllerType == NULL) {
- ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
- _("Could not lookup controller model for '%s'"), def->src);
- goto cleanup;
- }
-
- if (STRCASEEQ(vmDiskFileInfo->controllerType,
- "VirtualBusLogicController")) {
- *model = VIR_DOMAIN_CONTROLLER_MODEL_BUSLOGIC;
- } else if (STRCASEEQ(vmDiskFileInfo->controllerType,
- "VirtualLsiLogicController")) {
- *model = VIR_DOMAIN_CONTROLLER_MODEL_LSILOGIC;
- } else if (STRCASEEQ(vmDiskFileInfo->controllerType,
- "VirtualLsiLogicSASController")) {
- *model = VIR_DOMAIN_CONTROLLER_MODEL_LSISAS1068;
- } else if (STRCASEEQ(vmDiskFileInfo->controllerType,
- "ParaVirtualSCSIController")) {
- *model = VIR_DOMAIN_CONTROLLER_MODEL_VMPVSCSI;
- } else {
- ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
- _("Found unexpected controller model '%s' for disk '%s'"),
- vmDiskFileInfo->controllerType, def->src);
- goto cleanup;
- }
-
- result = 0;
-
- cleanup:
- /* Don't double free fileName */
- if (searchSpec != NULL && searchSpec->matchPattern != NULL) {
- searchSpec->matchPattern->value = NULL;
- }
-
- VIR_FREE(datastoreName);
- VIR_FREE(directoryName);
- VIR_FREE(fileName);
- VIR_FREE(datastorePath);
- esxVI_String_Free(&propertyNameList);
- esxVI_ObjectContent_Free(&datastore);
- esxVI_ManagedObjectReference_Free(&hostDatastoreBrowser);
- esxVI_HostDatastoreBrowserSearchSpec_Free(&searchSpec);
- esxVI_ManagedObjectReference_Free(&task);
- esxVI_TaskInfo_Free(&taskInfo);
- esxVI_HostDatastoreBrowserSearchResults_Free(&searchResults);
-
- return result;
-}
-
-
-
-int
-esxVMX_GatherSCSIControllers(esxVI_Context *ctx, virDomainDefPtr def,
+esxVMX_GatherSCSIControllers(esxVMX_Context *ctx, virDomainDefPtr def,
int virtualDev[4], bool present[4])
{
int result = -1;
@@ -923,8 +762,8 @@ esxVMX_GatherSCSIControllers(esxVI_Context *ctx, virDomainDefPtr def,
continue;
}
- if (ctx != NULL &&
- controller->model == VIR_DOMAIN_CONTROLLER_MODEL_AUTO) {
+ if (controller->model == VIR_DOMAIN_CONTROLLER_MODEL_AUTO &&
+ ctx->autodetectSCSIControllerModel != NULL) {
count = 0;
// try to autodetect the SCSI controller model by collecting
@@ -934,8 +773,9 @@ esxVMX_GatherSCSIControllers(esxVI_Context *ctx, virDomainDefPtr def,
if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI &&
disk->info.addr.drive.controller == controller->idx) {
- if (esxVMX_AutodetectSCSIControllerModel
- (ctx, disk, &autodetectedModels[count]) < 0) {
+ if (ctx->autodetectSCSIControllerModel
+ (disk, &autodetectedModels[count],
+ ctx->opaque) < 0) {
goto cleanup;
}
@@ -985,144 +825,12 @@ esxVMX_GatherSCSIControllers(esxVI_Context *ctx, virDomainDefPtr def,
-char *
-esxVMX_AbsolutePathToDatastorePath(esxVI_Context *ctx, const char *absolutePath)
-{
- bool success = false;
- char *copyOfAbsolutePath = NULL;
- char *tmp = NULL;
- char *saveptr = NULL;
- esxVI_String *propertyNameList = NULL;
- esxVI_ObjectContent *datastore = NULL;
-
- char *datastorePath = NULL;
- char *preliminaryDatastoreName = NULL;
- char *directoryAndFileName = NULL;
- char *datastoreName = NULL;
-
- if (esxVI_String_DeepCopyValue(©OfAbsolutePath, absolutePath) < 0) {
- return NULL;
- }
-
- /* Expected format: '/vmfs/volumes/<datastore>/<path>' */
- if ((tmp = STRSKIP(copyOfAbsolutePath, "/vmfs/volumes/")) == NULL ||
- (preliminaryDatastoreName = strtok_r(tmp, "/", &saveptr)) == NULL ||
- (directoryAndFileName = strtok_r(NULL, "", &saveptr)) == NULL) {
- ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
- _("Absolute path '%s' doesn't have expected format "
- "'/vmfs/volumes/<datastore>/<path>'"), absolutePath);
- goto cleanup;
- }
-
- if (ctx != NULL) {
- if (esxVI_String_AppendValueToList(&propertyNameList,
- "summary.name") < 0 ||
- esxVI_LookupDatastoreByAbsolutePath(ctx, absolutePath,
- propertyNameList, &datastore,
- esxVI_Occurrence_OptionalItem) < 0) {
- goto cleanup;
- }
-
- if (datastore == NULL) {
- if (esxVI_LookupDatastoreByName(ctx, preliminaryDatastoreName,
- propertyNameList, &datastore,
- esxVI_Occurrence_OptionalItem) < 0) {
- goto cleanup;
- }
- }
-
- if (datastore != NULL) {
- if (esxVI_GetStringValue(datastore, "summary.name", &datastoreName,
- esxVI_Occurrence_RequiredItem)) {
- goto cleanup;
- }
- }
-
- if (datastoreName == NULL) {
- VIR_WARN("Could not retrieve datastore name for absolute "
- "path '%s', falling back to preliminary name '%s'",
- absolutePath, preliminaryDatastoreName);
-
- datastoreName = preliminaryDatastoreName;
- }
- } else {
- datastoreName = preliminaryDatastoreName;
- }
-
- if (virAsprintf(&datastorePath, "[%s] %s", datastoreName,
- directoryAndFileName) < 0) {
- virReportOOMError();
- goto cleanup;
- }
-
- /* FIXME: Check if referenced path/file really exists */
-
- success = true;
-
- cleanup:
- if (! success) {
- VIR_FREE(datastorePath);
- }
-
- VIR_FREE(copyOfAbsolutePath);
- esxVI_String_Free(&propertyNameList);
- esxVI_ObjectContent_Free(&datastore);
-
- return datastorePath;
-}
-
-
-
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* VMX -> Domain XML
*/
-char *
-esxVMX_ParseFileName(esxVI_Context *ctx, const char *fileName,
- const char *datastoreName, const char *directoryName)
-{
- char *src = NULL;
-
- if (STRPREFIX(fileName, "/vmfs/volumes/")) {
- /* Found absolute path referencing a file inside a datastore */
- return esxVMX_AbsolutePathToDatastorePath(ctx, fileName);
- } else if (STRPREFIX(fileName, "/")) {
- /* Found absolute path referencing a file outside a datastore */
- src = strdup(fileName);
-
- if (src == NULL) {
- virReportOOMError();
- return NULL;
- }
-
- /* FIXME: Check if referenced path/file really exists */
-
- return src;
- } else if (strchr(fileName, '/') != NULL) {
- /* Found relative path, this is not supported */
- ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
- _("Found relative path '%s' in VMX file, this is not "
- "supported"), fileName);
- return NULL;
- } else {
- /* Found single file name referencing a file inside a datastore */
- if (virAsprintf(&src, "[%s] %s/%s", datastoreName, directoryName,
- fileName) < 0) {
- virReportOOMError();
- return NULL;
- }
-
- /* FIXME: Check if referenced path/file really exists */
-
- return src;
- }
-}
-
-
-
virDomainDefPtr
-esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
- const char *datastoreName, const char *directoryName,
+esxVMX_ParseConfig(esxVMX_Context *ctx, virCapsPtr caps, const char *vmx,
esxVI_ProductVersion productVersion)
{
bool success = false;
@@ -1142,6 +850,12 @@ esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
int scsi_virtualDev[4] = { -1, -1, -1, -1 };
int unit;
+ if (ctx->parseFileName == NULL) {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("esxVMX_Context has no parseFileName function set"));
+ return NULL;
+ }
+
conf = virConfReadMem(vmx, strlen(vmx), VIR_CONF_FLAG_VMX_FORMAT);
if (conf == NULL) {
@@ -1429,7 +1143,6 @@ esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
if (esxVMX_ParseDisk(ctx, caps, conf, VIR_DOMAIN_DISK_DEVICE_DISK,
VIR_DOMAIN_DISK_BUS_SCSI, controller, unit,
- datastoreName, directoryName,
&def->disks[def->ndisks]) < 0) {
goto cleanup;
}
@@ -1441,7 +1154,6 @@ esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
if (esxVMX_ParseDisk(ctx, caps, conf, VIR_DOMAIN_DISK_DEVICE_CDROM,
VIR_DOMAIN_DISK_BUS_SCSI, controller, unit,
- datastoreName, directoryName,
&def->disks[def->ndisks]) < 0) {
goto cleanup;
}
@@ -1457,7 +1169,6 @@ esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
for (unit = 0; unit < 2; ++unit) {
if (esxVMX_ParseDisk(ctx, caps, conf, VIR_DOMAIN_DISK_DEVICE_DISK,
VIR_DOMAIN_DISK_BUS_IDE, bus, unit,
- datastoreName, directoryName,
&def->disks[def->ndisks]) < 0) {
goto cleanup;
}
@@ -1469,7 +1180,6 @@ esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
if (esxVMX_ParseDisk(ctx, caps, conf, VIR_DOMAIN_DISK_DEVICE_CDROM,
VIR_DOMAIN_DISK_BUS_IDE, bus, unit,
- datastoreName, directoryName,
&def->disks[def->ndisks]) < 0) {
goto cleanup;
}
@@ -1484,7 +1194,6 @@ esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
for (unit = 0; unit < 2; ++unit) {
if (esxVMX_ParseDisk(ctx, caps, conf, VIR_DOMAIN_DISK_DEVICE_FLOPPY,
VIR_DOMAIN_DISK_BUS_FDC, 0, unit,
- datastoreName, directoryName,
&def->disks[def->ndisks]) < 0) {
goto cleanup;
}
@@ -1555,7 +1264,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
def->nserials = 0;
for (port = 0; port < 4; ++port) {
- if (esxVMX_ParseSerial(ctx, conf, port, datastoreName, directoryName,
+ if (esxVMX_ParseSerial(ctx, conf, port,
&def->serials[def->nserials]) < 0) {
goto cleanup;
}
@@ -1574,7 +1283,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
def->nparallels = 0;
for (port = 0; port < 3; ++port) {
- if (esxVMX_ParseParallel(ctx, conf, port, datastoreName, directoryName,
+ if (esxVMX_ParseParallel(ctx, conf, port,
&def->parallels[def->nparallels]) < 0) {
goto cleanup;
}
@@ -1752,9 +1461,8 @@ struct _virDomainDiskDef {
};*/
int
-esxVMX_ParseDisk(esxVI_Context *ctx, virCapsPtr caps, virConfPtr conf,
+esxVMX_ParseDisk(esxVMX_Context *ctx, virCapsPtr caps, virConfPtr conf,
int device, int busType, int controllerOrBus, int unit,
- const char *datastoreName, const char *directoryName,
virDomainDiskDefPtr *def)
{
/*
@@ -1996,8 +1704,7 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virCapsPtr caps, virConfPtr conf,
}
(*def)->type = VIR_DOMAIN_DISK_TYPE_FILE;
- (*def)->src = esxVMX_ParseFileName(ctx, fileName, datastoreName,
- directoryName);
+ (*def)->src = ctx->parseFileName(fileName, ctx->opaque);
(*def)->cachemode = writeThrough ? VIR_DOMAIN_DISK_CACHE_WRITETHRU
: VIR_DOMAIN_DISK_CACHE_DEFAULT;
@@ -2031,8 +1738,7 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virCapsPtr caps, virConfPtr conf,
}
(*def)->type = VIR_DOMAIN_DISK_TYPE_FILE;
- (*def)->src = esxVMX_ParseFileName(ctx, fileName, datastoreName,
- directoryName);
+ (*def)->src = ctx->parseFileName(fileName, ctx->opaque);
if ((*def)->src == NULL) {
goto cleanup;
@@ -2068,8 +1774,7 @@ esxVMX_ParseDisk(esxVI_Context *ctx, virCapsPtr caps, virConfPtr conf,
}
(*def)->type = VIR_DOMAIN_DISK_TYPE_FILE;
- (*def)->src = esxVMX_ParseFileName(ctx, fileName, datastoreName,
- directoryName);
+ (*def)->src = ctx->parseFileName(fileName, ctx->opaque);
if ((*def)->src == NULL) {
goto cleanup;
@@ -2358,8 +2063,7 @@ esxVMX_ParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def)
int
-esxVMX_ParseSerial(esxVI_Context *ctx, virConfPtr conf, int port,
- const char *datastoreName, const char *directoryName,
+esxVMX_ParseSerial(esxVMX_Context *ctx, virConfPtr conf, int port,
virDomainChrDefPtr *def)
{
int result = -1;
@@ -2439,9 +2143,7 @@ esxVMX_ParseSerial(esxVI_Context *ctx, virConfPtr conf, int port,
} else if (STRCASEEQ(fileType, "file")) {
(*def)->target.port = port;
(*def)->type = VIR_DOMAIN_CHR_TYPE_FILE;
- (*def)->data.file.path = esxVMX_ParseFileName(ctx, fileName,
- datastoreName,
- directoryName);
+ (*def)->data.file.path = ctx->parseFileName(fileName, ctx->opaque);
if ((*def)->data.file.path == NULL) {
goto cleanup;
@@ -2488,8 +2190,7 @@ esxVMX_ParseSerial(esxVI_Context *ctx, virConfPtr conf, int port,
int
-esxVMX_ParseParallel(esxVI_Context *ctx, virConfPtr conf, int port,
- const char *datastoreName, const char *directoryName,
+esxVMX_ParseParallel(esxVMX_Context *ctx, virConfPtr conf, int port,
virDomainChrDefPtr *def)
{
int result = -1;
@@ -2569,9 +2270,7 @@ esxVMX_ParseParallel(esxVI_Context *ctx, virConfPtr conf, int port,
} else if (STRCASEEQ(fileType, "file")) {
(*def)->target.port = port;
(*def)->type = VIR_DOMAIN_CHR_TYPE_FILE;
- (*def)->data.file.path = esxVMX_ParseFileName(ctx, fileName,
- datastoreName,
- directoryName);
+ (*def)->data.file.path = ctx->parseFileName(fileName, ctx->opaque);
if ((*def)->data.file.path == NULL) {
goto cleanup;
@@ -2612,70 +2311,7 @@ esxVMX_ParseParallel(esxVI_Context *ctx, virConfPtr conf, int port,
*/
char *
-esxVMX_FormatFileName(esxVI_Context *ctx ATTRIBUTE_UNUSED, const char *src)
-{
- bool success = false;
- char *datastoreName = NULL;
- char *directoryName = NULL;
- char *fileName = NULL;
- char *absolutePath = NULL;
-
- if (STRPREFIX(src, "[")) {
- /* Found potential datastore related path */
- if (esxUtil_ParseDatastorePath(src, &datastoreName, &directoryName,
- &fileName) < 0) {
- goto cleanup;
- }
-
- if (directoryName == NULL) {
- if (virAsprintf(&absolutePath, "/vmfs/volumes/%s/%s",
- datastoreName, fileName) < 0) {
- virReportOOMError();
- goto cleanup;
- }
- } else {
- if (virAsprintf(&absolutePath, "/vmfs/volumes/%s/%s/%s",
- datastoreName, directoryName, fileName) < 0) {
- virReportOOMError();
- goto cleanup;
- }
- }
- } else if (STRPREFIX(src, "/")) {
- /* Found absolute path */
- absolutePath = strdup(src);
-
- if (absolutePath == NULL) {
- virReportOOMError();
- goto cleanup;
- }
- } else {
- /* Found relative path, this is not supported */
- ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
- _("Found relative path '%s' in domain XML, this is not "
- "supported"), src);
- goto cleanup;
- }
-
- /* FIXME: Check if referenced path/file really exists */
-
- success = true;
-
- cleanup:
- if (! success) {
- VIR_FREE(absolutePath);
- }
-
- VIR_FREE(datastoreName);
- VIR_FREE(directoryName);
- VIR_FREE(fileName);
-
- return absolutePath;
-}
-
-
-
-char *
-esxVMX_FormatConfig(esxVI_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
+esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
esxVI_ProductVersion productVersion)
{
int i;
@@ -2685,6 +2321,12 @@ esxVMX_FormatConfig(esxVI_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
bool scsi_present[4] = { false, false, false, false };
int scsi_virtualDev[4] = { -1, -1, -1, -1 };
+ if (ctx->formatFileName == NULL) {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("esxVMX_Context has no formatFileName function set"));
+ return NULL;
+ }
+
memset(zero, 0, VIR_UUID_BUFLEN);
if (def->virtType != VIR_DOMAIN_VIRT_VMWARE) { /* FIXME: maybe add VIR_DOMAIN_VIRT_ESX ? */
@@ -2990,7 +2632,7 @@ esxVMX_FormatVNC(virDomainGraphicsDefPtr def, virBufferPtr buffer)
int
-esxVMX_FormatHardDisk(esxVI_Context *ctx, virDomainDiskDefPtr def,
+esxVMX_FormatHardDisk(esxVMX_Context *ctx, virDomainDiskDefPtr def,
virBufferPtr buffer)
{
int controllerOrBus, unit;
@@ -3050,7 +2692,7 @@ esxVMX_FormatHardDisk(esxVI_Context *ctx, virDomainDiskDefPtr def,
return -1;
}
- fileName = esxVMX_FormatFileName(ctx, def->src);
+ fileName = ctx->formatFileName(def->src, ctx->opaque);
if (fileName == NULL) {
return -1;
@@ -3081,7 +2723,7 @@ esxVMX_FormatHardDisk(esxVI_Context *ctx, virDomainDiskDefPtr def,
int
-esxVMX_FormatCDROM(esxVI_Context *ctx, virDomainDiskDefPtr def,
+esxVMX_FormatCDROM(esxVMX_Context *ctx, virDomainDiskDefPtr def,
virBufferPtr buffer)
{
int controllerOrBus, unit;
@@ -3132,7 +2774,7 @@ esxVMX_FormatCDROM(esxVI_Context *ctx, virDomainDiskDefPtr def,
return -1;
}
- fileName = esxVMX_FormatFileName(ctx, def->src);
+ fileName = ctx->formatFileName(def->src, ctx->opaque);
if (fileName == NULL) {
return -1;
@@ -3167,7 +2809,7 @@ esxVMX_FormatCDROM(esxVI_Context *ctx, virDomainDiskDefPtr def,
int
-esxVMX_FormatFloppy(esxVI_Context *ctx, virDomainDiskDefPtr def,
+esxVMX_FormatFloppy(esxVMX_Context *ctx, virDomainDiskDefPtr def,
virBufferPtr buffer)
{
int unit;
@@ -3195,7 +2837,7 @@ esxVMX_FormatFloppy(esxVI_Context *ctx, virDomainDiskDefPtr def,
return -1;
}
- fileName = esxVMX_FormatFileName(ctx, def->src);
+ fileName = ctx->formatFileName(def->src, ctx->opaque);
if (fileName == NULL) {
return -1;
@@ -3331,7 +2973,7 @@ esxVMX_FormatEthernet(virDomainNetDefPtr def, int controller,
int
-esxVMX_FormatSerial(esxVI_Context *ctx, virDomainChrDefPtr def,
+esxVMX_FormatSerial(esxVMX_Context *ctx, virDomainChrDefPtr def,
virBufferPtr buffer)
{
char *fileName = NULL;
@@ -3365,7 +3007,7 @@ esxVMX_FormatSerial(esxVI_Context *ctx, virDomainChrDefPtr def,
virBufferVSprintf(buffer, "serial%d.fileType = \"file\"\n",
def->target.port);
- fileName = esxVMX_FormatFileName(ctx, def->data.file.path);
+ fileName = ctx->formatFileName(def->data.file.path, ctx->opaque);
if (fileName == NULL) {
return -1;
@@ -3408,7 +3050,7 @@ esxVMX_FormatSerial(esxVI_Context *ctx, virDomainChrDefPtr def,
int
-esxVMX_FormatParallel(esxVI_Context *ctx, virDomainChrDefPtr def,
+esxVMX_FormatParallel(esxVMX_Context *ctx, virDomainChrDefPtr def,
virBufferPtr buffer)
{
char *fileName = NULL;
@@ -3443,7 +3085,7 @@ esxVMX_FormatParallel(esxVI_Context *ctx, virDomainChrDefPtr def,
virBufferVSprintf(buffer, "parallel%d.fileType = \"file\"\n",
def->target.port);
- fileName = esxVMX_FormatFileName(ctx, def->data.file.path);
+ fileName = ctx->formatFileName(def->data.file.path, ctx->opaque);
if (fileName == NULL) {
return -1;
diff --git a/src/esx/esx_vmx.h b/src/esx/esx_vmx.h
index bda98f0..a77264a 100644
--- a/src/esx/esx_vmx.h
+++ b/src/esx/esx_vmx.h
@@ -30,6 +30,37 @@
# include "domain_conf.h"
# include "esx_vi.h"
+typedef struct _esxVMX_Context esxVMX_Context;
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Context
+ */
+
+typedef char * (*esxVMX_ParseFileName)(const char *fileName, void *opaque);
+typedef char * (*esxVMX_FormatFileName)(const char *src, void *opaque);
+typedef int (*esxVMX_AutodetectSCSIControllerModel)(virDomainDiskDefPtr def,
+ int *model, void *opaque);
+
+/*
+ * esxVMX_ParseFileName is only used by esxVMX_ParseConfig.
+ * esxVMX_FormatFileName is only used by esxVMX_FormatConfig.
+ * esxVMX_AutodetectSCSIControllerModel is optionally used by esxVMX_FormatConfig.
+ */
+struct _esxVMX_Context {
+ void *opaque;
+ esxVMX_ParseFileName parseFileName;
+ esxVMX_FormatFileName formatFileName;
+ esxVMX_AutodetectSCSIControllerModel autodetectSCSIControllerModel;
+};
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Helpers
+ */
+
int
esxVMX_SCSIDiskNameToControllerAndUnit(const char *name, int *controller,
int *unit);
@@ -48,29 +79,17 @@ esxVMX_HandleLegacySCSIDiskDriverName(virDomainDefPtr def,
virDomainDiskDefPtr disk);
int
-esxVMX_AutodetectSCSIControllerModel(esxVI_Context *ctx,
- virDomainDiskDefPtr def, int *model);
-
-int
-esxVMX_GatherSCSIControllers(esxVI_Context *ctx, virDomainDefPtr def,
+esxVMX_GatherSCSIControllers(esxVMX_Context *ctx, virDomainDefPtr def,
int virtualDev[4], bool present[4]);
-char *
-esxVMX_AbsolutePathToDatastorePath(esxVI_Context *ctx, const char *absolutePath);
-
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* VMX -> Domain XML
*/
-char *
-esxVMX_ParseFileName(esxVI_Context *ctx, const char *fileName,
- const char *datastoreName, const char *directoryName);
-
virDomainDefPtr
-esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
- const char *datastoreName, const char *directoryName,
+esxVMX_ParseConfig(esxVMX_Context *ctx, virCapsPtr caps, const char *vmx,
esxVI_ProductVersion productVersion);
int
@@ -81,21 +100,18 @@ esxVMX_ParseSCSIController(virConfPtr conf, int controller, bool *present,
int *virtualDev);
int
-esxVMX_ParseDisk(esxVI_Context *ctx, virCapsPtr caps, virConfPtr conf,
+esxVMX_ParseDisk(esxVMX_Context *ctx, virCapsPtr caps, virConfPtr conf,
int device, int busType, int controllerOrBus, int unit,
- const char *datastoreName, const char *directoryName,
virDomainDiskDefPtr *def);
int
esxVMX_ParseEthernet(virConfPtr conf, int controller, virDomainNetDefPtr *def);
int
-esxVMX_ParseSerial(esxVI_Context *ctx, virConfPtr conf, int port,
- const char *datastoreName, const char *directoryName,
+esxVMX_ParseSerial(esxVMX_Context *ctx, virConfPtr conf, int port,
virDomainChrDefPtr *def);
int
-esxVMX_ParseParallel(esxVI_Context *ctx, virConfPtr conf, int port,
- const char *datastoreName, const char *directoryName,
+esxVMX_ParseParallel(esxVMX_Context *ctx, virConfPtr conf, int port,
virDomainChrDefPtr *def);
@@ -105,25 +121,22 @@ esxVMX_ParseParallel(esxVI_Context *ctx, virConfPtr conf, int port,
*/
char *
-esxVMX_FormatFileName(esxVI_Context *ctx, const char *src);
-
-char *
-esxVMX_FormatConfig(esxVI_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
+esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
esxVI_ProductVersion productVersion);
int
esxVMX_FormatVNC(virDomainGraphicsDefPtr def, virBufferPtr buffer);
int
-esxVMX_FormatHardDisk(esxVI_Context *ctx, virDomainDiskDefPtr def,
+esxVMX_FormatHardDisk(esxVMX_Context *ctx, virDomainDiskDefPtr def,
virBufferPtr buffer);
int
-esxVMX_FormatCDROM(esxVI_Context *ctx, virDomainDiskDefPtr def,
+esxVMX_FormatCDROM(esxVMX_Context *ctx, virDomainDiskDefPtr def,
virBufferPtr buffer);
int
-esxVMX_FormatFloppy(esxVI_Context *ctx, virDomainDiskDefPtr def,
+esxVMX_FormatFloppy(esxVMX_Context *ctx, virDomainDiskDefPtr def,
virBufferPtr buffer);
int
@@ -131,11 +144,11 @@ esxVMX_FormatEthernet(virDomainNetDefPtr def, int controller,
virBufferPtr buffer);
int
-esxVMX_FormatSerial(esxVI_Context *ctx, virDomainChrDefPtr def,
+esxVMX_FormatSerial(esxVMX_Context *ctx, virDomainChrDefPtr def,
virBufferPtr buffer);
int
-esxVMX_FormatParallel(esxVI_Context *ctx, virDomainChrDefPtr def,
+esxVMX_FormatParallel(esxVMX_Context *ctx, virDomainChrDefPtr def,
virBufferPtr buffer);
#endif /* __ESX_VMX_H__ */
diff --git a/tests/vmx2xmltest.c b/tests/vmx2xmltest.c
index f1d2471..50e7d0c 100644
--- a/tests/vmx2xmltest.c
+++ b/tests/vmx2xmltest.c
@@ -14,6 +14,7 @@
static char *progname = NULL;
static char *abs_srcdir = NULL;
static virCapsPtr caps = NULL;
+static esxVMX_Context ctx;
# define MAX_FILE 4096
@@ -87,8 +88,7 @@ testCompareFiles(const char *vmx, const char *xml,
goto failure;
}
- def = esxVMX_ParseConfig(NULL, caps, vmxData, "datastore", "directory",
- productVersion);
+ def = esxVMX_ParseConfig(&ctx, caps, vmxData, productVersion);
if (def == NULL) {
err = virGetLastError();
@@ -139,6 +139,49 @@ testCompareHelper(const void *data)
return testCompareFiles(vmx, xml, info->version);
}
+static char *
+testParseVMXFileName(const char *fileName, void *opaque ATTRIBUTE_UNUSED)
+{
+ char *copyOfFileName = NULL;
+ char *tmp = NULL;
+ char *saveptr = NULL;
+ char *datastoreName = NULL;
+ char *directoryAndFileName = NULL;
+ char *src = NULL;
+
+ if (STRPREFIX(fileName, "/vmfs/volumes/")) {
+ /* Found absolute path referencing a file inside a datastore */
+ copyOfFileName = strdup(fileName);
+
+ if (copyOfFileName == NULL) {
+ goto cleanup;
+ }
+
+ /* Expected format: '/vmfs/volumes/<datastore>/<path>' */
+ if ((tmp = STRSKIP(copyOfFileName, "/vmfs/volumes/")) == NULL ||
+ (datastoreName = strtok_r(tmp, "/", &saveptr)) == NULL ||
+ (directoryAndFileName = strtok_r(NULL, "", &saveptr)) == NULL) {
+ goto cleanup;
+ }
+
+ virAsprintf(&src, "[%s] %s", datastoreName, directoryAndFileName);
+ } else if (STRPREFIX(fileName, "/")) {
+ /* Found absolute path referencing a file outside a datastore */
+ src = strdup(fileName);
+ } else if (strchr(fileName, '/') != NULL) {
+ /* Found relative path, this is not supported */
+ src = NULL;
+ } else {
+ /* Found single file name referencing a file inside a datastore */
+ virAsprintf(&src, "[datastore] directory/%s", fileName);
+ }
+
+ cleanup:
+ VIR_FREE(copyOfFileName);
+
+ return src;
+}
+
static int
mymain(int argc, char **argv)
{
@@ -179,6 +222,11 @@ mymain(int argc, char **argv)
return EXIT_FAILURE;
}
+ ctx.opaque = NULL;
+ ctx.parseFileName = testParseVMXFileName;
+ ctx.formatFileName = NULL;
+ ctx.autodetectSCSIControllerModel = NULL;
+
DO_TEST("case-insensitive-1", "case-insensitive-1", esxVI_ProductVersion_ESX35);
DO_TEST("case-insensitive-2", "case-insensitive-2", esxVI_ProductVersion_ESX35);
diff --git a/tests/xml2vmxtest.c b/tests/xml2vmxtest.c
index 0a9bc53..eed3ac0 100644
--- a/tests/xml2vmxtest.c
+++ b/tests/xml2vmxtest.c
@@ -14,6 +14,7 @@
static char *progname = NULL;
static char *abs_srcdir = NULL;
static virCapsPtr caps = NULL;
+static esxVMX_Context ctx;
# define MAX_FILE 4096
@@ -92,7 +93,7 @@ testCompareFiles(const char *xml, const char *vmx,
goto failure;
}
- formatted = esxVMX_FormatConfig(NULL, caps, def, productVersion);
+ formatted = esxVMX_FormatConfig(&ctx, caps, def, productVersion);
if (formatted == NULL) {
goto failure;
@@ -134,6 +135,60 @@ testCompareHelper(const void *data)
}
static int
+testAutodetectSCSIControllerModel(virDomainDiskDefPtr def ATTRIBUTE_UNUSED,
+ int *model, void *opaque ATTRIBUTE_UNUSED)
+{
+ *model = VIR_DOMAIN_CONTROLLER_MODEL_LSILOGIC;
+
+ return 0;
+}
+
+static char *
+testFormatVMXFileName(const char *src, void *opaque ATTRIBUTE_UNUSED)
+{
+ bool success = false;
+ char *datastoreName = NULL;
+ char *directoryName = NULL;
+ char *fileName = NULL;
+ char *absolutePath = NULL;
+
+ if (STRPREFIX(src, "[")) {
+ /* Found potential datastore path */
+ if (esxUtil_ParseDatastorePath(src, &datastoreName, &directoryName,
+ &fileName) < 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);
+ }
+ } else if (STRPREFIX(src, "/")) {
+ /* Found absolute path */
+ absolutePath = strdup(src);
+ } else {
+ /* Found relative path, this is not supported */
+ goto cleanup;
+ }
+
+ success = true;
+
+ cleanup:
+ if (! success) {
+ VIR_FREE(absolutePath);
+ }
+
+ VIR_FREE(datastoreName);
+ VIR_FREE(directoryName);
+ VIR_FREE(fileName);
+
+ return absolutePath;
+}
+
+static int
mymain(int argc, char **argv)
{
int result = 0;
@@ -157,7 +212,7 @@ mymain(int argc, char **argv)
return EXIT_FAILURE;
}
-# define DO_TEST(_in, _out, _version) \
+# define DO_TEST(_in, _out, _version) \
do { \
struct testInfo info = { _in, _out, _version }; \
virResetLastError(); \
@@ -173,6 +228,11 @@ mymain(int argc, char **argv)
return EXIT_FAILURE;
}
+ ctx.opaque = NULL;
+ ctx.parseFileName = NULL;
+ ctx.formatFileName = testFormatVMXFileName;
+ ctx.autodetectSCSIControllerModel = testAutodetectSCSIControllerModel;
+
DO_TEST("minimal", "minimal", esxVI_ProductVersion_ESX35);
DO_TEST("minimal-64bit", "minimal-64bit", esxVI_ProductVersion_ESX35);
--
1.7.0.4
14 years, 3 months