[libvirt] [PATCH] Force FLR on for buggy SR-IOV devices.
by Chris Lalancette
Some buggy PCI devices actually support FLR, but
forget to advertise that fact in their PCI config space.
However, Virtual Functions on SR-IOV devices are
*required* to support FLR by the spec, so force has_flr
on if this is a virtual function.
Signed-off-by: Chris Lalancette <clalance(a)redhat.com>
---
src/util/pci.c | 48 ++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 44 insertions(+), 4 deletions(-)
diff --git a/src/util/pci.c b/src/util/pci.c
index c45b179..41e91af 100644
--- a/src/util/pci.c
+++ b/src/util/pci.c
@@ -183,6 +183,16 @@ pciOpenConfig(pciDevice *dev)
return 0;
}
+static void
+pciCloseConfig(pciDevice *dev)
+{
+ if (!dev)
+ return;
+
+ if (dev->fd >= 0)
+ close(dev->fd);
+}
+
static int
pciRead(pciDevice *dev, unsigned pos, uint8_t *buf, unsigned buflen)
{
@@ -380,11 +390,16 @@ pciFindExtendedCapabilityOffset(pciDevice *dev, unsigned capability)
return 0;
}
-static unsigned
+/* detects whether this device has FLR. Returns 0 if the device does
+ * not have FLR, 1 if it does, and -1 on error
+ */
+static int
pciDetectFunctionLevelReset(pciDevice *dev)
{
uint32_t caps;
uint8_t pos;
+ char *path;
+ int found;
/* The PCIe Function Level Reset capability allows
* individual device functions to be reset without
@@ -413,6 +428,25 @@ pciDetectFunctionLevelReset(pciDevice *dev)
}
}
+ /* there are some buggy devices that do support FLR, but forget to
+ * advertise that fact in their capabilities. However, FLR is *required*
+ * to be present for virtual functions (VFs), so if we see that this
+ * device is a VF, we just assume FLR works
+ */
+
+ if (virAsprintf(&path, PCI_SYSFS "devices/%s/physfn", dev->name) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ found = virFileExists(path);
+ VIR_FREE(path);
+ if (found) {
+ VIR_DEBUG("%s %s: buggy device didn't advertise FLR, but is a VF; forcing flr on",
+ dev->id, dev->name);
+ return 1;
+ }
+
VIR_DEBUG("%s %s: no FLR capability found", dev->id, dev->name);
return 0;
@@ -626,6 +660,8 @@ pciTryPowerManagementReset(pciDevice *dev)
static int
pciInitDevice(pciDevice *dev)
{
+ int flr;
+
if (pciOpenConfig(dev) < 0) {
virReportSystemError(errno,
_("Failed to open config space file '%s'"),
@@ -635,7 +671,12 @@ pciInitDevice(pciDevice *dev)
dev->pcie_cap_pos = pciFindCapabilityOffset(dev, PCI_CAP_ID_EXP);
dev->pci_pm_cap_pos = pciFindCapabilityOffset(dev, PCI_CAP_ID_PM);
- dev->has_flr = pciDetectFunctionLevelReset(dev);
+ flr = pciDetectFunctionLevelReset(dev);
+ if (flr < 0) {
+ pciCloseConfig(dev);
+ return flr;
+ }
+ dev->has_flr = flr;
dev->has_pm_reset = pciDetectPowerManagementReset(dev);
dev->initted = 1;
return 0;
@@ -1098,8 +1139,7 @@ pciFreeDevice(pciDevice *dev)
if (!dev)
return;
VIR_DEBUG("%s %s: freeing", dev->id, dev->name);
- if (dev->fd >= 0)
- close(dev->fd);
+ pciCloseConfig(dev);
VIR_FREE(dev);
}
--
1.7.1.1
14 years, 4 months
[libvirt] [RFC PATCH 0/4] fix secondary bus reset with active devices logic
by Chris Wright
The current logic can allow libvirt to issue a secondary bus reset
despite the host having devices on the same bus as a device that's being
assigned to a guest. The following patches refactor the code a little
and then update the secondary bus reset logic to properly deal with
active devices. This has been lightly tested, testing is still incomplete,
hence the RFC to get any style comments out of the way once testing
verifies this is working as expected.
The following scenarios have been successfully tested:
- Do not issue a secondary bus reset:
- start guest w/ domain conf including hostdev that shares bus w/
devices owned by host
- use attach-device to dynamically add hostdev to guest, hostdev
shares bus w/ devices owned by host
- attempt to node-reset a device assigned to guest
- Issue a secondary bus reset:
- start guest w/ domain conf including all devices on bus[1]
- use attach-device to dynamically add hostdev to guest, hostdev
does not share bus with other devices
Not yet tested:
- Issue a secondary bus reset:
- when shutting down domain
- when detaching device from domain
[1] guest did not succesfully start w/ these devices, unclear if this
patch series is implicated.
Chris Wright (4):
qemuGetPciHostDeviceList take hostdev list directly
Add helpers qemuPrepareHostdevPCIDevices and qemuDomainReAttachHostdevDevices
qemudDomainAttachHostPciDevice refactor to use new helpers
pciResetDevice: use inactive devices to determine safe reset
src/qemu/qemu_driver.c | 87 ++++++++++++++++++++----------------------------
src/util/pci.c | 20 ++++++-----
src/util/pci.h | 3 +-
src/xen/xen_driver.c | 2 +-
4 files changed, 50 insertions(+), 62 deletions(-)
14 years, 4 months
[libvirt] libvirt on x64
by Tavares, John
I just logged onto the first X64 based machine with libvirt (0.3.3-18.5) installed on it and I am only seeing the X64 based version of the shared library. Here is what I am seeing:
$ rpm -qal libvirt | grep libvirt.so
/usr/lib64/libvirt.so.0
/usr/lib64/libvirt.so.0.3.3
Is there any reason why the 32-bit version is not also installed?? My application is 32-bit based, so it will not work on this hardware because of this.
Thanks.
John
14 years, 4 months
[libvirt] [PATCH] build: fix VPATH builds
by Eric Blake
After the recent libvirt-qemu library addition, VPATH builds fail with:
CC libvirt_qemu_la-libvirt-qemu.lo
In file included from ../../src/libvirt-qemu.c:29:
../../include/libvirt/libvirt-qemu.h:17:22: error: libvirt.h: No such file or directory
...
CCLD libvirt-qmeu.la
/usr/bin/ld: cannot open linker script file libvirt_qemu.syms: No such file or directory
This fixes both issues (there are still some documentation VPATH issues,
but those don't show up with 'make all').
* configure.ac (LIBVIRT_QEMU_SYMBOL_FILE): While libvirt.syms is
generated and lives in $(builddir), libvirt_qemu.syms is static
and lives in $(srcdir).
* include/libvirt/libvirt-qemu.h (includes): Pull in libvirt.h via
the public location, since this is a public header.
---
Tested with both in-tree and VPATH builds.
Should libvirt-qemu.h be using <libvirt/libvirt.h> instead of
"libvirt/libvirt.h"?
configure.ac | 2 +-
include/libvirt/libvirt-qemu.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/configure.ac b/configure.ac
index 08b7eb6..98d2f6e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1833,7 +1833,7 @@ CYGWIN_EXTRA_PYTHON_LIBADD=
MINGW_EXTRA_LDFLAGS=
WIN32_EXTRA_CFLAGS=
LIBVIRT_SYMBOL_FILE=libvirt.syms
-LIBVIRT_QEMU_SYMBOL_FILE=libvirt_qemu.syms
+LIBVIRT_QEMU_SYMBOL_FILE='$(srcdir)/libvirt_qemu.syms'
case "$host" in
*-*-cygwin*)
CYGWIN_EXTRA_LDFLAGS="-no-undefined"
diff --git a/include/libvirt/libvirt-qemu.h b/include/libvirt/libvirt-qemu.h
index d21fd92..9c191c7 100644
--- a/include/libvirt/libvirt-qemu.h
+++ b/include/libvirt/libvirt-qemu.h
@@ -14,7 +14,7 @@
#ifndef __VIR_QEMU_H__
# define __VIR_QEMU_H__
-# include "libvirt.h"
+# include "libvirt/libvirt.h"
# ifdef __cplusplus
extern "C" {
--
1.7.1.1
14 years, 4 months
[libvirt] [PATCH] Force FLR on for buggy SR-IOV devices.
by Chris Lalancette
Some buggy PCI devices actually support FLR, but
forget to advertise that fact in their PCI config space.
However, Virtual Functions on SR-IOV devices are
*required* to support FLR by the spec, so force has_flr
on if this is a virtual function.
Signed-off-by: Chris Lalancette <clalance(a)redhat.com>
---
src/util/pci.c | 22 ++++++++++++++++++++++
1 files changed, 22 insertions(+), 0 deletions(-)
diff --git a/src/util/pci.c b/src/util/pci.c
index c45b179..4bfad2c 100644
--- a/src/util/pci.c
+++ b/src/util/pci.c
@@ -385,6 +385,7 @@ pciDetectFunctionLevelReset(pciDevice *dev)
{
uint32_t caps;
uint8_t pos;
+ char *path;
/* The PCIe Function Level Reset capability allows
* individual device functions to be reset without
@@ -413,6 +414,27 @@ pciDetectFunctionLevelReset(pciDevice *dev)
}
}
+ /* there are some buggy devices that do support FLR, but forget to
+ * advertise that fact in their capabilities. However, FLR is *required*
+ * to be present for virtual functions (VFs), so if we see that this
+ * device is a VF, we just assume FLR works
+ */
+
+ if (virAsprintf(&path, PCI_SYSFS "devices/%s/physfn", dev->name) < 0) {
+ VIR_ERROR("Failed to allocate memory when checking FLR for device %s",
+ dev->id);
+ return 0;
+ }
+
+ if (virFileExists(path)) {
+ VIR_FREE(path);
+ VIR_DEBUG("%s %s: buggy device didn't advertise FLR, but is a VF; forcing flr on",
+ dev->id, dev->name);
+ return 1;
+ }
+
+ VIR_FREE(path);
+
VIR_DEBUG("%s %s: no FLR capability found", dev->id, dev->name);
return 0;
--
1.7.1.1
14 years, 4 months
[libvirt] Parameters for macros in docs?
by Justin Clift
Hi all,
The (autogenerated) docs aren't showing the parameters needed for the
libvirt macros.
For example, this is VIR_USE_CPU in the source:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/**
* VIR_USE_CPU:
* @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes) (IN/OUT)
* @cpu: the physical CPU number
*
* This macro is to be used in conjunction with virDomainPinVcpu() API.
* USE_CPU macro set the bit (CPU usable) of the related cpu in cpumap.
*/
#define VIR_USE_CPU(cpumap,cpu) (cpumap[(cpu)/8] |= (1<<((cpu)%8)))
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
In the API docs on the website, this is shown:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
VIR_USE_CPU
#define VIR_USE_CPU
This macro is to be used in conjunction with virDomainPinVcpu() API.
USE_CPU macro set the bit (CPU usable) of the related cpu in cpumap.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
To me, it makess sense to show the parameters needed for each macro.
The information is passed along by the Python doc generation script, but
is disregarded in the final XSLT transformation to produce the html
docs.
Wondering if that's on purpose, or are we ok to display the macro
parameters too?
Regards and best wishes,
Justin Clift
14 years, 4 months
[libvirt] IO controller groups?
by Jon Masters
Folks,
Anyone got any information about support in libvirt for automatic
handling of IO controller throttling/IO limits with recent kernels? I'd
love it if libvirt just supported assigning IO bandwidth automatically.
:)
Jon.
14 years, 4 months
[libvirt] [PATCH] esx: Support vSphere 4.1
by Matthias Bolte
Also accept version > 4.1, but output a warning.
---
src/esx/esx_driver.c | 12 ++++++++----
src/esx/esx_vi.c | 27 ++++++++++++++++++++++++---
src/esx/esx_vi.h | 10 ++++++++--
src/esx/esx_vmx.c | 9 +++++++++
4 files changed, 49 insertions(+), 9 deletions(-)
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index 5922cb6..e33976c 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -353,9 +353,11 @@ esxConnectToHost(esxPrivate *priv, virConnectAuthPtr auth,
if (expectedProductVersion == esxVI_ProductVersion_ESX) {
if (priv->host->productVersion != esxVI_ProductVersion_ESX35 &&
- priv->host->productVersion != esxVI_ProductVersion_ESX40) {
+ priv->host->productVersion != esxVI_ProductVersion_ESX40 &&
+ priv->host->productVersion != esxVI_ProductVersion_ESX41 &&
+ priv->host->productVersion != esxVI_ProductVersion_ESX4x) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
- _("%s is neither an ESX 3.5 host nor an ESX 4.0 host"),
+ _("%s is neither an ESX 3.5 host nor an ESX 4.x host"),
hostname);
goto cleanup;
}
@@ -462,10 +464,12 @@ esxConnectToVCenter(esxPrivate *priv, virConnectAuthPtr auth,
}
if (priv->vCenter->productVersion != esxVI_ProductVersion_VPX25 &&
- priv->vCenter->productVersion != esxVI_ProductVersion_VPX40) {
+ priv->vCenter->productVersion != esxVI_ProductVersion_VPX40 &&
+ priv->vCenter->productVersion != esxVI_ProductVersion_VPX41 &&
+ priv->vCenter->productVersion != esxVI_ProductVersion_VPX4x) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("%s is neither a vCenter 2.5 server nor a vCenter "
- "4.0 server"), hostname);
+ "4.x server"), hostname);
goto cleanup;
}
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index 8c43d67..69ba7a9 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -378,9 +378,16 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
ctx->apiVersion = esxVI_APIVersion_25;
} else if (STRPREFIX(ctx->service->about->apiVersion, "4.0")) {
ctx->apiVersion = esxVI_APIVersion_40;
+ } else if (STRPREFIX(ctx->service->about->apiVersion, "4.1")) {
+ ctx->apiVersion = esxVI_APIVersion_41;
+ } else if (STRPREFIX(ctx->service->about->apiVersion, "4.")) {
+ ctx->apiVersion = esxVI_APIVersion_4x;
+
+ VIR_WARN("Found untested VI API major/minor version '%s'",
+ ctx->service->about->apiVersion);
} else {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
- _("Expecting VI API major/minor version '2.5' or '4.0' "
+ _("Expecting VI API major/minor version '2.5' or '4.x' "
"but found '%s'"), ctx->service->about->apiVersion);
goto cleanup;
}
@@ -400,10 +407,17 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
ctx->productVersion = esxVI_ProductVersion_ESX35;
} else if (STRPREFIX(ctx->service->about->version, "4.0")) {
ctx->productVersion = esxVI_ProductVersion_ESX40;
+ } else if (STRPREFIX(ctx->service->about->version, "4.1")) {
+ ctx->productVersion = esxVI_ProductVersion_ESX41;
+ } else if (STRPREFIX(ctx->service->about->version, "4.")) {
+ ctx->productVersion = esxVI_ProductVersion_ESX4x;
+
+ VIR_WARN("Found untested ESX major/minor version '%s'",
+ ctx->service->about->version);
} else {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting ESX major/minor version '3.5' or "
- "'4.0' but found '%s'"),
+ "'4.x' but found '%s'"),
ctx->service->about->version);
goto cleanup;
}
@@ -412,9 +426,16 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
ctx->productVersion = esxVI_ProductVersion_VPX25;
} else if (STRPREFIX(ctx->service->about->version, "4.0")) {
ctx->productVersion = esxVI_ProductVersion_VPX40;
+ } else if (STRPREFIX(ctx->service->about->version, "4.1")) {
+ ctx->productVersion = esxVI_ProductVersion_VPX41;
+ } else if (STRPREFIX(ctx->service->about->version, "4.")) {
+ ctx->productVersion = esxVI_ProductVersion_VPX4x;
+
+ VIR_WARN("Found untested VPX major/minor version '%s'",
+ ctx->service->about->version);
} else {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
- _("Expecting VPX major/minor version '2.5' or '4.0' "
+ _("Expecting VPX major/minor version '2.5' or '4.x' "
"but found '%s'"), ctx->service->about->version);
goto cleanup;
}
diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h
index f5e89e9..9eb5094 100644
--- a/src/esx/esx_vi.h
+++ b/src/esx/esx_vi.h
@@ -94,7 +94,9 @@ enum _esxVI_APIVersion {
esxVI_APIVersion_Undefined = 0,
esxVI_APIVersion_Unknown,
esxVI_APIVersion_25,
- esxVI_APIVersion_40
+ esxVI_APIVersion_40,
+ esxVI_APIVersion_41,
+ esxVI_APIVersion_4x /* > 4.1 */
};
/*
@@ -110,10 +112,14 @@ enum _esxVI_ProductVersion {
esxVI_ProductVersion_ESX = (1 << 1) << 16,
esxVI_ProductVersion_ESX35 = esxVI_ProductVersion_ESX | 1,
esxVI_ProductVersion_ESX40 = esxVI_ProductVersion_ESX | 2,
+ esxVI_ProductVersion_ESX41 = esxVI_ProductVersion_ESX | 3,
+ esxVI_ProductVersion_ESX4x = esxVI_ProductVersion_ESX | 4, /* > 4.1 */
esxVI_ProductVersion_VPX = (1 << 2) << 16,
esxVI_ProductVersion_VPX25 = esxVI_ProductVersion_VPX | 1,
- esxVI_ProductVersion_VPX40 = esxVI_ProductVersion_VPX | 2
+ esxVI_ProductVersion_VPX40 = esxVI_ProductVersion_VPX | 2,
+ esxVI_ProductVersion_VPX41 = esxVI_ProductVersion_VPX | 3,
+ esxVI_ProductVersion_VPX4x = esxVI_ProductVersion_VPX | 4 /* > 4.1 */
};
enum _esxVI_Occurrence {
diff --git a/src/esx/esx_vmx.c b/src/esx/esx_vmx.c
index e075149..c63b159 100644
--- a/src/esx/esx_vmx.c
+++ b/src/esx/esx_vmx.c
@@ -1184,6 +1184,7 @@ esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
* 4 7 API
* ESX 3.5 + 2.5
* ESX 4.0 + + 4.0
+ * ESX 4.1 + + 4.1
* GSX 2.0 + + 2.5
*/
switch (productVersion) {
@@ -1201,7 +1202,9 @@ esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
case esxVI_ProductVersion_GSX20:
case esxVI_ProductVersion_ESX40:
+ case esxVI_ProductVersion_ESX41:
case esxVI_ProductVersion_VPX40:
+ case esxVI_ProductVersion_VPX41:
if (virtualHW_version != 4 && virtualHW_version != 7) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting VMX entry 'virtualHW.version' to be 4 or 7 "
@@ -1212,6 +1215,10 @@ esxVMX_ParseConfig(esxVI_Context *ctx, virCapsPtr caps, const char *vmx,
break;
+ case esxVI_ProductVersion_ESX4x:
+ case esxVI_ProductVersion_VPX4x:
+ break;
+
default:
ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Unexpected product version"));
@@ -2702,6 +2709,8 @@ esxVMX_FormatConfig(esxVI_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
case esxVI_ProductVersion_GSX20:
case esxVI_ProductVersion_ESX40:
+ case esxVI_ProductVersion_ESX41:
+ case esxVI_ProductVersion_ESX4x:
virBufferAddLit(&buffer, "virtualHW.version = \"7\"\n");
break;
--
1.7.0.4
14 years, 4 months
[libvirt] [PATCH] esx: Don't ignore the vcenter query parameter
by Matthias Bolte
Since 070f61002f47b602c15d1e4950a122ac9edefe1b the vcenter query
parameter has been ignored, because the refactoring to use
esxUtil_ParseQuery was incomplete. This effectively broke migration,
because the vcenter query parameter is essential for a migration.
---
src/esx/esx_driver.c | 9 ++++++++-
1 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index acf8908..33f421d 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -475,11 +475,18 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED)
}
/* Login to vCenter */
- if (vCenter != NULL) {
+ if (parsedQuery->vCenter != NULL) {
VIR_FREE(url);
VIR_FREE(password);
VIR_FREE(username);
+ vCenter = strdup(parsedQuery->vCenter);
+
+ if (vCenter == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
/* If a vCenter is specified resolve the hostname */
if (STRNEQ(vCenter, "*") &&
esxUtil_ResolveHostname(vCenter, vCenterIpAddress,
--
1.7.0.4
14 years, 4 months
[libvirt] [PATCH v2] esx: Add autodetection for the SCSI controller model
by Matthias Bolte
This works for file-backed SCSI disk device with a datastore
related source path.
---
v2:
- check that ESX reports the same controller model for all disks attached to
the SCSI controller, otherwise let autodetection fail
docs/drvesx.html.in | 9 ++
docs/schemas/domain.rng | 1 +
src/conf/domain_conf.c | 1 +
src/conf/domain_conf.h | 1 +
src/esx/esx_vi_generator.input | 149 +++++++++++++++++++++++
src/esx/esx_vi_generator.py | 3 +
src/esx/esx_vmx.c | 256 +++++++++++++++++++++++++++++++++++++---
src/esx/esx_vmx.h | 8 +-
8 files changed, 407 insertions(+), 21 deletions(-)
diff --git a/docs/drvesx.html.in b/docs/drvesx.html.in
index 88c70bc..e8cee77 100644
--- a/docs/drvesx.html.in
+++ b/docs/drvesx.html.in
@@ -292,6 +292,15 @@ ethernet0.checkMACAddress = "false"
<h4>SCSI controller models</h4>
<dl>
+ <dt><code>auto</code></dt>
+ <dd>
+ This isn't a actual controller model. If specified the ESX driver
+ tries to detect the SCSI controller model referenced in the
+ <code>.vmdk</code> file and use it. Autodetection fails when a
+ SCSI controller has multiple disks attached and the SCSI controller
+ models referenced in the <code>.vmdk</code> files are inconsistent.
+ <span class="since">Since 0.8.3</span>
+ </dd>
<dt><code>buslogic</code></dt>
<dd>
BusLogic SCSI controller for older guests.
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index 6240518..7be10df 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -673,6 +673,7 @@
<optional>
<attribute name="model">
<choice>
+ <value>auto</value>
<value>buslogic</value>
<value>lsilogic</value>
<value>lsisas1068</value>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 6ebf982..bc579ca 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -140,6 +140,7 @@ VIR_ENUM_IMPL(virDomainController, VIR_DOMAIN_CONTROLLER_TYPE_LAST,
"virtio-serial")
VIR_ENUM_IMPL(virDomainControllerModel, VIR_DOMAIN_CONTROLLER_MODEL_LAST,
+ "auto",
"buslogic",
"lsilogic",
"lsisas1068",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 4abe376..984f65b 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -196,6 +196,7 @@ enum virDomainControllerType {
enum virDomainControllerModel {
+ VIR_DOMAIN_CONTROLLER_MODEL_AUTO,
VIR_DOMAIN_CONTROLLER_MODEL_BUSLOGIC,
VIR_DOMAIN_CONTROLLER_MODEL_LSILOGIC,
VIR_DOMAIN_CONTROLLER_MODEL_LSISAS1068,
diff --git a/src/esx/esx_vi_generator.input b/src/esx/esx_vi_generator.input
index ff65178..b4b33f6 100644
--- a/src/esx/esx_vi_generator.input
+++ b/src/esx/esx_vi_generator.input
@@ -184,6 +184,40 @@ object Event
end
+object FileInfo
+ String path r
+ Long fileSize o
+ DateTime modification o
+end
+
+
+object FileQuery
+end
+
+
+object FileQueryFlags
+ Boolean fileType r
+ Boolean fileSize r
+ Boolean modification r
+end
+
+
+object FloppyImageFileInfo extends FileInfo
+end
+
+
+object FloppyImageFileQuery extends FileQuery
+end
+
+
+object FolderFileInfo extends FileInfo
+end
+
+
+object FolderFileQuery extends FileQuery
+end
+
+
object HostCpuIdInfo
Int level r
String vendor o
@@ -194,6 +228,22 @@ object HostCpuIdInfo
end
+object HostDatastoreBrowserSearchResults
+ ManagedObjectReference datastore o
+ String folderPath o
+ FileInfo file ol
+end
+
+
+object HostDatastoreBrowserSearchSpec
+ FileQuery query ol
+ FileQueryFlags details o
+ Boolean searchCaseInsensitive o
+ String matchPattern ol
+ Boolean sortFoldersFirst o
+end
+
+
object HostFileSystemVolume
String type r
String name r
@@ -225,6 +275,14 @@ object HostVmfsVolume extends HostFileSystemVolume
end
+object IsoImageFileInfo extends FileInfo
+end
+
+
+object IsoImageFileQuery extends FileQuery
+end
+
+
object LocalDatastoreInfo extends DatastoreInfo
String path o
end
@@ -424,6 +482,14 @@ object TaskInfo
end
+object TemplateConfigFileInfo extends VmConfigFileInfo
+end
+
+
+object TemplateConfigFileQuery extends VmConfigFileQuery
+end
+
+
object TraversalSpec extends SelectionSpec
String type r
String path r
@@ -502,6 +568,82 @@ object VirtualMachineSnapshotTree
end
+object VmConfigFileInfo extends FileInfo
+ Int configVersion o
+end
+
+
+object VmConfigFileQuery extends FileQuery
+ VmConfigFileQueryFilter filter o
+ VmConfigFileQueryFlags details o
+end
+
+
+object VmConfigFileQueryFilter
+ Int matchConfigVersion ol
+end
+
+
+object VmConfigFileQueryFlags
+ Boolean configVersion r
+end
+
+
+object VmDiskFileInfo extends FileInfo
+ String diskType o
+ Long capacityKb o
+ Int hardwareVersion o
+ String controllerType o
+ String diskExtents ol
+end
+
+
+object VmDiskFileQuery extends FileQuery
+ VmDiskFileQueryFilter filter o
+ VmDiskFileQueryFlags details o
+end
+
+
+object VmDiskFileQueryFilter
+ String diskType ol
+ Int matchHardwareVersion ol
+ String controllerType ol
+end
+
+
+object VmDiskFileQueryFlags
+ Boolean diskType r
+ Boolean capacityKb r
+ Boolean hardwareVersion r
+ Boolean controllerType o
+ Boolean diskExtents o
+end
+
+
+object VmLogFileInfo extends FileInfo
+end
+
+
+object VmLogFileQuery extends FileQuery
+end
+
+
+object VmNvramFileInfo extends FileInfo
+end
+
+
+object VmNvramFileQuery extends FileQuery
+end
+
+
+object VmSnapshotFileInfo extends FileInfo
+end
+
+
+object VmSnapshotFileQuery extends FileQuery
+end
+
+
object VmfsDatastoreInfo extends DatastoreInfo
HostVmfsVolume vmfs o
end
@@ -658,6 +800,13 @@ method RevertToSnapshot_Task returns ManagedObjectReference r
end
+method SearchDatastore_Task returns ManagedObjectReference r
+ ManagedObjectReference _this r
+ String datastorePath r
+ HostDatastoreBrowserSearchSpec searchSpec o
+end
+
+
method SessionIsActive returns Boolean r
ManagedObjectReference _this:SessionManager r
String sessionID r
diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py
index ff3e3d1..82bc9b6 100755
--- a/src/esx/esx_vi_generator.py
+++ b/src/esx/esx_vi_generator.py
@@ -1123,7 +1123,10 @@ additional_enum_features = { "ManagedEntityStatus" : Enum.FEATURE__ANY_TYPE
additional_object_features = { "DatastoreInfo" : Object.FEATURE__ANY_TYPE | Object.FEATURE__DYNAMIC_CAST,
"Event" : Object.FEATURE__LIST,
+ "FileInfo" : Object.FEATURE__DYNAMIC_CAST,
+ "FileQuery" : Object.FEATURE__DYNAMIC_CAST,
"HostCpuIdInfo" : Object.FEATURE__ANY_TYPE | Object.FEATURE__LIST,
+ "HostDatastoreBrowserSearchResults" : Object.FEATURE__ANY_TYPE,
"ManagedObjectReference" : Object.FEATURE__ANY_TYPE,
"ObjectContent" : Object.FEATURE__DEEP_COPY | Object.FEATURE__LIST,
"PerfCounterInfo" : Object.FEATURE__LIST,
diff --git a/src/esx/esx_vmx.c b/src/esx/esx_vmx.c
index c69e116..9035233 100644
--- a/src/esx/esx_vmx.c
+++ b/src/esx/esx_vmx.c
@@ -29,6 +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"
@@ -433,6 +434,7 @@ def->parallels[0]...
* are actually SCSI controller models in the ESX case */
VIR_ENUM_DECL(esxVMX_SCSIControllerModel)
VIR_ENUM_IMPL(esxVMX_SCSIControllerModel, VIR_DOMAIN_CONTROLLER_MODEL_LAST,
+ "auto", /* just to match virDomainControllerModel, will never be used */
"buslogic",
"lsilogic",
"lsisas1068",
@@ -716,34 +718,244 @@ esxVMX_HandleLegacySCSIDiskDriverName(virDomainDefPtr def,
int
-esxVMX_GatherSCSIControllers(virDomainDefPtr def, int virtualDev[4],
- bool present[4])
+esxVMX_AutodetectSCSIControllerModel(esxVI_Context *ctx,
+ virDomainDiskDefPtr def, int *model)
{
- int i;
+ 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_ParseDatastoreRelatedPath(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_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,
+ int virtualDev[4], bool present[4])
+{
+ int result = -1;
+ int i, k;
virDomainDiskDefPtr disk;
- virDomainControllerDefPtr controller = NULL;
+ virDomainControllerDefPtr controller;
+ bool controllerHasDisksAttached;
+ int count = 0;
+ int *autodetectedModels;
- for (i = 0; i < def->ndisks; ++i) {
- disk = def->disks[i];
+ if (VIR_ALLOC_N(autodetectedModels, def->ndisks) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ for (i = 0; i < def->ncontrollers; ++i) {
+ controller = def->controllers[i];
- if (disk->bus != VIR_DOMAIN_DISK_BUS_SCSI) {
+ if (controller->type != VIR_DOMAIN_CONTROLLER_TYPE_SCSI) {
+ // skip non-SCSI controllers
continue;
}
- controller = NULL;
+ controllerHasDisksAttached = false;
- for (i = 0; i < def->ncontrollers; ++i) {
- if (def->controllers[i]->idx == disk->info.addr.drive.controller) {
- controller = def->controllers[i];
+ for (k = 0; k < def->ndisks; ++k) {
+ disk = def->disks[k];
+
+ if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI &&
+ disk->info.addr.drive.controller == controller->idx) {
+ controllerHasDisksAttached = true;
break;
}
}
- if (controller == NULL) {
- ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
- _("Missing SCSI controller for index %d"),
- disk->info.addr.drive.controller);
- return -1;
+ if (! controllerHasDisksAttached) {
+ // skip SCSI controllers without attached disks
+ continue;
+ }
+
+ if (ctx != NULL &&
+ controller->model == VIR_DOMAIN_CONTROLLER_MODEL_AUTO) {
+ count = 0;
+
+ // try to autodetect the SCSI controller model by collecting
+ // SCSI controller model of all disks attached to this controller
+ for (k = 0; k < def->ndisks; ++k) {
+ disk = def->disks[k];
+
+ if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI &&
+ disk->info.addr.drive.controller == controller->idx) {
+ if (esxVMX_AutodetectSCSIControllerModel
+ (ctx, disk, &autodetectedModels[count]) < 0) {
+ goto cleanup;
+ }
+
+ ++count;
+ }
+ }
+
+ // autodetection fails when the disks attached to one controller
+ // have inconsistent SCSI controller models
+ for (k = 0; k < count; ++k) {
+ if (autodetectedModels[k] != autodetectedModels[0]) {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Disks on SCSI controller %d have inconsistent "
+ "controller models, cannot autodetect model"),
+ controller->idx);
+ goto cleanup;
+ }
+ }
+
+ controller->model = autodetectedModels[0];
}
if (controller->model != -1 &&
@@ -756,14 +968,19 @@ esxVMX_GatherSCSIControllers(virDomainDefPtr def, int virtualDev[4],
"'controller' to be 'buslogic' or 'lsilogic' or "
"'lsisas1068' or 'vmpvscsi' but found '%s'"),
virDomainControllerModelTypeToString(controller->model));
- return -1;
+ goto cleanup;
}
present[controller->idx] = true;
virtualDev[controller->idx] = controller->model;
}
- return 0;
+ result = 0;
+
+ cleanup:
+ VIR_FREE(autodetectedModels);
+
+ return result;
}
@@ -2620,7 +2837,8 @@ esxVMX_FormatConfig(esxVI_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
}
}
- if (esxVMX_GatherSCSIControllers(def, scsi_virtualDev, scsi_present) < 0) {
+ if (esxVMX_GatherSCSIControllers(ctx, def, scsi_virtualDev,
+ scsi_present) < 0) {
goto failure;
}
diff --git a/src/esx/esx_vmx.h b/src/esx/esx_vmx.h
index a9015fb..3ccae7a 100644
--- a/src/esx/esx_vmx.h
+++ b/src/esx/esx_vmx.h
@@ -48,8 +48,12 @@ esxVMX_HandleLegacySCSIDiskDriverName(virDomainDefPtr def,
virDomainDiskDefPtr disk);
int
-esxVMX_GatherSCSIControllers(virDomainDefPtr def, int virtualDev[4],
- bool present[4]);
+esxVMX_AutodetectSCSIControllerModel(esxVI_Context *ctx,
+ virDomainDiskDefPtr def, int *model);
+
+int
+esxVMX_GatherSCSIControllers(esxVI_Context *ctx, virDomainDefPtr def,
+ int virtualDev[4], bool present[4]);
char *
esxVMX_AbsolutePathToDatastoreRelatedPath(esxVI_Context *ctx,
--
1.7.0.4
14 years, 4 months