diff --git a/configure.ac b/configure.ac index 7b9e38ae19..e68f5f63ae 100644 --- a/configure.ac +++ b/configure.ac @@ -1936,6 +1936,12 @@ if test "$with_storage_gluster" = "yes"; then fi AM_CONDITIONAL([WITH_STORAGE_GLUSTER], [test "$with_storage_gluster" = "yes"]) +if test "$with_storage_fs" = "yes" || + test "$with_storage_gluster" = "yes"; then + AC_PATH_PROG([GLUSTER_CLI], [gluster], [], [$PATH:/sbin:/usr/sbin]) + AC_DEFINE_UNQUOTED([GLUSTER_CLI], ["$GLUSTER_CLI"], + [Location or name of the gluster command line tool]) +fi LIBPARTED_CFLAGS= LIBPARTED_LIBS= diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c index adf0311166..1c299d6303 100644 --- a/src/storage/storage_backend.c +++ b/src/storage/storage_backend.c @@ -1636,3 +1636,92 @@ virStorageBackendStablePath(virStoragePoolObjPtr pool, return stablepath; } + +#ifdef GLUSTER_CLI +int +virStorageBackendFindGlusterPoolSources(const char *host, + int pooltype, + virStoragePoolSourceListPtr list) +{ + char *outbuf = NULL; + virCommandPtr cmd = NULL; + xmlDocPtr doc = NULL; + xmlXPathContextPtr ctxt = NULL; + xmlNodePtr *nodes = NULL; + virStoragePoolSource *src = NULL; + size_t i; + int nnodes; + int rc; + + int ret = -1; + + cmd = virCommandNewArgList(GLUSTER_CLI, + "--xml", + "--log-file=/dev/null", + "volume", "info", "all", NULL); + + virCommandAddArgFormat(cmd, "--remote-host=%s", host); + virCommandSetOutputBuffer(cmd, &outbuf); + + if (virCommandRun(cmd, &rc) < 0) + goto cleanup; + + if (rc != 0) { + VIR_INFO("failed to query host '%s' for gluster volumes: %s", + host, outbuf); + ret = 0; + goto cleanup; + } + + if (!(doc = virXMLParseStringCtxt(outbuf, _("(gluster_cli_output)"), + &ctxt))) + goto cleanup; + + if ((nnodes = virXPathNodeSet("//volumes/volume", ctxt, &nodes)) <= 0) { + VIR_INFO("no gluster volumes available on '%s'", host); + ret = 0; + goto cleanup; + } + + for (i = 0; i < nnodes; i++) { + ctxt->node = nodes[i]; + + if (!(src = virStoragePoolSourceListNewSource(list))) + goto cleanup; + + if (!(src->dir = virXPathString("string(//name)", ctxt))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to extract gluster volume name")); + goto cleanup; + } + + if (VIR_ALLOC_N(src->hosts, 1) < 0) + goto cleanup; + src->nhost = 1; + + if (VIR_STRDUP(src->hosts[0].name, host) < 0) + goto cleanup; + + src->format = pooltype; + } + + ret = 0; + + cleanup: + VIR_FREE(nodes); + xmlXPathFreeContext(ctxt); + xmlFreeDoc(doc); + VIR_FREE(outbuf); + virCommandFree(cmd); + return ret; +} +#else /* #ifdef GLUSTER_CLI */ +int +virStorageBackendFindGlusterPoolSources(const char *host ATTRIBUTE_UNUSED, + int pooltype ATTRIBUTE_UNUSED, + virStoragePoolSourceListPtr list ATTRIBUTE_UNUSED) +{ + VIR_INFO("gluster cli tool not installed"); + return 0; +} +#endif /* #ifdef GLUSTER_CLI */ diff --git a/src/storage/storage_backend.h b/src/storage/storage_backend.h index 9b8ef7fa35..c0d16685a6 100644 --- a/src/storage/storage_backend.h +++ b/src/storage/storage_backend.h @@ -87,6 +87,10 @@ int virStorageBackendFindFSImageTool(char **tool); virStorageBackendBuildVolFrom virStorageBackendFSImageToolTypeToFunc(int tool_type); +int virStorageBackendFindGlusterPoolSources(const char *host, + int pooltype, + virStoragePoolSourceListPtr list); + typedef struct _virStorageBackend virStorageBackend; typedef virStorageBackend *virStorageBackendPtr; diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c index 561581ea68..1c3665dcdd 100644 --- a/src/storage/storage_backend_fs.c +++ b/src/storage/storage_backend_fs.c @@ -316,6 +316,11 @@ virStorageBackendFileSystemNetFindPoolSources(virConnectPtr conn ATTRIBUTE_UNUSE virStorageBackendFileSystemNetFindNFSPoolSources(&state); + if (virStorageBackendFindGlusterPoolSources(state.host, + VIR_STORAGE_POOL_NETFS_GLUSTERFS, + &state.list) < 0) + goto cleanup; + if (!(ret = virStoragePoolSourceListFormat(&state.list))) goto cleanup;