[libvirt] [PATCH] docs: mention domain <clock> improvements
by Eric Blake
Add documentation for features added a while ago.
* docs/formatdomain.html.in (Time keeping): Update documentation
of <clock> element to match 0.8.0 addition.
---
Please double-check me. The conversion from schemas/domain.rng
to text, coupled with list traffic about the patches, was pretty
overwhelming. I hope I haven't over-trivialized the various options,
but am pretty sure I didn't omit any.
docs/formatdomain.html.in | 76 ++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 71 insertions(+), 5 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index a23663a..be0446d 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -395,13 +395,18 @@
<pre>
...
- <clock offset="localtime"/>
+ <clock offset="localtime">
+ <timer name="rtc" tickpolicy="catchup" track="guest">
+ <catchup threshold=123 slew=120 limit=10000/>
+ </timer>
+ <timer name="pit" tickpolicy="none"/>
+ </clock>
...</pre>
<dl>
<dt><code>clock</code></dt>
<dd>
- <p>The <code>offset</code> attribute takes three possible
+ <p>The <code>offset</code> attribute takes four possible
values, allowing fine grained control over how the guest
clock is synchronized to the host. NB, not all hypervisors
support all modes.</p>
@@ -419,6 +424,7 @@
<dd>
The guest clock will be synchronized to the requested timezone
using the <code>timezone</code> attribute.
+ <span class="since">Since 0.7.7</span>
</dd>
<dt><code>variable</code></dt>
<dd>
@@ -428,14 +434,74 @@
The guest is free to adjust the RTC over time an expect
that it will be honoured at next reboot. This is in
contrast to 'utc' mode, where the RTC adjustments are
- lost at each reboot.
+ lost at each reboot. <span class="since">Since 0.7.7</span>
</dd>
</dl>
<p>
- NB, at time of writing, only QEMU supports the variable
- clock mode, or custom timezones.
+ A <code>clock</code> may have zero or more
+ <code>timer</code>sub-elements. <span class="since">Since
+ 0.8.0</span>
</p>
</dd>
+ <dt><code>timer</code></dt>
+ <dd>
+ <p>
+ Each timer element requires a <code>name</code> attribute,
+ and has other optional attributes that depend on
+ the <code>name</code> specified. Various hypervisors
+ support different combinations of attributes.
+ </p>
+ <dl>
+ <dt><code>name</code></dt>
+ <dd>
+ The <code>name</code> attribute selects which timer is
+ being modified, and can be one of "platform", "pit",
+ "rtc", "hpet", or "tsc".
+ </dd>
+ <dt><code>track</code></dt>
+ <dd>
+ The <code>track</code> attribute specifies what the timer
+ tracks, and can be "boot", "guest", or "wall".
+ Only valid for <code>name="rtc"</code>
+ or <code>name="platform"</code>.
+ </dd>
+ <dt><code>tickpolicy</code></dt>
+ <dd>
+ The <code>tickpolicy</code> attribute determines how
+ missed ticks in the guest are handled, and can be "delay",
+ "catchup", "merge", or "discard". If the policy is
+ "catchup", there can be further details in
+ the <code>catchup</code> sub-element.
+ <dl>
+ <dt><code>catchup</code></dt>
+ <dd>
+ The <code>catchup</code> element has three optional
+ attributes, each a positive integer. The attributes
+ are <code>threshold</code>, <code>slew</code>,
+ and <code>limit</code>.
+ </dd>
+ </dl>
+ </dd>
+ <dt><code>frequency</code></dt>
+ <dd>
+ The <code>frequency</code> attribute is an unsigned
+ integer specifying the frequency at
+ which <code>name="tsc"</code> runs.
+ </dd>
+ <dt><code>mode</code></dt>
+ <dd>
+ The <code>mode</code> attribute controls how
+ the <code>name="tsc"</code> timer is managed, and can be
+ "auto", "native", "emulate", "paravirt", or "smpsafe".
+ Other timers are always emulated.
+ </dd>
+ <dt><code>present</code></dt>
+ <dd>
+ The <code>present</code> attribute can be "yes" or "no" to
+ specify whether a particular timer is available to the guest.
+ </dd>
+ </dl>
+ </dd>
</dl>
<h3><a name="elementsDevices">Devices</a></h3>
--
1.7.0.1
14 years, 7 months
[libvirt] [PATCH] esx: Add read-only storage pool access
by Matthias Bolte
Add VIR_STORAGE_POOL_INACCESSIBLE to denote a running but inaccessible
storage pool. For example an NFS pool is inaccessible when the NFS
server is currently unreachable.
Add CIFS to the list of network file systems because ESX distinguishes
between NFS and CIFS.
Alter the esxVI_ProductVersion enum in a way that allows to check for
product type by masking.
Make esxVI_*_CastFromAnyType dynamically dispatched in order to handle
the DatastoreInfo type and inheriting types properly.
Allow esxVI_X_DynamicCast to be called successfully on objects with
type X. This is necessary for handling DatastoreInfo and inheriting
types properly.
---
include/libvirt/libvirt.h.in | 1 +
po/POTFILES.in | 1 +
src/conf/storage_conf.c | 2 +-
src/conf/storage_conf.h | 1 +
src/esx/esx_storage_driver.c | 606 +++++++++++++++++++++++++++++++++++++++-
src/esx/esx_vi.c | 126 ++++++++-
src/esx/esx_vi.h | 26 ++-
src/esx/esx_vi_generator.input | 59 ++++
src/esx/esx_vi_generator.py | 20 ++-
src/esx/esx_vi_types.c | 44 ++-
tools/virsh.c | 4 +
11 files changed, 845 insertions(+), 45 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index db107cc..838028d 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -1118,6 +1118,7 @@ typedef enum {
VIR_STORAGE_POOL_BUILDING = 1, /* Initializing pool, not available */
VIR_STORAGE_POOL_RUNNING = 2, /* Running normally */
VIR_STORAGE_POOL_DEGRADED = 3, /* Running degraded */
+ VIR_STORAGE_POOL_INACCESSIBLE = 4, /* Running, but not accessible */
} virStoragePoolState;
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 88218bd..e047b1b 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -19,6 +19,7 @@ src/cpu/cpu_map.c
src/cpu/cpu_x86.c
src/datatypes.c
src/esx/esx_driver.c
+src/esx/esx_storage_driver.c
src/esx/esx_util.c
src/esx/esx_vi.c
src/esx/esx_vi_methods.c
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index 6218e02..c1595aa 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -61,7 +61,7 @@ VIR_ENUM_IMPL(virStoragePoolFormatFileSystem,
VIR_ENUM_IMPL(virStoragePoolFormatFileSystemNet,
VIR_STORAGE_POOL_NETFS_LAST,
- "auto", "nfs", "glusterfs")
+ "auto", "nfs", "glusterfs", "cifs")
VIR_ENUM_IMPL(virStoragePoolFormatDisk,
VIR_STORAGE_POOL_DISK_LAST,
diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h
index 1c9ba04..5813489 100644
--- a/src/conf/storage_conf.h
+++ b/src/conf/storage_conf.h
@@ -405,6 +405,7 @@ enum virStoragePoolFormatFileSystemNet {
VIR_STORAGE_POOL_NETFS_AUTO = 0,
VIR_STORAGE_POOL_NETFS_NFS,
VIR_STORAGE_POOL_NETFS_GLUSTERFS,
+ VIR_STORAGE_POOL_NETFS_CIFS,
VIR_STORAGE_POOL_NETFS_LAST,
};
VIR_ENUM_DECL(virStoragePoolFormatFileSystemNet)
diff --git a/src/esx/esx_storage_driver.c b/src/esx/esx_storage_driver.c
index 97b92a5..c82667b 100644
--- a/src/esx/esx_storage_driver.c
+++ b/src/esx/esx_storage_driver.c
@@ -29,6 +29,7 @@
#include "memory.h"
#include "logging.h"
#include "uuid.h"
+#include "storage_conf.h"
#include "esx_private.h"
#include "esx_storage_driver.h"
#include "esx_vi.h"
@@ -65,17 +66,596 @@ esxStorageClose(virConnectPtr conn)
+static int
+esxNumberOfStoragePools(virConnectPtr conn)
+{
+ int result = 0;
+ esxPrivate *priv = conn->storagePrivateData;
+ esxVI_ObjectContent *datastoreList = NULL;
+ esxVI_ObjectContent *datastore = NULL;
+
+ if (esxVI_EnsureSession(priv->host) < 0) {
+ goto failure;
+ }
+
+ if (esxVI_LookupObjectContentByType(priv->host, priv->host->datacenter,
+ "Datastore", NULL, esxVI_Boolean_True,
+ &datastoreList) < 0) {
+ goto failure;
+ }
+
+ for (datastore = datastoreList; datastore != NULL;
+ datastore = datastore->_next) {
+ ++result;
+ }
+
+ cleanup:
+ esxVI_ObjectContent_Free(&datastoreList);
+
+ return result;
+
+ failure:
+ result = -1;
+
+ goto cleanup;
+}
+
+
+
+static int
+esxListStoragePools(virConnectPtr conn, char **const names, int maxnames)
+{
+ esxPrivate *priv = conn->storagePrivateData;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_DynamicProperty *dynamicProperty = NULL;
+ esxVI_ObjectContent *datastoreList = NULL;
+ esxVI_ObjectContent *datastore = NULL;
+ int count = 0;
+ int i;
+
+ if (names == NULL || maxnames < 0) {
+ ESX_ERROR(VIR_ERR_INVALID_ARG, "%s", _("Invalid argument"));
+ return -1;
+ }
+
+ if (maxnames == 0) {
+ return 0;
+ }
+
+ if (esxVI_EnsureSession(priv->host) < 0) {
+ goto failure;
+ }
+
+ if (esxVI_String_AppendValueToList(&propertyNameList,
+ "summary.name") < 0 ||
+ esxVI_LookupObjectContentByType(priv->host, priv->host->datacenter,
+ "Datastore", propertyNameList,
+ esxVI_Boolean_True,
+ &datastoreList) < 0) {
+ goto failure;
+ }
+
+ for (datastore = datastoreList; datastore != NULL;
+ datastore = datastore->_next) {
+ for (dynamicProperty = datastore->propSet; dynamicProperty != NULL;
+ dynamicProperty = dynamicProperty->_next) {
+ if (STREQ(dynamicProperty->name, "summary.name")) {
+ if (esxVI_AnyType_ExpectType(dynamicProperty->val,
+ esxVI_Type_String) < 0) {
+ goto failure;
+ }
+
+ names[count] = strdup(dynamicProperty->val->string);
+
+ if (names[count] == NULL) {
+ virReportOOMError();
+ goto failure;
+ }
+
+ ++count;
+ break;
+ } else {
+ VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
+ }
+ }
+ }
+
+ cleanup:
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&datastoreList);
+
+ return count;
+
+ failure:
+ for (i = 0; i < count; ++i) {
+ VIR_FREE(names[i]);
+ }
+
+ count = -1;
+
+ goto cleanup;
+}
+
+
+
+static int
+esxNumberOfDefinedStoragePools(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+ /* ESX storage pools are always active */
+ return 0;
+}
+
+
+
+static int
+esxListDefinedStoragePools(virConnectPtr conn ATTRIBUTE_UNUSED,
+ char **const names ATTRIBUTE_UNUSED,
+ int maxnames ATTRIBUTE_UNUSED)
+{
+ /* ESX storage pools are always active */
+ return 0;
+}
+
+
+
+static virStoragePoolPtr
+esxStoragePoolLookupByName(virConnectPtr conn, const char *name)
+{
+ esxPrivate *priv = conn->storagePrivateData;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *datastore = NULL;
+ esxVI_Boolean accessible = esxVI_Boolean_Undefined;
+ char *summaryUrl = NULL;
+ char *suffix = NULL;
+ int suffixLength;
+ char uuid_string[VIR_UUID_STRING_BUFLEN] = "00000000-00000000-0000-000000000000";
+ unsigned char uuid[VIR_UUID_BUFLEN];
+ char *realName = NULL;
+ virStoragePoolPtr pool = NULL;
+
+ if (esxVI_EnsureSession(priv->host) < 0) {
+ goto cleanup;
+ }
+
+ if (esxVI_String_AppendValueListToList(&propertyNameList,
+ "summary.accessible\0"
+ "summary.name\0"
+ "summary.url\0") < 0 ||
+ esxVI_LookupDatastoreByName(priv->host, name,
+ propertyNameList, &datastore,
+ esxVI_Occurrence_RequiredItem) < 0 ||
+ esxVI_GetBoolean(datastore, "summary.accessible",
+ &accessible, esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ /*
+ * Datastores don't have a UUID. We can use the 'summary.url' property as
+ * source for a "UUID" on ESX, because the property value has this format:
+ *
+ * summary.url = /vmfs/volumes/4b0beca7-7fd401f3-1d7f-000ae484a6a3
+ * summary.url = /vmfs/volumes/b24b7a78-9d82b4f5 (short format)
+ *
+ * The 'summary.url' property comes in two forms, with a complete "UUID"
+ * and a short "UUID".
+ *
+ * But this trailing "UUID" is not guaranteed to be there. On the other
+ * hand we already rely on another implementation detail of the ESX server:
+ * The object name of virtual machine contains an integer, we use that as
+ * domain ID.
+ *
+ * The 'summary.url' property of an inaccessible datastore is invalid.
+ */
+ if (accessible == esxVI_Boolean_True &&
+ priv->host->productVersion & esxVI_ProductVersion_ESX) {
+ if (esxVI_GetStringValue(datastore, "summary.url", &summaryUrl,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ if ((suffix = STRSKIP(summaryUrl, "/vmfs/volumes/")) == NULL) {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Datastore URL '%s' has unexpected prefix, "
+ "expecting '/vmfs/volumes/' prefix"), summaryUrl);
+ goto cleanup;
+ }
+
+ suffixLength = strlen(suffix);
+
+ if ((suffixLength == 35 && /* = strlen("4b0beca7-7fd401f3-1d7f-000ae484a6a3") */
+ suffix[8] == '-' && suffix[17] == '-' && suffix[22] == '-') ||
+ (suffixLength == 17 && /* = strlen("b24b7a78-9d82b4f5") */
+ suffix[8] == '-')) {
+ /*
+ * Intentionally use memcpy here, because we want to be able to
+ * replace a prefix of the initial Zero-UUID. virStrncpy would
+ * null-terminate the string in an unwanted place.
+ */
+ memcpy(uuid_string, suffix, suffixLength);
+ } else {
+ VIR_WARN("Datastore URL suffix '%s' has unexpected format, "
+ "cannot deduce a UUID from it", suffix);
+ }
+ }
+
+ if (virUUIDParse(uuid_string, uuid) < 0) {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Could not parse UUID from string '%s'"),
+ uuid_string);
+ goto cleanup;
+ }
+
+ if (esxVI_GetStringValue(datastore, "summary.name", &realName,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ pool = virGetStoragePool(conn, realName, uuid);
+
+ cleanup:
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&datastore);
+
+ return pool;
+}
+
+
+
+static virStoragePoolPtr
+esxStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
+{
+ esxPrivate *priv = conn->storagePrivateData;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *datastore = NULL;
+ char uuid_string[VIR_UUID_STRING_BUFLEN] = "";
+ char *name = NULL;
+ virStoragePoolPtr pool = NULL;
+
+ if (! (priv->host->productVersion & esxVI_ProductVersion_ESX)) {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Lookup by UUID is supported on ESX only"));
+ return NULL;
+ }
+
+ if (esxVI_EnsureSession(priv->host) < 0) {
+ goto cleanup;
+ }
+
+ /*
+ * Convert from UUID to datastore URL form by stripping the second '-':
+ *
+ * <---- 14 ----><-------- 22 --------> <---- 13 ---><-------- 22 -------->
+ * 4b0beca7-7fd4-01f3-1d7f-000ae484a6a3 -> 4b0beca7-7fd401f3-1d7f-000ae484a6a3
+ */
+ virUUIDFormat(uuid, uuid_string);
+ memmove(uuid_string + 13, uuid_string + 14, 22 + 1);
+
+ /*
+ * Use esxVI_LookupDatastoreByName because it also does try to match "UUID"
+ * part of the 'summary.url' property if there is no name match.
+ */
+ if (esxVI_String_AppendValueToList(&propertyNameList, "summary.name") < 0 ||
+ esxVI_LookupDatastoreByName(priv->host, uuid_string,
+ propertyNameList, &datastore,
+ esxVI_Occurrence_OptionalItem) < 0) {
+ goto cleanup;
+ }
+
+ /*
+ * If the first try didn't succeed and the trailing 16 digits are zero then
+ * the "UUID" could be a short one. Strip the 16 zeros and try again:
+ *
+ * <------ 17 -----> <------ 17 ----->
+ * b24b7a78-9d82b4f5-0000-000000000000 -> b24b7a78-9d82b4f5
+ */
+ if (datastore == NULL && STREQ(uuid_string + 17, "-0000-000000000000")) {
+ uuid_string[17] = '\0';
+
+ if (esxVI_LookupDatastoreByName(priv->host, uuid_string,
+ propertyNameList, &datastore,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+ }
+
+ if (datastore == NULL) {
+ virUUIDFormat(uuid, uuid_string);
+
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Could not find datastore with UUID '%s'"),
+ uuid_string);
+
+ goto cleanup;
+ }
+
+ if (esxVI_GetStringValue(datastore, "summary.name", &name,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ pool = virGetStoragePool(conn, name, uuid);
+
+ cleanup:
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&datastore);
+
+ return pool;
+}
+
+
+
+static int
+esxStoragePoolRefresh(virStoragePoolPtr pool,
+ unsigned int flags ATTRIBUTE_UNUSED)
+{
+ int result = 0;
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ esxVI_ObjectContent *datastore = NULL;
+
+ if (esxVI_EnsureSession(priv->host) < 0) {
+ goto failure;
+ }
+
+ if (esxVI_LookupDatastoreByName(priv->host, pool->name, NULL, &datastore,
+ esxVI_Occurrence_RequiredItem) < 0 ||
+ esxVI_RefreshDatastore(priv->host, datastore->obj) < 0) {
+ goto failure;
+ }
+
+ cleanup:
+ esxVI_ObjectContent_Free(&datastore);
+
+ return result;
+
+ failure:
+ result = -1;
+
+ goto cleanup;
+}
+
+
+
+static int
+esxStoragePoolGetInfo(virStoragePoolPtr pool, virStoragePoolInfoPtr info)
+{
+ int result = 0;
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *datastore = NULL;
+ esxVI_DynamicProperty *dynamicProperty = NULL;
+ esxVI_Boolean accessible = esxVI_Boolean_Undefined;
+
+ memset(info, 0, sizeof (*info));
+
+ if (esxVI_EnsureSession(priv->host) < 0) {
+ goto failure;
+ }
+
+ if (esxVI_String_AppendValueListToList(&propertyNameList,
+ "summary.accessible\0"
+ "summary.capacity\0"
+ "summary.freeSpace\0") < 0 ||
+ esxVI_LookupDatastoreByName(priv->host, pool->name,
+ propertyNameList, &datastore,
+ esxVI_Occurrence_RequiredItem) < 0 ||
+ esxVI_GetBoolean(datastore, "summary.accessible",
+ &accessible, esxVI_Occurrence_RequiredItem) < 0) {
+ goto failure;
+ }
+
+ if (accessible == esxVI_Boolean_True) {
+ info->state = VIR_STORAGE_POOL_RUNNING;
+
+ for (dynamicProperty = datastore->propSet; dynamicProperty != NULL;
+ dynamicProperty = dynamicProperty->_next) {
+ if (STREQ(dynamicProperty->name, "summary.capacity")) {
+ if (esxVI_AnyType_ExpectType(dynamicProperty->val,
+ esxVI_Type_Long) < 0) {
+ goto failure;
+ }
+
+ info->capacity = dynamicProperty->val->int64;
+ } else if (STREQ(dynamicProperty->name, "summary.freeSpace")) {
+ if (esxVI_AnyType_ExpectType(dynamicProperty->val,
+ esxVI_Type_Long) < 0) {
+ goto failure;
+ }
+
+ info->available = dynamicProperty->val->int64;
+ }
+ }
+
+ info->allocation = info->capacity - info->available;
+ } else {
+ info->state = VIR_STORAGE_POOL_INACCESSIBLE;
+ }
+
+ cleanup:
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&datastore);
+
+ return result;
+
+ failure:
+ memset(info, 0, sizeof (*info));
+
+ result = -1;
+
+ goto cleanup;
+}
+
+
+
+static char *
+esxStoragePoolGetXMLDesc(virStoragePoolPtr pool, unsigned int flags)
+{
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *datastore = NULL;
+ esxVI_DynamicProperty *dynamicProperty = NULL;
+ esxVI_Boolean accessible = esxVI_Boolean_Undefined;
+ virStoragePoolDef def;
+ esxVI_DatastoreInfo *info = NULL;
+ esxVI_LocalDatastoreInfo *localInfo = NULL;
+ esxVI_NasDatastoreInfo *nasInfo = NULL;
+ esxVI_VmfsDatastoreInfo *vmfsInfo = NULL;
+ char *xml = NULL;
+
+ virCheckFlags(0, NULL);
+
+ memset(&def, 0, sizeof (def));
+
+ if (esxVI_EnsureSession(priv->host) < 0) {
+ goto failure;
+ }
+
+ if (esxVI_String_AppendValueListToList(&propertyNameList,
+ "summary.accessible\0"
+ "summary.capacity\0"
+ "summary.freeSpace\0"
+ "info\0") < 0 ||
+ esxVI_LookupDatastoreByName(priv->host, pool->name,
+ propertyNameList, &datastore,
+ esxVI_Occurrence_RequiredItem) < 0 ||
+ esxVI_GetBoolean(datastore, "summary.accessible",
+ &accessible, esxVI_Occurrence_RequiredItem) < 0) {
+ goto failure;
+ }
+
+ def.name = pool->name;
+ memcpy(def.uuid, pool->uuid, VIR_UUID_BUFLEN);
+
+ if (accessible == esxVI_Boolean_True) {
+ for (dynamicProperty = datastore->propSet; dynamicProperty != NULL;
+ dynamicProperty = dynamicProperty->_next) {
+ if (STREQ(dynamicProperty->name, "summary.capacity")) {
+ if (esxVI_AnyType_ExpectType(dynamicProperty->val,
+ esxVI_Type_Long) < 0) {
+ goto failure;
+ }
+
+ def.capacity = dynamicProperty->val->int64;
+ } else if (STREQ(dynamicProperty->name, "summary.freeSpace")) {
+ if (esxVI_AnyType_ExpectType(dynamicProperty->val,
+ esxVI_Type_Long) < 0) {
+ goto failure;
+ }
+
+ def.available = dynamicProperty->val->int64;
+ } else if (STREQ(dynamicProperty->name, "info")) {
+ if (esxVI_DatastoreInfo_CastFromAnyType(dynamicProperty->val,
+ &info) < 0) {
+ goto failure;
+ }
+ }
+ }
+
+ def.allocation = def.capacity - def.available;
+
+ /* See vSphere API documentation about HostDatastoreSystem for details */
+ if ((localInfo = esxVI_LocalDatastoreInfo_DynamicCast(info)) != NULL) {
+ def.type = VIR_STORAGE_POOL_DIR;
+ def.target.path = localInfo->path;
+ } else if ((nasInfo = esxVI_NasDatastoreInfo_DynamicCast(info)) != NULL) {
+ def.type = VIR_STORAGE_POOL_NETFS;
+ def.source.host.name = nasInfo->nas->remoteHost;
+ def.source.dir = nasInfo->nas->remotePath;
+
+ if (STRCASEEQ(nasInfo->nas->type, "NFS")) {
+ def.source.format = VIR_STORAGE_POOL_NETFS_NFS;
+ } else if (STRCASEEQ(nasInfo->nas->type, "CIFS")) {
+ def.source.format = VIR_STORAGE_POOL_NETFS_CIFS;
+ } else {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Datastore has unexpected type '%s'"),
+ nasInfo->nas->type);
+ goto failure;
+ }
+ } else if ((vmfsInfo = esxVI_VmfsDatastoreInfo_DynamicCast(info)) != NULL) {
+ def.type = VIR_STORAGE_POOL_FS;
+ /* FIXME */
+ } else {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("DatastoreInfo has unexpected type"));
+ goto failure;
+ }
+ }
+
+ xml = virStoragePoolDefFormat(&def);
+
+ cleanup:
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&datastore);
+ esxVI_DatastoreInfo_Free(&info);
+
+ return xml;
+
+ failure:
+ VIR_FREE(xml);
+
+ goto cleanup;
+}
+
+
+
+static int
+esxStoragePoolGetAutostart(virStoragePoolPtr pool ATTRIBUTE_UNUSED,
+ int *autostart)
+{
+ /* ESX storage pools are always active */
+ *autostart = 1;
+
+ return 0;
+}
+
+
+
+static int
+esxStoragePoolSetAutostart(virStoragePoolPtr pool ATTRIBUTE_UNUSED,
+ int autostart)
+{
+ /* Just accept autostart activation, but fail on autostart deactivation */
+ autostart = (autostart != 0);
+
+ if (! autostart) {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Cannot deactivate storage pool autostart"));
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
+static int
+esxStoragePoolIsActive(virStoragePoolPtr pool ATTRIBUTE_UNUSED)
+{
+ /* ESX storage pools are always active */
+ return 1;
+}
+
+
+
+static int
+esxStoragePoolIsPersistent(virStoragePoolPtr pool ATTRIBUTE_UNUSED)
+{
+ /* ESX has no concept of transient pools, so all of them are persistent */
+ return 1;
+}
+
+
static virStorageDriver esxStorageDriver = {
"ESX", /* name */
esxStorageOpen, /* open */
esxStorageClose, /* close */
- NULL, /* numOfPools */
- NULL, /* listPools */
- NULL, /* numOfDefinedPools */
- NULL, /* listDefinedPools */
+ esxNumberOfStoragePools, /* numOfPools */
+ esxListStoragePools, /* listPools */
+ esxNumberOfDefinedStoragePools, /* numOfDefinedPools */
+ esxListDefinedStoragePools, /* listDefinedPools */
NULL, /* findPoolSources */
- NULL, /* poolLookupByName */
- NULL, /* poolLookupByUUID */
+ esxStoragePoolLookupByName, /* poolLookupByName */
+ esxStoragePoolLookupByUUID, /* poolLookupByUUID */
NULL, /* poolLookupByVolume */
NULL, /* poolCreateXML */
NULL, /* poolDefineXML */
@@ -84,11 +664,11 @@ static virStorageDriver esxStorageDriver = {
NULL, /* poolCreate */
NULL, /* poolDestroy */
NULL, /* poolDelete */
- NULL, /* poolRefresh */
- NULL, /* poolGetInfo */
- NULL, /* poolGetXMLDesc */
- NULL, /* poolGetAutostart */
- NULL, /* poolSetAutostart */
+ esxStoragePoolRefresh, /* poolRefresh */
+ esxStoragePoolGetInfo, /* poolGetInfo */
+ esxStoragePoolGetXMLDesc, /* poolGetXMLDesc */
+ esxStoragePoolGetAutostart, /* poolGetAutostart */
+ esxStoragePoolSetAutostart, /* poolSetAutostart */
NULL, /* poolNumOfVolumes */
NULL, /* poolListVolumes */
NULL, /* volLookupByName */
@@ -101,8 +681,8 @@ static virStorageDriver esxStorageDriver = {
NULL, /* volGetInfo */
NULL, /* volGetXMLDesc */
NULL, /* volGetPath */
- NULL, /* poolIsActive */
- NULL, /* poolIsPersistent */
+ esxStoragePoolIsActive, /* poolIsActive */
+ esxStoragePoolIsPersistent, /* poolIsPersistent */
};
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index 966ef85..7a39fc2 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -1530,6 +1530,114 @@ esxVI_GetVirtualMachineQuestionInfo
int
+esxVI_GetBoolean(esxVI_ObjectContent *objectContent, const char *propertyName,
+ esxVI_Boolean *value, esxVI_Occurrence occurence)
+{
+ esxVI_DynamicProperty *dynamicProperty;
+
+ if (value == NULL || *value != esxVI_Boolean_Undefined) {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
+ return -1;
+ }
+
+ for (dynamicProperty = objectContent->propSet; dynamicProperty != NULL;
+ dynamicProperty = dynamicProperty->_next) {
+ if (STREQ(dynamicProperty->name, propertyName)) {
+ if (esxVI_AnyType_ExpectType(dynamicProperty->val,
+ esxVI_Type_Boolean) < 0) {
+ return -1;
+ }
+
+ *value = dynamicProperty->val->boolean;
+ break;
+ }
+ }
+
+ if (*value == esxVI_Boolean_Undefined &&
+ occurence == esxVI_Occurrence_RequiredItem) {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Missing '%s' property"), propertyName);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
+int
+esxVI_GetStringValue(esxVI_ObjectContent *objectContent,
+ const char *propertyName,
+ char **value, esxVI_Occurrence occurence)
+{
+ esxVI_DynamicProperty *dynamicProperty;
+
+ if (value == NULL || *value != NULL) {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
+ return -1;
+ }
+
+ for (dynamicProperty = objectContent->propSet; dynamicProperty != NULL;
+ dynamicProperty = dynamicProperty->_next) {
+ if (STREQ(dynamicProperty->name, propertyName)) {
+ if (esxVI_AnyType_ExpectType(dynamicProperty->val,
+ esxVI_Type_String) < 0) {
+ return -1;
+ }
+
+ *value = dynamicProperty->val->string;
+ break;
+ }
+ }
+
+ if (*value == NULL && occurence == esxVI_Occurrence_RequiredItem) {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Missing '%s' property"), propertyName);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
+int
+esxVI_GetManagedObjectReference(esxVI_ObjectContent *objectContent,
+ const char *propertyName,
+ esxVI_ManagedObjectReference **value,
+ esxVI_Occurrence occurence)
+{
+ esxVI_DynamicProperty *dynamicProperty;
+
+ if (value == NULL || *value != NULL) {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
+ return -1;
+ }
+
+ for (dynamicProperty = objectContent->propSet; dynamicProperty != NULL;
+ dynamicProperty = dynamicProperty->_next) {
+ if (STREQ(dynamicProperty->name, propertyName)) {
+ if (esxVI_ManagedObjectReference_CastFromAnyType
+ (dynamicProperty->val, value) < 0) {
+ return -1;
+ }
+
+ break;
+ }
+ }
+
+ if (*value == NULL && occurence == esxVI_Occurrence_RequiredItem) {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Missing '%s' property"), propertyName);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
+int
esxVI_LookupNumberOfDomainsByPowerState(esxVI_Context *ctx,
esxVI_VirtualMachinePowerState powerState,
esxVI_Boolean inverse)
@@ -2161,7 +2269,7 @@ esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name,
esxVI_ObjectContent *candidate = NULL;
esxVI_DynamicProperty *dynamicProperty = NULL;
esxVI_Boolean accessible = esxVI_Boolean_Undefined;
- size_t offset = strlen("/vmfs/volumes/");
+ int offset = 14; /* = strlen("/vmfs/volumes/") */
int numInaccessibleDatastores = 0;
if (datastore == NULL || *datastore != NULL) {
@@ -2227,9 +2335,7 @@ esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name,
for (dynamicProperty = candidate->propSet; dynamicProperty != NULL;
dynamicProperty = dynamicProperty->_next) {
- if (STREQ(dynamicProperty->name, "summary.accessible")) {
- /* Ignore it */
- } else if (STREQ(dynamicProperty->name, "summary.name")) {
+ if (STREQ(dynamicProperty->name, "summary.name")) {
if (esxVI_AnyType_ExpectType(dynamicProperty->val,
esxVI_Type_String) < 0) {
goto failure;
@@ -2244,7 +2350,8 @@ esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name,
/* Found datastore with matching name */
goto cleanup;
}
- } else if (STREQ(dynamicProperty->name, "summary.url")) {
+ } else if (STREQ(dynamicProperty->name, "summary.url") &&
+ ctx->productVersion & esxVI_ProductVersion_ESX) {
if (accessible == esxVI_Boolean_False) {
/*
* The 'summary.url' property of an inaccessible datastore
@@ -2276,8 +2383,6 @@ esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name,
/* Found datastore with matching URL suffix */
goto cleanup;
}
- } else {
- VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
}
}
}
@@ -2309,9 +2414,10 @@ esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name,
-int esxVI_LookupTaskInfoByTask(esxVI_Context *ctx,
- esxVI_ManagedObjectReference *task,
- esxVI_TaskInfo **taskInfo)
+int
+esxVI_LookupTaskInfoByTask(esxVI_Context *ctx,
+ esxVI_ManagedObjectReference *task,
+ esxVI_TaskInfo **taskInfo)
{
int result = 0;
esxVI_String *propertyNameList = NULL;
diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h
index d581a59..e84f62b 100644
--- a/src/esx/esx_vi.h
+++ b/src/esx/esx_vi.h
@@ -98,11 +98,14 @@ enum _esxVI_APIVersion {
enum _esxVI_ProductVersion {
esxVI_ProductVersion_Undefined = 0,
- esxVI_ProductVersion_GSX20,
- esxVI_ProductVersion_ESX35,
- esxVI_ProductVersion_ESX40,
- esxVI_ProductVersion_VPX25,
- esxVI_ProductVersion_VPX40
+ esxVI_ProductVersion_GSX = 0x1000,
+ esxVI_ProductVersion_GSX20 = 0x1001,
+ esxVI_ProductVersion_ESX = 0x2000,
+ esxVI_ProductVersion_ESX35 = 0x2001,
+ esxVI_ProductVersion_ESX40 = 0x2002,
+ esxVI_ProductVersion_VPX = 0x4000,
+ esxVI_ProductVersion_VPX25 = 0x4001,
+ esxVI_ProductVersion_VPX40 = 0x4002
};
enum _esxVI_Occurrence {
@@ -272,6 +275,19 @@ int esxVI_GetVirtualMachineQuestionInfo
(esxVI_ObjectContent *virtualMachine,
esxVI_VirtualMachineQuestionInfo **questionInfo);
+int esxVI_GetBoolean(esxVI_ObjectContent *objectContent,
+ const char *propertyName,
+ esxVI_Boolean *value, esxVI_Occurrence occurence);
+
+int esxVI_GetStringValue(esxVI_ObjectContent *objectContent,
+ const char *propertyName,
+ char **value, esxVI_Occurrence occurence);
+
+int esxVI_GetManagedObjectReference(esxVI_ObjectContent *objectContent,
+ const char *propertyName,
+ esxVI_ManagedObjectReference **value,
+ esxVI_Occurrence occurence);
+
int esxVI_LookupNumberOfDomainsByPowerState
(esxVI_Context *ctx, esxVI_VirtualMachinePowerState powerState,
esxVI_Boolean inverse);
diff --git a/src/esx/esx_vi_generator.input b/src/esx/esx_vi_generator.input
index 5e5e6ba..ff65178 100644
--- a/src/esx/esx_vi_generator.input
+++ b/src/esx/esx_vi_generator.input
@@ -146,6 +146,14 @@ object ChoiceOption extends OptionType
end
+object DatastoreInfo
+ String name r
+ String url r
+ Long freeSpace r
+ Long maxFileSize r
+end
+
+
object Description
String label r
String summary r
@@ -186,6 +194,47 @@ object HostCpuIdInfo
end
+object HostFileSystemVolume
+ String type r
+ String name r
+ Long capacity r
+end
+
+
+object HostNasVolume extends HostFileSystemVolume
+ String remoteHost r
+ String remotePath r
+ String userName o
+end
+
+
+object HostScsiDiskPartition
+ String diskName r
+ Int partition r
+end
+
+
+object HostVmfsVolume extends HostFileSystemVolume
+ Int blockSizeMb r
+ Int maxBlocks r
+ Int majorVersion r
+ String version r
+ String uuid r
+ HostScsiDiskPartition extent rl
+ Boolean vmfsUpgradable r
+end
+
+
+object LocalDatastoreInfo extends DatastoreInfo
+ String path o
+end
+
+
+object NasDatastoreInfo extends DatastoreInfo
+ HostNasVolume nas o
+end
+
+
object ObjectContent
ManagedObjectReference obj r
DynamicProperty propSet ol
@@ -453,6 +502,11 @@ object VirtualMachineSnapshotTree
end
+object VmfsDatastoreInfo extends DatastoreInfo
+ HostVmfsVolume vmfs o
+end
+
+
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Methods
#
@@ -571,6 +625,11 @@ method ReconfigVM_Task returns ManagedObjectReference r
end
+method RefreshDatastore
+ ManagedObjectReference _this r
+end
+
+
method RegisterVM_Task returns ManagedObjectReference r
ManagedObjectReference _this r
String path r
diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py
index d249e2d..8df0e80 100755
--- a/src/esx/esx_vi_generator.py
+++ b/src/esx/esx_vi_generator.py
@@ -382,6 +382,9 @@ class Object:
self.properties = properties
self.extended_by = extended_by
+ if self.extended_by is not None:
+ self.extended_by.sort();
+
def generate_struct_members(self, add_banner = False, struct_gap = False):
global objects_by_name
@@ -765,7 +768,18 @@ class Object:
# cast from any type
if self.features & Object.FEATURE__ANY_TYPE:
source += "/* esxVI_%s_CastFromAnyType */\n" % self.name
- source += "ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(%s)\n" % self.name
+ source += "ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(%s,\n" % self.name
+
+ if self.extended_by is None:
+ source += "{\n"
+ source += "})\n\n"
+ else:
+ source += "{\n"
+
+ for extended_by in self.extended_by:
+ source += " ESX_VI__TEMPLATE__DISPATCH__CAST_FROM_ANY_TYPE(%s)\n" % extended_by
+
+ source += "})\n\n"
if self.features & Object.FEATURE__LIST:
source += "/* esxVI_%s_CastListFromAnyType */\n" % self.name
@@ -1084,7 +1098,8 @@ additional_enum_features = { "ManagedEntityStatus" : Enum.FEATURE__ANY_TYPE
"VirtualMachinePowerState" : Enum.FEATURE__ANY_TYPE }
-additional_object_features = { "Event" : Object.FEATURE__LIST,
+additional_object_features = { "DatastoreInfo" : Object.FEATURE__ANY_TYPE | Object.FEATURE__DYNAMIC_CAST,
+ "Event" : Object.FEATURE__LIST,
"HostCpuIdInfo" : Object.FEATURE__ANY_TYPE | Object.FEATURE__LIST,
"ManagedObjectReference" : Object.FEATURE__ANY_TYPE,
"ObjectContent" : Object.FEATURE__DEEP_COPY | Object.FEATURE__LIST,
@@ -1224,6 +1239,7 @@ for obj in objects_by_name.values():
extended_obj.extended_by = [obj.name]
else:
extended_obj.extended_by.append(obj.name)
+ extended_obj.extended_by.sort()
diff --git a/src/esx/esx_vi_types.c b/src/esx/esx_vi_types.c
index 7d2c02c..8334efd 100644
--- a/src/esx/esx_vi_types.c
+++ b/src/esx/esx_vi_types.c
@@ -183,7 +183,7 @@
-#define ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(_type) \
+#define ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(_type, _dispatch) \
int \
esxVI_##_type##_CastFromAnyType(esxVI_AnyType *anyType, \
esxVI_##_type **ptrptr) \
@@ -194,11 +194,16 @@
return -1; \
} \
\
- if (anyType->type != esxVI_Type_##_type) { \
+ switch (anyType->type) { \
+ _dispatch \
+ \
+ case esxVI_Type_##_type: \
+ break; \
+ \
+ default: \
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, \
- "Expecting type '%s' but found '%s'", \
- esxVI_Type_ToString(esxVI_Type_##_type), \
- anyType->other); \
+ _("Call to %s for unexpected type '%s'"), \
+ __FUNCTION__, anyType->other); \
return -1; \
} \
\
@@ -505,7 +510,7 @@
\
default: \
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, \
- "Call to %s for unexpected type '%s'", __FUNCTION__, \
+ _("Call to %s for unexpected type '%s'"), __FUNCTION__, \
esxVI_Type_ToString(item->_type)); \
return _error_return; \
}
@@ -526,6 +531,13 @@
+#define ESX_VI__TEMPLATE__DISPATCH__CAST_FROM_ANY_TYPE(_type) \
+ case esxVI_Type_##_type: \
+ return esxVI_##_type##_Deserialize(anyType->node, \
+ (esxVI_##_type **)ptrptr);
+
+
+
#define ESX_VI__TEMPLATE__DISPATCH__SERIALIZE(_type) \
case esxVI_Type_##_type: \
return esxVI_##_type##_Serialize((esxVI_##_type *)item, element, \
@@ -540,6 +552,13 @@
+#define ESX_VI__TEMPLATE__DYNAMIC_CAST__ACCEPT(__type) \
+ if (((esxVI_Object *)item)->_type == esxVI_Type_##__type) { \
+ return item; \
+ }
+
+
+
#define ESX_VI__TEMPLATE__DYNAMIC_CAST(__type, _accept) \
esxVI_##__type * \
esxVI_##__type##_DynamicCast(void *item) \
@@ -550,6 +569,8 @@
return NULL; \
} \
\
+ ESX_VI__TEMPLATE__DYNAMIC_CAST__ACCEPT(__type) \
+ \
_accept \
\
return NULL; \
@@ -557,13 +578,6 @@
-#define ESX_VI__TEMPLATE__DYNAMIC_CAST__ACCEPT(__type) \
- if (((esxVI_Object *)item)->_type == esxVI_Type_##__type) { \
- return item; \
- }
-
-
-
#define ESX_VI__TEMPLATE__DYNAMIC_SERIALIZE(__type, _dispatch, _serialize) \
ESX_VI__TEMPLATE__SERIALIZE_EXTRA(__type, \
ESX_VI__TEMPLATE__DISPATCH(__type, _dispatch, -1), \
@@ -1357,7 +1371,9 @@ ESX_VI__TEMPLATE__DEEP_COPY(ManagedObjectReference,
ESX_VI__TEMPLATE__LIST__APPEND(ManagedObjectReference)
/* esxVI_ManagedObjectReference_CastFromAnyType */
-ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(ManagedObjectReference)
+ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(ManagedObjectReference,
+{
+})
/* esxVI_ManagedObjectReference_CastListFromAnyType */
ESX_VI__TEMPLATE__LIST__CAST_FROM_ANY_TYPE(ManagedObjectReference)
diff --git a/tools/virsh.c b/tools/virsh.c
index 0a63f1b..4108e1e 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -5151,6 +5151,10 @@ cmdPoolInfo(vshControl *ctl, const vshCmd *cmd)
vshPrint(ctl, "%-15s %s\n", _("State:"),
_("degraded"));
break;
+ case VIR_STORAGE_POOL_INACCESSIBLE:
+ vshPrint(ctl, "%-15s %s\n", _("State:"),
+ _("inaccessible"));
+ break;
}
if (info.state == VIR_STORAGE_POOL_RUNNING ||
--
1.7.0.4
14 years, 7 months
[libvirt] [PATCH] qemu_conf: fix flag value
by Eric Blake
(gdb) p/x QEMUD_CMD_FLAG_VNET_HOST
$7 = 0xffffffff80000000
Oops - that meant we were incorrectly setting QEMU_CMD_FLAG_RTC_TD_HACK
for qemu-kvm-0.12.3 (and probably botching a few other settings as well).
* src/qemu/qemu_conf.h (QEMUD_CMD_FLAG_VNET_HOST): Avoid sign
extension.
* tests/qemuhelpdata/qemu-kvm-0.12.3: New file.
* tests/qemuhelptest.c (mymain): Add another case.
---
It didn't help that the test was truncating output to 31 bits,
and getting confused with sign extension as well.
src/qemu/qemu_conf.h | 8 +-
tests/qemuhelpdata/qemu-kvm-0.12.3 | 216 ++++++++++++++++++++++++++++++++++++
tests/qemuhelptest.c | 39 ++++++-
3 files changed, 255 insertions(+), 8 deletions(-)
create mode 100644 tests/qemuhelpdata/qemu-kvm-0.12.3
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index b2820f0..a101e47 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -1,7 +1,7 @@
/*
* qemu_conf.h: QEMU configuration management
*
- * Copyright (C) 2006, 2007, 2009, 2010 Red Hat, Inc.
+ * Copyright (C) 2006-2007, 2009-2010 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -64,7 +64,7 @@ enum qemud_cmd_flags {
QEMUD_CMD_FLAG_DRIVE_FORMAT = (1 << 14), /* Is -drive format= avail */
QEMUD_CMD_FLAG_VGA = (1 << 15), /* Is -vga avail */
- /* features added in qemu-0.10.0 */
+ /* features added in qemu-0.10.0 or later */
QEMUD_CMD_FLAG_0_10 = (1 << 16),
QEMUD_CMD_FLAG_NET_NAME = QEMUD_CMD_FLAG_0_10, /* -net ...,name=str */
QEMUD_CMD_FLAG_HOST_NET_ADD = QEMUD_CMD_FLAG_0_10, /* host_net_add monitor command */
@@ -83,8 +83,8 @@ enum qemud_cmd_flags {
QEMUD_CMD_FLAG_SMP_TOPOLOGY = (1 << 28), /* Is sockets=s,cores=c,threads=t available for -smp? */
QEMUD_CMD_FLAG_NETDEV = (1 << 29), /* The -netdev flag & netdev_add/remove monitor commands */
QEMUD_CMD_FLAG_RTC = (1 << 30), /* The -rtc flag for clock options */
- QEMUD_CMD_FLAG_VNET_HOST = (1 << 31), /* vnet-host support is available in qemu */
- QEMUD_CMD_FLAG_RTC_TD_HACK = (1LL << 32), /* -rtd-td-hack available */
+ QEMUD_CMD_FLAG_VNET_HOST = (1LL << 31), /* vnet-host support is available in qemu */
+ QEMUD_CMD_FLAG_RTC_TD_HACK = (1LL << 32), /* -rtc-td-hack available */
QEMUD_CMD_FLAG_NO_HPET = (1LL << 33), /* -no-hpet flag is supported */
QEMUD_CMD_FLAG_NO_KVM_PIT = (1LL << 34), /* -no-kvm-pit-reinjection supported */
QEMUD_CMD_FLAG_TDF = (1LL << 35), /* -tdf flag (user-mode pit catchup) */
diff --git a/tests/qemuhelpdata/qemu-kvm-0.12.3 b/tests/qemuhelpdata/qemu-kvm-0.12.3
new file mode 100644
index 0000000..54a804f
--- /dev/null
+++ b/tests/qemuhelpdata/qemu-kvm-0.12.3
@@ -0,0 +1,216 @@
+QEMU PC emulator version 0.12.3 (qemu-kvm-0.12.3), Copyright (c) 2003-2008 Fabrice Bellard
+usage: qemu [options] [disk_image]
+
+'disk_image' is a raw hard image image for IDE hard disk 0
+
+Standard options:
+-h or -help display this help and exit
+-version display version information and exit
+-M machine select emulated machine (-M ? for list)
+-cpu cpu select CPU (-cpu ? for list)
+-smp n[,maxcpus=cpus][,cores=cores][,threads=threads][,sockets=sockets]
+ set the number of CPUs to 'n' [default=1]
+ maxcpus= maximum number of total cpus, including
+ offline CPUs for hotplug etc.
+ cores= number of CPU cores on one socket
+ threads= number of threads on one CPU core
+ sockets= number of discrete sockets in the system
+-numa node[,mem=size][,cpus=cpu[-cpu]][,nodeid=node]
+-fda/-fdb file use 'file' as floppy disk 0/1 image
+-hda/-hdb file use 'file' as IDE hard disk 0/1 image
+-hdc/-hdd file use 'file' as IDE hard disk 2/3 image
+-cdrom file use 'file' as IDE cdrom image (cdrom is ide1 master)
+-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][,index=i]
+ [,cyls=c,heads=h,secs=s[,trans=t]][,snapshot=on|off]
+ [,cache=writethrough|writeback|none][,format=f][,serial=s]
+ [,addr=A][,id=name][,aio=threads|native]
+ [,boot=on|off]
+ use 'file' as a drive image
+-set group.id.arg=value
+ set <arg> parameter for item <id> of type <group>
+ i.e. -set drive.$id.file=/path/to/image
+-global driver.property=value
+ set a global default for a driver property
+-mtdblock file use 'file' as on-board Flash memory image
+-sd file use 'file' as SecureDigital card image
+-pflash file use 'file' as a parallel flash image
+-boot [order=drives][,once=drives][,menu=on|off]
+ 'drives': floppy (a), hard disk (c), CD-ROM (d), network (n)
+-snapshot write to temporary files instead of disk image files
+-m megs set virtual RAM size to megs MB [default=128]
+-k language use keyboard layout (for example 'fr' for French)
+-audio-help print list of audio drivers and their options
+-soundhw c1,... enable audio support
+ and only specified sound cards (comma separated list)
+ use -soundhw ? to get the list of supported cards
+ use -soundhw all to enable all of them
+-usb enable the USB driver (will be the default soon)
+-usbdevice name add the host or guest USB device 'name'
+-device driver[,options] add device
+-name string1[,process=string2] set the name of the guest
+ string1 sets the window title and string2 the process name (on Linux)
+-uuid %08x-%04x-%04x-%04x-%012x
+ specify machine UUID
+
+Display options:
+-nographic disable graphical output and redirect serial I/Os to console
+-curses use a curses/ncurses interface instead of SDL
+-no-frame open SDL window without a frame and window decorations
+-alt-grab use Ctrl-Alt-Shift to grab mouse (instead of Ctrl-Alt)
+-ctrl-grab use Right-Ctrl to grab mouse (instead of Ctrl-Alt)
+-no-quit disable SDL window close capability
+-sdl enable SDL
+-portrait rotate graphical output 90 deg left (only PXA LCD)
+-vga [std|cirrus|vmware|xenfb|none]
+ select video card type
+-full-screen start in full screen
+-vnc display start a VNC server on display
+
+1 target only:
+-win2k-hack use it when installing Windows 2000 to avoid a disk full bug
+-no-fd-bootchk disable boot signature checking for floppy disks
+-no-acpi disable ACPI
+-no-hpet disable HPET
+-balloon none disable balloon device
+-balloon virtio[,addr=str]
+ enable virtio balloon device (default)
+-acpitable [sig=str][,rev=n][,oem_id=str][,oem_table_id=str][,oem_rev=n][,asl_compiler_id=str][,asl_compiler_rev=n][,data=file1[:file2]...]
+ ACPI table description
+-smbios file=binary
+ Load SMBIOS entry from binary file
+-smbios type=0[,vendor=str][,version=str][,date=str][,release=%d.%d]
+ Specify SMBIOS type 0 fields
+-smbios type=1[,manufacturer=str][,product=str][,version=str][,serial=str]
+ [,uuid=uuid][,sku=str][,family=str]
+ Specify SMBIOS type 1 fields
+
+Network options:
+-net nic[,vlan=n][,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v]
+ create a new Network Interface Card and connect it to VLAN 'n'
+-net user[,vlan=n][,name=str][,net=addr[/mask]][,host=addr][,restrict=y|n]
+ [,hostname=host][,dhcpstart=addr][,dns=addr][,tftp=dir][,bootfile=f]
+ [,hostfwd=rule][,guestfwd=rule][,smb=dir[,smbserver=addr]]
+ connect the user mode network stack to VLAN 'n', configure its
+ DHCP server and enabled optional services
+-net tap[,vlan=n][,name=str][,fd=h][,ifname=name][,script=file][,downscript=dfile][,sndbuf=nbytes][,vnet_hdr=on|off][,vhost=on|off][,vhostfd=h]
+ connect the host TAP network interface to VLAN 'n' and use the
+ network scripts 'file' (default=/etc/qemu-ifup)
+ and 'dfile' (default=/etc/qemu-ifdown);
+ use '[down]script=no' to disable script execution;
+ use 'fd=h' to connect to an already opened TAP interface
+ use 'sndbuf=nbytes' to limit the size of the send buffer; the
+ default of 'sndbuf=1048576' can be disabled using 'sndbuf=0'
+ use vnet_hdr=off to avoid enabling the IFF_VNET_HDR tap flag; use
+ vnet_hdr=on to make the lack of IFF_VNET_HDR support an error condition
+ use vhost=on to enable experimental in kernel accelerator
+ use 'vhostfd=h' to connect to an already opened vhost net device
+-net socket[,vlan=n][,name=str][,fd=h][,listen=[host]:port][,connect=host:port]
+ connect the vlan 'n' to another VLAN using a socket connection
+-net socket[,vlan=n][,name=str][,fd=h][,mcast=maddr:port]
+ connect the vlan 'n' to multicast maddr and port
+-net dump[,vlan=n][,file=f][,len=n]
+ dump traffic on vlan 'n' to file 'f' (max n bytes per packet)
+-net none use it alone to have zero network devices; if no -net option
+ is provided, the default is '-net nic -net user'
+-netdev [user|tap|socket],id=str[,option][,option][,...]
+
+Character device options:
+-chardev null,id=id
+-chardev socket,id=id[,host=host],port=host[,to=to][,ipv4][,ipv6][,nodelay]
+ [,server][,nowait][,telnet] (tcp)
+-chardev socket,id=id,path=path[,server][,nowait][,telnet] (unix)
+-chardev udp,id=id[,host=host],port=port[,localaddr=localaddr]
+ [,localport=localport][,ipv4][,ipv6]
+-chardev msmouse,id=id
+-chardev vc,id=id[[,width=width][,height=height]][[,cols=cols][,rows=rows]]
+-chardev file,id=id,path=path
+-chardev pipe,id=id,path=path
+-chardev pty,id=id
+-chardev stdio,id=id
+-chardev tty,id=id,path=path
+-chardev parport,id=id,path=path
+
+Bluetooth(R) options:
+-bt hci,null dumb bluetooth HCI - doesn't respond to commands
+-bt hci,host[:id]
+ use host's HCI with the given name
+-bt hci[,vlan=n]
+ emulate a standard HCI in virtual scatternet 'n'
+-bt vhci[,vlan=n]
+ add host computer to virtual scatternet 'n' using VHCI
+-bt device:dev[,vlan=n]
+ emulate a bluetooth device 'dev' in scatternet 'n'
+
+Linux/Multiboot boot specific:
+-kernel bzImage use 'bzImage' as kernel image
+-append cmdline use 'cmdline' as kernel command line
+-initrd file use 'file' as initial ram disk
+
+Debug/Expert options:
+-serial dev redirect the serial port to char device 'dev'
+-parallel dev redirect the parallel port to char device 'dev'
+-monitor dev redirect the monitor to char device 'dev'
+-qmp dev like -monitor but opens in 'control' mode.
+-mon chardev=[name][,mode=readline|control][,default]
+-pidfile file write PID to 'file'
+-singlestep always run in singlestep mode
+-S freeze CPU at startup (use 'c' to start execution)
+-gdb dev wait for gdb connection on 'dev'
+-s shorthand for -gdb tcp::1234
+-d item1,... output log to /tmp/qemu.log (use -d ? for a list of log items)
+-hdachs c,h,s[,t]
+ force hard disk 0 physical geometry and the optional BIOS
+ translation (t=none or lba) (usually qemu can guess them)
+-L path set the directory for the BIOS, VGA BIOS and keymaps
+-bios file set the filename for the BIOS
+-no-reboot exit instead of rebooting
+-no-shutdown stop before shutdown
+-loadvm [tag|id]
+ start right away with a saved state (loadvm in monitor)
+-daemonize daemonize QEMU after initializing
+-option-rom rom load a file, rom, into the option ROM space
+-clock force the use of the given methods for timer alarm.
+ To see what timers are available use -clock ?
+-rtc [base=utc|localtime|date][,clock=host|vm][,driftfix=none|slew]
+ set the RTC base and clock, enable drift fix for clock ticks
+-icount [N|auto]
+ enable virtual instruction counter with 2^N clock ticks per
+ instruction
+-watchdog i6300esb|ib700
+ enable virtual hardware watchdog [default=none]
+-watchdog-action reset|shutdown|poweroff|pause|debug|none
+ action when watchdog fires [default=reset]
+-echr chr set terminal escape character instead of ctrl-a
+-virtioconsole c
+ set virtio console
+-show-cursor show cursor
+-tb-size n set TB size
+-incoming p prepare for incoming migration, listen on port p
+-nodefaults don't create default devices.
+-chroot dir Chroot to dir just before starting the VM.
+-runas user Change to user id user just before starting the VM.
+-readconfig <file>
+-writeconfig <file>
+ read/write config file
+-no-kvm disable KVM hardware virtualization
+-no-kvm-irqchip disable KVM kernel mode PIC/IOAPIC/LAPIC
+-no-kvm-pit disable KVM kernel mode PIT
+-no-kvm-pit-reinjection disable KVM kernel mode PIT interrupt reinjection
+-pcidevice host=bus:dev.func[,dma=none][,name=string]
+ expose a PCI device to the guest OS.
+ dma=none: don't perform any dma translations (default is to use an iommu)
+ 'string' is used in log output.
+-enable-nesting enable support for running a VM inside the VM (AMD only)
+-nvram FILE provide ia64 nvram contents
+-tdf enable guest time drift compensation
+-kvm-shadow-memory MEGABYTES
+ allocate MEGABYTES for kvm mmu shadowing
+-mem-path FILE provide backing storage for guest RAM
+-mem-prealloc preallocate guest memory (use with -mempath)
+
+During emulation, the following keys are useful:
+ctrl-alt-f toggle full screen
+ctrl-alt-n switch to virtual console 'n'
+ctrl-alt toggle mouse and keyboard grab
+
+When using -nographic, press 'ctrl-a h' to get some help.
diff --git a/tests/qemuhelptest.c b/tests/qemuhelptest.c
index b8c4b91..517a8fe 100644
--- a/tests/qemuhelptest.c
+++ b/tests/qemuhelptest.c
@@ -21,13 +21,14 @@ struct testInfo {
static char *progname;
static char *abs_srcdir;
-static void printMismatchedFlags(int got, int expect)
+static void printMismatchedFlags(unsigned long long got,
+ unsigned long long expect)
{
int i;
- for (i = 0 ; i < (sizeof(got)*8) ; i++) {
- int gotFlag = (got & (1 << i));
- int expectFlag = (expect & (1 << i));
+ for (i = 0 ; i < (sizeof(got)*CHAR_BIT) ; i++) {
+ unsigned long long gotFlag = (got & (1LL << i));
+ unsigned long long expectFlag = (expect & (1LL << i));
if (gotFlag && !expectFlag)
fprintf(stderr, "Extra flag %i\n", i);
if (!gotFlag && expectFlag)
@@ -245,6 +246,36 @@ mymain(int argc, char **argv)
QEMUD_CMD_FLAG_RTC |
QEMUD_CMD_FLAG_NO_HPET,
12001, 0, 0);
+ DO_TEST("qemu-kvm-0.12.3",
+ QEMUD_CMD_FLAG_VNC_COLON |
+ QEMUD_CMD_FLAG_NO_REBOOT |
+ QEMUD_CMD_FLAG_DRIVE |
+ QEMUD_CMD_FLAG_DRIVE_BOOT |
+ QEMUD_CMD_FLAG_NAME |
+ QEMUD_CMD_FLAG_UUID |
+ QEMUD_CMD_FLAG_VNET_HDR |
+ QEMUD_CMD_FLAG_MIGRATE_QEMU_TCP |
+ QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC |
+ QEMUD_CMD_FLAG_DRIVE_CACHE_V2 |
+ QEMUD_CMD_FLAG_KVM |
+ QEMUD_CMD_FLAG_DRIVE_FORMAT |
+ QEMUD_CMD_FLAG_DRIVE_SERIAL |
+ QEMUD_CMD_FLAG_VGA |
+ QEMUD_CMD_FLAG_0_10 |
+ QEMUD_CMD_FLAG_PCIDEVICE |
+ QEMUD_CMD_FLAG_MEM_PATH |
+ QEMUD_CMD_FLAG_SDL |
+ QEMUD_CMD_FLAG_MIGRATE_QEMU_UNIX |
+ QEMUD_CMD_FLAG_CHARDEV |
+ QEMUD_CMD_FLAG_BALLOON |
+ QEMUD_CMD_FLAG_DEVICE |
+ QEMUD_CMD_FLAG_SMP_TOPOLOGY |
+ QEMUD_CMD_FLAG_RTC |
+ QEMUD_CMD_FLAG_VNET_HOST |
+ QEMUD_CMD_FLAG_NO_HPET |
+ QEMUD_CMD_FLAG_NO_KVM_PIT |
+ QEMUD_CMD_FLAG_TDF,
+ 12003, 1, 0);
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
--
1.7.0.1
14 years, 7 months
[libvirt] [PATCH] qemu: Clarify a couple error messages
by Cole Robinson
A fedora translator filed:
https://bugzilla.redhat.com/show_bug.cgi?id=580816
Pointing out these two error messages as unclear: "write save" sounds
like a typo without context, and lack of a colon made the second message
difficult to parse.
Signed-off-by: Cole Robinson <crobinso(a)redhat.com>
---
src/qemu/qemu_driver.c | 8 +++++---
1 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 582fdee..9ae8307 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4805,7 +4805,8 @@ static int qemudDomainSaveFileOpHook(int fd, void *data) {
if (safewrite(fd, hdata->header, sizeof(*hdata->header)) != sizeof(*hdata->header)) {
ret = errno;
qemuReportError(VIR_ERR_OPERATION_FAILED,
- _("failed to write save header to '%s'"), hdata->path);
+ _("failed to write domain save file header to '%s'"),
+ hdata->path);
goto endjob;
}
@@ -5005,8 +5006,9 @@ static int qemudDomainSaveFlag(virDomainPtr dom, const char *path,
if (statfs_ret == -1) {
virReportSystemError(errno,
- _("Failed to create domain save file '%s'"
- " statfs of all elements of path failed."),
+ _("Failed to create domain save file "
+ "'%s': statfs of all elements of path "
+ "failed"),
path);
VIR_FREE(dirpath);
goto endjob;
--
1.6.6.1
14 years, 7 months
[libvirt] [PATCH] virFileResolveLink: fix return value
by Eric Blake
virFileResolveLink was returning a positive value on error,
thus confusing callers that assumed failure was < 0. The
confusion is further evidenced by callers that would have
ended up calling virReportSystemError with a negative value
instead of a valid errno.
Fixes Red Hat BZ #591363.
* src/util/util.c (virFileResolveLink): Live up to documentation.
* src/qemu/qemu_security_dac.c
(qemuSecurityDACRestoreSecurityFileLabel): Adjust callers.
* src/security/security_selinux.c
(SELinuxRestoreSecurityFileLabel): Likewise.
* src/storage/storage_backend_disk.c
(virStorageBackendDiskDeleteVol): Likewise.
---
Thanks to Daniel P. Berrange for helping isolate the cause
of the bugzilla failure. I validated that the only instance
of 'cannot stat %s' in libvirt.po comes from
SELinuxRestoreSecurityFileLabel, and that it does indeed
have the ability to dereference a NULL pointer before this fix.
src/qemu/qemu_security_dac.c | 5 ++---
src/security/security_selinux.c | 7 +++----
src/storage/storage_backend_disk.c | 7 +++----
src/util/util.c | 6 +++---
4 files changed, 11 insertions(+), 14 deletions(-)
diff --git a/src/qemu/qemu_security_dac.c b/src/qemu/qemu_security_dac.c
index 364227d..a816441 100644
--- a/src/qemu/qemu_security_dac.c
+++ b/src/qemu/qemu_security_dac.c
@@ -75,13 +75,12 @@ qemuSecurityDACRestoreSecurityFileLabel(const char *path)
{
struct stat buf;
int rc = -1;
- int err;
char *newpath = NULL;
VIR_INFO("Restoring DAC user and group on '%s'", path);
- if ((err = virFileResolveLink(path, &newpath)) < 0) {
- virReportSystemError(err,
+ if (virFileResolveLink(path, &newpath) < 0) {
+ virReportSystemError(errno,
_("cannot resolve symlink %s"), path);
goto err;
}
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index 47534df..669ef42 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008,2009 Red Hat, Inc.
+ * Copyright (C) 2008-2010 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -353,13 +353,12 @@ SELinuxRestoreSecurityFileLabel(const char *path)
struct stat buf;
security_context_t fcon = NULL;
int rc = -1;
- int err;
char *newpath = NULL;
VIR_INFO("Restoring SELinux context on '%s'", path);
- if ((err = virFileResolveLink(path, &newpath)) < 0) {
- virReportSystemError(err,
+ if (virFileResolveLink(path, &newpath) < 0) {
+ virReportSystemError(errno,
_("cannot resolve symlink %s"), path);
goto err;
}
diff --git a/src/storage/storage_backend_disk.c b/src/storage/storage_backend_disk.c
index 836d1ca..7188386 100644
--- a/src/storage/storage_backend_disk.c
+++ b/src/storage/storage_backend_disk.c
@@ -1,7 +1,7 @@
/*
* storage_backend_disk.c: storage backend for disk handling
*
- * Copyright (C) 2007-2008 Red Hat, Inc.
+ * Copyright (C) 2007-2008, 2010 Red Hat, Inc.
* Copyright (C) 2007-2008 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -612,13 +612,12 @@ virStorageBackendDiskDeleteVol(virConnectPtr conn ATTRIBUTE_UNUSED,
unsigned int flags ATTRIBUTE_UNUSED)
{
char *part_num = NULL;
- int err;
char *devpath = NULL;
char *devname, *srcname;
int rc = -1;
- if ((err = virFileResolveLink(vol->target.path, &devpath)) < 0) {
- virReportSystemError(err,
+ if (virFileResolveLink(vol->target.path, &devpath) < 0) {
+ virReportSystemError(errno,
_("Couldn't read volume target path '%s'"),
vol->target.path);
goto cleanup;
diff --git a/src/util/util.c b/src/util/util.c
index 26ac6ba..e937d39 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -1182,7 +1182,7 @@ int virFileLinkPointsTo(const char *checkLink,
* real path
*
* Return 0 if path was not a symbolic, or the link was
- * resolved. Return -1 upon error
+ * resolved. Return -1 with errno set upon error
*/
int virFileResolveLink(const char *linkpath,
char **resultpath)
@@ -1192,11 +1192,11 @@ int virFileResolveLink(const char *linkpath,
*resultpath = NULL;
if (lstat(linkpath, &st) < 0)
- return errno;
+ return -1;
if (!S_ISLNK(st.st_mode)) {
if (!(*resultpath = strdup(linkpath)))
- return -ENOMEM;
+ return -1;
return 0;
}
--
1.7.0.1
14 years, 7 months
[libvirt] [PATCH] lxcFreezeContainer: avoid test-after-deref of never-NULL pointer
by Jim Meyering
This addresses another coverity-spotted "flaw".
However, since "cgroup" is never NULL after that initial "if" stmt,
the only penalty is that the useless cleanup test would make a reviewer
try to figure out how cgroup could be NULL there.
>From d89098801d4e5011e07994cf0391ace2363d8971 Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyering(a)redhat.com>
Date: Mon, 17 May 2010 19:18:12 +0200
Subject: [PATCH] lxcFreezeContainer: avoid test-after-deref of never-NULL pointer
* src/lxc/lxc_driver.c (lxcFreezeContainer): Remove test-after-deref.
Correct indentation in expression.
---
src/lxc/lxc_driver.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index fc0df37..8c3bbd3 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -2276,69 +2276,71 @@ static int lxcDomainSetAutostart(virDomainPtr dom,
}
} else {
if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
virReportSystemError(errno,
_("Failed to delete symlink '%s'"),
autostartLink);
goto cleanup;
}
}
vm->autostart = autostart;
ret = 0;
cleanup:
VIR_FREE(configFile);
VIR_FREE(autostartLink);
if (vm)
virDomainObjUnlock(vm);
lxcDriverUnlock(driver);
return ret;
}
static int lxcFreezeContainer(lxc_driver_t *driver, virDomainObjPtr vm)
{
int timeout = 1000; /* In milliseconds */
int check_interval = 1; /* In milliseconds */
int exp = 10;
int waited_time = 0;
int ret = -1;
char *state = NULL;
virCgroupPtr cgroup = NULL;
if (!(driver->cgroup &&
- virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) == 0))
+ virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) == 0))
return -1;
+ /* From here on, we know that cgroup != NULL. */
+
while (waited_time < timeout) {
int r;
/*
* Writing "FROZEN" to the "freezer.state" freezes the group,
* i.e., the container, temporarily transiting "FREEZING" state.
* Once the freezing is completed, the state of the group transits
* to "FROZEN".
* (see linux-2.6/Documentation/cgroups/freezer-subsystem.txt)
*/
r = virCgroupSetFreezerState(cgroup, "FROZEN");
/*
* Returning EBUSY explicitly indicates that the group is
* being freezed but incomplete and other errors are true
* errors.
*/
if (r < 0 && r != -EBUSY) {
VIR_DEBUG("Writing freezer.state failed with errno: %d", r);
goto error;
}
if (r == -EBUSY)
VIR_DEBUG0("Writing freezer.state gets EBUSY");
/*
* Unfortunately, returning 0 (success) is likely to happen
* even when the freezing has not been completed. Sometimes
* the state of the group remains "FREEZING" like when
* returning -EBUSY and even worse may never transit to
* "FROZEN" even if writing "FROZEN" again.
*
* So we don't trust the return value anyway and always
* decide that the freezing has been complete only with
* the state actually transit to "FROZEN".
@@ -2351,68 +2353,67 @@ static int lxcFreezeContainer(lxc_driver_t *driver, virDomainObjPtr vm)
VIR_DEBUG("Reading freezer.state failed with errno: %d", r);
goto error;
}
VIR_DEBUG("Read freezer.state: %s", state);
if (STREQ(state, "FROZEN")) {
ret = 0;
goto cleanup;
}
waited_time += check_interval;
/*
* Increasing check_interval exponentially starting with
* small initial value treats nicely two cases; One is
* a container is under no load and waiting for long period
* makes no sense. The other is under heavy load. The container
* may stay longer time in FREEZING or never transit to FROZEN.
* In that case, eager polling will just waste CPU time.
*/
check_interval *= exp;
VIR_FREE(state);
}
VIR_DEBUG0("lxcFreezeContainer timeout");
error:
/*
* If timeout or an error on reading the state occurs,
* activate the group again and return an error.
* This is likely to fall the group back again gracefully.
*/
virCgroupSetFreezerState(cgroup, "THAWED");
ret = -1;
cleanup:
- if (cgroup)
- virCgroupFree(&cgroup);
+ virCgroupFree(&cgroup);
VIR_FREE(state);
return ret;
}
static int lxcDomainSuspend(virDomainPtr dom)
{
lxc_driver_t *driver = dom->conn->privateData;
virDomainObjPtr vm;
virDomainEventPtr event = NULL;
int ret = -1;
lxcDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
if (!vm) {
char uuidstr[VIR_UUID_STRING_BUFLEN];
virUUIDFormat(dom->uuid, uuidstr);
lxcError(VIR_ERR_NO_DOMAIN,
_("No domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
if (!virDomainObjIsActive(vm)) {
lxcError(VIR_ERR_OPERATION_INVALID,
"%s", _("Domain is not running"));
goto cleanup;
}
if (vm->state != VIR_DOMAIN_PAUSED) {
if (lxcFreezeContainer(driver, vm) < 0) {
lxcError(VIR_ERR_OPERATION_FAILED,
"%s", _("Suspend operation failed"));
goto cleanup;
--
1.7.1.250.g7d1e8
14 years, 7 months
[libvirt] [PATCH 0/2] Fix multiple NULL pointer problems in monitor usage
by Daniel P. Berrange
These two patches address multiple problems in usage of the monitor
which lead to a crash on NULL pointer. The first patch fixes all the
actual root cause problems. The second patch provides a safety net
in case I missed any, or people introduce similar bugs in the future
14 years, 7 months
[libvirt] [PATCH] tests: Skip daemon-conf test if dir exceeds UNIX_PATH_MAX
by Cole Robinson
The max path length for unix sockets is pretty small (108, see man 7 unix).
If 'make check' is run from a directory that exceeds this, one of the tests
will fail, and in such a way that requires manually editting the test to
determine why.
There are certainly other ways to handle this, but I've chosen just to skip
the offending test if we will exceed the length limitation.
Signed-off-by: Cole Robinson <crobinso(a)redhat.com>
---
tests/daemon-conf | 22 ++++++++++++++--------
1 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/tests/daemon-conf b/tests/daemon-conf
index 10c1628..8eed4c4 100755
--- a/tests/daemon-conf
+++ b/tests/daemon-conf
@@ -76,16 +76,22 @@ sed 's,^log_outputs.*,log_outputs="3:file:'"$(pwd)/log"'",' tmp.conf > k \
|| fail=1
mv k tmp.conf || fail=1
-$abs_top_builddir/daemon/libvirtd --pid-file=pid-file --config=tmp.conf > log 2>&1 & pid=$!
-sleep $sleep_secs
-kill $pid
+# Unix socket max path size is 108 on linux. If the generated sock path
+# exceeds this, the test will fail, so skip it if CWD is too long
+SOCKPATH=`pwd`/libvirt-sock
+if test ${#SOCKPATH} -lt 108 ; then
-RET=0
-# Expect an orderly shut-down and successful exit.
-wait $pid || RET=1
+ $abs_top_builddir/daemon/libvirtd --pid-file=pid-file --config=tmp.conf > log 2>&1 & pid=$!
+ sleep $sleep_secs
+ kill $pid
-test_result $i "valid config file (sleeping $sleep_secs seconds)" $RET
-test $RET = 0 || fail=1
+ RET=0
+ # Expect an orderly shut-down and successful exit.
+ wait $pid || RET=1
+
+ test_result $i "valid config file (sleeping $sleep_secs seconds)" $RET
+ test $RET = 0 || fail=1
+fi
test_final $i $fail
--
1.6.6.1
14 years, 7 months
[libvirt] [PATCH v3] pci: Give an explicit error if device not found
by Cole Robinson
v2: Use intended F_OK. Drop devdir param, just check dev->path for device
existence.
v3: Use virReportSystemError, include dev->path in error message.
Signed-off-by: Cole Robinson <crobinso(a)redhat.com>
---
src/util/pci.c | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/src/util/pci.c b/src/util/pci.c
index 81193b7..a1bd8e3 100644
--- a/src/util/pci.c
+++ b/src/util/pci.c
@@ -1046,6 +1046,14 @@ pciGetDevice(unsigned domain,
snprintf(dev->path, sizeof(dev->path),
PCI_SYSFS "devices/%s/config", dev->name);
+ if (access(dev->path, F_OK) != 0) {
+ virReportSystemError(errno,
+ _("Device %s not found: could not access %s"),
+ dev->name, dev->path);
+ pciFreeDevice(dev);
+ return NULL;
+ }
+
vendor = pciReadDeviceID(dev, "vendor");
product = pciReadDeviceID(dev, "device");
--
1.6.6.1
14 years, 7 months
[libvirt] [PATCH v2] tests: Skip daemon-conf test if dir exceeds UNIX_PATH_MAX
by Cole Robinson
The max path length for unix sockets is pretty small (108, see man 7 unix).
If 'make check' is run from a directory that exceeds this, one of the tests
will fail, and in such a way that requires manually editting the test to
determine why.
There are certainly other ways to handle this, but I've chosen just to skip
the offending test if we will exceed the length limitation.
v2: Drop bashism, use test infrastructure to warn and skip
Signed-off-by: Cole Robinson <crobinso(a)redhat.com>
---
tests/daemon-conf | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/tests/daemon-conf b/tests/daemon-conf
index 10c1628..14d4ced 100755
--- a/tests/daemon-conf
+++ b/tests/daemon-conf
@@ -76,6 +76,13 @@ sed 's,^log_outputs.*,log_outputs="3:file:'"$(pwd)/log"'",' tmp.conf > k \
|| fail=1
mv k tmp.conf || fail=1
+# Unix socket max path size is 108 on linux. If the generated sock path
+# exceeds this, the test will fail, so skip it if CWD is too long
+SOCKPATH=`pwd`/libvirt-sock
+if test 108 -lt `echo $SOCKPATH | wc -c`; then
+ skip_test_ "CWD too long"
+fi
+
$abs_top_builddir/daemon/libvirtd --pid-file=pid-file --config=tmp.conf > log 2>&1 & pid=$!
sleep $sleep_secs
kill $pid
--
1.6.6.1
14 years, 7 months