[libvirt] [PATCH] Move the tunnelled migration unix socket to /var/lib/libvirt/qemu
by Chris Lalancette
Since the qemu process is running as qemu:qemu, it can't actually
look at the unix socket in /var/run/libvirt/qemu which is owned by
root and has permission 700. Move the unix socket to
/var/lib/libvirt/qemu, which is already owned by qemu:qemu.
Thanks to Justin Clift for test this out for me.
Signed-off-by: Chris Lalancette <clalance(a)redhat.com>
---
src/qemu/qemu_driver.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index b6b6633..007b09a 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -10470,7 +10470,7 @@ qemudDomainMigratePrepareTunnel(virConnectPtr dconn,
vm->def->id = -1;
if (virAsprintf(&unixfile, "%s/qemu.tunnelmigrate.dest.%s",
- driver->stateDir, vm->def->name) < 0) {
+ driver->libDir, vm->def->name) < 0) {
virReportOOMError();
goto endjob;
}
@@ -10941,7 +10941,7 @@ static int doTunnelMigrate(virDomainPtr dom,
/* Stage 1. setup local support infrastructure */
if (virAsprintf(&unixfile, "%s/qemu.tunnelmigrate.src.%s",
- driver->stateDir, vm->def->name) < 0) {
+ driver->libDir, vm->def->name) < 0) {
virReportOOMError();
goto cleanup;
}
--
1.7.2.1
14 years, 8 months
[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, 8 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, 8 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, 8 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, 8 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, 8 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, 8 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, 8 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, 8 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, 8 months