mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-22 12:35:17 +00:00
virstorageobj: Move virStoragePoolObjSourceFindDuplicate and friends up
This function is going to be made static in used in virStoragePoolObjAssignDef(). Therefore move it and all the static functions it calls a few lines up. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> Reviewed-by: John Ferlan <jferlan@redhat.com>
This commit is contained in:
parent
4391b5222f
commit
d13009007c
@ -1118,6 +1118,400 @@ virStoragePoolObjIsDuplicate(virStoragePoolObjListPtr pools,
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
getSCSIHostNumber(virStorageAdapterSCSIHostPtr scsi_host,
|
||||
unsigned int *hostnum)
|
||||
{
|
||||
int ret = -1;
|
||||
unsigned int num;
|
||||
char *name = NULL;
|
||||
|
||||
if (scsi_host->has_parent) {
|
||||
virPCIDeviceAddressPtr addr = &scsi_host->parentaddr;
|
||||
unsigned int unique_id = scsi_host->unique_id;
|
||||
|
||||
if (!(name = virSCSIHostGetNameByParentaddr(addr->domain,
|
||||
addr->bus,
|
||||
addr->slot,
|
||||
addr->function,
|
||||
unique_id)))
|
||||
goto cleanup;
|
||||
if (virSCSIHostGetNumber(name, &num) < 0)
|
||||
goto cleanup;
|
||||
} else {
|
||||
if (virSCSIHostGetNumber(scsi_host->name, &num) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
*hostnum = num;
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
virStorageIsSameHostnum(const char *name,
|
||||
unsigned int scsi_hostnum)
|
||||
{
|
||||
unsigned int fc_hostnum;
|
||||
|
||||
if (virSCSIHostGetNumber(name, &fc_hostnum) == 0 &&
|
||||
scsi_hostnum == fc_hostnum)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* matchFCHostToSCSIHost:
|
||||
*
|
||||
* @conn: Connection pointer
|
||||
* @fchost: fc_host adapter ptr (either def or pool->def)
|
||||
* @scsi_hostnum: Already determined "scsi_pool" hostnum
|
||||
*
|
||||
* Returns true/false whether there is a match between the incoming
|
||||
* fc_adapter host# and the scsi_host host#
|
||||
*/
|
||||
static bool
|
||||
matchFCHostToSCSIHost(virConnectPtr conn,
|
||||
virStorageAdapterFCHostPtr fchost,
|
||||
unsigned int scsi_hostnum)
|
||||
{
|
||||
bool ret = false;
|
||||
char *name = NULL;
|
||||
char *scsi_host_name = NULL;
|
||||
char *parent_name = NULL;
|
||||
|
||||
/* If we have a parent defined, get its hostnum, and compare to the
|
||||
* scsi_hostnum. If they are the same, then we have a match
|
||||
*/
|
||||
if (fchost->parent &&
|
||||
virStorageIsSameHostnum(fchost->parent, scsi_hostnum))
|
||||
return true;
|
||||
|
||||
/* If we find an fc adapter name, then either libvirt created a vHBA
|
||||
* for this fc_host or a 'virsh nodedev-create' generated a vHBA.
|
||||
*/
|
||||
if ((name = virVHBAGetHostByWWN(NULL, fchost->wwnn, fchost->wwpn))) {
|
||||
|
||||
/* Get the scsi_hostN for the vHBA in order to see if it
|
||||
* matches our scsi_hostnum
|
||||
*/
|
||||
if (virStorageIsSameHostnum(name, scsi_hostnum)) {
|
||||
ret = true;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* We weren't provided a parent, so we have to query the node
|
||||
* device driver in order to ascertain the parent of the vHBA.
|
||||
* If the parent fc_hostnum is the same as the scsi_hostnum, we
|
||||
* have a match.
|
||||
*/
|
||||
if (conn && !fchost->parent) {
|
||||
if (virAsprintf(&scsi_host_name, "scsi_%s", name) < 0)
|
||||
goto cleanup;
|
||||
if ((parent_name = virNodeDeviceGetParentName(conn,
|
||||
scsi_host_name))) {
|
||||
if (virStorageIsSameHostnum(parent_name, scsi_hostnum)) {
|
||||
ret = true;
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
/* Throw away the error and fall through */
|
||||
virResetLastError();
|
||||
VIR_DEBUG("Could not determine parent vHBA");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* NB: Lack of a name means that this vHBA hasn't yet been created,
|
||||
* which means our scsi_host cannot be using the vHBA. Furthermore,
|
||||
* lack of a provided parent means libvirt is going to choose the
|
||||
* "best" fc_host capable adapter based on availabilty. That could
|
||||
* conflict with an existing scsi_host definition, but there's no
|
||||
* way to know that now.
|
||||
*/
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(name);
|
||||
VIR_FREE(parent_name);
|
||||
VIR_FREE(scsi_host_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
matchSCSIAdapterParent(virStorageAdapterSCSIHostPtr pool_scsi_host,
|
||||
virStorageAdapterSCSIHostPtr def_scsi_host)
|
||||
{
|
||||
virPCIDeviceAddressPtr pooladdr = &pool_scsi_host->parentaddr;
|
||||
virPCIDeviceAddressPtr defaddr = &def_scsi_host->parentaddr;
|
||||
|
||||
if (pooladdr->domain == defaddr->domain &&
|
||||
pooladdr->bus == defaddr->bus &&
|
||||
pooladdr->slot == defaddr->slot &&
|
||||
pooladdr->function == defaddr->function &&
|
||||
pool_scsi_host->unique_id == def_scsi_host->unique_id)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
virStoragePoolSourceMatchSingleHost(virStoragePoolSourcePtr poolsrc,
|
||||
virStoragePoolSourcePtr defsrc)
|
||||
{
|
||||
if (poolsrc->nhost != 1 && defsrc->nhost != 1)
|
||||
return false;
|
||||
|
||||
if (defsrc->hosts[0].port &&
|
||||
poolsrc->hosts[0].port != defsrc->hosts[0].port)
|
||||
return false;
|
||||
|
||||
return STREQ(poolsrc->hosts[0].name, defsrc->hosts[0].name);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
virStoragePoolSourceISCSIMatch(virStoragePoolObjPtr obj,
|
||||
virStoragePoolDefPtr def)
|
||||
{
|
||||
virStoragePoolSourcePtr poolsrc = &obj->def->source;
|
||||
virStoragePoolSourcePtr defsrc = &def->source;
|
||||
|
||||
/* NB: Do not check the source host name */
|
||||
if (STRNEQ_NULLABLE(poolsrc->initiator.iqn, defsrc->initiator.iqn))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static virStoragePoolObjPtr
|
||||
virStoragePoolObjSourceMatchTypeDIR(virStoragePoolObjPtr obj,
|
||||
virStoragePoolDefPtr def)
|
||||
{
|
||||
if (obj->def->type == VIR_STORAGE_POOL_DIR) {
|
||||
if (STREQ(obj->def->target.path, def->target.path))
|
||||
return obj;
|
||||
} else if (obj->def->type == VIR_STORAGE_POOL_GLUSTER) {
|
||||
if (STREQ(obj->def->source.name, def->source.name) &&
|
||||
STREQ_NULLABLE(obj->def->source.dir, def->source.dir) &&
|
||||
virStoragePoolSourceMatchSingleHost(&obj->def->source,
|
||||
&def->source))
|
||||
return obj;
|
||||
} else if (obj->def->type == VIR_STORAGE_POOL_NETFS) {
|
||||
if (STREQ(obj->def->source.dir, def->source.dir) &&
|
||||
virStoragePoolSourceMatchSingleHost(&obj->def->source,
|
||||
&def->source))
|
||||
return obj;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static virStoragePoolObjPtr
|
||||
virStoragePoolObjSourceMatchTypeISCSI(virStoragePoolObjPtr obj,
|
||||
virStoragePoolDefPtr def,
|
||||
virConnectPtr conn)
|
||||
{
|
||||
virStorageAdapterPtr pool_adapter = &obj->def->source.adapter;
|
||||
virStorageAdapterPtr def_adapter = &def->source.adapter;
|
||||
virStorageAdapterSCSIHostPtr pool_scsi_host;
|
||||
virStorageAdapterSCSIHostPtr def_scsi_host;
|
||||
virStorageAdapterFCHostPtr pool_fchost;
|
||||
virStorageAdapterFCHostPtr def_fchost;
|
||||
unsigned int pool_hostnum;
|
||||
unsigned int def_hostnum;
|
||||
unsigned int scsi_hostnum;
|
||||
|
||||
if (pool_adapter->type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST &&
|
||||
def_adapter->type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST) {
|
||||
pool_fchost = &pool_adapter->data.fchost;
|
||||
def_fchost = &def_adapter->data.fchost;
|
||||
|
||||
if (STREQ(pool_fchost->wwnn, def_fchost->wwnn) &&
|
||||
STREQ(pool_fchost->wwpn, def_fchost->wwpn))
|
||||
return obj;
|
||||
} else if (pool_adapter->type == VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST &&
|
||||
def_adapter->type == VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST) {
|
||||
pool_scsi_host = &pool_adapter->data.scsi_host;
|
||||
def_scsi_host = &def_adapter->data.scsi_host;
|
||||
|
||||
if (pool_scsi_host->has_parent &&
|
||||
def_scsi_host->has_parent &&
|
||||
matchSCSIAdapterParent(pool_scsi_host, def_scsi_host))
|
||||
return obj;
|
||||
|
||||
if (getSCSIHostNumber(pool_scsi_host, &pool_hostnum) < 0 ||
|
||||
getSCSIHostNumber(def_scsi_host, &def_hostnum) < 0)
|
||||
return NULL;
|
||||
if (pool_hostnum == def_hostnum)
|
||||
return obj;
|
||||
} else if (pool_adapter->type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST &&
|
||||
def_adapter->type == VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST) {
|
||||
pool_fchost = &pool_adapter->data.fchost;
|
||||
def_scsi_host = &def_adapter->data.scsi_host;
|
||||
|
||||
/* Get the scsi_hostN for the scsi_host source adapter def */
|
||||
if (getSCSIHostNumber(def_scsi_host, &scsi_hostnum) < 0)
|
||||
return NULL;
|
||||
|
||||
if (matchFCHostToSCSIHost(conn, pool_fchost, scsi_hostnum))
|
||||
return obj;
|
||||
|
||||
} else if (pool_adapter->type == VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST &&
|
||||
def_adapter->type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST) {
|
||||
pool_scsi_host = &pool_adapter->data.scsi_host;
|
||||
def_fchost = &def_adapter->data.fchost;
|
||||
|
||||
if (getSCSIHostNumber(pool_scsi_host, &scsi_hostnum) < 0)
|
||||
return NULL;
|
||||
|
||||
if (matchFCHostToSCSIHost(conn, def_fchost, scsi_hostnum))
|
||||
return obj;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static virStoragePoolObjPtr
|
||||
virStoragePoolObjSourceMatchTypeDEVICE(virStoragePoolObjPtr obj,
|
||||
virStoragePoolDefPtr def)
|
||||
{
|
||||
virStoragePoolObjPtr matchobj = NULL;
|
||||
|
||||
if (obj->def->type == VIR_STORAGE_POOL_ISCSI) {
|
||||
if (def->type != VIR_STORAGE_POOL_ISCSI)
|
||||
return NULL;
|
||||
|
||||
if ((matchobj = virStoragePoolSourceFindDuplicateDevices(obj, def))) {
|
||||
if (!virStoragePoolSourceISCSIMatch(matchobj, def))
|
||||
return NULL;
|
||||
}
|
||||
return matchobj;
|
||||
}
|
||||
|
||||
if (def->type == VIR_STORAGE_POOL_ISCSI)
|
||||
return NULL;
|
||||
|
||||
/* VIR_STORAGE_POOL_FS
|
||||
* VIR_STORAGE_POOL_LOGICAL
|
||||
* VIR_STORAGE_POOL_DISK
|
||||
* VIR_STORAGE_POOL_ZFS */
|
||||
return virStoragePoolSourceFindDuplicateDevices(obj, def);
|
||||
}
|
||||
|
||||
|
||||
struct _virStoragePoolObjFindDuplicateData {
|
||||
virConnectPtr conn;
|
||||
virStoragePoolDefPtr def;
|
||||
};
|
||||
|
||||
static int
|
||||
virStoragePoolObjSourceFindDuplicateCb(const void *payload,
|
||||
const void *name ATTRIBUTE_UNUSED,
|
||||
const void *opaque)
|
||||
{
|
||||
virStoragePoolObjPtr obj = (virStoragePoolObjPtr) payload;
|
||||
struct _virStoragePoolObjFindDuplicateData *data =
|
||||
(struct _virStoragePoolObjFindDuplicateData *) opaque;
|
||||
|
||||
/* Don't match against ourself if re-defining existing pool ! */
|
||||
if (STREQ(obj->def->name, data->def->name))
|
||||
return 0;
|
||||
|
||||
switch ((virStoragePoolType)obj->def->type) {
|
||||
case VIR_STORAGE_POOL_DIR:
|
||||
case VIR_STORAGE_POOL_GLUSTER:
|
||||
case VIR_STORAGE_POOL_NETFS:
|
||||
if (data->def->type == obj->def->type &&
|
||||
virStoragePoolObjSourceMatchTypeDIR(obj, data->def))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case VIR_STORAGE_POOL_SCSI:
|
||||
if (data->def->type == obj->def->type &&
|
||||
virStoragePoolObjSourceMatchTypeISCSI(obj, data->def, data->conn))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case VIR_STORAGE_POOL_ISCSI:
|
||||
case VIR_STORAGE_POOL_ISCSI_DIRECT:
|
||||
case VIR_STORAGE_POOL_FS:
|
||||
case VIR_STORAGE_POOL_LOGICAL:
|
||||
case VIR_STORAGE_POOL_DISK:
|
||||
case VIR_STORAGE_POOL_ZFS:
|
||||
if ((data->def->type == VIR_STORAGE_POOL_ISCSI ||
|
||||
data->def->type == VIR_STORAGE_POOL_ISCSI_DIRECT ||
|
||||
data->def->type == VIR_STORAGE_POOL_FS ||
|
||||
data->def->type == VIR_STORAGE_POOL_LOGICAL ||
|
||||
data->def->type == VIR_STORAGE_POOL_DISK ||
|
||||
data->def->type == VIR_STORAGE_POOL_ZFS) &&
|
||||
virStoragePoolObjSourceMatchTypeDEVICE(obj, data->def))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case VIR_STORAGE_POOL_SHEEPDOG:
|
||||
if (data->def->type == obj->def->type &&
|
||||
virStoragePoolSourceMatchSingleHost(&obj->def->source,
|
||||
&data->def->source))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case VIR_STORAGE_POOL_MPATH:
|
||||
/* Only one mpath pool is valid per host */
|
||||
if (data->def->type == obj->def->type)
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case VIR_STORAGE_POOL_VSTORAGE:
|
||||
if (data->def->type == obj->def->type &&
|
||||
STREQ(obj->def->source.name, data->def->source.name))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case VIR_STORAGE_POOL_RBD:
|
||||
case VIR_STORAGE_POOL_LAST:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
virStoragePoolObjSourceFindDuplicate(virConnectPtr conn,
|
||||
virStoragePoolObjListPtr pools,
|
||||
virStoragePoolDefPtr def)
|
||||
{
|
||||
struct _virStoragePoolObjFindDuplicateData data = { .conn = conn,
|
||||
.def = def };
|
||||
virStoragePoolObjPtr obj = NULL;
|
||||
|
||||
virObjectRWLockRead(pools);
|
||||
obj = virHashSearch(pools->objs, virStoragePoolObjSourceFindDuplicateCb,
|
||||
&data, NULL);
|
||||
virObjectRWUnlock(pools);
|
||||
|
||||
if (obj) {
|
||||
virReportError(VIR_ERR_OPERATION_FAILED,
|
||||
_("Storage source conflict with pool: '%s'"),
|
||||
obj->def->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virStoragePoolObjAssignDef:
|
||||
* @pools: Storage Pool object list pointer
|
||||
@ -1529,400 +1923,6 @@ virStoragePoolObjGetNames(virStoragePoolObjListPtr pools,
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
getSCSIHostNumber(virStorageAdapterSCSIHostPtr scsi_host,
|
||||
unsigned int *hostnum)
|
||||
{
|
||||
int ret = -1;
|
||||
unsigned int num;
|
||||
char *name = NULL;
|
||||
|
||||
if (scsi_host->has_parent) {
|
||||
virPCIDeviceAddressPtr addr = &scsi_host->parentaddr;
|
||||
unsigned int unique_id = scsi_host->unique_id;
|
||||
|
||||
if (!(name = virSCSIHostGetNameByParentaddr(addr->domain,
|
||||
addr->bus,
|
||||
addr->slot,
|
||||
addr->function,
|
||||
unique_id)))
|
||||
goto cleanup;
|
||||
if (virSCSIHostGetNumber(name, &num) < 0)
|
||||
goto cleanup;
|
||||
} else {
|
||||
if (virSCSIHostGetNumber(scsi_host->name, &num) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
*hostnum = num;
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
virStorageIsSameHostnum(const char *name,
|
||||
unsigned int scsi_hostnum)
|
||||
{
|
||||
unsigned int fc_hostnum;
|
||||
|
||||
if (virSCSIHostGetNumber(name, &fc_hostnum) == 0 &&
|
||||
scsi_hostnum == fc_hostnum)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* matchFCHostToSCSIHost:
|
||||
*
|
||||
* @conn: Connection pointer
|
||||
* @fchost: fc_host adapter ptr (either def or pool->def)
|
||||
* @scsi_hostnum: Already determined "scsi_pool" hostnum
|
||||
*
|
||||
* Returns true/false whether there is a match between the incoming
|
||||
* fc_adapter host# and the scsi_host host#
|
||||
*/
|
||||
static bool
|
||||
matchFCHostToSCSIHost(virConnectPtr conn,
|
||||
virStorageAdapterFCHostPtr fchost,
|
||||
unsigned int scsi_hostnum)
|
||||
{
|
||||
bool ret = false;
|
||||
char *name = NULL;
|
||||
char *scsi_host_name = NULL;
|
||||
char *parent_name = NULL;
|
||||
|
||||
/* If we have a parent defined, get its hostnum, and compare to the
|
||||
* scsi_hostnum. If they are the same, then we have a match
|
||||
*/
|
||||
if (fchost->parent &&
|
||||
virStorageIsSameHostnum(fchost->parent, scsi_hostnum))
|
||||
return true;
|
||||
|
||||
/* If we find an fc adapter name, then either libvirt created a vHBA
|
||||
* for this fc_host or a 'virsh nodedev-create' generated a vHBA.
|
||||
*/
|
||||
if ((name = virVHBAGetHostByWWN(NULL, fchost->wwnn, fchost->wwpn))) {
|
||||
|
||||
/* Get the scsi_hostN for the vHBA in order to see if it
|
||||
* matches our scsi_hostnum
|
||||
*/
|
||||
if (virStorageIsSameHostnum(name, scsi_hostnum)) {
|
||||
ret = true;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* We weren't provided a parent, so we have to query the node
|
||||
* device driver in order to ascertain the parent of the vHBA.
|
||||
* If the parent fc_hostnum is the same as the scsi_hostnum, we
|
||||
* have a match.
|
||||
*/
|
||||
if (conn && !fchost->parent) {
|
||||
if (virAsprintf(&scsi_host_name, "scsi_%s", name) < 0)
|
||||
goto cleanup;
|
||||
if ((parent_name = virNodeDeviceGetParentName(conn,
|
||||
scsi_host_name))) {
|
||||
if (virStorageIsSameHostnum(parent_name, scsi_hostnum)) {
|
||||
ret = true;
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
/* Throw away the error and fall through */
|
||||
virResetLastError();
|
||||
VIR_DEBUG("Could not determine parent vHBA");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* NB: Lack of a name means that this vHBA hasn't yet been created,
|
||||
* which means our scsi_host cannot be using the vHBA. Furthermore,
|
||||
* lack of a provided parent means libvirt is going to choose the
|
||||
* "best" fc_host capable adapter based on availabilty. That could
|
||||
* conflict with an existing scsi_host definition, but there's no
|
||||
* way to know that now.
|
||||
*/
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(name);
|
||||
VIR_FREE(parent_name);
|
||||
VIR_FREE(scsi_host_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
matchSCSIAdapterParent(virStorageAdapterSCSIHostPtr pool_scsi_host,
|
||||
virStorageAdapterSCSIHostPtr def_scsi_host)
|
||||
{
|
||||
virPCIDeviceAddressPtr pooladdr = &pool_scsi_host->parentaddr;
|
||||
virPCIDeviceAddressPtr defaddr = &def_scsi_host->parentaddr;
|
||||
|
||||
if (pooladdr->domain == defaddr->domain &&
|
||||
pooladdr->bus == defaddr->bus &&
|
||||
pooladdr->slot == defaddr->slot &&
|
||||
pooladdr->function == defaddr->function &&
|
||||
pool_scsi_host->unique_id == def_scsi_host->unique_id)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
virStoragePoolSourceMatchSingleHost(virStoragePoolSourcePtr poolsrc,
|
||||
virStoragePoolSourcePtr defsrc)
|
||||
{
|
||||
if (poolsrc->nhost != 1 && defsrc->nhost != 1)
|
||||
return false;
|
||||
|
||||
if (defsrc->hosts[0].port &&
|
||||
poolsrc->hosts[0].port != defsrc->hosts[0].port)
|
||||
return false;
|
||||
|
||||
return STREQ(poolsrc->hosts[0].name, defsrc->hosts[0].name);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
virStoragePoolSourceISCSIMatch(virStoragePoolObjPtr obj,
|
||||
virStoragePoolDefPtr def)
|
||||
{
|
||||
virStoragePoolSourcePtr poolsrc = &obj->def->source;
|
||||
virStoragePoolSourcePtr defsrc = &def->source;
|
||||
|
||||
/* NB: Do not check the source host name */
|
||||
if (STRNEQ_NULLABLE(poolsrc->initiator.iqn, defsrc->initiator.iqn))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static virStoragePoolObjPtr
|
||||
virStoragePoolObjSourceMatchTypeDIR(virStoragePoolObjPtr obj,
|
||||
virStoragePoolDefPtr def)
|
||||
{
|
||||
if (obj->def->type == VIR_STORAGE_POOL_DIR) {
|
||||
if (STREQ(obj->def->target.path, def->target.path))
|
||||
return obj;
|
||||
} else if (obj->def->type == VIR_STORAGE_POOL_GLUSTER) {
|
||||
if (STREQ(obj->def->source.name, def->source.name) &&
|
||||
STREQ_NULLABLE(obj->def->source.dir, def->source.dir) &&
|
||||
virStoragePoolSourceMatchSingleHost(&obj->def->source,
|
||||
&def->source))
|
||||
return obj;
|
||||
} else if (obj->def->type == VIR_STORAGE_POOL_NETFS) {
|
||||
if (STREQ(obj->def->source.dir, def->source.dir) &&
|
||||
virStoragePoolSourceMatchSingleHost(&obj->def->source,
|
||||
&def->source))
|
||||
return obj;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static virStoragePoolObjPtr
|
||||
virStoragePoolObjSourceMatchTypeISCSI(virStoragePoolObjPtr obj,
|
||||
virStoragePoolDefPtr def,
|
||||
virConnectPtr conn)
|
||||
{
|
||||
virStorageAdapterPtr pool_adapter = &obj->def->source.adapter;
|
||||
virStorageAdapterPtr def_adapter = &def->source.adapter;
|
||||
virStorageAdapterSCSIHostPtr pool_scsi_host;
|
||||
virStorageAdapterSCSIHostPtr def_scsi_host;
|
||||
virStorageAdapterFCHostPtr pool_fchost;
|
||||
virStorageAdapterFCHostPtr def_fchost;
|
||||
unsigned int pool_hostnum;
|
||||
unsigned int def_hostnum;
|
||||
unsigned int scsi_hostnum;
|
||||
|
||||
if (pool_adapter->type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST &&
|
||||
def_adapter->type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST) {
|
||||
pool_fchost = &pool_adapter->data.fchost;
|
||||
def_fchost = &def_adapter->data.fchost;
|
||||
|
||||
if (STREQ(pool_fchost->wwnn, def_fchost->wwnn) &&
|
||||
STREQ(pool_fchost->wwpn, def_fchost->wwpn))
|
||||
return obj;
|
||||
} else if (pool_adapter->type == VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST &&
|
||||
def_adapter->type == VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST) {
|
||||
pool_scsi_host = &pool_adapter->data.scsi_host;
|
||||
def_scsi_host = &def_adapter->data.scsi_host;
|
||||
|
||||
if (pool_scsi_host->has_parent &&
|
||||
def_scsi_host->has_parent &&
|
||||
matchSCSIAdapterParent(pool_scsi_host, def_scsi_host))
|
||||
return obj;
|
||||
|
||||
if (getSCSIHostNumber(pool_scsi_host, &pool_hostnum) < 0 ||
|
||||
getSCSIHostNumber(def_scsi_host, &def_hostnum) < 0)
|
||||
return NULL;
|
||||
if (pool_hostnum == def_hostnum)
|
||||
return obj;
|
||||
} else if (pool_adapter->type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST &&
|
||||
def_adapter->type == VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST) {
|
||||
pool_fchost = &pool_adapter->data.fchost;
|
||||
def_scsi_host = &def_adapter->data.scsi_host;
|
||||
|
||||
/* Get the scsi_hostN for the scsi_host source adapter def */
|
||||
if (getSCSIHostNumber(def_scsi_host, &scsi_hostnum) < 0)
|
||||
return NULL;
|
||||
|
||||
if (matchFCHostToSCSIHost(conn, pool_fchost, scsi_hostnum))
|
||||
return obj;
|
||||
|
||||
} else if (pool_adapter->type == VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST &&
|
||||
def_adapter->type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST) {
|
||||
pool_scsi_host = &pool_adapter->data.scsi_host;
|
||||
def_fchost = &def_adapter->data.fchost;
|
||||
|
||||
if (getSCSIHostNumber(pool_scsi_host, &scsi_hostnum) < 0)
|
||||
return NULL;
|
||||
|
||||
if (matchFCHostToSCSIHost(conn, def_fchost, scsi_hostnum))
|
||||
return obj;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static virStoragePoolObjPtr
|
||||
virStoragePoolObjSourceMatchTypeDEVICE(virStoragePoolObjPtr obj,
|
||||
virStoragePoolDefPtr def)
|
||||
{
|
||||
virStoragePoolObjPtr matchobj = NULL;
|
||||
|
||||
if (obj->def->type == VIR_STORAGE_POOL_ISCSI) {
|
||||
if (def->type != VIR_STORAGE_POOL_ISCSI)
|
||||
return NULL;
|
||||
|
||||
if ((matchobj = virStoragePoolSourceFindDuplicateDevices(obj, def))) {
|
||||
if (!virStoragePoolSourceISCSIMatch(matchobj, def))
|
||||
return NULL;
|
||||
}
|
||||
return matchobj;
|
||||
}
|
||||
|
||||
if (def->type == VIR_STORAGE_POOL_ISCSI)
|
||||
return NULL;
|
||||
|
||||
/* VIR_STORAGE_POOL_FS
|
||||
* VIR_STORAGE_POOL_LOGICAL
|
||||
* VIR_STORAGE_POOL_DISK
|
||||
* VIR_STORAGE_POOL_ZFS */
|
||||
return virStoragePoolSourceFindDuplicateDevices(obj, def);
|
||||
}
|
||||
|
||||
|
||||
struct _virStoragePoolObjFindDuplicateData {
|
||||
virConnectPtr conn;
|
||||
virStoragePoolDefPtr def;
|
||||
};
|
||||
|
||||
static int
|
||||
virStoragePoolObjSourceFindDuplicateCb(const void *payload,
|
||||
const void *name ATTRIBUTE_UNUSED,
|
||||
const void *opaque)
|
||||
{
|
||||
virStoragePoolObjPtr obj = (virStoragePoolObjPtr) payload;
|
||||
struct _virStoragePoolObjFindDuplicateData *data =
|
||||
(struct _virStoragePoolObjFindDuplicateData *) opaque;
|
||||
|
||||
/* Don't match against ourself if re-defining existing pool ! */
|
||||
if (STREQ(obj->def->name, data->def->name))
|
||||
return 0;
|
||||
|
||||
switch ((virStoragePoolType)obj->def->type) {
|
||||
case VIR_STORAGE_POOL_DIR:
|
||||
case VIR_STORAGE_POOL_GLUSTER:
|
||||
case VIR_STORAGE_POOL_NETFS:
|
||||
if (data->def->type == obj->def->type &&
|
||||
virStoragePoolObjSourceMatchTypeDIR(obj, data->def))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case VIR_STORAGE_POOL_SCSI:
|
||||
if (data->def->type == obj->def->type &&
|
||||
virStoragePoolObjSourceMatchTypeISCSI(obj, data->def, data->conn))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case VIR_STORAGE_POOL_ISCSI:
|
||||
case VIR_STORAGE_POOL_ISCSI_DIRECT:
|
||||
case VIR_STORAGE_POOL_FS:
|
||||
case VIR_STORAGE_POOL_LOGICAL:
|
||||
case VIR_STORAGE_POOL_DISK:
|
||||
case VIR_STORAGE_POOL_ZFS:
|
||||
if ((data->def->type == VIR_STORAGE_POOL_ISCSI ||
|
||||
data->def->type == VIR_STORAGE_POOL_ISCSI_DIRECT ||
|
||||
data->def->type == VIR_STORAGE_POOL_FS ||
|
||||
data->def->type == VIR_STORAGE_POOL_LOGICAL ||
|
||||
data->def->type == VIR_STORAGE_POOL_DISK ||
|
||||
data->def->type == VIR_STORAGE_POOL_ZFS) &&
|
||||
virStoragePoolObjSourceMatchTypeDEVICE(obj, data->def))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case VIR_STORAGE_POOL_SHEEPDOG:
|
||||
if (data->def->type == obj->def->type &&
|
||||
virStoragePoolSourceMatchSingleHost(&obj->def->source,
|
||||
&data->def->source))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case VIR_STORAGE_POOL_MPATH:
|
||||
/* Only one mpath pool is valid per host */
|
||||
if (data->def->type == obj->def->type)
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case VIR_STORAGE_POOL_VSTORAGE:
|
||||
if (data->def->type == obj->def->type &&
|
||||
STREQ(obj->def->source.name, data->def->source.name))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case VIR_STORAGE_POOL_RBD:
|
||||
case VIR_STORAGE_POOL_LAST:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
virStoragePoolObjSourceFindDuplicate(virConnectPtr conn,
|
||||
virStoragePoolObjListPtr pools,
|
||||
virStoragePoolDefPtr def)
|
||||
{
|
||||
struct _virStoragePoolObjFindDuplicateData data = { .conn = conn,
|
||||
.def = def };
|
||||
virStoragePoolObjPtr obj = NULL;
|
||||
|
||||
virObjectRWLockRead(pools);
|
||||
obj = virHashSearch(pools->objs, virStoragePoolObjSourceFindDuplicateCb,
|
||||
&data, NULL);
|
||||
virObjectRWUnlock(pools);
|
||||
|
||||
if (obj) {
|
||||
virReportError(VIR_ERR_OPERATION_FAILED,
|
||||
_("Storage source conflict with pool: '%s'"),
|
||||
obj->def->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define MATCH(FLAG) (flags & (FLAG))
|
||||
static bool
|
||||
virStoragePoolObjMatch(virStoragePoolObjPtr obj,
|
||||
|
Loading…
x
Reference in New Issue
Block a user