storage: Allow multiple hosts for a storage pool

The current storage pools for NFS and iSCSI only require one host to
connect to. Future storage pools like RBD and Sheepdog will require
multiple hosts.

This patch allows multiple source hosts and rewrites the current
storage drivers.

Signed-off-by: Wido den Hollander <wido@widodh.nl>
This commit is contained in:
Wido den Hollander 2012-04-25 12:43:09 +02:00 committed by Daniel Veillard
parent 9d2ac5453e
commit 122fa379de
7 changed files with 118 additions and 40 deletions

View File

@ -233,6 +233,7 @@ Patches have also been contributed by:
MATSUDA Daiki <matsudadik@intellilink.co.jp>
Jan Kiszka <jan.kiszka@siemens.com>
Ryan Woodsmall <rwoodsmall@gmail.com>
Wido den Hollander <wido@widodh.nl>
[....send patches to get your name here....]

View File

@ -276,7 +276,11 @@ virStoragePoolSourceClear(virStoragePoolSourcePtr source)
if (!source)
return;
VIR_FREE(source->host.name);
for (i = 0 ; i < source->nhost ; i++) {
VIR_FREE(source->hosts[i].name);
}
VIR_FREE(source->hosts);
for (i = 0 ; i < source->ndevice ; i++) {
VIR_FREE(source->devices[i].freeExtents);
VIR_FREE(source->devices[i].path);
@ -404,6 +408,7 @@ virStoragePoolDefParseSource(xmlXPathContextPtr ctxt,
char *authType = NULL;
int nsource, i;
virStoragePoolOptionsPtr options;
char *name = NULL;
char *port = NULL;
relnode = ctxt->node;
@ -431,17 +436,34 @@ virStoragePoolDefParseSource(xmlXPathContextPtr ctxt,
VIR_FREE(format);
}
source->host.name = virXPathString("string(./host/@name)", ctxt);
port = virXPathString("string(./host/@port)", ctxt);
if (port) {
if (virStrToLong_i(port, NULL, 10, &source->host.port) < 0) {
virStorageReportError(VIR_ERR_XML_ERROR,
_("Invalid port number: %s"),
port);
source->nhost = virXPathNodeSet("./host", ctxt, &nodeset);
if (source->nhost) {
if (VIR_ALLOC_N(source->hosts, source->nhost) < 0) {
virReportOOMError();
goto cleanup;
}
}
for (i = 0 ; i < source->nhost ; i++) {
name = virXMLPropString(nodeset[i], "name");
if (name == NULL) {
virStorageReportError(VIR_ERR_XML_ERROR,
"%s", _("missing storage pool host name"));
goto cleanup;
}
source->hosts[i].name = name;
port = virXMLPropString(nodeset[i], "port");
if (port) {
if (virStrToLong_i(port, NULL, 10, &source->hosts[i].port) < 0) {
virStorageReportError(VIR_ERR_XML_ERROR,
_("Invalid port number: %s"),
port);
goto cleanup;
}
}
}
}
source->initiator.iqn = virXPathString("string(./initiator/iqn/@name)", ctxt);
@ -675,7 +697,7 @@ virStoragePoolDefParseXML(xmlXPathContextPtr ctxt) {
}
if (options->flags & VIR_STORAGE_POOL_SOURCE_HOST) {
if (!ret->source.host.name) {
if (!ret->source.nhost) {
virStorageReportError(VIR_ERR_XML_ERROR,
"%s",
_("missing storage pool source host name"));
@ -801,12 +823,13 @@ virStoragePoolSourceFormat(virBufferPtr buf,
int i, j;
virBufferAddLit(buf," <source>\n");
if ((options->flags & VIR_STORAGE_POOL_SOURCE_HOST) &&
src->host.name) {
virBufferAsprintf(buf, " <host name='%s'", src->host.name);
if (src->host.port)
virBufferAsprintf(buf, " port='%d'", src->host.port);
virBufferAddLit(buf, "/>\n");
if ((options->flags & VIR_STORAGE_POOL_SOURCE_HOST) && src->nhost) {
for (i = 0; i < src->nhost; i++) {
virBufferAsprintf(buf, " <host name='%s'", src->hosts[i].name);
if (src->hosts[i].port)
virBufferAsprintf(buf, " port='%d'", src->hosts[i].port);
virBufferAddLit(buf, "/>\n");
}
}
if ((options->flags & VIR_STORAGE_POOL_SOURCE_DEVICE) &&
@ -1678,7 +1701,8 @@ int virStoragePoolSourceFindDuplicate(virStoragePoolObjListPtr pools,
break;
case VIR_STORAGE_POOL_NETFS:
if ((STREQ(pool->def->source.dir, def->source.dir)) \
&& (STREQ(pool->def->source.host.name, def->source.host.name)))
&& (pool->def->source.nhost == 1 && def->source.nhost == 1) \
&& (STREQ(pool->def->source.hosts[0].name, def->source.hosts[0].name)))
matchpool = pool;
break;
case VIR_STORAGE_POOL_SCSI:
@ -1689,13 +1713,15 @@ int virStoragePoolSourceFindDuplicate(virStoragePoolObjListPtr pools,
{
matchpool = virStoragePoolSourceFindDuplicateDevices(pool, def);
if (matchpool) {
if (STREQ(matchpool->def->source.host.name, def->source.host.name)) {
if ((matchpool->def->source.initiator.iqn) && (def->source.initiator.iqn)) {
if (STREQ(matchpool->def->source.initiator.iqn, def->source.initiator.iqn))
break;
matchpool = NULL;
if (matchpool->def->source.nhost == 1 && def->source.nhost == 1) {
if (STREQ(matchpool->def->source.hosts[0].name, def->source.hosts[0].name)) {
if ((matchpool->def->source.initiator.iqn) && (def->source.initiator.iqn)) {
if (STREQ(matchpool->def->source.initiator.iqn, def->source.initiator.iqn))
break;
matchpool = NULL;
}
break;
}
break;
}
matchpool = NULL;
}

View File

@ -212,8 +212,9 @@ struct _virStoragePoolSourceDevice {
typedef struct _virStoragePoolSource virStoragePoolSource;
typedef virStoragePoolSource *virStoragePoolSourcePtr;
struct _virStoragePoolSource {
/* An optional host */
virStoragePoolSourceHost host;
/* An optional (maybe multiple) host(s) */
size_t nhost;
virStoragePoolSourceHostPtr hosts;
/* And either one or more devices ... */
int ndevice;

View File

@ -544,8 +544,12 @@ esxStoragePoolGetXMLDesc(virStoragePoolPtr pool, unsigned int flags)
if (esxVI_LocalDatastoreInfo_DynamicCast(info) != NULL) {
def.type = VIR_STORAGE_POOL_DIR;
} else if ((nasInfo = esxVI_NasDatastoreInfo_DynamicCast(info)) != NULL) {
if (VIR_ALLOC_N(def.source.hosts, 1) < 0) {
virReportOOMError();
goto cleanup;
}
def.type = VIR_STORAGE_POOL_NETFS;
def.source.host.name = nasInfo->nas->remoteHost;
def.source.hosts[0].name = nasInfo->nas->remoteHost;
def.source.dir = nasInfo->nas->remotePath;
if (STRCASEEQ(nasInfo->nas->type, "NFS")) {

View File

@ -206,7 +206,13 @@ virStorageBackendFileSystemNetFindPoolSourcesFunc(virStoragePoolObjPtr pool ATTR
if (!(src = virStoragePoolSourceListNewSource(&state->list)))
goto cleanup;
if (!(src->host.name = strdup(state->host)) ||
if (src->nhost != 1) {
virStorageReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Expected exactly 1 host for the storage pool"));
goto cleanup;
}
if (!(src->hosts[0].name = strdup(state->host)) ||
!(src->dir = strdup(path))) {
virReportOOMError();
goto cleanup;
@ -260,8 +266,14 @@ virStorageBackendFileSystemNetFindPoolSources(virConnectPtr conn ATTRIBUTE_UNUSE
if (!source)
goto cleanup;
state.host = source->host.name;
prog[3] = source->host.name;
if (source->nhost != 1) {
virStorageReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Expected exactly 1 host for the storage pool"));
goto cleanup;
}
state.host = source->hosts[0].name;
prog[3] = source->hosts[0].name;
if (virStorageBackendRunProgRegex(NULL, prog, 1, regexes, vars,
virStorageBackendFileSystemNetFindPoolSourcesFunc,
@ -387,7 +399,12 @@ virStorageBackendFileSystemMount(virStoragePoolObjPtr pool) {
int ret;
if (pool->def->type == VIR_STORAGE_POOL_NETFS) {
if (pool->def->source.host.name == NULL) {
if (pool->def->source.nhost != 1) {
virStorageReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Expected exactly 1 host for the storage pool"));
return -1;
}
if (pool->def->source.hosts[0].name == NULL) {
virStorageReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("missing source host"));
return -1;
@ -415,7 +432,7 @@ virStorageBackendFileSystemMount(virStoragePoolObjPtr pool) {
if (pool->def->type == VIR_STORAGE_POOL_NETFS) {
if (virAsprintf(&src, "%s:%s",
pool->def->source.host.name,
pool->def->source.hosts[0].name,
pool->def->source.dir) == -1) {
virReportOOMError();
return -1;
@ -452,7 +469,12 @@ virStorageBackendFileSystemUnmount(virStoragePoolObjPtr pool) {
int ret;
if (pool->def->type == VIR_STORAGE_POOL_NETFS) {
if (pool->def->source.host.name == NULL) {
if (pool->def->source.nhost != 1) {
virStorageReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Expected exactly 1 host for the storage pool"));
return -1;
}
if (pool->def->source.hosts[0].name == NULL) {
virStorageReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("missing source host"));
return -1;

View File

@ -96,13 +96,19 @@ virStorageBackendISCSIPortal(virStoragePoolSourcePtr source)
char ipaddr[NI_MAXHOST];
char *portal;
if (virStorageBackendISCSITargetIP(source->host.name,
if (source->nhost != 1) {
virStorageReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Expected exactly 1 host for the storage pool"));
return NULL;
}
if (virStorageBackendISCSITargetIP(source->hosts[0].name,
ipaddr, sizeof(ipaddr)) < 0)
return NULL;
if (virAsprintf(&portal, "%s:%d,1", ipaddr,
source->host.port ?
source->host.port : 3260) < 0) {
source->hosts[0].port ?
source->hosts[0].port : 3260) < 0) {
virReportOOMError();
return NULL;
}
@ -563,6 +569,12 @@ virStorageBackendISCSIFindPoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
list.type)))
return NULL;
if (source->nhost != 1) {
virStorageReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Expected exactly 1 host for the storage pool"));
goto cleanup;
}
if (!(portal = virStorageBackendISCSIPortal(source)))
goto cleanup;
@ -581,7 +593,7 @@ virStorageBackendISCSIFindPoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
virReportOOMError();
goto cleanup;
}
list.sources[i].host = source->host;
list.sources[i].host = source->hosts[0];
list.sources[i].initiator = source->initiator;
list.sources[i].ndevice = 1;
list.sources[i].devices[0].path = targets[i];
@ -617,7 +629,13 @@ virStorageBackendISCSICheckPool(virConnectPtr conn ATTRIBUTE_UNUSED,
*isActive = false;
if (pool->def->source.host.name == NULL) {
if (pool->def->source.nhost != 1) {
virStorageReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Expected exactly 1 host for the storage pool"));
return -1;
}
if (pool->def->source.hosts[0].name == NULL) {
virStorageReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("missing source host"));
return -1;
@ -649,7 +667,13 @@ virStorageBackendISCSIStartPool(virConnectPtr conn ATTRIBUTE_UNUSED,
int ret = -1;
const char *loginargv[] = { "--login", NULL };
if (pool->def->source.host.name == NULL) {
if (pool->def->source.nhost != 1) {
virStorageReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Expected exactly 1 host for the storage pool"));
return -1;
}
if (pool->def->source.hosts[0].name == NULL) {
virStorageReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("missing source host"));
return -1;

View File

@ -4053,14 +4053,14 @@ testStorageFindPoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
break;
case VIR_STORAGE_POOL_NETFS:
if (!source || !source->host.name) {
if (!source || !source->hosts[0].name) {
testError(VIR_ERR_INVALID_ARG,
"%s", "hostname must be specified for netfs sources");
goto cleanup;
}
if (virAsprintf(&ret, defaultPoolSourcesNetFSXML,
source->host.name) < 0)
source->hosts[0].name) < 0)
virReportOOMError();
break;