[libvirt] [python v3 PATCH] Add dict check for setTime and allow pass 'seconds' parameter
by Luyao Huang
When pass None or a empty dictionary to time, it will
report error.Allow a one-element dictionary which
contains 'seconds',setting JUST seconds will do the
sane thing of passing 0 for nseconds, instead of
erroring out.If dict have a unkown key, it will report error.
Signed-off-by: Luyao Huang <lhuang(a)redhat.com>
---
libvirt-override-virDomain.py | 6 +++---
libvirt-override.c | 41 +++++++++++++++++++++++++++++------------
2 files changed, 32 insertions(+), 15 deletions(-)
diff --git a/libvirt-override-virDomain.py b/libvirt-override-virDomain.py
index a50ec0d..2a4c4c9 100644
--- a/libvirt-override-virDomain.py
+++ b/libvirt-override-virDomain.py
@@ -66,9 +66,9 @@
if ret == -1: raise libvirtError ('virDomainGetTime() failed', dom=self)
return ret
- def setTime(self, time=None, flags=0):
- """Set guest time to the given value. @time is a dict conatining
- 'seconds' field for seconds and 'nseconds' field for nanosecons """
+ def setTime(self, time, flags=0):
+ """Set guest time to the given value. @time is a dict containing
+ 'seconds' field for seconds and 'nseconds' field for nanoseconds """
ret = libvirtmod.virDomainSetTime(self._o, time, flags)
if ret == -1: raise libvirtError ('virDomainSetTime() failed', dom=self)
return ret
diff --git a/libvirt-override.c b/libvirt-override.c
index a53b46f..1d1714a 100644
--- a/libvirt-override.c
+++ b/libvirt-override.c
@@ -7784,6 +7784,8 @@ static PyObject *
libvirt_virDomainSetTime(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
PyObject *py_retval = NULL;
PyObject *pyobj_domain;
+ PyObject *pyobj_seconds;
+ PyObject *pyobj_nseconds;
PyObject *py_dict;
virDomainPtr domain;
long long seconds = 0;
@@ -7797,25 +7799,40 @@ libvirt_virDomainSetTime(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
return NULL;
domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
- py_dict_size = PyDict_Size(py_dict);
+ if (!PyDict_Check(py_dict)) {
+ PyErr_Format(PyExc_TypeError, "time must be dict");
+ return NULL;
+ }
- if (py_dict_size == 2) {
- PyObject *pyobj_seconds, *pyobj_nseconds;
+ py_dict_size = PyDict_Size(py_dict);
- if (!(pyobj_seconds = PyDict_GetItemString(py_dict, "seconds")) ||
- (libvirt_longlongUnwrap(pyobj_seconds, &seconds) < 0)) {
- PyErr_Format(PyExc_LookupError, "malformed or missing 'seconds'");
+ if ((pyobj_seconds = PyDict_GetItemString(py_dict, "seconds")) != NULL) {
+ if (libvirt_longlongUnwrap(pyobj_seconds, &seconds) < 0) {
+ PyErr_Format(PyExc_LookupError, "malformed 'seconds'");
goto cleanup;
}
+ } else {
+ PyErr_Format(PyExc_LookupError, "Dictionary must contains "
+ "'seconds'");
+ goto cleanup;
+ }
- if (!(pyobj_nseconds = PyDict_GetItemString(py_dict, "nseconds")) ||
- (libvirt_uintUnwrap(pyobj_nseconds, &nseconds) < 0)) {
- PyErr_Format(PyExc_LookupError, "malformed or missing 'nseconds'");
+ if ((pyobj_nseconds = PyDict_GetItemString(py_dict, "nseconds")) != NULL) {
+ if (libvirt_uintUnwrap(pyobj_nseconds, &nseconds) < 0) {
+ PyErr_Format(PyExc_LookupError, "malformed 'nseconds'");
goto cleanup;
}
- } else if (py_dict_size > 0) {
- PyErr_Format(PyExc_LookupError, "Dictionary must contain "
- "'seconds' and 'nseconds'");
+ } else if (py_dict_size == 1) {
+ nseconds = 0;
+ } else {
+ PyErr_Format(PyExc_LookupError, "Dictionary contains "
+ "unknown key");
+ goto cleanup;
+ }
+
+ if (py_dict_size > 2) {
+ PyErr_Format(PyExc_LookupError, "Dictionary contains "
+ "unknown key");
goto cleanup;
}
--
1.8.3.1
10 years
[libvirt] [PATCH v2] esx: Simplify VI (vSphere) API and VMware product version handling
by Matthias Bolte
Store version numbers in this format
version = 1000000 * major + 1000 * minor + micro
produced by virParseVersionString instead of dedicated enums.
Split the complex esxVI_ProductVersion enum into a simpler
esxVI_ProductLine enum and a product version number.
Relax API and product version number checks to accept everything that
is equal or greater than the supported minimum version. VMware ESX
went through 3 major versions and the vSphere API always stayed
backward compatible. This commit assumes that this will also be true
for future VMware ESX versions.
Also reword error messages in esxConnectTo* to say what was expected
and what was found instead (suggested by Richard W.M. Jones).
---
v2: - Fix copy&paste accident that replaced hostname with conn->uri->server
in esxConnectToVCenter
- Fix and improve commit message
src/esx/esx_driver.c | 59 +++++---------
src/esx/esx_vi.c | 215 ++++++++++++++++++++++++++-------------------------
src/esx/esx_vi.h | 55 +++----------
3 files changed, 140 insertions(+), 189 deletions(-)
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index 39784b9..64265ed 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -646,9 +646,9 @@ esxConnectToHost(esxPrivate *priv,
esxVI_String *propertyNameList = NULL;
esxVI_ObjectContent *hostSystem = NULL;
esxVI_Boolean inMaintenanceMode = esxVI_Boolean_Undefined;
- esxVI_ProductVersion expectedProductVersion = STRCASEEQ(conn->uri->scheme, "esx")
- ? esxVI_ProductVersion_ESX
- : esxVI_ProductVersion_GSX;
+ esxVI_ProductLine expectedProductLine = STRCASEEQ(conn->uri->scheme, "esx")
+ ? esxVI_ProductLine_ESX
+ : esxVI_ProductLine_GSX;
if (!vCenterIpAddress || *vCenterIpAddress) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
@@ -695,25 +695,13 @@ esxConnectToHost(esxPrivate *priv,
goto cleanup;
}
- if (expectedProductVersion == esxVI_ProductVersion_ESX) {
- if (priv->host->productVersion != esxVI_ProductVersion_ESX35 &&
- priv->host->productVersion != esxVI_ProductVersion_ESX40 &&
- priv->host->productVersion != esxVI_ProductVersion_ESX41 &&
- priv->host->productVersion != esxVI_ProductVersion_ESX4x &&
- priv->host->productVersion != esxVI_ProductVersion_ESX50 &&
- priv->host->productVersion != esxVI_ProductVersion_ESX51 &&
- priv->host->productVersion != esxVI_ProductVersion_ESX5x) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("%s is neither an ESX 3.5, 4.x nor 5.x host"),
- conn->uri->server);
- goto cleanup;
- }
- } else { /* GSX */
- if (priv->host->productVersion != esxVI_ProductVersion_GSX20) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("%s isn't a GSX 2.0 host"), conn->uri->server);
- goto cleanup;
- }
+ if (priv->host->productLine != expectedProductLine) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Expecting '%s' to be a %s host, but found a %s host"),
+ conn->uri->server,
+ esxVI_ProductLineToDisplayName(expectedProductLine),
+ esxVI_ProductLineToDisplayName(priv->host->productLine));
+ goto cleanup;
}
/* Query the host for maintenance mode and vCenter IP address */
@@ -815,16 +803,12 @@ esxConnectToVCenter(esxPrivate *priv,
goto cleanup;
}
- if (priv->vCenter->productVersion != esxVI_ProductVersion_VPX25 &&
- priv->vCenter->productVersion != esxVI_ProductVersion_VPX40 &&
- priv->vCenter->productVersion != esxVI_ProductVersion_VPX41 &&
- priv->vCenter->productVersion != esxVI_ProductVersion_VPX4x &&
- priv->vCenter->productVersion != esxVI_ProductVersion_VPX50 &&
- priv->vCenter->productVersion != esxVI_ProductVersion_VPX51 &&
- priv->vCenter->productVersion != esxVI_ProductVersion_VPX5x) {
+ if (priv->vCenter->productLine != esxVI_ProductLine_VPX) {
virReportError(VIR_ERR_INTERNAL_ERROR,
- _("%s is neither a vCenter 2.5, 4.x nor 5.x server"),
- hostname);
+ _("Expecting '%s' to be a %s host but found a %s host"),
+ hostname,
+ esxVI_ProductLineToDisplayName(esxVI_ProductLine_VPX),
+ esxVI_ProductLineToDisplayName(priv->vCenter->productLine));
goto cleanup;
}
@@ -1217,14 +1201,7 @@ esxConnectGetVersion(virConnectPtr conn, unsigned long *version)
{
esxPrivate *priv = conn->privateData;
- if (virParseVersionString(priv->primary->service->about->version,
- version, false) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Could not parse version number from '%s'"),
- priv->primary->service->about->version);
-
- return -1;
- }
+ *version = priv->primary->productVersion;
return 0;
}
@@ -2934,7 +2911,7 @@ esxConnectDomainXMLToNative(virConnectPtr conn, const char *nativeFormat,
}
virtualHW_version = esxVI_ProductVersionToDefaultVirtualHWVersion
- (priv->primary->productVersion);
+ (priv->primary->productLine, priv->primary->productVersion);
if (virtualHW_version < 0) {
return NULL;
@@ -3190,7 +3167,7 @@ esxDomainDefineXML(virConnectPtr conn, const char *xml)
/* Build VMX from domain XML */
virtualHW_version = esxVI_ProductVersionToDefaultVirtualHWVersion
- (priv->primary->productVersion);
+ (priv->primary->productLine, priv->primary->productVersion);
if (virtualHW_version < 0) {
goto cleanup;
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index b00d8e7..d28b8e0 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -1040,98 +1040,77 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
return -1;
}
- if (STREQ(ctx->service->about->apiType, "HostAgent") ||
- STREQ(ctx->service->about->apiType, "VirtualCenter")) {
- if (STRPREFIX(ctx->service->about->apiVersion, "2.5")) {
- 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;
- } else if (STRPREFIX(ctx->service->about->apiVersion, "5.0")) {
- ctx->apiVersion = esxVI_APIVersion_50;
- } else if (STRPREFIX(ctx->service->about->apiVersion, "5.1")) {
- ctx->apiVersion = esxVI_APIVersion_51;
- } else if (STRPREFIX(ctx->service->about->apiVersion, "5.")) {
- ctx->apiVersion = esxVI_APIVersion_5x;
- } else {
+ if (STRNEQ(ctx->service->about->apiType, "HostAgent") &&
+ STRNEQ(ctx->service->about->apiType, "VirtualCenter")) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Expecting VI API type 'HostAgent' or 'VirtualCenter' "
+ "but found '%s'"), ctx->service->about->apiType);
+ return -1;
+ }
+
+ if (virParseVersionString(ctx->service->about->apiVersion,
+ &ctx->apiVersion, true) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not parse VI API version '%s'"),
+ ctx->service->about->apiVersion);
+ return -1;
+ }
+
+ if (ctx->apiVersion < 1000000 * 2 + 1000 * 5 /* 2.5 */) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Minimum supported %s version is %s but found version '%s'"),
+ "VI API", "2.5", ctx->service->about->apiVersion);
+ return -1;
+ }
+
+ if (virParseVersionString(ctx->service->about->version,
+ &ctx->productVersion, true) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not parse product version '%s'"),
+ ctx->service->about->version);
+ return -1;
+ }
+
+ if (STREQ(ctx->service->about->productLineId, "gsx")) {
+ if (ctx->productVersion < 1000000 * 2 + 1000 * 0 /* 2.0 */) {
virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Expecting VI API major/minor version '2.5', '4.x' or "
- "'5.x' but found '%s'"), ctx->service->about->apiVersion);
+ _("Minimum supported %s version is %s but found version '%s'"),
+ esxVI_ProductLineToDisplayName(esxVI_ProductLine_GSX),
+ "2.0", ctx->service->about->version);
return -1;
}
- if (STREQ(ctx->service->about->productLineId, "gsx")) {
- if (STRPREFIX(ctx->service->about->version, "2.0")) {
- ctx->productVersion = esxVI_ProductVersion_GSX20;
- } else {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Expecting GSX major/minor version '2.0' but "
- "found '%s'"), ctx->service->about->version);
- return -1;
- }
- } else if (STREQ(ctx->service->about->productLineId, "esx") ||
- STREQ(ctx->service->about->productLineId, "embeddedEsx")) {
- if (STRPREFIX(ctx->service->about->version, "3.5")) {
- 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;
- } else if (STRPREFIX(ctx->service->about->version, "5.0")) {
- ctx->productVersion = esxVI_ProductVersion_ESX50;
- } else if (STRPREFIX(ctx->service->about->version, "5.1")) {
- ctx->productVersion = esxVI_ProductVersion_ESX51;
- } else if (STRPREFIX(ctx->service->about->version, "5.")) {
- ctx->productVersion = esxVI_ProductVersion_ESX5x;
- } else {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Expecting ESX major/minor version '3.5', "
- "'4.x' or '5.x' but found '%s'"),
- ctx->service->about->version);
- return -1;
- }
- } else if (STREQ(ctx->service->about->productLineId, "vpx")) {
- if (STRPREFIX(ctx->service->about->version, "2.5")) {
- 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;
- } else if (STRPREFIX(ctx->service->about->version, "5.0")) {
- ctx->productVersion = esxVI_ProductVersion_VPX50;
- } else if (STRPREFIX(ctx->service->about->version, "5.1")) {
- ctx->productVersion = esxVI_ProductVersion_VPX51;
- } else if (STRPREFIX(ctx->service->about->version, "5.")) {
- ctx->productVersion = esxVI_ProductVersion_VPX5x;
- } else {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Expecting VPX major/minor version '2.5', '4.x' "
- "or '5.x' but found '%s'"),
- ctx->service->about->version);
- return -1;
- }
- } else {
+ ctx->productLine = esxVI_ProductLine_GSX;
+ } else if (STREQ(ctx->service->about->productLineId, "esx") ||
+ STREQ(ctx->service->about->productLineId, "embeddedEsx")) {
+ if (ctx->productVersion < 1000000 * 3 + 1000 * 5 /* 3.5 */) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Minimum supported %s version is %s but found version '%s'"),
+ esxVI_ProductLineToDisplayName(esxVI_ProductLine_ESX),
+ "3.5", ctx->service->about->version);
+ return -1;
+ }
+
+ ctx->productLine = esxVI_ProductLine_ESX;
+ } else if (STREQ(ctx->service->about->productLineId, "vpx")) {
+ if (ctx->productVersion < 1000000 * 2 + 1000 * 5 /* 2.5 */) {
virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Expecting product 'gsx' or 'esx' or 'embeddedEsx' "
- "or 'vpx' but found '%s'"),
- ctx->service->about->productLineId);
+ _("Minimum supported %s version is %s but found version '%s'"),
+ esxVI_ProductLineToDisplayName(esxVI_ProductLine_VPX),
+ "2.5", ctx->service->about->version);
return -1;
}
+
+ ctx->productLine = esxVI_ProductLine_VPX;
} else {
virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Expecting VI API type 'HostAgent' or 'VirtualCenter' "
- "but found '%s'"), ctx->service->about->apiType);
+ _("Expecting product 'gsx' or 'esx' or 'embeddedEsx' "
+ "or 'vpx' but found '%s'"),
+ ctx->service->about->productLineId);
return -1;
}
- if (ctx->productVersion & esxVI_ProductVersion_ESX) {
+ if (ctx->productLine == esxVI_ProductLine_ESX) {
/*
* FIXME: Actually this should be detected by really calling
* QueryVirtualDiskUuid and checking if a NotImplemented fault is
@@ -1142,7 +1121,7 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
ctx->hasQueryVirtualDiskUuid = true;
}
- if (ctx->productVersion & esxVI_ProductVersion_VPX) {
+ if (ctx->productLine == esxVI_ProductLine_VPX) {
ctx->hasSessionIsActive = true;
}
@@ -4770,9 +4749,33 @@ esxVI_ParseHostCpuIdInfo(esxVI_ParsedHostCpuIdInfo *parsedHostCpuIdInfo,
+const char *
+esxVI_ProductLineToDisplayName(esxVI_ProductLine productLine)
+{
+ switch (productLine) {
+ case esxVI_ProductLine_GSX:
+ return "Server/GSX";
+
+ case esxVI_ProductLine_ESX:
+ return "ESX(i)";
+
+ case esxVI_ProductLine_VPX:
+ return "vCenter/VPX";
+
+ default:
+ return "<unknown>";
+ }
+}
+
+
+
int
-esxVI_ProductVersionToDefaultVirtualHWVersion(esxVI_ProductVersion productVersion)
+esxVI_ProductVersionToDefaultVirtualHWVersion(esxVI_ProductLine productLine,
+ unsigned long productVersion)
{
+ /* product version == 1000000 * major + 1000 * minor + micro */
+ int major = productVersion / 1000000;
+
/*
* virtualHW.version compatibility matrix:
*
@@ -4785,35 +4788,39 @@ esxVI_ProductVersionToDefaultVirtualHWVersion(esxVI_ProductVersion productVersio
* ESX 5.5 + + + + + 5.5
* GSX 2.0 + + 2.5
*/
- switch (productVersion) {
- case esxVI_ProductVersion_ESX35:
- case esxVI_ProductVersion_VPX25:
- return 4;
-
- case esxVI_ProductVersion_GSX20:
- case esxVI_ProductVersion_ESX40:
- case esxVI_ProductVersion_ESX41:
- case esxVI_ProductVersion_VPX40:
- case esxVI_ProductVersion_VPX41:
+ switch (productLine) {
+ case esxVI_ProductLine_GSX:
return 7;
- case esxVI_ProductVersion_ESX4x:
- case esxVI_ProductVersion_VPX4x:
- return 7;
+ case esxVI_ProductLine_ESX:
+ switch (major) {
+ case 3:
+ return 4;
- case esxVI_ProductVersion_ESX50:
- case esxVI_ProductVersion_VPX50:
- return 8;
+ case 4:
+ return 7;
- case esxVI_ProductVersion_ESX51:
- case esxVI_ProductVersion_ESX5x:
- case esxVI_ProductVersion_VPX51:
- case esxVI_ProductVersion_VPX5x:
- return 8;
+ case 5:
+ default:
+ return 8;
+ }
+
+ case esxVI_ProductLine_VPX:
+ switch (major) {
+ case 2:
+ return 4;
+
+ case 4:
+ return 7;
+
+ case 5:
+ default:
+ return 8;
+ }
default:
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("Unexpected product version"));
+ _("Unexpected product line"));
return -1;
}
}
diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h
index dac36cd..b7f0160 100644
--- a/src/esx/esx_vi.h
+++ b/src/esx/esx_vi.h
@@ -75,8 +75,7 @@
-typedef enum _esxVI_APIVersion esxVI_APIVersion;
-typedef enum _esxVI_ProductVersion esxVI_ProductVersion;
+typedef enum _esxVI_ProductLine esxVI_ProductLine;
typedef enum _esxVI_Occurrence esxVI_Occurrence;
typedef struct _esxVI_ParsedHostCpuIdInfo esxVI_ParsedHostCpuIdInfo;
typedef struct _esxVI_CURL esxVI_CURL;
@@ -90,45 +89,10 @@ typedef struct _esxVI_List esxVI_List;
-enum _esxVI_APIVersion {
- esxVI_APIVersion_Undefined = 0,
- esxVI_APIVersion_Unknown,
- esxVI_APIVersion_25,
- esxVI_APIVersion_40,
- esxVI_APIVersion_41,
- esxVI_APIVersion_4x, /* > 4.1 */
- esxVI_APIVersion_50,
- esxVI_APIVersion_51,
- esxVI_APIVersion_5x /* > 5.1 */
-};
-
-/*
- * AAAABBBB: where AAAA0000 is the product and BBBB the version. this format
- * allows simple bitmask testing for a product independent of the version
- */
-enum _esxVI_ProductVersion {
- esxVI_ProductVersion_Undefined = 0,
-
- esxVI_ProductVersion_GSX = (1 << 0) << 16,
- esxVI_ProductVersion_GSX20 = esxVI_ProductVersion_GSX | 1,
-
- 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_ESX50 = esxVI_ProductVersion_ESX | 5,
- esxVI_ProductVersion_ESX51 = esxVI_ProductVersion_ESX | 6,
- esxVI_ProductVersion_ESX5x = esxVI_ProductVersion_ESX | 7, /* > 5.1 */
-
- esxVI_ProductVersion_VPX = (1 << 2) << 16,
- esxVI_ProductVersion_VPX25 = esxVI_ProductVersion_VPX | 1,
- esxVI_ProductVersion_VPX40 = esxVI_ProductVersion_VPX | 2,
- esxVI_ProductVersion_VPX41 = esxVI_ProductVersion_VPX | 3,
- esxVI_ProductVersion_VPX4x = esxVI_ProductVersion_VPX | 4, /* > 4.1 */
- esxVI_ProductVersion_VPX50 = esxVI_ProductVersion_VPX | 5,
- esxVI_ProductVersion_VPX51 = esxVI_ProductVersion_VPX | 6,
- esxVI_ProductVersion_VPX5x = esxVI_ProductVersion_VPX | 7 /* > 5.1 */
+enum _esxVI_ProductLine {
+ esxVI_ProductLine_GSX = 0,
+ esxVI_ProductLine_ESX,
+ esxVI_ProductLine_VPX
};
enum _esxVI_Occurrence {
@@ -226,8 +190,9 @@ struct _esxVI_Context {
char *username;
char *password;
esxVI_ServiceContent *service;
- esxVI_APIVersion apiVersion;
- esxVI_ProductVersion productVersion;
+ unsigned long apiVersion; /* = 1000000 * major + 1000 * minor + micro */
+ esxVI_ProductLine productLine;
+ unsigned long productVersion; /* = 1000000 * major + 1000 * minor + micro */
esxVI_UserSession *session; /* ... except the session ... */
virMutexPtr sessionLock; /* ... that is protected by this mutex */
esxVI_Datacenter *datacenter;
@@ -536,8 +501,10 @@ int esxVI_WaitForTaskCompletion(esxVI_Context *ctx,
int esxVI_ParseHostCpuIdInfo(esxVI_ParsedHostCpuIdInfo *parsedHostCpuIdInfo,
esxVI_HostCpuIdInfo *hostCpuIdInfo);
+const char *esxVI_ProductLineToDisplayName(esxVI_ProductLine productLine);
+
int esxVI_ProductVersionToDefaultVirtualHWVersion
- (esxVI_ProductVersion productVersion);
+ (esxVI_ProductLine productLine, unsigned long productVersion);
int esxVI_LookupHostInternetScsiHbaStaticTargetByName
(esxVI_Context *ctx, const char *name,
--
1.8.3.2
10 years
[libvirt] [[PATCH libvirt-java]] Implement Connect.listAllDomains
by Cédric Bosdonnat
From: Cédric Bosdonnat <cedric.bosdonnat(a)free.fr>
---
src/main/java/org/libvirt/Connect.java | 46 +++++++++++++++++++++++++
src/main/java/org/libvirt/jna/Libvirt.java | 2 ++
src/test/java/org/libvirt/TestJavaBindings.java | 1 +
3 files changed, 49 insertions(+)
diff --git a/src/main/java/org/libvirt/Connect.java b/src/main/java/org/libvirt/Connect.java
index fedc60e..390ed89 100644
--- a/src/main/java/org/libvirt/Connect.java
+++ b/src/main/java/org/libvirt/Connect.java
@@ -24,6 +24,7 @@ import com.sun.jna.Memory;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.LongByReference;
+import com.sun.jna.ptr.PointerByReference;
/**
* The Connect object represents a connection to a local or remote
@@ -33,6 +34,28 @@ import com.sun.jna.ptr.LongByReference;
*/
public class Connect {
+ static final class ListAllDomainsFlags {
+ static final int VIR_CONNECT_LIST_DOMAINS_ACTIVE = (1 << 0);
+ static final int VIR_CONNECT_LIST_DOMAINS_INACTIVE = (1 << 1);
+
+ static final int VIR_CONNECT_LIST_DOMAINS_PERSISTENT = (1 << 2);
+ static final int VIR_CONNECT_LIST_DOMAINS_TRANSIENT = (1 << 3);
+
+ static final int VIR_CONNECT_LIST_DOMAINS_RUNNING = (1 << 4);
+ static final int VIR_CONNECT_LIST_DOMAINS_PAUSED = (1 << 5);
+ static final int VIR_CONNECT_LIST_DOMAINS_SHUTOFF = (1 << 6);
+ static final int VIR_CONNECT_LIST_DOMAINS_OTHER = (1 << 7);
+
+ static final int VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE = (1 << 8);
+ static final int VIR_CONNECT_LIST_DOMAINS_NO_MANAGEDSAVE = (1 << 9);
+
+ static final int VIR_CONNECT_LIST_DOMAINS_AUTOSTART = (1 << 10);
+ static final int VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART = (1 << 11);
+
+ static final int VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT = (1 << 12);
+ static final int VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT = (1 << 13);
+ }
+
/**
* Get the version of a connection.
*
@@ -758,6 +781,29 @@ public class Connect {
}
/**
+ * Lists a possibly filtered list of all the domains.
+ *
+ * @param flags bitwise-OR of ListAllDomainsFlags
+ *
+ * @return and array of the IDs of the active domains
+ * @throws LibvirtException
+ */
+ public Domain[] listAllDomains(int flags) throws LibvirtException {
+ PointerByReference domainsRef = new PointerByReference();
+ int ret = libvirt.virConnectListAllDomains(VCP, domainsRef, flags);
+ processError(ret);
+
+ Pointer[] pointers = domainsRef.getValue().getPointerArray(0);
+ Domain[] domains = new Domain[ret];
+ for (int i = 0; i < ret; i++) {
+ DomainPointer domainPtr = new DomainPointer();
+ domainPtr.setPointer(pointers[i]);
+ domains[i] = new Domain(this, domainPtr);
+ }
+ return domains;
+ }
+
+ /**
* Provides the list of names of interfaces on this host
*
* @return an Array of Strings that contains the names of the interfaces on
diff --git a/src/main/java/org/libvirt/jna/Libvirt.java b/src/main/java/org/libvirt/jna/Libvirt.java
index 0e4c9fc..1331f80 100644
--- a/src/main/java/org/libvirt/jna/Libvirt.java
+++ b/src/main/java/org/libvirt/jna/Libvirt.java
@@ -8,6 +8,7 @@ import com.sun.jna.Platform;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.LongByReference;
+import com.sun.jna.ptr.PointerByReference;
/**
* The libvirt interface which is exposed via JNA. The complete API is
@@ -135,6 +136,7 @@ public interface Libvirt extends Library {
int virConnectListDefinedStoragePools(ConnectionPointer virConnectPtr, Pointer[] names, int maxnames);
int virConnectListDefinedInterfaces(ConnectionPointer virConnectPtr, Pointer[] name, int maxNames);
int virConnectListDomains(ConnectionPointer virConnectPtr, int[] ids, int maxnames);
+ int virConnectListAllDomains(ConnectionPointer virConnectPtr, PointerByReference domains, int flags);
int virConnectListInterfaces(ConnectionPointer virConnectPtr, Pointer[] name, int maxNames);
int virConnectListNetworks(ConnectionPointer virConnectPtr, Pointer[] name, int maxnames);
int virConnectListNWFilters(ConnectionPointer virConnectPtr, Pointer[] name, int maxnames);
diff --git a/src/test/java/org/libvirt/TestJavaBindings.java b/src/test/java/org/libvirt/TestJavaBindings.java
index 0123e6a..2703aa3 100644
--- a/src/test/java/org/libvirt/TestJavaBindings.java
+++ b/src/test/java/org/libvirt/TestJavaBindings.java
@@ -137,6 +137,7 @@ public final class TestJavaBindings extends TestCase {
assertEquals("Number of listed domains", 2, conn.listDomains().length);
assertEquals("Number of defined domains", 1, conn.numOfDefinedDomains());
assertEquals("Number of listed defined domains", 1, conn.listDefinedDomains().length);
+ assertEquals("Number of all listed domains", 3, conn.listAllDomains(0).length);
assertTrue("Domain1 should be persistent", dom1.isPersistent() == 1);
assertTrue("Domain1 should not be active", dom1.isActive() == 0);
assertTrue("Domain2 should be active", dom2.isActive() == 1);
--
1.8.4.5
10 years
[libvirt] [PATCH v2 0/8] Post-copy live migration support
by Cristian Klein
Qemu currently implements pre-copy live migration. VM memory pages are
first copied from the source hypervisor to the destination, potentially
multiple times as pages get dirtied during transfer, then VCPU state
is migrated. Unfortunately, if the VM dirties memory faster than the
network bandwidth, then pre-copy cannot finish. `virsh` currently
includes an option to suspend a VM after a timeout, so that migration
may finish, but at the expense of downtime.
A future version of qemu will implement post-copy live migration. The
VCPU state is first migrated to the destination hypervisor, then
memory pages are pulled from the source hypervisor. Post-copy has the
potential to do migration with zero-downtime, despite the VM dirtying
pages fast, with minimum performance impact. On the other hand, one
post-copy is in progress, any network failure would render the VM
unusable, as its memory is partitioned between the source and
destination hypervisor. Therefore, post-copy should only be used when
necessary.
Post-copy migration in qemu will work as follows:
(1) The `x-postcopy-ram` migration capability needs to be set.
(2) Migration is started.
(3) When the user decides so, post-copy migration is activated by
sending the `migrate-start-postcopy` command. Qemu acknowledges by
setting migration status to `postcopy-active`.
v2:
- Fixed formatting
- Set target version to libvirt 1.2.10
- Only use JSON monitor
- Renamed `qemuMigrateStartPostCopy` to `qemuDomainMigrateStartPostCopy`
- Added parameter `flags` to domainMigrateStartPostCopy (currently unused)
- Misc fixes required for `make check`
- Stop perform phase, when post-copy starts
- Wait for post-copy completion in confirm phase, before killing source VM
Implementation note: `qemuMigrationWaitForCompletion` is overloaded. When
called the first time it waits for post-copy to start, when called the
second time it waits for post-copy to complete. I did so to reduce
code duplication, but am not sure this is the best solution.
Cristian Klein (8):
Added public API to enable post-copy migration
Added public API to start post-copy migration
Added low-level API to qemu post-copy migration
Implemented VIR_MIGRATE_POSTCOPY in qemu driver
Added job type VIR_DOMAIN_JOB_PHASE1_COMPLETED
Implemented post-copy migration logic in qemu
Implement virDomainMigrateStartPostCopy in qemu
virsh: add postcopy-after option to migrate command
include/libvirt/libvirt.h.in | 5 +++
src/driver.h | 5 +++
src/libvirt.c | 46 ++++++++++++++++++++++++
src/libvirt_public.syms | 5 +++
src/qemu/qemu_driver.c | 58 ++++++++++++++++++++++++++++++
src/qemu/qemu_migration.c | 85 ++++++++++++++++++++++++++++++++++++++++++--
src/qemu/qemu_migration.h | 3 +-
src/qemu/qemu_monitor.c | 24 +++++++++++--
src/qemu/qemu_monitor.h | 4 +++
src/qemu/qemu_monitor_json.c | 23 +++++++++++-
src/qemu/qemu_monitor_json.h | 1 +
src/remote/remote_driver.c | 1 +
src/remote/remote_protocol.x | 13 ++++++-
src/remote_protocol-structs | 5 +++
tools/virsh-domain.c | 75 ++++++++++++++++++++++++++++++++++++--
tools/virsh.pod | 5 +++
16 files changed, 347 insertions(+), 11 deletions(-)
--
1.9.1
10 years
[libvirt] [sandbox PATCH 0/2] v1.1 bugfix: support dhcp network interfaces
by Gene Czarcinski
Resubmitted to add "sandbox PATCH" to Subject
v1.1 adds some documentation changes.
Support for a network such as -N dhcp,source=default was not working
in that dhclient was not being started. Although I am not sure what
the real problem is, the solution is to use g_spawn_sync() instead of
g_spawn_async() to start /sbin/dhclient.
The second patch addes "-v" to the dhclient arguments to improve debugging
info. The dhclient into will be in /var/log/messages the Secure Contrainer
host system and not in the container itself.
Gene Czarcinski (2):
v1.1 for dhclient use g_spawn_sync()
v1.1 add -v to dhclient parameter arguments
libvirt-sandbox/libvirt-sandbox-init-common.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
--
1.9.3
10 years
[libvirt] [PATCH] Require at least one console for LXC domain
by Ján Tomko
A domain without a console quietly dies soon after start,
because we try to set /dev/null as a controlling TTY
2014-10-30 15:10:59.705+0000: 1: error : lxcContainerSetupFDs:283 :
ioctl(TIOCSTTY) failed: Inappropriate ioctl for device
Report an error early instead of trying to start it.
https://bugzilla.redhat.com/show_bug.cgi?id=1155410
---
src/lxc/lxc_container.c | 6 ++++--
src/lxc/lxc_process.c | 6 ++++++
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index f02b959..8aba3ba 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -2093,8 +2093,10 @@ static int lxcContainerChild(void *data)
if (virAsprintf(&ttyPath, "%s/%s.devpts/%s",
LXC_STATE_DIR, vmDef->name, tty) < 0)
goto cleanup;
- } else if (VIR_STRDUP(ttyPath, "/dev/null") < 0) {
- goto cleanup;
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("At least one tty is required"));
+ goto cleanup;
}
VIR_DEBUG("Container TTY path: %s", ttyPath);
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
index ed30c37..6c83fdb 100644
--- a/src/lxc/lxc_process.c
+++ b/src/lxc/lxc_process.c
@@ -1144,6 +1144,12 @@ int virLXCProcessStart(virConnectPtr conn,
vm->def, NULL) < 0)
goto cleanup;
+ if (vm->def->nconsoles == 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("At least one PTY console is required"));
+ goto cleanup;
+ }
+
for (i = 0; i < vm->def->nconsoles; i++) {
char *ttyPath;
if (vm->def->consoles[i]->source.type != VIR_DOMAIN_CHR_TYPE_PTY) {
--
2.0.4
10 years
[libvirt] [v5][Patch 0/4] Libvirt CPU enhancements for Power KVM
by Prerna Saxena
This patch series is a collection of enhancements for PowerPC CPUs on PowerKVM.
In this iteration, I have followed Dan's suggestion on using existing cpu mode
format to describe powerPC compatibility mode.
Hope this can finally make it for 1.2.10 !
Series Summary:
==========
Patch 1/4 : Introduce a new architecture 'ppc64le' for libvirt.
Patch 2/4 : Add libvirt support for VMs running in 'compat' mode on Power KVM.
Patch 3/4 : Improve PVR handling to fall back to cpu generation.
Patch 4/4 : Add documentation describing compat mode usage for PowerPC guests.
Detail:
====
* PowerPC has traditionally been a Big-endian architecture. However, with PowerPC ISA version 2.07, it can run in Little-endian mode as well. IBM Power8 processors, compliant with ISA 2.07 allow launching VMs in little-endian mode. This is signified by 'ppc64le' architecture. Patch 1 adds this support to libvirt, to allow running VMs based on ppc64le architecture.
* Patch 2,3 tweak libvirt to correctly model PowerPC CPUs based on recent PowerKVM implementation.
PowerKVM permits VMs with vcpus in the following allowed modes :
i) Host native mode:
where the vcpu seen in the VM belongs to the same processor generation as the host.
Example: A POWER7 host, conforming to PowerISA version 2.06, will run VMs with "power7" vcpus.
ii) Binary Compatibility ("compat") mode:
PowerISA allows processors to run VMs in binary compatibility ("compat") mode supporting an older version of ISA.
As an example: In compatibility mode, a POWER7 host can run a "power6" VM, conforming to power ISA v2.05.
Similarly, a POWER8 host can run a "power7" VM conforming to PowerISA v2.06.
QEMU has recently added support to explicitly denote a VM running in compatibility mode through commits 6d9412ea & 8dfa3a5e85. Henceforth, VMs of type (i) will be invoked with the QEMU invocation "-cpu host", while VMs of type (ii) will be invoked using "-cpu host, compat=power6".
Now, an explicit cpu selection using "-cpu POWER6" is not valid. Instead, the recommended practice is to use the matching compat mode, if the requested cpu type differs from the host.
Patches 2-3 address various aspects of this change.
* Patch 2 : Adds support for generating the correct command line for QEMU. Existing xml semantics of 'host-model' are interpreted differently on PowerPc architecture to signify this type.
* Patch 3 : PowerKVM vCPUs differ uniquely across generations ( such as power6, power7, power8). Each generation signifies a new PowerISA version that exhibits features unique to that generation. The higher order 16 bits of PVR denote the processor generation and the lower order 16 bits denote the cpu chip (sub)version.
For all practical purposes of launching a VM, we care about the generation the vCPU will belong to, and not specifically the chip version. In fact, PowerKVM does not seek out specification of a unique chip version(such as POWER7_v2.3) for running a vCPU. This patch updates the libvirt PVR check to reflect this relationship.
* Patch 4 : Documentation is added to explain functionality introduced by Patch 2.
Changelog:
=========
v1 : https://www.redhat.com/archives/libvir-list/2014-June/msg01338.html
v2 : http://www.redhat.com/archives/libvir-list/2014-October/msg00351.html
v3 : http://www.mail-archive.com/libvir-list@redhat.com/msg104010.html
v4: http://www.mail-archive.com/libvir-list@redhat.com/msg104067.html
Changes since v4:
================
* Patches 1,3 already ack'ed by Michal, and have been posted unchanged.
* In Patch 2,Discarded fallback=compat, and implemented Dan's suggestion to overload cpu mode "host-model".
Now, on PowerPc, a VM with this XML schema will automatically be a compat-mode VM:
<cpu mode='host-model'>
<model>power7</model>
</cpu>
* Introduced a new patch '4' to add documentation that explains this.
Regards,
--
Prerna Saxena
Linux Technology Centre,
IBM Systems and Technology Lab,
Bangalore, India
10 years
[libvirt] [PATCH v4 0/3] add nodeset check in numatune
by Chen Fan
when setting elements memnode and nodeset in attribute numatune more
than the host nodes in XML file, VM boot should fail. so add check for
that.
Chen Fan (3):
bitmap: add virBitmapLastSetBit for finding the last bit position of
bitmap
numatune: add check for numatune nodeset range
virnuma: use virNumaNodesetIsAvailable checking nodeset in
virNumaSetupMemoryPolicy
src/conf/numatune_conf.c | 28 ++++++++++
src/conf/numatune_conf.h | 1 +
src/libvirt_private.syms | 2 +
src/qemu/qemu_command.c | 4 ++
src/util/virbitmap.c | 45 ++++++++++++++++
src/util/virbitmap.h | 3 ++
src/util/virnuma.c | 61 +++++++++++++++-------
src/util/virnuma.h | 1 +
...rgv-numatune-static-nodeset-exceed-hostnode.xml | 36 +++++++++++++
tests/qemuxml2argvmock.c | 9 ++++
tests/qemuxml2argvtest.c | 1 +
tests/virbitmaptest.c | 13 ++++-
12 files changed, 184 insertions(+), 20 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-static-nodeset-exceed-hostnode.xml
--
1.9.3
10 years
[libvirt] [PATCH 2/2] qemu: migration: Ignore null ptr in qemuMigrationStopNBDServer
by weiwei li
qemuMigrationCookiePtr mig->nbd may be null when MigrationCookie
do not have nbd information ,but nbd port did allocated before and
must be released here, so ignore mig->nbd null ptr and just warn.
Signed-off-by: Weiwei Li <nuonuoli(a)tencent.com>
---
src/qemu/qemu_migration.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 0ad8054..134b041 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -1584,7 +1584,7 @@ qemuMigrationStopNBDServer(virQEMUDriverPtr driver,
qemuDomainObjPrivatePtr priv = vm->privateData;
if (!mig->nbd)
- return;
+ VIR_WARN("mig->nbd is null");
if (qemuDomainObjEnterMonitorAsync(driver, vm,
QEMU_ASYNC_JOB_MIGRATION_IN) < 0)
--
1.7.1
10 years
[libvirt] [PATCH] examples: add systemtap script to ease lock debugging
by Martin Kletzander
As discussed before, this simple script should help with debugging
deadlocks, although there are still some caveats. RWLocks are not
handled by this and if your deadlock if very racy, it may not lock
up when running with this script due to the slowdown.
Signed-off-by: Martin Kletzander <mkletzan(a)redhat.com>
---
examples/systemtap/lock-debug.stp | 118 ++++++++++++++++++++++++++++++++++++++
1 file changed, 118 insertions(+)
create mode 100644 examples/systemtap/lock-debug.stp
diff --git a/examples/systemtap/lock-debug.stp b/examples/systemtap/lock-debug.stp
new file mode 100644
index 0000000..8f06340
--- /dev/null
+++ b/examples/systemtap/lock-debug.stp
@@ -0,0 +1,118 @@
+#!/usr/bin/stap --ldd -d /usr/sbin/libvirtd -c libvirtd
+#
+# Usage with installed libvirt daemon:
+# stap --ldd -d /usr/sbin/libvirtd -c libvirtd \
+# lock-debug.stp /usr/lib/libvirt.so
+#
+# If made executable; simple './lock-debug.stp' should work too.
+#
+# TODOs:
+#
+# Document usage with uninstalled daemon and libs. Assuming CWD is toplevel
+# source git directory, it should be only slight modification to the following:
+#
+# ./run stap --ldd -c daemon/libvirtd -d daemon/libvirtd
+# examples/systemtap/lock-debug.stp src/.libs/libvirt.so
+#
+# Debug RWLock mechanisms as well.
+#
+# Author: Martin Kletzander <mkletzan(a)redhat.com>
+
+
+global mx_tolock
+global mx_locked
+
+
+function filter()
+{
+ if (pid() != target())
+ return 1
+
+ return 0
+}
+
+probe library = process( %( $# > 0 %? @1 %: "/usr/lib/libvirt.so" %) )
+{
+ if (filter()) next
+}
+
+probe lock = library.function("virMutexLock")
+{
+ lockname = usymdata($m)
+}
+
+probe unlock = library.function("virMutexUnlock")
+{
+ lockname = usymdata($m)
+}
+
+probe begin
+{
+ %( $# > 1 %? println("error: Too many parameters"); exit();
+ %: print("Started, press ^C when the proccess hangs\n"); %)
+}
+
+probe lock.call
+{
+ mx_tolock[lockname, tid()] = sprint_usyms(ubacktrace())
+}
+
+probe lock.return
+{
+ if ([lockname, tid()] in mx_tolock) {
+ mx_locked[lockname, tid()] = mx_tolock[lockname, tid()]
+ delete mx_tolock[lockname, tid()]
+ } else {
+ printf("internal error: lock acquired unwillingly?\n")
+ }
+}
+
+probe unlock.call
+{
+ found = 0
+
+ foreach ([lock, tid] in mx_locked) {
+ if (lock != lockname)
+ continue
+ if (tid != tid()) {
+ printf("Warning: lock released on different thread that locked it.\n")
+ printf("Lock trace:\n%s\n", mx_locked[lock, tid])
+ printf("Unlock trace:\n%s\n", sprint_usyms(ubacktrace()))
+ }
+
+ found = tid
+ break
+ }
+
+ if (found && [lockname, found] in mx_locked)
+ delete mx_locked[lockname, found]
+}
+
+probe end
+{
+ tmp = 0
+
+ printf("\n=============\n")
+
+ foreach (bt1 = [lock1, tid1] in mx_tolock) {
+ deadlock = 0
+
+ foreach (bt2 = [lock2, tid2] in mx_tolock) {
+ if (lock1 == lock2) {
+ if (!tmp++)
+ printf("The following locks cannot be acquired:\n")
+
+ if (!deadlock++)
+ printf("Lock %s was locked in thread %d with this trace:\n%s\n",
+ lock1, tid1, bt1)
+
+ printf("and is waiting to be locked by thread %d here:\n%s\n",
+ tid2, bt2)
+ }
+ }
+ if (deadlock)
+ printf("---\n")
+ }
+ if (!tmp)
+ printf("No deadlocks found, sorry.\n")
+}
--
2.1.2
10 years