[Date Prev][Date Next] [Thread Prev][Thread Next]
[Thread Index]
[Date Index]
[Author Index]
[libvirt] [PATCH] storage pool discovery
- From: David Lively <dlively virtualiron com>
- To: libvir-list <libvir-list redhat com>
- Subject: [libvirt] [PATCH] storage pool discovery
- Date: Thu, 21 Aug 2008 10:29:43 -0400
Hi Folks -
Here's my second pass at storage pool discovery. I've taken Daniel's
suggestion and made it return a single XML doc containing <source>
elements rather than an array of <pool> docs (and also incorporated
suggestions from Daniel V and Jim M).
Note that the storage <source> <name> patch is closely related
(without it, the <source> docs returned for logical pools aren't
correct).
Dave
diff --git a/configure.in b/configure.in
index 0513a72..f29a0fa 100644
--- a/configure.in
+++ b/configure.in
@@ -660,6 +660,11 @@ if test "$with_storage_fs" = "yes" -o "$with_storage_fs" = "check"; then
fi
fi
AM_CONDITIONAL([WITH_STORAGE_FS], [test "$with_storage_fs" = "yes"])
+if test "$with_storage_fs" = "yes"; then
+ AC_PATH_PROG([SHOWMOUNT], [showmount], [], [$PATH:/sbin:/usr/sbin])
+ AC_DEFINE_UNQUOTED([SHOWMOUNT], ["$SHOWMOUNT"],
+ [Location or name of the showmount program])
+fi
AC_PATH_PROG([QEMU_IMG], [qemu-img], [], [$PATH:/sbin:/usr/sbin:/bin:/usr/bin])
if test -n "$QEMU_IMG" ; then
diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h
index 9c3e1c2..5308fa9 100644
--- a/include/libvirt/libvirt.h
+++ b/include/libvirt/libvirt.h
@@ -890,6 +890,14 @@ int virConnectListDefinedStoragePools(virConnectPtr conn,
int maxnames);
/*
+ * Query a host for storage pools of a particular type
+ */
+char * virConnectDiscoverStoragePools(virConnectPtr conn,
+ const char *type,
+ const char *srcSpec,
+ unsigned int flags);
+
+/*
* Lookup pool by name or uuid
*/
virStoragePoolPtr virStoragePoolLookupByName (virConnectPtr conn,
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index f077a26..3d06d76 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -890,6 +890,14 @@ int virConnectListDefinedStoragePools(virConnectPtr conn,
int maxnames);
/*
+ * Query a host for storage pools of a particular type
+ */
+char * virConnectDiscoverStoragePools(virConnectPtr conn,
+ const char *type,
+ const char *srcSpec,
+ unsigned int flags);
+
+/*
* Lookup pool by name or uuid
*/
virStoragePoolPtr virStoragePoolLookupByName (virConnectPtr conn,
diff --git a/qemud/remote.c b/qemud/remote.c
index b5a6ec9..43b3a56 100644
--- a/qemud/remote.c
+++ b/qemud/remote.c
@@ -2958,6 +2958,27 @@ remoteDispatchListStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED,
}
static int
+remoteDispatchDiscoverStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED,
+ struct qemud_client *client,
+ remote_message_header *req,
+ remote_discover_storage_pools_args *args,
+ remote_discover_storage_pools_ret *ret)
+{
+ CHECK_CONN(client);
+
+ ret->xml =
+ virConnectDiscoverStoragePools (client->conn,
+ args->type,
+ args->srcSpec ? *args->srcSpec : NULL,
+ args->flags);
+ if (ret->xml == NULL)
+ return -1;
+
+ return 0;
+}
+
+
+static int
remoteDispatchStoragePoolCreate (struct qemud_server *server ATTRIBUTE_UNUSED,
struct qemud_client *client,
remote_message_header *req,
diff --git a/qemud/remote_dispatch_localvars.h b/qemud/remote_dispatch_localvars.h
index d889c8a..6915d5a 100644
--- a/qemud/remote_dispatch_localvars.h
+++ b/qemud/remote_dispatch_localvars.h
@@ -137,6 +137,8 @@ remote_domain_attach_device_args lv_remote_domain_attach_device_args;
remote_num_of_networks_ret lv_remote_num_of_networks_ret;
remote_storage_pool_get_info_args lv_remote_storage_pool_get_info_args;
remote_storage_pool_get_info_ret lv_remote_storage_pool_get_info_ret;
+remote_discover_storage_pools_args lv_remote_discover_storage_pools_args;
+remote_discover_storage_pools_ret lv_remote_discover_storage_pools_ret;
remote_list_storage_pools_args lv_remote_list_storage_pools_args;
remote_list_storage_pools_ret lv_remote_list_storage_pools_ret;
remote_domain_restore_args lv_remote_domain_restore_args;
diff --git a/qemud/remote_dispatch_proc_switch.h b/qemud/remote_dispatch_proc_switch.h
index ebb2433..1850b92 100644
--- a/qemud/remote_dispatch_proc_switch.h
+++ b/qemud/remote_dispatch_proc_switch.h
@@ -41,6 +41,15 @@ case REMOTE_PROC_AUTH_SASL_STEP:
case REMOTE_PROC_CLOSE:
fn = (dispatch_fn) remoteDispatchClose;
break;
+case REMOTE_PROC_DISCOVER_STORAGE_POOLS:
+ fn = (dispatch_fn) remoteDispatchDiscoverStoragePools;
+ args_filter = (xdrproc_t) xdr_remote_discover_storage_pools_args;
+ args = (char *) &lv_remote_discover_storage_pools_args;
+ memset (&lv_remote_discover_storage_pools_args, 0, sizeof lv_remote_discover_storage_pools_args);
+ ret_filter = (xdrproc_t) xdr_remote_discover_storage_pools_ret;
+ ret = (char *) &lv_remote_discover_storage_pools_ret;
+ memset (&lv_remote_discover_storage_pools_ret, 0, sizeof lv_remote_discover_storage_pools_ret);
+ break;
case REMOTE_PROC_DOMAIN_ATTACH_DEVICE:
fn = (dispatch_fn) remoteDispatchDomainAttachDevice;
args_filter = (xdrproc_t) xdr_remote_domain_attach_device_args;
diff --git a/qemud/remote_dispatch_prototypes.h b/qemud/remote_dispatch_prototypes.h
index 1d9d794..134ec43 100644
--- a/qemud/remote_dispatch_prototypes.h
+++ b/qemud/remote_dispatch_prototypes.h
@@ -8,6 +8,7 @@ static int remoteDispatchAuthSaslInit (struct qemud_server *server, struct qemud
static int remoteDispatchAuthSaslStart (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_auth_sasl_start_args *args, remote_auth_sasl_start_ret *ret);
static int remoteDispatchAuthSaslStep (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_auth_sasl_step_args *args, remote_auth_sasl_step_ret *ret);
static int remoteDispatchClose (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, void *ret);
+static int remoteDispatchDiscoverStoragePools (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_discover_storage_pools_args *args, remote_discover_storage_pools_ret *ret);
static int remoteDispatchDomainAttachDevice (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_attach_device_args *args, void *ret);
static int remoteDispatchDomainBlockPeek (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_block_peek_args *args, remote_domain_block_peek_ret *ret);
static int remoteDispatchDomainBlockStats (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_block_stats_args *args, remote_domain_block_stats_ret *ret);
diff --git a/qemud/remote_protocol.c b/qemud/remote_protocol.c
index 1a8e68d..cce359f 100644
--- a/qemud/remote_protocol.c
+++ b/qemud/remote_protocol.c
@@ -1501,6 +1501,28 @@ xdr_remote_list_defined_storage_pools_ret (XDR *xdrs, remote_list_defined_storag
}
bool_t
+xdr_remote_discover_storage_pools_args (XDR *xdrs, remote_discover_storage_pools_args *objp)
+{
+
+ if (!xdr_remote_nonnull_string (xdrs, &objp->type))
+ return FALSE;
+ if (!xdr_remote_string (xdrs, &objp->srcSpec))
+ return FALSE;
+ if (!xdr_u_int (xdrs, &objp->flags))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_remote_discover_storage_pools_ret (XDR *xdrs, remote_discover_storage_pools_ret *objp)
+{
+
+ if (!xdr_remote_nonnull_string (xdrs, &objp->xml))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
xdr_remote_storage_pool_lookup_by_uuid_args (XDR *xdrs, remote_storage_pool_lookup_by_uuid_args *objp)
{
diff --git a/qemud/remote_protocol.h b/qemud/remote_protocol.h
index 1ad0c54..b632761 100644
--- a/qemud/remote_protocol.h
+++ b/qemud/remote_protocol.h
@@ -836,6 +836,18 @@ struct remote_list_defined_storage_pools_ret {
};
typedef struct remote_list_defined_storage_pools_ret remote_list_defined_storage_pools_ret;
+struct remote_discover_storage_pools_args {
+ remote_nonnull_string type;
+ remote_string srcSpec;
+ u_int flags;
+};
+typedef struct remote_discover_storage_pools_args remote_discover_storage_pools_args;
+
+struct remote_discover_storage_pools_ret {
+ remote_nonnull_string xml;
+};
+typedef struct remote_discover_storage_pools_ret remote_discover_storage_pools_ret;
+
struct remote_storage_pool_lookup_by_uuid_args {
remote_uuid uuid;
};
@@ -1336,6 +1348,8 @@ extern bool_t xdr_remote_list_storage_pools_ret (XDR *, remote_list_storage_poo
extern bool_t xdr_remote_num_of_defined_storage_pools_ret (XDR *, remote_num_of_defined_storage_pools_ret*);
extern bool_t xdr_remote_list_defined_storage_pools_args (XDR *, remote_list_defined_storage_pools_args*);
extern bool_t xdr_remote_list_defined_storage_pools_ret (XDR *, remote_list_defined_storage_pools_ret*);
+extern bool_t xdr_remote_discover_storage_pools_args (XDR *, remote_discover_storage_pools_args*);
+extern bool_t xdr_remote_discover_storage_pools_ret (XDR *, remote_discover_storage_pools_ret*);
extern bool_t xdr_remote_storage_pool_lookup_by_uuid_args (XDR *, remote_storage_pool_lookup_by_uuid_args*);
extern bool_t xdr_remote_storage_pool_lookup_by_uuid_ret (XDR *, remote_storage_pool_lookup_by_uuid_ret*);
extern bool_t xdr_remote_storage_pool_lookup_by_name_args (XDR *, remote_storage_pool_lookup_by_name_args*);
@@ -1515,6 +1529,8 @@ extern bool_t xdr_remote_list_storage_pools_ret ();
extern bool_t xdr_remote_num_of_defined_storage_pools_ret ();
extern bool_t xdr_remote_list_defined_storage_pools_args ();
extern bool_t xdr_remote_list_defined_storage_pools_ret ();
+extern bool_t xdr_remote_discover_storage_pools_args ();
+extern bool_t xdr_remote_discover_storage_pools_ret ();
extern bool_t xdr_remote_storage_pool_lookup_by_uuid_args ();
extern bool_t xdr_remote_storage_pool_lookup_by_uuid_ret ();
extern bool_t xdr_remote_storage_pool_lookup_by_name_args ();
diff --git a/qemud/remote_protocol.x b/qemud/remote_protocol.x
index 340203c..f8fffcc 100644
--- a/qemud/remote_protocol.x
+++ b/qemud/remote_protocol.x
@@ -762,6 +762,16 @@ struct remote_list_defined_storage_pools_ret {
remote_nonnull_string names<REMOTE_STORAGE_POOL_NAME_LIST_MAX>;
};
+struct remote_discover_storage_pools_args {
+ remote_nonnull_string type;
+ remote_string srcSpec;
+ unsigned flags;
+};
+
+struct remote_discover_storage_pools_ret {
+ remote_nonnull_string xml;
+};
+
struct remote_storage_pool_lookup_by_uuid_args {
remote_uuid uuid;
};
diff --git a/src/driver.h b/src/driver.h
index e060a38..04792a4 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -448,6 +448,11 @@ typedef int
(*virDrvConnectListDefinedStoragePools) (virConnectPtr conn,
char **const names,
int maxnames);
+typedef char *
+ (*virDrvConnectDiscoverStoragePools) (virConnectPtr conn,
+ const char *type,
+ const char *srcSpec,
+ unsigned int flags);
typedef virStoragePoolPtr
(*virDrvStoragePoolLookupByName) (virConnectPtr conn,
const char *name);
@@ -552,6 +557,7 @@ struct _virStorageDriver {
virDrvConnectListStoragePools listPools;
virDrvConnectNumOfDefinedStoragePools numOfDefinedPools;
virDrvConnectListDefinedStoragePools listDefinedPools;
+ virDrvConnectDiscoverStoragePools discoverPools;
virDrvStoragePoolLookupByName poolLookupByName;
virDrvStoragePoolLookupByUUID poolLookupByUUID;
virDrvStoragePoolLookupByVolume poolLookupByVolume;
diff --git a/src/internal.h b/src/internal.h
index 5120ed4..c2deea6 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -365,6 +365,14 @@ int __virDomainMigratePrepare (virConnectPtr dconn, char **cookie, int *cookiele
int __virDomainMigratePerform (virDomainPtr domain, const char *cookie, int cookielen, const char *uri, unsigned long flags, const char *dname, unsigned long bandwidth);
virDomainPtr __virDomainMigrateFinish (virConnectPtr dconn, const char *dname, const char *cookie, int cookielen, const char *uri, unsigned long flags);
+typedef struct _virStringList virStringList;
+
+struct _virStringList {
+ char *val;
+ int len;
+ struct _virStringList *next;
+};
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/src/libvirt.c b/src/libvirt.c
index 9cdec88..41500f4 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -3986,7 +3986,7 @@ virStoragePoolGetConnect (virStoragePoolPtr pool)
* Returns the number of pools found, or -1 on error
*/
int
-virConnectNumOfStoragePools (virConnectPtr conn)
+virConnectNumOfStoragePools (virConnectPtr conn)
{
DEBUG("conn=%p", conn);
@@ -4015,7 +4015,7 @@ virConnectNumOfStoragePools (virConnectPtr conn)
* Returns 0 on success, -1 on error
*/
int
-virConnectListStoragePools (virConnectPtr conn,
+virConnectListStoragePools (virConnectPtr conn,
char **const names,
int maxnames)
{
@@ -4104,6 +4104,50 @@ virConnectListDefinedStoragePools(virConnectPtr conn,
/**
+ * virConnectDiscoverStoragePools:
+ * @conn: pointer to hypervisor connection
+ * @type: type of storage pool sources to discover
+ * @srcSpec: XML document specifying discovery source
+ * @flags: flags for discovery (unused, pass 0)
+ *
+ * Talks to a storage backend and attempts to auto-discover the set of
+ * available storage pool sources. eg For iSCSI this would be a set of
+ * iSCSI targets. For NFS this would be a list of exported paths. The
+ * srcSpec (optional for some storage pool types, e.g. local ones) is
+ * an instance of the storage pool's source element specifying where
+ * to look for the pools.
+ *
+ * srcSpec is not required for some types (e.g., those querying
+ * local storage resources only)
+ *
+ * Returns an xml document consisting of a SourceList element
+ * containing a source document appropriate to the given pool
+ * type for each discovered source.
+ */
+char *
+virConnectDiscoverStoragePools(virConnectPtr conn,
+ const char *type,
+ const char *srcSpec,
+ unsigned int flags)
+{
+ if (!VIR_IS_CONNECT(conn)) {
+ virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+ return NULL;
+ }
+ if (type == NULL) {
+ virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return NULL;
+ }
+
+ if (conn->storageDriver && conn->storageDriver->discoverPools)
+ return conn->storageDriver->discoverPools (conn, type, srcSpec, flags);
+
+ virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+ return NULL;
+}
+
+
+/**
* virStoragePoolLookupByName:
* @conn: pointer to hypervisor connection
* @name: name of pool to fetch
diff --git a/src/remote_internal.c b/src/remote_internal.c
index e88c404..c678eeb 100644
--- a/src/remote_internal.c
+++ b/src/remote_internal.c
@@ -3044,6 +3044,47 @@ remoteListDefinedStoragePools (virConnectPtr conn,
return ret.names.names_len;
}
+static char *
+remoteDiscoverStoragePools (virConnectPtr conn,
+ const char *type,
+ const char *srcSpec,
+ unsigned int flags)
+{
+ remote_discover_storage_pools_args args;
+ remote_discover_storage_pools_ret ret;
+ GET_STORAGE_PRIVATE (conn, NULL);
+ const char *emptyString = "";
+ char *retval;
+
+ args.type = (char*)type;
+ /*
+ * I'd think the following would work here:
+ * args.srcSpec = (char**)&srcSpec;
+ * since srcSpec is a remote_string (not a remote_nonnull_string).
+ *
+ * But when srcSpec is NULL, this yields:
+ * libvir: Remote error : marshalling args
+ *
+ * So for now I'm working around this by turning NULL srcSpecs
+ * into empty strings.
+ */
+ args.srcSpec = srcSpec ? (char **)&srcSpec : (char **)&emptyString;
+ args.flags = flags;
+
+ memset (&ret, 0, sizeof ret);
+ if (call (conn, priv, 0, REMOTE_PROC_DISCOVER_STORAGE_POOLS,
+ (xdrproc_t) xdr_remote_discover_storage_pools_args, (char *) &args,
+ (xdrproc_t) xdr_remote_discover_storage_pools_ret, (char *) &ret) == -1)
+ return NULL;
+
+ retval = ret.xml;
+ ret.xml = NULL; /* To stop xdr_free free'ing it */
+
+ xdr_free ((xdrproc_t) xdr_remote_discover_storage_pools_ret, (char *) &ret);
+
+ return retval;
+}
+
static virStoragePoolPtr
remoteStoragePoolLookupByUUID (virConnectPtr conn,
const unsigned char *uuid)
@@ -4904,6 +4945,7 @@ static virStorageDriver storage_driver = {
.listPools = remoteListStoragePools,
.numOfDefinedPools = remoteNumOfDefinedStoragePools,
.listDefinedPools = remoteListDefinedStoragePools,
+ .discoverPools = remoteDiscoverStoragePools,
.poolLookupByUUID = remoteStoragePoolLookupByUUID,
.poolLookupByName = remoteStoragePoolLookupByName,
.poolLookupByVolume = remoteStoragePoolLookupByVolume,
diff --git a/src/storage_backend.h b/src/storage_backend.h
index 797ca01..c97ed48 100644
--- a/src/storage_backend.h
+++ b/src/storage_backend.h
@@ -63,6 +63,7 @@ struct _virStorageBackendPoolOptions {
virStoragePoolFormatFromString formatFromString;
};
+typedef char * (*virStorageBackendDiscoverPools)(virConnectPtr conn, const char *srcSpec, unsigned int flags);
typedef int (*virStorageBackendStartPool)(virConnectPtr conn, virStoragePoolObjPtr pool);
typedef int (*virStorageBackendBuildPool)(virConnectPtr conn, virStoragePoolObjPtr pool, unsigned int flags);
typedef int (*virStorageBackendRefreshPool)(virConnectPtr conn, virStoragePoolObjPtr pool);
@@ -80,6 +81,7 @@ typedef virStorageBackend *virStorageBackendPtr;
struct _virStorageBackend {
int type;
+ virStorageBackendDiscoverPools discoverPools;
virStorageBackendStartPool startPool;
virStorageBackendBuildPool buildPool;
virStorageBackendRefreshPool refreshPool;
diff --git a/src/storage_backend_fs.c b/src/storage_backend_fs.c
index 36bfac4..22acdbe 100644
--- a/src/storage_backend_fs.c
+++ b/src/storage_backend_fs.c
@@ -36,11 +36,16 @@
#include <mntent.h>
#include <string.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+
#include "internal.h"
#include "storage_backend_fs.h"
#include "storage_conf.h"
#include "util.h"
#include "memory.h"
+#include "xml.h"
enum {
VIR_STORAGE_POOL_FS_AUTO = 0,
@@ -442,6 +447,141 @@ static int virStorageBackendProbeFile(virConnectPtr conn,
}
#if WITH_STORAGE_FS
+struct _virNetfsDiscoverState {
+ const char *host;
+ virStringList *list;
+};
+
+typedef struct _virNetfsDiscoverState virNetfsDiscoverState;
+
+static int
+virStorageBackendFileSystemNetDiscoverPoolsFunc(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
+ char **const groups,
+ void *data)
+{
+ virNetfsDiscoverState *state = data;
+ virStringList *newItem;
+ const char *name, *path;
+
+ path = groups[0];
+
+ name = strrchr(path, '/');
+ if (name == NULL) {
+ virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("invalid netfs path (no slash): %s"), path);
+ return -1;
+ }
+ name += 1;
+
+ /* Append new XML desc to list */
+
+ if (VIR_ALLOC(newItem) != 0) {
+ virStorageReportError(conn, VIR_ERR_NO_MEMORY, "%s", _("new xml desc"));
+ return -1;
+ }
+
+ if (asprintf(&newItem->val,
+ "<source><host name='%s'/><dir path='%s'/></source>\n",
+ state->host, path) <= 0) {
+ virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("asprintf failed"));
+ VIR_FREE(newItem);
+ return -1;
+ }
+
+ newItem->len = strlen(newItem->val);
+ newItem->next = state->list;
+ state->list = newItem;
+
+ return 0;
+}
+
+static char *
+virStorageBackendFileSystemNetDiscoverPools(virConnectPtr conn,
+ const char *srcSpec,
+ unsigned int flags ATTRIBUTE_UNUSED)
+{
+ /*
+ * # showmount --no-headers -e HOSTNAME
+ * /tmp *
+ * /A dir demo1.foo.bar,demo2.foo.bar
+ *
+ * Extract directory name (including possible interior spaces ...).
+ */
+
+ const char *regexes[] = {
+ "^(/.*\\S) +\\S+$"
+ };
+ int vars[] = {
+ 1
+ };
+ xmlDocPtr doc = NULL;
+ xmlXPathContextPtr xpath_ctxt = NULL;
+ virNetfsDiscoverState state = { .host = NULL, .list = NULL };
+ const char *prog[] = { SHOWMOUNT, "--no-headers", "--exports", NULL, NULL };
+ const char *start_tag = "<SourceList>\n";
+ const char *end_tag = "</SourceList>\n";
+ int exitstatus, len;
+ virStringList *p;
+ char *retval = NULL;
+
+ doc = xmlReadDoc((const xmlChar *)srcSpec, "srcSpec.xml", NULL,
+ XML_PARSE_NOENT | XML_PARSE_NONET |
+ XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
+ if (doc == NULL) {
+ virStorageReportError(conn, VIR_ERR_XML_ERROR, "%s", _("bad <source> spec"));
+ goto cleanup;
+ }
+
+ xpath_ctxt = xmlXPathNewContext(doc);
+ if (xpath_ctxt == NULL) {
+ virStorageReportError(conn, VIR_ERR_NO_MEMORY, "%s", _("xpath_ctxt"));
+ goto cleanup;
+ }
+
+ state.host = virXPathString(conn, "string(/source/host/@name)", xpath_ctxt);
+ if (!state.host || !state.host[0]) {
+ virStorageReportError(conn, VIR_ERR_XML_ERROR, "%s",
+ _("missing <host> in <source> spec"));
+ goto cleanup;
+ }
+ prog[3] = state.host;
+
+ if (virStorageBackendRunProgRegex(conn, NULL, prog, 1, regexes, vars,
+ virStorageBackendFileSystemNetDiscoverPoolsFunc,
+ &state, &exitstatus) < 0)
+ goto cleanup;
+
+ /* Turn list of strings into final document */
+ len = strlen(start_tag) + strlen(end_tag);
+ for (p = state.list; p; p = p->next)
+ len += p->len;
+ if (VIR_ALLOC_N(retval, len+1) < 0) {
+ virStorageReportError(conn, VIR_ERR_NO_MEMORY, _("retval (%d bytes)"), len);
+ goto cleanup;
+ }
+ strcpy(retval, start_tag);
+ len = strlen(start_tag);
+ for (p = state.list; p; p = p->next) {
+ strcpy(retval + len, p->val);
+ len += p->len;
+ }
+ strcpy(retval + len, end_tag);
+
+ cleanup:
+ xmlFreeDoc(doc);
+ xmlXPathFreeContext(xpath_ctxt);
+ VIR_FREE(state.host);
+ while (state.list) {
+ p = state.list->next;
+ VIR_FREE(state.list);
+ state.list = p;
+ }
+
+ return retval;
+}
+
+
/**
* @conn connection to report errors against
* @pool storage pool to check for status
@@ -1114,6 +1254,7 @@ virStorageBackend virStorageBackendNetFileSystem = {
.buildPool = virStorageBackendFileSystemBuild,
.startPool = virStorageBackendFileSystemStart,
+ .discoverPools = virStorageBackendFileSystemNetDiscoverPools,
.refreshPool = virStorageBackendFileSystemRefresh,
.stopPool = virStorageBackendFileSystemStop,
.deletePool = virStorageBackendFileSystemDelete,
diff --git a/src/storage_backend_logical.c b/src/storage_backend_logical.c
index 0c4f6a5..890dcd2 100644
--- a/src/storage_backend_logical.c
+++ b/src/storage_backend_logical.c
@@ -259,6 +259,92 @@ virStorageBackendLogicalRefreshPoolFunc(virConnectPtr conn ATTRIBUTE_UNUSED,
static int
+virStorageBackendLogicalDiscoverPoolsFunc(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
+ char **const groups,
+ void *data)
+{
+ virStringList **rest = data;
+ virStringList *newItem;
+ const char *name = groups[0];
+
+ /* Append new XML desc to list */
+
+ if (VIR_ALLOC(newItem) != 0) {
+ virStorageReportError(conn, VIR_ERR_NO_MEMORY, "%s", _("new xml desc"));
+ return -1;
+ }
+
+ if (asprintf(&newItem->val, "<source><name>%s</name></source>\n", name) <= 0) {
+ virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("asprintf failed"));
+ VIR_FREE(newItem);
+ return -1;
+ }
+
+ newItem->len = strlen(newItem->val);
+ newItem->next = *rest;
+ *rest = newItem;
+
+ return 0;
+}
+
+static char *
+virStorageBackendLogicalDiscoverPools(virConnectPtr conn,
+ const char *srcSpec ATTRIBUTE_UNUSED,
+ unsigned int flags ATTRIBUTE_UNUSED)
+{
+ /*
+ * # sudo vgs --noheadings -o vg_name
+ * VolGroup00
+ * VolGroup01
+ */
+ const char *regexes[] = {
+ "^\\s*(\\S+)\\s*$"
+ };
+ int vars[] = {
+ 1
+ };
+ virStringList *descs = NULL;
+ const char *prog[] = { VGS, "--noheadings", "-o", "vg_name", NULL };
+ const char *start_tag = "<SourceList>\n";
+ const char *end_tag = "</SourceList>\n";
+ int exitstatus, len;
+ virStringList *p;
+ char *retval = NULL;
+
+ if (virStorageBackendRunProgRegex(conn, NULL, prog, 1, regexes, vars,
+ virStorageBackendLogicalDiscoverPoolsFunc,
+ &descs, &exitstatus) < 0)
+ return NULL;
+
+ /* Turn list of strings into final document */
+ len = strlen(start_tag) + strlen(end_tag);
+ for (p = descs; p; p = p->next)
+ len += p->len;
+ if (VIR_ALLOC_N(retval, len+1) < 0) {
+ virStorageReportError(conn, VIR_ERR_NO_MEMORY, _("retval (%d bytes)"), len);
+ goto cleanup;
+ }
+ strcpy(retval, start_tag);
+ len = strlen(start_tag);
+ for (p = descs; p; p = p->next) {
+ strcpy(retval + len, p->val);
+ len += p->len;
+ }
+ strcpy(retval + len, end_tag);
+
+ cleanup:
+ while (descs) {
+ p = descs->next;
+ VIR_FREE(descs);
+ descs = p;
+ }
+
+ return retval;
+}
+
+
+static int
virStorageBackendLogicalStartPool(virConnectPtr conn,
virStoragePoolObjPtr pool)
{
@@ -524,6 +610,7 @@ virStorageBackendLogicalDeleteVol(virConnectPtr conn,
virStorageBackend virStorageBackendLogical = {
.type = VIR_STORAGE_POOL_LOGICAL,
+ .discoverPools = virStorageBackendLogicalDiscoverPools,
.startPool = virStorageBackendLogicalStartPool,
.buildPool = virStorageBackendLogicalBuildPool,
.refreshPool = virStorageBackendLogicalRefreshPool,
diff --git a/src/storage_driver.c b/src/storage_driver.c
index 45f2635..642f9e1 100644
--- a/src/storage_driver.c
+++ b/src/storage_driver.c
@@ -386,6 +386,30 @@ storageListDefinedPools(virConnectPtr conn,
return -1;
}
+static char *
+storagePoolDiscover(virConnectPtr conn,
+ const char *type,
+ const char *srcSpec,
+ unsigned int flags)
+{
+ int backend_type;
+ virStorageBackendPtr backend;
+
+ backend_type = virStorageBackendFromString(type);
+ if (backend_type < 0)
+ return NULL;
+
+ backend = virStorageBackendForType(backend_type);
+ if (backend == NULL)
+ return NULL;
+
+ if (backend->discoverPools)
+ return backend->discoverPools(conn, srcSpec, flags);
+
+ return NULL;
+}
+
+
static virStoragePoolPtr
storagePoolCreate(virConnectPtr conn,
const char *xml,
@@ -1212,6 +1236,7 @@ static virStorageDriver storageDriver = {
storageListPools,
storageNumDefinedPools,
storageListDefinedPools,
+ storagePoolDiscover,
storagePoolLookupByName,
storagePoolLookupByUUID,
storagePoolLookupByVolume,
diff --git a/src/virsh.c b/src/virsh.c
index 67d9658..08fb425 100644
--- a/src/virsh.c
+++ b/src/virsh.c
@@ -3422,6 +3422,138 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
return TRUE;
}
+/*
+ * "pool-discover-as" command
+ */
+static vshCmdInfo info_pool_discover_as[] = {
+ {"syntax", "pool-discover-as <type> [options]"},
+ {"help", gettext_noop("discover pools")},
+ {"desc", gettext_noop("Returns discover of pools.")},
+ {NULL, NULL}
+};
+
+static vshCmdOptDef opts_pool_discover_as[] = {
+ {"type", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("type of storage pool to discover")},
+ {"host", VSH_OT_DATA, VSH_OFLAG_NONE, gettext_noop("optional host to query")},
+ {"port", VSH_OT_DATA, VSH_OFLAG_NONE, gettext_noop("optional port to query")},
+ {NULL, 0, 0, NULL}
+};
+
+static int
+cmdPoolDiscoverAs(vshControl * ctl, const vshCmd * cmd ATTRIBUTE_UNUSED)
+{
+ char *type, *host;
+ char *srcSpec = NULL;
+ char *srcList;
+ int found;
+
+ type = vshCommandOptString(cmd, "type", &found);
+ if (!found)
+ return FALSE;
+ host = vshCommandOptString(cmd, "host", &found);
+ if (!found)
+ host = NULL;
+
+ if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+ return FALSE;
+
+ if (host) {
+ int hostlen = strlen(host);
+ char *port = vshCommandOptString(cmd, "port", &found);
+ int ret;
+ if (!found) {
+ port = strrchr(host, ':');
+ if (port) {
+ if (*(++port))
+ hostlen = (int)(port - host - 1);
+ else
+ port = NULL;
+ }
+ }
+ ret = port ?
+ asprintf(&srcSpec,
+ "<source><host name='%.*s' port='%s'/></source>",
+ hostlen, host, port) :
+ asprintf(&srcSpec,
+ "<source><host name='%.*s'/></source>",
+ hostlen, host);
+ if (ret < 0) {
+ switch (errno) {
+ case ENOMEM:
+ vshError(ctl, FALSE, "%s", _("Out of memory"));
+ break;
+ default:
+ vshError(ctl, FALSE, _("asprintf failed (errno %d)"), errno);
+ }
+ return FALSE;
+ }
+ }
+
+ srcList = virConnectDiscoverStoragePools(ctl->conn, type, srcSpec, 0);
+ free(srcSpec);
+ if (srcList == NULL) {
+ vshError(ctl, FALSE, "%s", _("Failed to discover pools"));
+ return FALSE;
+ }
+ vshPrint(ctl, "%s", srcList);
+ free(srcList);
+
+ return TRUE;
+}
+
+
+/*
+ * "pool-discover" command
+ */
+static vshCmdInfo info_pool_discover[] = {
+ {"syntax", "pool-discover <type> [srcSpec]"},
+ {"help", gettext_noop("discover pools")},
+ {"desc", gettext_noop("Returns discover of pools.")},
+ {NULL, NULL}
+};
+
+static vshCmdOptDef opts_pool_discover[] = {
+ {"type", VSH_OT_DATA, VSH_OFLAG_REQ,
+ gettext_noop("type of storage pool to discover")},
+ {"srcSpec", VSH_OT_DATA, VSH_OFLAG_NONE,
+ gettext_noop("optional file of source xml to query for pools")},
+ {NULL, 0, 0, NULL}
+};
+
+static int
+cmdPoolDiscover(vshControl * ctl, const vshCmd * cmd ATTRIBUTE_UNUSED)
+{
+ char *type, *srcSpec, *srcSpecFile, *srcList;
+ int found;
+
+ type = vshCommandOptString(cmd, "type", &found);
+ if (!found)
+ return FALSE;
+ srcSpecFile = vshCommandOptString(cmd, "srcSpec", &found);
+ if (!found) {
+ srcSpecFile = NULL;
+ srcSpec = NULL;
+ }
+
+ if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+ return FALSE;
+
+ if (srcSpecFile && virFileReadAll(srcSpecFile, VIRSH_MAX_XML_FILE, &srcSpec) < 0)
+ return FALSE;
+
+ srcList = virConnectDiscoverStoragePools(ctl->conn, type, srcSpec, 0);
+ free(srcSpec);
+ if (srcList == NULL) {
+ vshError(ctl, FALSE, "%s", _("Failed to discover pools"));
+ return FALSE;
+ }
+ vshPrint(ctl, "%s", srcList);
+ free(srcList);
+
+ return TRUE;
+}
+
+
static double
prettyCapacity(unsigned long long val,
const char **unit) {
@@ -5388,6 +5520,8 @@ static const vshCmdDef commands[] = {
{"pool-define-as", cmdPoolDefineAs, opts_pool_define_as, info_pool_define_as},
{"pool-destroy", cmdPoolDestroy, opts_pool_destroy, info_pool_destroy},
{"pool-delete", cmdPoolDelete, opts_pool_delete, info_pool_delete},
+ {"pool-discover", cmdPoolDiscover, opts_pool_discover, info_pool_discover},
+ {"pool-discover-as", cmdPoolDiscoverAs, opts_pool_discover_as, info_pool_discover_as},
{"pool-dumpxml", cmdPoolDumpXML, opts_pool_dumpxml, info_pool_dumpxml},
{"pool-edit", cmdPoolEdit, opts_pool_edit, info_pool_edit},
{"pool-info", cmdPoolInfo, opts_pool_info, info_pool_info},
[Date Prev][Date Next] [Thread Prev][Thread Next]
[Thread Index]
[Date Index]
[Author Index]