[libvirt] [PATCH] bootloader_args is named bootargs in xen-xm
by Philipp Hahn
According to <xen-3.4.3/tools/python/xen/xm/create.py:158>
gopts.var('bootargs', val='NAME',
fn=set_value, default=None,
use="Arguments to pass to boot loader")
the "bootloader_args" parameter needs to be translated into "bootargs"
when using "virsh domxml-to-native xen-xm".
The reverse direction (domxml-from-native) is already okay.
This patch fixes domxml-to-native and adds two test files to catch this
problem.
Signed-off-by: Philipp Hahn <hahn(a)univention.de>
---
src/xen/xm_internal.c | 2 +-
tests/xmconfigdata/sexpr2xml-pv-bootloader.cfg | 12 +++++++++++
tests/xmconfigdata/sexpr2xml-pv-bootloader.xml | 26
++++++++++++++++++++++++
3 files changed, 39 insertions(+), 1 deletions(-)
create mode 100644 tests/xmconfigdata/sexpr2xml-pv-bootloader.cfg
create mode 100644 tests/xmconfigdata/sexpr2xml-pv-bootloader.xml
14 years, 3 months
[libvirt] vol-clone is slow
by Harald Dunkel
Hi folks,
Sorry to say, but it seems that vol-clone is a little bit
slow. To clone a 32G logical volume it took about 40 minutes.
If I use dd instead
dd if=/dev/storage/vol1.lv bs=64k of=/dev/storage/vol2.lv
it takes just 10 minutes, and the system load is lower,
too.
libvirt is 0.8.2-1, as found in Debian Testing.
Regards
Harri
14 years, 3 months
[libvirt] [PATCH] nwfilter: extend nmwfilter reload support
by Stefan Berger
In this patch I am extending the nwfilter module's reload support to
stop all ongoing threads (for learning IP addresses of interfaces) and
rebuild the filtering rules of all interfaces of all VMs when libvirt is
started. I could not test SIGHUP on my system since I currently get a
fault there in the daemon's call to pthread_join().
About the patch: The nwfilter functions require a virConnectPtr.
Therefore I am opening a connection in qemudStartup, which later on
needs to be closed outside where the driver lock is held since otherwise
it ends up in a deadlock due to virConnectClose() trying to lock the
driver as well.
Signed-off-by: Stefan Berger <stefanb(a)us.ibm.com>
---
src/nwfilter/nwfilter_driver.c | 3 +++
src/qemu/qemu_driver.c | 32 ++++++++++++++++++++++++++++++++
2 files changed, 35 insertions(+)
Index: libvirt-acl/src/nwfilter/nwfilter_driver.c
===================================================================
--- libvirt-acl.orig/src/nwfilter/nwfilter_driver.c
+++ libvirt-acl/src/nwfilter/nwfilter_driver.c
@@ -147,6 +147,9 @@ nwfilterDriverReload(void) {
return -1;
}
+ /* shut down all threads -- qemud for example will restart them */
+ virNWFilterLearnShutdown();
+
nwfilterDriverLock(driverState);
virNWFilterPoolLoadAllConfigs(NULL,
&driverState->pools,
Index: libvirt-acl/src/qemu/qemu_driver.c
===================================================================
--- libvirt-acl.orig/src/qemu/qemu_driver.c
+++ libvirt-acl/src/qemu/qemu_driver.c
@@ -170,6 +170,9 @@ static int qemuDetectVcpuPIDs(struct qem
static int qemuUpdateActivePciHostdevs(struct qemud_driver *driver,
virDomainDefPtr def);
+static int qemudVMFiltersInstantiate(virConnectPtr conn,
+ virDomainDefPtr def);
+
static struct qemud_driver *qemu_driver = NULL;
@@ -1423,6 +1426,10 @@ error:
return ret;
}
+struct virReconnectDomainData {
+ virConnectPtr conn;
+ struct qemud_driver *driver;
+};
/*
* Open an existing VM's monitor, re-detect VCPU threads
* and re-reserve the security labels in use
@@ -1431,9 +1438,11 @@ static void
qemuReconnectDomain(void *payload, const char *name ATTRIBUTE_UNUSED,
void *opaque)
{
virDomainObjPtr obj = payload;
- struct qemud_driver *driver = opaque;
+ struct virReconnectDomainData *data = opaque;
+ struct qemud_driver *driver = data->driver;
qemuDomainObjPrivatePtr priv;
unsigned long long qemuCmdFlags;
+ virConnectPtr conn = data->conn;
virDomainObjLock(obj);
@@ -1467,6 +1476,9 @@ qemuReconnectDomain(void *payload, const
obj) < 0)
goto error;
+ if (qemudVMFiltersInstantiate(conn, obj->def))
+ goto error;
+
if (obj->def->id >= driver->nextvmid)
driver->nextvmid = obj->def->id + 1;
@@ -1491,9 +1503,10 @@ error:
* about.
*/
static void
-qemuReconnectDomains(struct qemud_driver *driver)
+qemuReconnectDomains(virConnectPtr conn, struct qemud_driver *driver)
{
- virHashForEach(driver->domains.objs, qemuReconnectDomain, driver);
+ struct virReconnectDomainData data = {conn, driver};
+ virHashForEach(driver->domains.objs, qemuReconnectDomain, &data);
}
@@ -1691,6 +1704,7 @@ qemudStartup(int privileged) {
char *base = NULL;
char driverConf[PATH_MAX];
int rc;
+ virConnectPtr conn = NULL;
if (VIR_ALLOC(qemu_driver) < 0)
return -1;
@@ -1912,7 +1926,11 @@ qemudStartup(int privileged) {
1, NULL, NULL) < 0)
goto error;
- qemuReconnectDomains(qemu_driver);
+ conn = virConnectOpen(qemu_driver->privileged ?
+ "qemu:///system" :
+ "qemu:///session");
+
+ qemuReconnectDomains(conn, qemu_driver);
/* Then inactive persistent configs */
if (virDomainLoadAllConfigs(qemu_driver->caps,
@@ -1930,6 +1948,8 @@ qemudStartup(int privileged) {
qemudAutostartConfigs(qemu_driver);
+ if (conn)
+ virConnectClose(conn);
return 0;
@@ -1938,6 +1958,8 @@ out_of_memory:
error:
if (qemu_driver)
qemuDriverUnlock(qemu_driver);
+ if (conn)
+ virConnectClose(conn);
VIR_FREE(base);
qemudShutdown();
return -1;
@@ -12724,6 +12746,28 @@ qemudVMFilterRebuild(virConnectPtr conn
return 0;
}
+static int
+qemudVMFiltersInstantiate(virConnectPtr conn,
+ virDomainDefPtr def)
+{
+ int err = 0;
+ int i;
+
+ if (!conn)
+ return 1;
+
+ for (i = 0 ; i < def->nnets ; i++) {
+ virDomainNetDefPtr net = def->nets[i];
+ if ((net->filter) && (net->ifname)) {
+ if (virDomainConfNWFilterInstantiate(conn, net)) {
+ err = 1;
+ break;
+ }
+ }
+ }
+
+ return err;
+}
static virNWFilterCallbackDriver qemuCallbackDriver = {
.name = "QEMU",
14 years, 3 months
[libvirt] Possible documentation enhancement
by Daniel Kraft
Hi,
I just wanted to add hooks on a node and didn't succeed. The error message was:
Hook script execution failed: Hook script /etc/libvirt/hooks/qemu qemu failed
with error code 256:libvir: error : cannot execute binary
/etc/libvirt/hooks/qemu: Permission denied
After reading the whole relevant src/utils code without finding any reason for
this, I found out that it was apparmor's fault.
So maybe there's a profile for the hooks missing (at least in ubuntu's
packaging). And maybe there's room in the hook-docs for a hint about that.
Daniel
14 years, 3 months
[libvirt] [PATCH] esx: Add read-only storage volume access
by Matthias Bolte
This allows to list existing volumes and to retrieve information
about them.
---
src/esx/esx_driver.c | 112 +----------
src/esx/esx_storage_driver.c | 433 +++++++++++++++++++++++++++++++++++++++-
src/esx/esx_vi.c | 279 ++++++++++++++++++++++++++
src/esx/esx_vi.h | 9 +
src/esx/esx_vi_generator.input | 7 +
5 files changed, 724 insertions(+), 116 deletions(-)
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index 4fb357b..c54f81e 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -348,19 +348,7 @@ esxAutodetectSCSIControllerModel(virDomainDiskDefPtr def, int *model,
{
int result = -1;
esxVMX_Data *data = opaque;
- char *datastoreName = NULL;
- char *directoryName = NULL;
- char *fileName = NULL;
- char *datastorePath = NULL;
- esxVI_String *propertyNameList = NULL;
- esxVI_ObjectContent *datastore = NULL;
- esxVI_ManagedObjectReference *hostDatastoreBrowser = NULL;
- esxVI_HostDatastoreBrowserSearchSpec *searchSpec = NULL;
- esxVI_VmDiskFileQuery *vmDiskFileQuery = NULL;
- esxVI_ManagedObjectReference *task = NULL;
- esxVI_TaskInfoState taskInfoState;
- esxVI_TaskInfo *taskInfo = NULL;
- esxVI_HostDatastoreBrowserSearchResults *searchResults = NULL;
+ esxVI_FileInfo *fileInfo = NULL;
esxVI_VmDiskFileInfo *vmDiskFileInfo = NULL;
if (def->device != VIR_DOMAIN_DISK_DEVICE_DISK ||
@@ -375,87 +363,12 @@ esxAutodetectSCSIControllerModel(virDomainDiskDefPtr def, int *model,
return 0;
}
- if (esxUtil_ParseDatastorePath(def->src, &datastoreName, &directoryName,
- &fileName) < 0) {
+ if (esxVI_LookupFileInfoByDatastorePath(data->ctx, def->src, &fileInfo,
+ esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
- if (directoryName == NULL) {
- if (virAsprintf(&datastorePath, "[%s]", datastoreName) < 0) {
- virReportOOMError();
- goto cleanup;
- }
- } else {
- if (virAsprintf(&datastorePath, "[%s] %s", datastoreName,
- directoryName) < 0) {
- virReportOOMError();
- goto cleanup;
- }
- }
-
- /* Lookup HostDatastoreBrowser */
- if (esxVI_String_AppendValueToList(&propertyNameList, "browser") < 0 ||
- esxVI_LookupDatastoreByName(data->ctx, datastoreName, propertyNameList,
- &datastore,
- esxVI_Occurrence_RequiredItem) < 0 ||
- esxVI_GetManagedObjectReference(datastore, "browser",
- &hostDatastoreBrowser,
- esxVI_Occurrence_RequiredItem) < 0) {
- goto cleanup;
- }
-
- /* Build HostDatastoreBrowserSearchSpec */
- if (esxVI_HostDatastoreBrowserSearchSpec_Alloc(&searchSpec) < 0 ||
- esxVI_FileQueryFlags_Alloc(&searchSpec->details) < 0) {
- goto cleanup;
- }
-
- searchSpec->details->fileType = esxVI_Boolean_True;
- searchSpec->details->fileSize = esxVI_Boolean_False;
- searchSpec->details->modification = esxVI_Boolean_False;
-
- if (esxVI_VmDiskFileQuery_Alloc(&vmDiskFileQuery) < 0 ||
- esxVI_VmDiskFileQueryFlags_Alloc(&vmDiskFileQuery->details) < 0 ||
- esxVI_FileQuery_AppendToList
- (&searchSpec->query,
- esxVI_FileQuery_DynamicCast(vmDiskFileQuery)) < 0) {
- goto cleanup;
- }
-
- vmDiskFileQuery->details->diskType = esxVI_Boolean_False;
- vmDiskFileQuery->details->capacityKb = esxVI_Boolean_False;
- vmDiskFileQuery->details->hardwareVersion = esxVI_Boolean_False;
- vmDiskFileQuery->details->controllerType = esxVI_Boolean_True;
- vmDiskFileQuery->details->diskExtents = esxVI_Boolean_False;
-
- if (esxVI_String_Alloc(&searchSpec->matchPattern) < 0) {
- goto cleanup;
- }
-
- searchSpec->matchPattern->value = fileName;
-
- /* Search datastore for file */
- if (esxVI_SearchDatastore_Task(data->ctx, hostDatastoreBrowser,
- datastorePath, searchSpec, &task) < 0 ||
- esxVI_WaitForTaskCompletion(data->ctx, task, NULL, esxVI_Occurrence_None,
- esxVI_Boolean_False, &taskInfoState) < 0) {
- goto cleanup;
- }
-
- if (taskInfoState != esxVI_TaskInfoState_Success) {
- ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
- _("Could not serach in datastore '%s'"), datastoreName);
- goto cleanup;
- }
-
- if (esxVI_LookupTaskInfoByTask(data->ctx, task, &taskInfo) < 0 ||
- esxVI_HostDatastoreBrowserSearchResults_CastFromAnyType
- (taskInfo->result, &searchResults) < 0) {
- goto cleanup;
- }
-
- /* Interpret search result */
- vmDiskFileInfo = esxVI_VmDiskFileInfo_DynamicCast(searchResults->file);
+ vmDiskFileInfo = esxVI_VmDiskFileInfo_DynamicCast(fileInfo);
if (vmDiskFileInfo == NULL || vmDiskFileInfo->controllerType == NULL) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
@@ -485,22 +398,7 @@ esxAutodetectSCSIControllerModel(virDomainDiskDefPtr def, int *model,
result = 0;
cleanup:
- /* Don't double free fileName */
- if (searchSpec != NULL && searchSpec->matchPattern != NULL) {
- searchSpec->matchPattern->value = NULL;
- }
-
- VIR_FREE(datastoreName);
- VIR_FREE(directoryName);
- VIR_FREE(fileName);
- VIR_FREE(datastorePath);
- esxVI_String_Free(&propertyNameList);
- esxVI_ObjectContent_Free(&datastore);
- esxVI_ManagedObjectReference_Free(&hostDatastoreBrowser);
- esxVI_HostDatastoreBrowserSearchSpec_Free(&searchSpec);
- esxVI_ManagedObjectReference_Free(&task);
- esxVI_TaskInfo_Free(&taskInfo);
- esxVI_HostDatastoreBrowserSearchResults_Free(&searchResults);
+ esxVI_FileInfo_Free(&fileInfo);
return result;
}
diff --git a/src/esx/esx_storage_driver.c b/src/esx/esx_storage_driver.c
index 4fcc4af..644e66c 100644
--- a/src/esx/esx_storage_driver.c
+++ b/src/esx/esx_storage_driver.c
@@ -30,6 +30,7 @@
#include "logging.h"
#include "uuid.h"
#include "storage_conf.h"
+#include "storage_file.h"
#include "esx_private.h"
#include "esx_storage_driver.h"
#include "esx_vi.h"
@@ -356,6 +357,14 @@ esxStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
+static virStoragePoolPtr
+esxStoragePoolLookupByVolume(virStorageVolPtr volume)
+{
+ return esxStoragePoolLookupByName(volume->conn, volume->pool);
+}
+
+
+
static int
esxStoragePoolRefresh(virStoragePoolPtr pool, unsigned int flags)
{
@@ -602,6 +611,411 @@ esxStoragePoolSetAutostart(virStoragePoolPtr pool ATTRIBUTE_UNUSED,
static int
+esxStoragePoolNumberOfStorageVolumes(virStoragePoolPtr pool)
+{
+ bool success = false;
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ esxVI_HostDatastoreBrowserSearchResults *searchResultsList = NULL;
+ esxVI_HostDatastoreBrowserSearchResults *searchResults = NULL;
+ esxVI_FileInfo *fileInfo = NULL;
+ int count = 0;
+
+ if (esxVI_EnsureSession(priv->primary) < 0) {
+ return -1;
+ }
+
+ if (esxVI_LookupDatastoreContentByDatastoreName(priv->primary, pool->name,
+ &searchResultsList) < 0) {
+ goto cleanup;
+ }
+
+ /* Interpret search result */
+ for (searchResults = searchResultsList; searchResults != NULL;
+ searchResults = searchResults->_next) {
+ for (fileInfo = searchResults->file; fileInfo != NULL;
+ fileInfo = fileInfo->_next) {
+ ++count;
+ }
+ }
+
+ success = true;
+
+ cleanup:
+ esxVI_HostDatastoreBrowserSearchResults_Free(&searchResultsList);
+
+ return success ? count : -1;
+}
+
+
+
+static int
+esxStoragePoolListStorageVolumes(virStoragePoolPtr pool, char **const names,
+ int maxnames)
+{
+ bool success = false;
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ esxVI_HostDatastoreBrowserSearchResults *searchResultsList = NULL;
+ esxVI_HostDatastoreBrowserSearchResults *searchResults = NULL;
+ esxVI_FileInfo *fileInfo = NULL;
+ char *datastoreName = NULL;
+ char *directoryName = NULL;
+ char *fileName = NULL;
+ char *prefix = 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->primary) < 0) {
+ return -1;
+ }
+
+ if (esxVI_LookupDatastoreContentByDatastoreName(priv->primary, pool->name,
+ &searchResultsList) < 0) {
+ goto cleanup;
+ }
+
+ /* Interpret search result */
+ for (searchResults = searchResultsList; searchResults != NULL;
+ searchResults = searchResults->_next) {
+ VIR_FREE(datastoreName);
+ VIR_FREE(directoryName);
+ VIR_FREE(fileName);
+ VIR_FREE(prefix);
+
+ if (esxUtil_ParseDatastorePath(searchResults->folderPath, &datastoreName,
+ &directoryName, &fileName) < 0) {
+ goto cleanup;
+ }
+
+ if (directoryName != NULL) {
+ if (virAsprintf(&prefix, "%s/%s", directoryName, fileName) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ } else {
+ prefix = strdup(fileName);
+
+ if (prefix == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ }
+
+ for (fileInfo = searchResults->file; fileInfo != NULL;
+ fileInfo = fileInfo->_next) {
+ if (*prefix == '\0') {
+ names[count] = strdup(fileInfo->path);
+
+ if (names[count] == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ } else if (virAsprintf(&names[count], "%s/%s", prefix,
+ fileInfo->path) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ ++count;
+ }
+ }
+
+ success = true;
+
+ cleanup:
+ if (! success) {
+ for (i = 0; i < count; ++i) {
+ VIR_FREE(names[i]);
+ }
+
+ count = -1;
+ }
+
+ esxVI_HostDatastoreBrowserSearchResults_Free(&searchResultsList);
+ VIR_FREE(datastoreName);
+ VIR_FREE(directoryName);
+ VIR_FREE(fileName);
+ VIR_FREE(prefix);
+
+ return count;
+}
+
+
+
+static virStorageVolPtr
+esxStorageVolumeLookupByName(virStoragePoolPtr pool, const char *name)
+{
+ virStorageVolPtr volume = NULL;
+ esxPrivate *priv = pool->conn->storagePrivateData;
+ char *datastorePath = NULL;
+ esxVI_FileInfo *fileInfo = NULL;
+
+ if (esxVI_EnsureSession(priv->primary) < 0) {
+ return NULL;
+ }
+
+ if (virAsprintf(&datastorePath, "[%s] %s", pool->name, name) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (esxVI_LookupFileInfoByDatastorePath(priv->primary, datastorePath,
+ &fileInfo,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ volume = virGetStorageVol(pool->conn, pool->name, name, datastorePath);
+
+ cleanup:
+ VIR_FREE(datastorePath);
+ esxVI_FileInfo_Free(&fileInfo);
+
+ return volume;
+}
+
+
+
+static virStorageVolPtr
+esxStorageVolumeLookupByKeyOrPath(virConnectPtr conn, const char *keyOrPath)
+{
+ virStorageVolPtr volume = NULL;
+ esxPrivate *priv = conn->storagePrivateData;
+ char *datastoreName = NULL;
+ char *directoryName = NULL;
+ char *fileName = NULL;
+ char *volumeName = NULL;
+ esxVI_FileInfo *fileInfo = NULL;
+
+ if (esxVI_EnsureSession(priv->primary) < 0) {
+ return NULL;
+ }
+
+ if (esxUtil_ParseDatastorePath(keyOrPath, &datastoreName, &directoryName,
+ &fileName) < 0) {
+ goto cleanup;
+ }
+
+ if (directoryName != NULL) {
+ if (virAsprintf(&volumeName, "%s/%s", directoryName, fileName) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ } else {
+ volumeName = strdup(fileName);
+
+ if (volumeName == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ }
+
+ if (esxVI_LookupFileInfoByDatastorePath(priv->primary, keyOrPath, &fileInfo,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ volume = virGetStorageVol(conn, datastoreName, volumeName, keyOrPath);
+
+ cleanup:
+ VIR_FREE(datastoreName);
+ VIR_FREE(directoryName);
+ VIR_FREE(fileName);
+ VIR_FREE(volumeName);
+ esxVI_FileInfo_Free(&fileInfo);
+
+ return volume;
+}
+
+
+
+static int
+esxStorageVolumeGetInfo(virStorageVolPtr volume, virStorageVolInfoPtr info)
+{
+ int result = -1;
+ esxPrivate *priv = volume->conn->storagePrivateData;
+ char *datastorePath = NULL;
+ esxVI_FileInfo *fileInfo = NULL;
+ esxVI_VmDiskFileInfo *vmDiskFileInfo = NULL;
+
+ memset(info, 0, sizeof (*info));
+
+ if (esxVI_EnsureSession(priv->primary) < 0) {
+ return -1;
+ }
+
+ if (virAsprintf(&datastorePath, "[%s] %s", volume->pool, volume->name) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (esxVI_LookupFileInfoByDatastorePath(priv->primary, datastorePath,
+ &fileInfo,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ vmDiskFileInfo = esxVI_VmDiskFileInfo_DynamicCast(fileInfo);
+
+ info->type = VIR_STORAGE_VOL_FILE;
+
+ if (vmDiskFileInfo != NULL) {
+ info->capacity = vmDiskFileInfo->capacityKb->value * 1024; /* Scale from kilobyte to byte */
+ info->allocation = vmDiskFileInfo->fileSize->value;
+ } else {
+ info->capacity = fileInfo->fileSize->value;
+ info->allocation = fileInfo->fileSize->value;
+ }
+
+ result = 0;
+
+ cleanup:
+ VIR_FREE(datastorePath);
+ esxVI_FileInfo_Free(&fileInfo);
+
+ return result;
+}
+
+
+
+static char *
+esxStorageVolumeDumpXML(virStorageVolPtr volume, unsigned int flags)
+{
+ esxPrivate *priv = volume->conn->storagePrivateData;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *datastore = NULL;
+ esxVI_DynamicProperty *dynamicProperty = NULL;
+ esxVI_DatastoreInfo *datastoreInfo = NULL;
+ virStoragePoolDef pool;
+ char *datastorePath = NULL;
+ esxVI_FileInfo *fileInfo = NULL;
+ esxVI_VmDiskFileInfo *vmDiskFileInfo = NULL;
+ esxVI_IsoImageFileInfo *isoImageFileInfo = NULL;
+ esxVI_FloppyImageFileInfo *floppyImageFileInfo = NULL;
+ virStorageVolDef def;
+ char *xml = NULL;
+
+ virCheckFlags(0, NULL);
+
+ memset(&pool, 0, sizeof (pool));
+ memset(&def, 0, sizeof (def));
+
+ if (esxVI_EnsureSession(priv->primary) < 0) {
+ return NULL;
+ }
+
+ /* Lookup storage pool type */
+ if (esxVI_String_AppendValueToList(&propertyNameList, "info") < 0 ||
+ esxVI_LookupDatastoreByName(priv->primary, volume->pool,
+ propertyNameList, &datastore,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ for (dynamicProperty = datastore->propSet; dynamicProperty != NULL;
+ dynamicProperty = dynamicProperty->_next) {
+ if (STREQ(dynamicProperty->name, "info")) {
+ if (esxVI_DatastoreInfo_CastFromAnyType(dynamicProperty->val,
+ &datastoreInfo) < 0) {
+ goto cleanup;
+ }
+
+ break;
+ }
+ }
+
+ if (esxVI_LocalDatastoreInfo_DynamicCast(datastoreInfo) != NULL) {
+ pool.type = VIR_STORAGE_POOL_DIR;
+ } else if (esxVI_NasDatastoreInfo_DynamicCast(datastoreInfo) != NULL) {
+ pool.type = VIR_STORAGE_POOL_NETFS;
+ } else if (esxVI_VmfsDatastoreInfo_DynamicCast(datastoreInfo) != NULL) {
+ pool.type = VIR_STORAGE_POOL_FS;
+ } else {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("DatastoreInfo has unexpected type"));
+ goto cleanup;
+ }
+
+ /* Lookup file info */
+ if (virAsprintf(&datastorePath, "[%s] %s", volume->pool, volume->name) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (esxVI_LookupFileInfoByDatastorePath(priv->primary, datastorePath,
+ &fileInfo,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ vmDiskFileInfo = esxVI_VmDiskFileInfo_DynamicCast(fileInfo);
+ isoImageFileInfo = esxVI_IsoImageFileInfo_DynamicCast(fileInfo);
+ floppyImageFileInfo = esxVI_FloppyImageFileInfo_DynamicCast(fileInfo);
+
+ def.name = volume->name;
+ def.key = datastorePath;
+ def.type = VIR_STORAGE_VOL_FILE;
+ def.target.path = datastorePath;
+
+ if (vmDiskFileInfo != NULL) {
+ def.capacity = vmDiskFileInfo->capacityKb->value * 1024; /* Scale from kilobyte to byte */
+ def.allocation = vmDiskFileInfo->fileSize->value;
+
+ def.target.format = VIR_STORAGE_FILE_VMDK;
+ } else if (isoImageFileInfo != NULL) {
+ def.capacity = fileInfo->fileSize->value;
+ def.allocation = fileInfo->fileSize->value;
+
+ def.target.format = VIR_STORAGE_FILE_ISO;
+ } else if (floppyImageFileInfo != NULL) {
+ def.capacity = fileInfo->fileSize->value;
+ def.allocation = fileInfo->fileSize->value;
+
+ def.target.format = VIR_STORAGE_FILE_RAW;
+ } else {
+ ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("File '%s' has unknown type"), datastorePath);
+ goto cleanup;
+ }
+
+ xml = virStorageVolDefFormat(&pool, &def);
+
+ cleanup:
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&datastore);
+ esxVI_DatastoreInfo_Free(&datastoreInfo);
+ VIR_FREE(datastorePath);
+ esxVI_FileInfo_Free(&fileInfo);
+
+ return xml;
+}
+
+
+
+static char *
+esxStorageVolumeGetPath(virStorageVolPtr volume)
+{
+ char *path;
+
+ if (virAsprintf(&path, "[%s] %s", volume->pool, volume->name) < 0) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ return path;
+}
+
+
+
+static int
esxStoragePoolIsActive(virStoragePoolPtr pool ATTRIBUTE_UNUSED)
{
/* ESX storage pools are always active */
@@ -618,6 +1032,7 @@ esxStoragePoolIsPersistent(virStoragePoolPtr pool ATTRIBUTE_UNUSED)
}
+
static virStorageDriver esxStorageDriver = {
"ESX", /* name */
esxStorageOpen, /* open */
@@ -629,7 +1044,7 @@ static virStorageDriver esxStorageDriver = {
NULL, /* findPoolSources */
esxStoragePoolLookupByName, /* poolLookupByName */
esxStoragePoolLookupByUUID, /* poolLookupByUUID */
- NULL, /* poolLookupByVolume */
+ esxStoragePoolLookupByVolume, /* poolLookupByVolume */
NULL, /* poolCreateXML */
NULL, /* poolDefineXML */
NULL, /* poolBuild */
@@ -642,18 +1057,18 @@ static virStorageDriver esxStorageDriver = {
esxStoragePoolGetXMLDesc, /* poolGetXMLDesc */
esxStoragePoolGetAutostart, /* poolGetAutostart */
esxStoragePoolSetAutostart, /* poolSetAutostart */
- NULL, /* poolNumOfVolumes */
- NULL, /* poolListVolumes */
- NULL, /* volLookupByName */
- NULL, /* volLookupByKey */
- NULL, /* volLookupByPath */
+ esxStoragePoolNumberOfStorageVolumes, /* poolNumOfVolumes */
+ esxStoragePoolListStorageVolumes, /* poolListVolumes */
+ esxStorageVolumeLookupByName, /* volLookupByName */
+ esxStorageVolumeLookupByKeyOrPath, /* volLookupByKey */
+ esxStorageVolumeLookupByKeyOrPath, /* volLookupByPath */
NULL, /* volCreateXML */
NULL, /* volCreateXMLFrom */
NULL, /* volDelete */
NULL, /* volWipe */
- NULL, /* volGetInfo */
- NULL, /* volGetXMLDesc */
- NULL, /* volGetPath */
+ esxStorageVolumeGetInfo, /* volGetInfo */
+ esxStorageVolumeDumpXML, /* volGetXMLDesc */
+ esxStorageVolumeGetPath, /* volGetPath */
esxStoragePoolIsActive, /* poolIsActive */
esxStoragePoolIsPersistent, /* poolIsPersistent */
};
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index 55c5246..c6b2b63 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -2925,6 +2925,285 @@ esxVI_LookupCurrentSnapshotTree
int
+esxVI_LookupFileInfoByDatastorePath(esxVI_Context *ctx,
+ const char *datastorePath,
+ esxVI_FileInfo **fileInfo,
+ esxVI_Occurrence occurrence)
+{
+ int result = -1;
+ char *datastoreName = NULL;
+ char *directoryName = NULL;
+ char *fileName = NULL;
+ char *datastorePathWithoutFileName = NULL;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *datastore = NULL;
+ esxVI_ManagedObjectReference *hostDatastoreBrowser = NULL;
+ esxVI_HostDatastoreBrowserSearchSpec *searchSpec = NULL;
+ esxVI_VmDiskFileQuery *vmDiskFileQuery = NULL;
+ esxVI_IsoImageFileQuery *isoImageFileQuery = NULL;
+ esxVI_FloppyImageFileQuery *floppyImageFileQuery = NULL;
+ esxVI_ManagedObjectReference *task = NULL;
+ esxVI_TaskInfoState taskInfoState;
+ esxVI_TaskInfo *taskInfo = NULL;
+ esxVI_HostDatastoreBrowserSearchResults *searchResults = NULL;
+
+ if (fileInfo == NULL || *fileInfo != NULL) {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
+ return -1;
+ }
+
+ if (esxUtil_ParseDatastorePath(datastorePath, &datastoreName,
+ &directoryName, &fileName) < 0) {
+ goto cleanup;
+ }
+
+ if (directoryName == NULL) {
+ if (virAsprintf(&datastorePathWithoutFileName, "[%s]",
+ datastoreName) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ } else {
+ if (virAsprintf(&datastorePathWithoutFileName, "[%s] %s",
+ datastoreName, directoryName) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ }
+
+ /* Lookup HostDatastoreBrowser */
+ if (esxVI_String_AppendValueToList(&propertyNameList, "browser") < 0 ||
+ esxVI_LookupDatastoreByName(ctx, datastoreName, propertyNameList,
+ &datastore,
+ esxVI_Occurrence_RequiredItem) < 0 ||
+ esxVI_GetManagedObjectReference(datastore, "browser",
+ &hostDatastoreBrowser,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ /* Build HostDatastoreBrowserSearchSpec */
+ if (esxVI_HostDatastoreBrowserSearchSpec_Alloc(&searchSpec) < 0 ||
+ esxVI_FileQueryFlags_Alloc(&searchSpec->details) < 0) {
+ goto cleanup;
+ }
+
+ searchSpec->details->fileType = esxVI_Boolean_True;
+ searchSpec->details->fileSize = esxVI_Boolean_True;
+ searchSpec->details->modification = esxVI_Boolean_False;
+
+ if (esxVI_VmDiskFileQuery_Alloc(&vmDiskFileQuery) < 0 ||
+ esxVI_VmDiskFileQueryFlags_Alloc(&vmDiskFileQuery->details) < 0 ||
+ esxVI_FileQuery_AppendToList
+ (&searchSpec->query,
+ esxVI_FileQuery_DynamicCast(vmDiskFileQuery)) < 0) {
+ goto cleanup;
+ }
+
+ vmDiskFileQuery->details->diskType = esxVI_Boolean_False;
+ vmDiskFileQuery->details->capacityKb = esxVI_Boolean_True;
+ vmDiskFileQuery->details->hardwareVersion = esxVI_Boolean_False;
+ vmDiskFileQuery->details->controllerType = esxVI_Boolean_True;
+ vmDiskFileQuery->details->diskExtents = esxVI_Boolean_False;
+
+ if (esxVI_IsoImageFileQuery_Alloc(&isoImageFileQuery) < 0 ||
+ esxVI_FileQuery_AppendToList
+ (&searchSpec->query,
+ esxVI_FileQuery_DynamicCast(isoImageFileQuery)) < 0) {
+ goto cleanup;
+ }
+
+ if (esxVI_FloppyImageFileQuery_Alloc(&floppyImageFileQuery) < 0 ||
+ esxVI_FileQuery_AppendToList
+ (&searchSpec->query,
+ esxVI_FileQuery_DynamicCast(floppyImageFileQuery)) < 0) {
+ goto cleanup;
+ }
+
+ if (esxVI_String_Alloc(&searchSpec->matchPattern) < 0) {
+ goto cleanup;
+ }
+
+ searchSpec->matchPattern->value = fileName;
+
+ /* Search datastore for file */
+ if (esxVI_SearchDatastore_Task(ctx, hostDatastoreBrowser,
+ datastorePathWithoutFileName, searchSpec,
+ &task) < 0 ||
+ esxVI_WaitForTaskCompletion(ctx, task, NULL, esxVI_Occurrence_None,
+ esxVI_Boolean_False, &taskInfoState) < 0) {
+ goto cleanup;
+ }
+
+ if (taskInfoState != esxVI_TaskInfoState_Success) {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Could not serach in datastore '%s'"), datastoreName);
+ goto cleanup;
+ }
+
+ if (esxVI_LookupTaskInfoByTask(ctx, task, &taskInfo) < 0 ||
+ esxVI_HostDatastoreBrowserSearchResults_CastFromAnyType
+ (taskInfo->result, &searchResults) < 0) {
+ goto cleanup;
+ }
+
+ /* Interpret search result */
+ if (searchResults->file == NULL) {
+ if (occurrence == esxVI_Occurrence_OptionalItem) {
+ result = 0;
+
+ goto cleanup;
+ } else {
+ ESX_VI_ERROR(VIR_ERR_NO_STORAGE_VOL,
+ _("No storage volume with key or path '%s'"),
+ datastorePath);
+ goto cleanup;
+ }
+ }
+
+ *fileInfo = searchResults->file;
+ searchResults->file = NULL;
+
+ result = 0;
+
+ cleanup:
+ /* Don't double free fileName */
+ if (searchSpec != NULL && searchSpec->matchPattern != NULL) {
+ searchSpec->matchPattern->value = NULL;
+ }
+
+ VIR_FREE(datastoreName);
+ VIR_FREE(directoryName);
+ VIR_FREE(fileName);
+ VIR_FREE(datastorePathWithoutFileName);
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&datastore);
+ esxVI_ManagedObjectReference_Free(&hostDatastoreBrowser);
+ esxVI_HostDatastoreBrowserSearchSpec_Free(&searchSpec);
+ esxVI_ManagedObjectReference_Free(&task);
+ esxVI_TaskInfo_Free(&taskInfo);
+ esxVI_HostDatastoreBrowserSearchResults_Free(&searchResults);
+
+ return result;
+}
+
+
+
+int
+esxVI_LookupDatastoreContentByDatastoreName
+ (esxVI_Context *ctx, const char *datastoreName,
+ esxVI_HostDatastoreBrowserSearchResults **searchResultsList)
+{
+ int result = -1;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *datastore = NULL;
+ esxVI_ManagedObjectReference *hostDatastoreBrowser = NULL;
+ esxVI_HostDatastoreBrowserSearchSpec *searchSpec = NULL;
+ esxVI_VmDiskFileQuery *vmDiskFileQuery = NULL;
+ esxVI_IsoImageFileQuery *isoImageFileQuery = NULL;
+ esxVI_FloppyImageFileQuery *floppyImageFileQuery = NULL;
+ char *datastorePath = NULL;
+ esxVI_ManagedObjectReference *task = NULL;
+ esxVI_TaskInfoState taskInfoState;
+ esxVI_TaskInfo *taskInfo = NULL;
+
+ if (searchResultsList == NULL || *searchResultsList != NULL) {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
+ return -1;
+ }
+
+ /* Lookup Datastore and HostDatastoreBrowser */
+ if (esxVI_String_AppendValueToList(&propertyNameList, "browser") < 0 ||
+ esxVI_LookupDatastoreByName(ctx, datastoreName, propertyNameList,
+ &datastore,
+ esxVI_Occurrence_RequiredItem) < 0 ||
+ esxVI_GetManagedObjectReference(datastore, "browser",
+ &hostDatastoreBrowser,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ /* Build HostDatastoreBrowserSearchSpec */
+ if (esxVI_HostDatastoreBrowserSearchSpec_Alloc(&searchSpec) < 0 ||
+ esxVI_FileQueryFlags_Alloc(&searchSpec->details) < 0) {
+ goto cleanup;
+ }
+
+ searchSpec->details->fileType = esxVI_Boolean_True;
+ searchSpec->details->fileSize = esxVI_Boolean_True;
+ searchSpec->details->modification = esxVI_Boolean_False;
+
+ if (esxVI_VmDiskFileQuery_Alloc(&vmDiskFileQuery) < 0 ||
+ esxVI_VmDiskFileQueryFlags_Alloc(&vmDiskFileQuery->details) < 0 ||
+ esxVI_FileQuery_AppendToList
+ (&searchSpec->query,
+ esxVI_FileQuery_DynamicCast(vmDiskFileQuery)) < 0) {
+ goto cleanup;
+ }
+
+ vmDiskFileQuery->details->diskType = esxVI_Boolean_False;
+ vmDiskFileQuery->details->capacityKb = esxVI_Boolean_True;
+ vmDiskFileQuery->details->hardwareVersion = esxVI_Boolean_False;
+ vmDiskFileQuery->details->controllerType = esxVI_Boolean_True;
+ vmDiskFileQuery->details->diskExtents = esxVI_Boolean_False;
+
+ if (esxVI_IsoImageFileQuery_Alloc(&isoImageFileQuery) < 0 ||
+ esxVI_FileQuery_AppendToList
+ (&searchSpec->query,
+ esxVI_FileQuery_DynamicCast(isoImageFileQuery)) < 0) {
+ goto cleanup;
+ }
+
+ if (esxVI_FloppyImageFileQuery_Alloc(&floppyImageFileQuery) < 0 ||
+ esxVI_FileQuery_AppendToList
+ (&searchSpec->query,
+ esxVI_FileQuery_DynamicCast(floppyImageFileQuery)) < 0) {
+ goto cleanup;
+ }
+
+ /* Search datastore for files */
+ if (virAsprintf(&datastorePath, "[%s]", datastoreName) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (esxVI_SearchDatastoreSubFolders_Task(ctx, hostDatastoreBrowser,
+ datastorePath, searchSpec,
+ &task) < 0 ||
+ esxVI_WaitForTaskCompletion(ctx, task, NULL, esxVI_Occurrence_None,
+ esxVI_Boolean_False, &taskInfoState) < 0) {
+ goto cleanup;
+ }
+
+ if (taskInfoState != esxVI_TaskInfoState_Success) {
+ ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Could not serach in datastore '%s'"), datastoreName);
+ goto cleanup;
+ }
+
+ if (esxVI_LookupTaskInfoByTask(ctx, task, &taskInfo) < 0 ||
+ esxVI_HostDatastoreBrowserSearchResults_CastListFromAnyType
+ (taskInfo->result, searchResultsList) < 0) {
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&datastore);
+ esxVI_ManagedObjectReference_Free(&hostDatastoreBrowser);
+ esxVI_HostDatastoreBrowserSearchSpec_Free(&searchSpec);
+ VIR_FREE(datastorePath);
+ esxVI_ManagedObjectReference_Free(&task);
+ esxVI_TaskInfo_Free(&taskInfo);
+
+ return result;
+}
+
+
+
+int
esxVI_HandleVirtualMachineQuestion
(esxVI_Context *ctx, esxVI_ManagedObjectReference *virtualMachine,
esxVI_VirtualMachineQuestionInfo *questionInfo,
diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h
index d5dc9d5..42f535f 100644
--- a/src/esx/esx_vi.h
+++ b/src/esx/esx_vi.h
@@ -397,6 +397,15 @@ int esxVI_LookupCurrentSnapshotTree
esxVI_VirtualMachineSnapshotTree **currentSnapshotTree,
esxVI_Occurrence occurrence);
+int esxVI_LookupFileInfoByDatastorePath(esxVI_Context *ctx,
+ const char *datastorePath,
+ esxVI_FileInfo **fileInfo,
+ esxVI_Occurrence occurrence);
+
+int esxVI_LookupDatastoreContentByDatastoreName
+ (esxVI_Context *ctx, const char *datastoreName,
+ esxVI_HostDatastoreBrowserSearchResults **searchResultsList);
+
int esxVI_HandleVirtualMachineQuestion
(esxVI_Context *ctx,
esxVI_ManagedObjectReference *virtualMachine,
diff --git a/src/esx/esx_vi_generator.input b/src/esx/esx_vi_generator.input
index ab50ea5..0fb9448 100644
--- a/src/esx/esx_vi_generator.input
+++ b/src/esx/esx_vi_generator.input
@@ -813,6 +813,13 @@ method RevertToSnapshot_Task returns ManagedObjectReference r
end
+method SearchDatastoreSubFolders_Task returns ManagedObjectReference r
+ ManagedObjectReference _this r
+ String datastorePath r
+ HostDatastoreBrowserSearchSpec searchSpec o
+end
+
+
method SearchDatastore_Task returns ManagedObjectReference r
ManagedObjectReference _this r
String datastorePath r
--
1.7.0.4
14 years, 3 months
[libvirt] Feature-Request: Network-Hook
by Daniel Kraft
Hi,
I already talked about that issue with photron on the irc channel. Thanks for
the great response and the hint that I should come up with this here.
I need to add a physical interface to a bridge generated from libvirt. More
precisely, I need a vlan-ethernet-device in my bridge to allow guest-clusters
to communicate efficiently (i.e. without a gateway).
For this example let's say, I want eth0.2 to be a member of the bridge virbr2.
So I could add code to the start-guest hook which checks if eth0.2 is member
of the same bridge as the configured interface's tun device(s) and if not, add it.
Then I'd add code to the stop-guest hook which checks if there are interfaces
other than the configured ones as members of the bridge and if not, remove
eth0.2 from the bridge so that the bridge could be removed (or would be empty
at least).
This is all ugly and most likely unstable, because it's at the wrong position.
Depending on the way of the implementation it could happen that eth0.2 is
removed even if there are guests relying on it or that eth0.2 isn't removed if
it should be (e.g. if there are manually added interfaces on the bridge).
Endless debugging sessions and a huge amount of code would be the result.
Anything would be very clear if I had a network hook script. Something like a
"<script path='...'>" node in the network xml. There I could very cleanly add
and remove secondary interfaces or modify properties of the bridge. So the
perfect position of that hook would be *after* the bridge has been created.
The parameters should at least be
- bridge name
- action (start, stop, ...)
Any hints to existing features that could help me to realize that use-case are
very welcome ;)
Daniel
14 years, 3 months
Re: [libvirt] [PATCH] Add support for vendor/product
by Patrick Dignan
On 08/06/2010 02:22 PM, Dignan, Pat wrote:
> From: Patrick Dignan<pat_dignan(a)dell.com>
>
> ---
> docs/schemas/storagepool.rng | 52 ++++++++++++++++++++
> src/conf/storage_conf.c | 14 +++++
> src/conf/storage_conf.h | 6 ++
> .../pool-iscsi-vendor-product.xml | 19 +++++++
> .../pool-iscsi-vendor-product.xml | 22 ++++++++
> tests/storagepoolxml2xmltest.c | 1 +
> 6 files changed, 114 insertions(+), 0 deletions(-)
> create mode 100644 tests/storagepoolxml2xmlin/pool-iscsi-vendor-product.xml
> create mode 100644 tests/storagepoolxml2xmlout/pool-iscsi-vendor-product.xml
>
> diff --git a/docs/schemas/storagepool.rng b/docs/schemas/storagepool.rng
> index b911f7c..a8a3f36 100644
> --- a/docs/schemas/storagepool.rng
> +++ b/docs/schemas/storagepool.rng
> @@ -103,6 +103,23 @@
> <ref name='target'/>
> </define>
>
> +<define name='sourceinfovendor'>
> +<optional>
> +<element name='vendor'>
> +<attribute name='name'>
> +<text/>
> +</attribute>
> +</element>
> +</optional>
> +<optional>
> +<element name='product'>
> +<attribute name='name'>
> +<text/>
> +</attribute>
> +</element>
> +</optional>
> +</define>
> +
> <define name='commonmetadata'>
> <element name='name'>
> <ref name='name'/>
> @@ -272,6 +289,9 @@
> <value>ocfs2</value>
> </choice>
> </attribute>
> +<optional>
> +<ref name='sourceinfovendor'/>
> +</optional>
> </element>
> </optional>
> </define>
> @@ -286,6 +306,9 @@
> <value>nfs</value>
> </choice>
> </attribute>
> +<optional>
> +<ref name='sourceinfovendor'/>
> +</optional>
> </element>
> </optional>
> </define>
> @@ -307,6 +330,9 @@
> <value>lvm2</value>
> </choice>
> </attribute>
> +<optional>
> +<ref name='sourceinfovendor'/>
> +</optional>
> </element>
> </optional>
> </define>
> @@ -321,6 +347,9 @@
> <value>lvm2</value>
> </choice>
> </attribute>
> +<optional>
> +<ref name='sourceinfovendor'/>
> +</optional>
> </element>
> </optional>
> </define>
> @@ -330,13 +359,20 @@
> <optional>
> <element name='source'>
> <empty/>
> +<optional>
> +<ref name='sourceinfovendor'/>
> +</optional>
> </element>
> </optional>
> </define>
> +
> <define name='sourcefs'>
> <element name='source'>
> <ref name='sourceinfodev'/>
> <ref name='sourcefmtfs'/>
> +<optional>
> +<ref name='sourceinfovendor'/>
> +</optional>
> </element>
> </define>
>
> @@ -345,6 +381,9 @@
> <ref name='sourceinfohost'/>
> <ref name='sourceinfodir'/>
> <ref name='sourcefmtnetfs'/>
> +<optional>
> +<ref name='sourceinfovendor'/>
> +</optional>
> </element>
> </define>
>
> @@ -359,6 +398,9 @@
> </optional>
> </oneOrMore>
> <ref name='sourcefmtlogical'/>
> +<optional>
> +<ref name='sourceinfovendor'/>
> +</optional>
> </element>
> </define>
>
> @@ -366,6 +408,9 @@
> <element name='source'>
> <ref name='sourceinfodev'/>
> <ref name='sourcefmtdisk'/>
> +<optional>
> +<ref name='sourceinfovendor'/>
> +</optional>
> </element>
> </define>
>
> @@ -379,12 +424,19 @@
> <optional>
> <ref name='sourceinfoauth'/>
> </optional>
> +<optional>
> +<ref name='sourceinfovendor'/>
> +</optional>
> </element>
> </define>
>
> <define name='sourcescsi'>
> <element name='source'>
> <ref name='sourceinfoadapter'/>
> +<optional>
> +<ref name='sourceinfovendor'/>
> +</optional>
> +
> </element>
> </define>
>
> diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
> index bf86c93..6e3cce6 100644
> --- a/src/conf/storage_conf.c
> +++ b/src/conf/storage_conf.c
> @@ -284,6 +284,8 @@ virStoragePoolSourceFree(virStoragePoolSourcePtr source) {
> VIR_FREE(source->name);
> VIR_FREE(source->adapter);
> VIR_FREE(source->initiator.iqn);
> + VIR_FREE(source->vendor);
> + VIR_FREE(source->product);
>
> if (source->authType == VIR_STORAGE_POOL_AUTH_CHAP) {
> VIR_FREE(source->auth.chap.login);
> @@ -465,6 +467,9 @@ virStoragePoolDefParseSource(xmlXPathContextPtr ctxt,
> goto cleanup;
> }
>
> + source->vendor = virXPathString("string(./vendor/@name)", ctxt);
> + source->product = virXPathString("string(./product/@name)", ctxt);
> +
> ret = 0;
> cleanup:
> ctxt->node = relnode;
> @@ -838,6 +843,15 @@ virStoragePoolSourceFormat(virBufferPtr buf,
> virBufferVSprintf(buf,"<auth type='chap' login='%s' passwd='%s'/>\n",
> src->auth.chap.login,
> src->auth.chap.passwd);
> +
> + if (src->vendor != NULL) {
> + virBufferVSprintf(buf,"<vendor name='%s'/>\n", src->vendor);
> + }
> +
> + if (src->product != NULL) {
> + virBufferVSprintf(buf,"<product name='%s'/>\n", src->product);
> + }
> +
> virBufferAddLit(buf,"</source>\n");
>
> return 0;
> diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h
> index bedee9e..5f17b5a 100644
> --- a/src/conf/storage_conf.h
> +++ b/src/conf/storage_conf.h
> @@ -237,6 +237,12 @@ struct _virStoragePoolSource {
> virStoragePoolAuthChap chap;
> } auth;
>
> + /* Vendor of the the source */
> + char *vendor;
> +
> + /* Product name of the source*/
> + char *product;
> +
> int format; /* Pool type specific format such as filesystem type, or lvm version, etc */
> };
>
> diff --git a/tests/storagepoolxml2xmlin/pool-iscsi-vendor-product.xml b/tests/storagepoolxml2xmlin/pool-iscsi-vendor-product.xml
> new file mode 100644
> index 0000000..01fbd9b
> --- /dev/null
> +++ b/tests/storagepoolxml2xmlin/pool-iscsi-vendor-product.xml
> @@ -0,0 +1,19 @@
> +<pool type='iscsi'>
> +<name>virtimages</name>
> +<uuid>e9392370-2917-565e-692b-d057f46512d6</uuid>
> +<source>
> +<host name="iscsi.example.com"/>
> +<device path="demo-target"/>
> +<auth type='chap' login='foobar' passwd='frobbar'/>
> +<vendor name='test-vendor'/>
> +<product name='test-product'/>
> +</source>
> +<target>
> +<path>/dev/disk/by-path</path>
> +<permissions>
> +<mode>0700</mode>
> +<owner>0</owner>
> +<group>0</group>
> +</permissions>
> +</target>
> +</pool>
> diff --git a/tests/storagepoolxml2xmlout/pool-iscsi-vendor-product.xml b/tests/storagepoolxml2xmlout/pool-iscsi-vendor-product.xml
> new file mode 100644
> index 0000000..baab6c0
> --- /dev/null
> +++ b/tests/storagepoolxml2xmlout/pool-iscsi-vendor-product.xml
> @@ -0,0 +1,22 @@
> +<pool type='iscsi'>
> +<name>virtimages</name>
> +<uuid>e9392370-2917-565e-692b-d057f46512d6</uuid>
> +<capacity>0</capacity>
> +<allocation>0</allocation>
> +<available>0</available>
> +<source>
> +<host name='iscsi.example.com'/>
> +<device path='demo-target'/>
> +<auth type='chap' login='foobar' passwd='frobbar'/>
> +<vendor name='test-vendor'/>
> +<product name='test-product'/>
> +</source>
> +<target>
> +<path>/dev/disk/by-path</path>
> +<permissions>
> +<mode>0700</mode>
> +<owner>0</owner>
> +<group>0</group>
> +</permissions>
> +</target>
> +</pool>
> diff --git a/tests/storagepoolxml2xmltest.c b/tests/storagepoolxml2xmltest.c
> index 33a7343..2ec29e3 100644
> --- a/tests/storagepoolxml2xmltest.c
> +++ b/tests/storagepoolxml2xmltest.c
> @@ -96,6 +96,7 @@ mymain(int argc, char **argv)
> DO_TEST("pool-scsi");
> DO_TEST("pool-mpath");
> DO_TEST("pool-iscsi-multiiqn");
> + DO_TEST("pool-iscsi-vendor-product");
>
> return (ret==0 ? EXIT_SUCCESS : EXIT_FAILURE);
> }
My git-email-fu was bad. This message was supposed to be part of this
email:
I've fixed the aforementioned issues. I decided to allow vendor
and product to be set independently of each other in order to
allow greater flexibility at the possible expense of namespace
clashes.
I'm sending this (hopefully) using git-send-email, so I hope that
resolves any spacing issues
Best,
Patrick Dignan
14 years, 3 months
[libvirt] [PATCH] phyp: Fixing possible buffer overflow
by Eduardo Otubo
The line src/phyp/phyp_driver.c:427 was crashing by buffer overflow
if the return of the command wasn't <=10. The highest number for a
LPAR ID is 256 per machine, no need to allocate 10 bytes for it. So,
adjusting the correct size (+1 byte for the '\n') and checking for
errors.
---
src/phyp/phyp_driver.c | 9 +++++++--
1 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c
index ee1e21b..f8fd29b 100644
--- a/src/phyp/phyp_driver.c
+++ b/src/phyp/phyp_driver.c
@@ -383,7 +383,7 @@ phypListDomainsGeneric(virConnectPtr conn, int *ids, int nids,
int got = 0;
char *char_ptr;
unsigned int i = 0, j = 0;
- char id_c[10];
+ char id_c[4];
char *cmd = NULL;
char *ret = NULL;
const char *state;
@@ -394,7 +394,7 @@ phypListDomainsGeneric(virConnectPtr conn, int *ids, int nids,
else
state = " ";
- memset(id_c, 0, 10);
+ memset(id_c, 0, 4);
virBufferAddLit(&buf, "lssyscfg -r lpar");
if (system_type == HMC)
@@ -410,6 +410,11 @@ phypListDomainsGeneric(virConnectPtr conn, int *ids, int nids,
ret = phypExec(session, cmd, &exit_status, conn);
+ if (strlen(ret) > 4) {
+ VIR_ERROR0(ret);
+ goto err;
+ }
+
/* I need to parse the textual return in order to get the ret */
if (exit_status < 0 || ret == NULL)
goto err;
--
1.7.0.4
14 years, 3 months
[libvirt] [PATCH] docs: significant expansion of custom hook script information
by Justin Clift
---
Also available for easy review online here for a while:
http://justinclift.fedorapeople.org/libvirt_docs/hooks.html
docs/hooks.html.in | 226 +++++++++++++++++++++++++++++++++++++--------------
1 files changed, 164 insertions(+), 62 deletions(-)
diff --git a/docs/hooks.html.in b/docs/hooks.html.in
index 2afdecf..5eeec27 100644
--- a/docs/hooks.html.in
+++ b/docs/hooks.html.in
@@ -2,69 +2,171 @@
<html>
<body>
<h1>Hooks for specific system management</h1>
- <p>Libvirt includes synchronous hooks, starting from version 0.8.0, as a
- way to tie in specific tailored system actions at a specific time.
- If these scripts are present on the host where the hypervisor
- is running, then they are called when the libvirt daemon is doingi
- some significant action.</p>
- <p>The scripts are expected to execute quickly, return a zero exit
- status if all conditions are set for the daemon to continue the
- action (non zero will be considered a failure which may
- be ignored but in general will stop the ongoing operation).
- The script also should not call back into libvirt as the daemon
- is waiting for the script exit and deadlock is likely to occur.</p>
- <p>The scripts are stored in the directory <code>/etc/libvirt/hooks/</code>
- when using a standard installation path
- (<code>$SYSCONF_DIR/libvirt/hooks/</code> in general).</p>
- <p>Each script is given the following command line arguments:</p>
- <ul>
- <li> the first argument is the name of the object involved in the
- operation, or '-' if there is none.
- <li> the second argument is the name of the operation.
- <li> the third argument is a suboperation indication like 'start' or
- 'end', or '-' if there is none.
- <li> the last argument is an extra argument string or '-' if there
- is none.
- </ul>
- <p>There are currently scripts for 3 domains of operation:
+
+ <ul id="toc"></ul>
+
+ <h2><a name="intro">Custom event scripts</a></h2>
+ <p>Beginning with libvirt 0.8.0, specific events on a host system will
+ trigger custom scripts.</p>
+ <p>These custom <b>hook</b> scripts are executed when any of the following
+ actions occur:</p>
<ul>
- <li><p><code>/etc/libvirt/hooks/daemon</code> script if
- present is called at 3 points in time:</p>
- <p>at daemon startup, typically started with the following
- arguments:</p>
- <pre>/etc/libvirt/hooks/daemon - start - start</pre>
- <p>at daemon shutdown when it is about to exit, with the following
- arguments:</p>
- <pre>/etc/libvirt/hooks/daemon - shutdown - shutdown</pre>
- <p>When the daemon is asked to reload its driver state when
- receiving the SIGHUP signal, arguments are:</p>
- <pre>/etc/libvirt/hooks/daemon - reload begin SIGHUP</pre>
- </li>
- <li><p><code>/etc/libvirt/hooks/qemu</code> script and <br/>
- <code>/etc/libvirt/hooks/lxc</code> associate hooks for domain
- operation on the respective QEmu/KVM and LXC drivers.</p>
- <p> The domain related hooks also receive the full XML description
- for the concerned domain on their stdin, which allows them to get
- all the information from the domain, including UUID or storage
- if that is needed for the script operation.</p>
- <p> Currently only domain startup and domain end operations
- involve the hook, the first one just before the domain gets
- created.
- For example if starting a QEmu domain named <code>test</code>
- the following script will get called:</p>
- <pre>/etc/libvirt/hooks/qemu test start begin -</pre>
- <p> note that a non-zero return value from the script will abort the
- domain startup operation, and if an error string is passed on
- stderr by the hook script, it will be provided back to the user
- at the libvirt API level.</p>
- <p> For domain shutdown, the script will be called just after the
- domain has finished execution, and the script will get:</p>
- <pre>/etc/libvirt/hooks/qemu test stopped end -</pre>
- <p> It is expected that other operations will be associated to hooks
- but at the time of 0.8.0 only those 2 are associated to the
- domains life cycle</p>
- </li>
+ <li>The libvirt daemon starts, stops, or reloads its
+ configuration<br/><br/></li>
+ <li>A QEMU guest is started or stopped<br/><br/></li>
+ <li>An LXC guest is started or stopped<br/><br/></li>
</ul>
- <p></p>
+
+ <h2><a name="location">Script Location</a></h2>
+ <p>The libvirt hook scripts are located in the directory
+ <code>$SYSCONF_DIR/etc/libvirt/hooks/</code>.
+ <p>With Fedora and RHEL, this is <code>/etc/libvirt/hooks/</code>.
+ On other Linux distributions this may be different.</p>
+ <br/>
+
+ <h2><a name="names">Script names</a></h2>
+ <p>At present, there are three hook scripts:</p>
+ <ul>
+ <li><code>/etc/libvirt/hooks/daemon</code><br/><br/>
+ Executed when the libvirt daemon is started, stopped, or reloads
+ its configuration<br/><br/></li>
+ <li><code>/etc/libvirt/hooks/qemu</code><br/><br/>
+ Executed when a QEMU guest is started, stopped, or migrated<br/><br/></li>
+ <li><code>/etc/libvirt/hooks/lxc</code><br /><br/>
+ Executed when an LXC guest is started or stopped</li>
+ </ul>
+ <br/>
+
+ <h2><a name="structure">Script structure</a></h2>
+ <p>The hook scripts are executed using standard Linux process creation
+ functions. Therefore, they must begin with the declaration of the
+ command interpreter to use.</p>
+ <p>For example:</p>
+ <pre>#!/bin/bash</pre>
+ <p>or:</p>
+ <pre>#!/usr/bin/python</pre>
+ <p>Other command interpreters are equally valid, as is any executable
+ binary, so you are welcome to use your favourite languages.</p>
+ <br/>
+
+ <h2><a name="arguments">Script arguments</a></h2>
+ <p>The hook scripts are called with specific command line arguments,
+ depending upon the script, and the operation being performed.</p>
+ <p>The guest hook scripts, qemu and lxc, are also given the <b>full</b>
+ XML description for the domain on their stdin. This includes items
+ such the UUID of the domain and its storage information, and is
+ intended to provide all the libvirt information the script needs.</p>
+
+ <p>The command line arguments take this approach:</p>
+ <ol>
+ <li>The first argument is the name of the <b>object</b> involved in the
+ operation, or '-' if there is none.<br/><br/>
+ For example, the name of a guest being started.<br/><br/></li>
+ <li>The second argument is the name of the <b>operation</b> being
+ performed.<br/><br/>
+ For example, "start" if a guest is being started.<br/><br/></li>
+ <li>The third argument is a <b>sub-operation</b> indication, or '-' if there
+ is none.<br/><br/></li>
+ <li>The last argument is an <b>extra argument</b> string, or '-' if there is
+ none.</li>
+ </ol>
+
+ <h4><a name="arguments_specifics">Specifics</a></h4>
+ <p>This translates to the following specifics for each hook script:</p>
+
+ <h5><a name="daemon">/etc/libvirt/hooks/daemon</a></h5>
+ <ul>
+ <li>When the libvirt daemon is started, this script is called as:<br/>
+ <pre>/etc/libvirt/hooks/daemon - start - start</pre></li>
+ <li>When the libvirt daemon is shut down, this script is called as:<br/>
+ <pre>/etc/libvirt/hooks/daemon - shutdown - shutdown</pre></li>
+ <li>When the libvirt daemon receives the SIGHUP signal, it reloads its
+ configuration and triggers the hook script as:<br/>
+ <pre>/etc/libvirt/hooks/daemon - reload begin SIGHUP</pre></li>
+ </ul>
+
+ <h5><a name="qemu">/etc/libvirt/hooks/qemu</a></h5>
+ <ul>
+ <li>When a QEMU guest is started, the qemu hook script is called as:<br/>
+ <pre>/etc/libvirt/hooks/qemu guest_name start begin -</pre></li>
+ <li>When a QEMU guest is stopped, the qemu hook script is called
+ as:<br/>
+ <pre>/etc/libvirt/hooks/qemu guest_name stopped end -</pre></li>
+ </ul>
+
+ <h5><a name="lxc">/etc/libvirt/hooks/lxc</a></h5>
+ <ul>
+ <li>When an LXC guest is started, the lxc hook script is called as:<br/>
+ <pre>/etc/libvirt/hooks/lxc guest_name start begin -</pre></li>
+ <li>When a LXC guest is stopped, the lxc hook script is called
+ as:<br/>
+ <pre>/etc/libvirt/hooks/lxc guest_name stopped end -</pre></li>
+ </ul>
+ <br/>
+
+ <h2><a name="execution">Script execution</a></h2>
+ <ul>
+ <li>The "start" operation for the guest hook scripts, qemu and lxc,
+ executes <b>prior</b> to the guest being created. This allows the
+ guest start operation to be aborted if the script returns indicating
+ failure.<br/><br/></li>
+ <li>The "shutdown" operation for the guest hook scripts, qemu and lxc,
+ executes <b>after</b> the guest has stopped. If the hook script
+ indicates failure in its return, the shut down of the guest cannot
+ be aborted because it has already been performed.<br/><br/></li>
+ <li>Hook scripts execute in a synchronous fashion. Libvirt waits
+ for them to return before continuing the given operation.<br/><br/>
+ This is most noticeable with the guest start operation, as a lengthy
+ operation in the hook script can mean an extended wait for the guest
+ to be available to end users.<br/><br/></li>
+ <li>For a hook script to be utilised, it have it's execute bit set
+ (ie. chmod +x <i>qemu</i>), and must be present when the libvirt
+ daemon is started.<br/><br/></li>
+ <li>If a hook script is added to a host after the libvirt daemon is
+ already running, it won't be used until the libvirt daemon
+ next starts.</li>
+ </ul>
+ <br/>
+
+ <h2><a name="qemu_migration">QEMU guest migration</a></h2>
+ <p>Migration of a QEMU guest involves running the hook scripts on both the
+ source and destination hosts:</p>
+ <ol>
+ <li>At the beginning of the migration, the <i>qemu</i> hook script on
+ the <b>destination</b> host is executed with the "start"
+ operation.<br/><br/></li>
+ <li>If this hook script returns indicating success (error code 0), the
+ migration continues. Any other return code indicates failure, and
+ the migration is aborted.<br/><br/></li>
+ <li>The QEMU guest is then migrated to the destination host.<br/>
+ <br/></li>
+ <li>Unless an error occurs during the migration process, the <i>qemu</i>
+ hook script on the source host is then executed with the "stopped"
+ operation, to indicate it is no longer running on this
+ host.<br/><br/>
+ Regardless of the return code from this hook script, the migration
+ is not aborted as it has already been performed.</li>
+ </ol>
+ <br/>
+
+ <h2><a name="recursive">Calling libvirt functions from within a hook script</a></h2>
+ <p><b>DO NOT DO THIS!</b></p>
+ <p>A hook script must not call back into libvirt, as the libvirt daemon
+ is already waiting for the script to exit.</p>
+ <p>A deadlock is likely to occur.</p>
+ <br/>
+
+ <h2><a name="return_codes">Return codes and logging</a></h2>
+ <p>If a hook script returns with an exit code of 0, the libvirt daemon
+ regards this as successful and performs no logging of it.</p>
+ <p>However, if a hook script returns with a non zero exit code, the libvirt
+ daemon regards this as a failure, logs it with return code 256, and
+ additionally logs anything on stderr the hook script returns.</p>
+ <p>For example, a hook script might use this code to indicate failure,
+ and send a text string to stderr:</p>
+ <pre>echo "Could not find required XYZZY" >&2
+exit 1</pre>
+ <p>The resulting entry in the libvirt log will appear as:</p>
+ <pre>20:02:40.297: error : virHookCall:416 : Hook script execution failed: Hook script /etc/libvirt/hooks/qemu qemu failed with error code 256:Could not find required XYZZY</pre>
</body>
</html>
--
1.7.2
14 years, 3 months
[libvirt] Callback and stream questions
by arnaud.champion@devatom.fr
Hi,
I would know if there is some callbacks for network adding/change/remove and for storage pool add/change/remove, I haven't seen these kind of callback in the API documentation.
Also, I don't understand the use of the virStream... functions (what is it used for ?)
Thanks
Arnaud Champion
14 years, 3 months