https://bugzilla.redhat.com/show_bug.cgi?id=1171984
During storage pool Create or CreateXML add a call prior to the backend
startPool that will compare the resolved source host name of the network
storage pool to be started against the active, network storage pools
resolved host name to ensure the to be started definition won't
duplicate an existing, active pool for the same pool source path's.
Signed-off-by: John Ferlan <jferlan(a)redhat.com>
---
src/conf/storage_conf.c | 80 +++++++++++++++++++++++++++++++++++++++++++-
src/conf/storage_conf.h | 6 +++-
src/libvirt_private.syms | 1 +
src/storage/storage_driver.c | 9 ++++-
4 files changed, 93 insertions(+), 3 deletions(-)
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index 4852dfb..4793817 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -1,7 +1,7 @@
/*
* storage_conf.c: config handling for storage driver
*
- * Copyright (C) 2006-2014 Red Hat, Inc.
+ * Copyright (C) 2006-2015 Red Hat, Inc.
* Copyright (C) 2006-2008 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -43,6 +43,7 @@
#include "virbuffer.h"
#include "viralloc.h"
#include "virfile.h"
+#include "virsocketaddr.h"
#include "virstring.h"
#include "virlog.h"
@@ -2571,6 +2572,83 @@ virStoragePoolSourceFindDuplicate(virConnectPtr conn,
return ret;
}
+/*
+ * Prior to starting a storage pool, this API will check to see whether
+ * any currently active pool is already using the same source dir/device
+ * and same resolved host name as the proposed definition. To do this,
+ * query the host in order to compare the resolved names for the pool
+ * and the definition.
+ *
+ * Returns 0 if the definition doesn't match any host, returns -1 on error
+ */
+int
+virStoragePoolSourceHostCompare(virStoragePoolObjListPtr pools,
+ virStoragePoolDefPtr def)
+{
+ int ret = -1;
+ size_t i;
+
+ if (def->type != VIR_STORAGE_POOL_NETFS &&
+ def->type != VIR_STORAGE_POOL_GLUSTER &&
+ def->type != VIR_STORAGE_POOL_ISCSI &&
+ def->type != VIR_STORAGE_POOL_SHEEPDOG)
+ return 0;
+
+ for (i = 0; i < pools->count; i++) {
+ virStoragePoolObjPtr pool = pools->objs[i];
+ virStoragePoolSourcePtr poolsrc, defsrc;
+
+ virStoragePoolObjLock(pool);
+
+ poolsrc = &pool->def->source;
+ defsrc = &def->source;
+ if (pool->active && pool->def->type == def->type &&
+ poolsrc->nhost == 1 && defsrc->nhost == 1) {
+
+ bool matchsrc = false;
+ const char *poolhost = poolsrc->hosts[0].name;
+ const char *defhost = defsrc->hosts[0].name;
+
+ /* Only check the port if the to be started pool supplied one */
+ if (defsrc->hosts[0].port != 0) {
+ if (poolsrc->hosts[0].port != defsrc->hosts[0].port) {
+ virStoragePoolObjUnlock(pool);
+ continue;
+ }
+ }
+
+ if (pool->def->type == VIR_STORAGE_POOL_NETFS ||
+ pool->def->type == VIR_STORAGE_POOL_GLUSTER) {
+ matchsrc = STREQ(poolsrc->dir, defsrc->dir);
+ } else if (pool->def->type == VIR_STORAGE_POOL_ISCSI) {
+ if (virStoragePoolSourceFindDuplicateDevices(pool, def))
+ matchsrc = true;
+ } else if (pool->def->type == VIR_STORAGE_POOL_SHEEPDOG) {
+ matchsrc = true;
+ }
+
+ if (matchsrc) {
+ ret = virSocketAddrIsSameTCPHost(poolhost, defhost);
+ virStoragePoolObjUnlock(pool);
+ if (ret == 0)
+ continue;
+ if (ret == 1) {
+ virReportError(VIR_ERR_OPERATION_FAILED,
+ _("Storage source conflict with pool:
'%s'"),
+ pool->def->name);
+ ret = -1;
+ }
+ goto cleanup;
+ }
+ }
+ virStoragePoolObjUnlock(pool);
+ }
+ ret = 0;
+
+ cleanup:
+ return ret;
+}
+
void
virStoragePoolObjLock(virStoragePoolObjPtr obj)
{
diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h
index 7471006..0d46376 100644
--- a/src/conf/storage_conf.h
+++ b/src/conf/storage_conf.h
@@ -1,7 +1,7 @@
/*
* storage_conf.h: config handling for storage driver
*
- * Copyright (C) 2006-2008, 2010-2014 Red Hat, Inc.
+ * Copyright (C) 2006-2008, 2010-2015 Red Hat, Inc.
* Copyright (C) 2006-2008 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -417,6 +417,10 @@ int virStoragePoolSourceFindDuplicate(virConnectPtr conn,
virStoragePoolObjListPtr pools,
virStoragePoolDefPtr def);
+int virStoragePoolSourceHostCompare(virStoragePoolObjListPtr pools,
+ virStoragePoolDefPtr def)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
void virStoragePoolObjLock(virStoragePoolObjPtr obj);
void virStoragePoolObjUnlock(virStoragePoolObjPtr obj);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 34cb871..a489c83 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -836,6 +836,7 @@ virStoragePoolSourceDeviceClear;
virStoragePoolSourceFindDuplicate;
virStoragePoolSourceFindDuplicateDevices;
virStoragePoolSourceFree;
+virStoragePoolSourceHostCompare;
virStoragePoolSourceListFormat;
virStoragePoolSourceListNewSource;
virStoragePoolTypeFromString;
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index 306d98e..922863a 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -1,7 +1,7 @@
/*
* storage_driver.c: core driver for storage APIs
*
- * Copyright (C) 2006-2014 Red Hat, Inc.
+ * Copyright (C) 2006-2015 Red Hat, Inc.
* Copyright (C) 2006-2008 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -674,8 +674,12 @@ storagePoolCreateXML(virConnectPtr conn,
if ((backend = virStorageBackendForType(def->type)) == NULL)
goto cleanup;
+ if (virStoragePoolSourceHostCompare(&driver->pools, def) < 0)
+ goto cleanup;
+
if (!(pool = virStoragePoolObjAssignDef(&driver->pools, def)))
goto cleanup;
+
def = NULL;
if (backend->startPool &&
@@ -846,6 +850,9 @@ storagePoolCreate(virStoragePoolPtr obj,
goto cleanup;
}
+ if (virStoragePoolSourceHostCompare(&driver->pools, pool->def) < 0)
+ goto cleanup;
+
VIR_INFO("Starting up storage pool '%s'", pool->def->name);
if (backend->startPool &&
backend->startPool(obj->conn, pool) < 0)
--
2.1.0