https://bugzilla.redhat.com/show_bug.cgi?id=1138516
The disk backend uses 'parted' in order to create and delete partitions
on the disk for use in the pool. At creation time, one can specify a
specific "name" for the volume as well as a specific volume target
format type. The name and volume target type "survive" only as long
as the pool is not refreshed or the libvirtd not restarted/reloaded.
The action immediately prior to the calling all the backend refreshPool
API's is to clear out all the existing volumes from the pool. The
theory being the refresh will be able to find all elements of the
pool using some mechanism. The disk refreshPool backend will use the
libvirt_parthelper utility to read the partitions found on the disk
in order to regenerate the elements of the pool Unfortunately, since
the "name" and target format type cannot be encoded, the data is now
lost and the defaults are used (for the "name", the partition path
is used and the default of 'none' is used for the target format type).
This patch solves this by adding the ability to save the XML generated
at create time into the stateDir and then use that during the refreshPool
backend API call to restore the specific fields that are lost.
Once the partition has been successfully created during the backend
call to createVol (virStorageBackendDiskCreateVol) and the various
XML fields updated, call the virStorageVolSaveStatus() API in order
to save the XML for later use.
Conversely, once the partition has been successfully removed during
the backend call to deleteVol (virStorageBackendDiskDeleteVol) call
the virStorageVolDeleteStatus() API in order to remove the XML file.
The virStorageBackendDiskUpdateStatus called after reading the data
about the partitions during the refreshPool will scan the pool->stateDir
for XML files. For each found and successfully parsed file, look
through the recently updated pool's volume list for a volume with
the same key. If one is found with a different name than in use
for the pool, then use the one from the stateDir and update the target
format type and save the updated pool volume.
Signed-off-by: John Ferlan <jferlan(a)redhat.com>
---
src/storage/storage_backend_disk.c | 90 +++++++++++++++++++++++++++++++++++++-
1 file changed, 88 insertions(+), 2 deletions(-)
diff --git a/src/storage/storage_backend_disk.c b/src/storage/storage_backend_disk.c
index 3f97fd9..90b468c 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-2014 Red Hat, Inc.
+ * Copyright (C) 2007-2015 Red Hat, Inc.
* Copyright (C) 2007-2008 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -333,6 +333,78 @@ virStorageBackendDiskReadGeometry(virStoragePoolObjPtr pool)
}
static int
+virStorageBackendDiskUpdateStatus(virStoragePoolObjPtr pool)
+{
+ DIR *dir;
+ struct dirent *entry;
+ virStorageVolDefPtr voldef = NULL, poolvol = NULL;
+ int ret = -1;
+
+ if (!(dir = opendir(pool->stateDir))) {
+ if (errno == ENOENT)
+ return 0;
+
+ virReportSystemError(errno, _("Failed to open dir '%s'"),
+ pool->stateDir);
+ return -1;
+ }
+
+ while ((ret = virDirRead(dir, &entry, pool->stateDir)) > 0) {
+ char *path;
+
+ if (entry->d_name[0] == '.' ||
+ !virFileHasSuffix(entry->d_name, ".xml"))
+ continue;
+
+ if (!(path = virFileBuildPath(pool->stateDir, entry->d_name, NULL)))
+ continue;
+
+ /* Unable to parse */
+ voldef = virStorageVolDefParseFile(pool->def, path);
+ VIR_FREE(path);
+ if (!voldef) {
+ ret = -1;
+ goto cleanup;
+ }
+
+ /* Search the current storage pool for the key from the file */
+ if ((poolvol = virStorageVolDefFindByKey(pool, voldef->key))) {
+
+ /* Swap name if necessary */
+ if (STRNEQ(voldef->name, poolvol->name)) {
+ char *tmp = poolvol->name;
+ poolvol->name = voldef->name;
+ voldef->name = tmp;
+ }
+
+ /* Same for target format type */
+ poolvol->target.format = voldef->target.format;
+
+ /* Update the saved file since we could have other changes
+ * as determined through refresh.
+ */
+ if (virStorageVolSaveStatus(pool, poolvol) < 0) {
+ virStorageVolDefFree(voldef);
+ ret = -1;
+ goto cleanup;
+ }
+ } else {
+ /* If we don't find the key in our current pool,
+ * then remove stale or transient file
+ */
+ unlink(entry->d_name);
+ }
+
+ /* Free the voldef (poolvol is just a pointer into poolobj */
+ virStorageVolDefFree(voldef);
+ }
+
+ cleanup:
+ closedir(dir);
+ return ret;
+}
+
+static int
virStorageBackendDiskRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
virStoragePoolObjPtr pool)
{
@@ -351,7 +423,13 @@ virStorageBackendDiskRefreshPool(virConnectPtr conn
ATTRIBUTE_UNUSED,
if (virStorageBackendDiskReadGeometry(pool) != 0)
return -1;
- return virStorageBackendDiskReadPartitions(pool, NULL);
+ if (virStorageBackendDiskReadPartitions(pool, NULL) < 0)
+ return -1;
+
+ if (virStorageBackendDiskUpdateStatus(pool) < 0)
+ return -1;
+
+ return 0;
}
@@ -690,6 +768,10 @@ virStorageBackendDiskCreateVol(virConnectPtr conn ATTRIBUTE_UNUSED,
if (virStorageBackendDiskReadPartitions(pool, vol) < 0)
goto cleanup;
+ /* Save the XML file in the stateDir for use by reload, restart, refresh */
+ if (virStorageVolSaveStatus(pool, vol) < 0)
+ goto cleanup;
+
res = 0;
cleanup:
@@ -775,6 +857,10 @@ virStorageBackendDiskDeleteVol(virConnectPtr conn ATTRIBUTE_UNUSED,
goto cleanup;
}
+ /* Remove the XML status file from stateDir */
+ if (virStorageVolDeleteStatus(pool, vol) < 0)
+ goto cleanup;
+
rc = 0;
cleanup:
VIR_FREE(devpath);
--
2.1.0