Discussion:
[Libstoragemgmt-devel] [PATCH 0/8] Add new method: lsm.Client.pool_raid_info/lsm_pool_raid_info().
Gris Ge
2015-03-20 15:18:22 UTC
Permalink
* This patch set is based on:
[PATCH V2 0/6] New HP SmartArray Plugin.

* New method to query pool raid information like:
* RAID type.
* Member type(disk RAID group or sub-pool).
* Member IDs(disk ids or parent pool ids).

* This is preparation for coming HW RAID dedicate API volume_create_raid().
# I intend to make sure every changes made by any API is queryable.

* I am new for manipulating array of string in C, not sure this is a correct
way to do so in libstoragemgmt. Please kindly pay extra care when reviewing
C API codes. Thank you very much in advance.

Gris Ge (8):
New method: lsm.Client.pool_raid_info()/lsm_pool_raid_info()
lsmcli: Add new command pool-raid-info
Tests: Add test for lsm.Client.pool_raid_info() and
lsm_pool_raid_info().
Simulator Plugin: Add lsm.Client.pool_raid_info() support.
Simulator C plugin: Add lsm_pool_raid_info() support.
ONTAP Plugin: Add lsm.Client.pool_raid_info() support.
MegaRAID Plugin: Add lsm.Client.pool_raid_info() support.
HP Smart Array Plugin: Add lsm.Client.pool_raid_info() support.

c_binding/include/libstoragemgmt/libstoragemgmt.h | 30 +++++++
.../libstoragemgmt/libstoragemgmt_capabilities.h | 4 +-
.../libstoragemgmt/libstoragemgmt_plug_interface.h | 29 +++++++
.../include/libstoragemgmt/libstoragemgmt_types.h | 17 ++++
c_binding/lsm_mgmt.cpp | 56 +++++++++++++
c_binding/lsm_plugin_ipc.cpp | 48 ++++++++++-
doc/man/lsmcli.1.in | 9 ++
plugin/hpsa/hpsa.py | 39 +++++++++
plugin/megaraid/megaraid.py | 54 ++++++++++++
plugin/ontap/ontap.py | 21 +++++
plugin/sim/simarray.py | 98 +++++++---------------
plugin/sim/simulator.py | 3 +
plugin/simc/simc_lsmplugin.c | 24 +++++-
python_binding/lsm/_client.py | 85 +++++++++++++++++++
python_binding/lsm/_data.py | 6 ++
test/cmdtest.py | 20 +++++
test/plugin_test.py | 10 +++
test/tester.c | 32 +++++++
tools/lsmcli/cmdline.py | 19 ++++-
tools/lsmcli/data_display.py | 41 +++++++++
20 files changed, 575 insertions(+), 70 deletions(-)
--
1.8.3.1
Gris Ge
2015-03-20 15:18:23 UTC
Permalink
* Python part:
* New python method: lsm.Client.pool_raid_info(pool,flags)
Query the RAID information for certain volume.
Returns [raid_type, member_type, member_ids]
* For sub-pool which allocated space from other pool(like NetApp ONTAP
volume which allocate space from ONTAP aggregate), the member_type
will be lsm.Pool.MEMBER_TYPE_POOL.
* For disk RAID pool which use the whole disk as RAID member(like NetApp
ONTAP aggregate or EMC VNX pool) which the member_type will be
lsm.Pool.MEMBER_TYPE_DISK.

* New constants:
* lsm.Pool.MEMBER_TYPE_POOL
* lsm.Pool.MEMBER_TYPE_DISK
* lsm.Pool.MEMBER_TYPE_OTHER
* lsm.Pool.MEMBER_TYPE_UNKNOWN

* New capability for this new method:
* lsm.Capabilities.POOL_RAID_INFO

* C part:
* New C functions:
* lsm_pool_raid_info()
For API user.
* lsm_plug_pool_raid_info()
For plugin.

* New constants:
* LSM_POOL_MEMBER_TYPE_POOL
* LSM_POOL_MEMBER_TYPE_DISK
* LSM_POOL_MEMBER_TYPE_OTHER
* LSM_POOL_MEMBER_TYPE_UNKNOWN
* LSM_CAP_POOL_RAID_INFO

* For detail information, please refer to docstring of
lsm.Client.pool_raid_info() method in python_binding/lsm/_client.py file
and lsm_pool_raid_info() method in
c_binding/include/libstoragemgmt/libstoragemgmt.h.

Signed-off-by: Gris Ge <***@redhat.com>
---
c_binding/include/libstoragemgmt/libstoragemgmt.h | 30 ++++++++
.../libstoragemgmt/libstoragemgmt_capabilities.h | 4 +-
.../libstoragemgmt/libstoragemgmt_plug_interface.h | 29 ++++++++
.../include/libstoragemgmt/libstoragemgmt_types.h | 17 +++++
c_binding/lsm_mgmt.cpp | 56 ++++++++++++++
c_binding/lsm_plugin_ipc.cpp | 48 +++++++++++-
python_binding/lsm/_client.py | 85 ++++++++++++++++++++++
python_binding/lsm/_data.py | 6 ++
8 files changed, 273 insertions(+), 2 deletions(-)

diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt.h b/c_binding/include/libstoragemgmt/libstoragemgmt.h
index 6e03f78..26c9701 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt.h
@@ -864,6 +864,36 @@ int LSM_DLL_EXPORT lsm_volume_raid_info(
uint32_t *strip_size, uint32_t *disk_count,
uint32_t *min_io_size, uint32_t *opt_io_size, lsm_flag flags);

+/**
+ * Retrieves the RAID info of given pool. New in version 1.2.
+ * @param[in] c Valid connection
+ * @param[in] pool The lsm_pool ptr.
+ * @param[out] raid_type
+ * Enum of lsm_volume_raid_type.
+ * @param[out] member_type
+ * Enum of lsm_pool_member_type.
+ * @param[out] member_count
+ * Count of pool RAID members.
+ * @param[out] member_ids
+ * Array of string(char *).
+ * When 'member_type' is LSM_POOL_MEMBER_TYPE_POOL,
+ * the 'member_ids' will contain a list of parent Pool
+ * IDs.
+ * When 'member_type' is LSM_POOL_MEMBER_TYPE_DISK,
+ * the 'member_ids' will contain a list of disk IDs.
+ * When 'member_type' is LSM_POOL_MEMBER_TYPE_OTHER or
+ * LSM_POOL_MEMBER_TYPE_UNKNOWN, the member_ids should
+ * be NULL and member_count should be 0.
+ * This memory of this array is allocated by malloc,
+ * user should free this array of string by themselves.
+ * @param[in] flags Reserved, set to 0
+ * @return LSM_ERR_OK on success else error reason.
+ */
+int LSM_DLL_EXPORT lsm_pool_raid_info(
+ lsm_connect *c, lsm_pool *pool, lsm_volume_raid_type *raid_type,
+ lsm_pool_member_type *member_type, uint32_t *member_count,
+ char **member_ids[], lsm_flag flags);
+
#ifdef __cplusplus
}
#endif
diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt_capabilities.h b/c_binding/include/libstoragemgmt/libstoragemgmt_capabilities.h
index 18490f3..9e96035 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt_capabilities.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt_capabilities.h
@@ -113,7 +113,9 @@ typedef enum {
LSM_CAP_TARGET_PORTS = 216, /**< List target ports */
LSM_CAP_TARGET_PORTS_QUICK_SEARCH = 217, /**< Filtering occurs on array */

- LSM_CAP_DISKS = 220 /**< List disk drives */
+ LSM_CAP_DISKS = 220, /**< List disk drives */
+ LSM_CAP_POOL_RAID_INFO = 221,
+ /**^ Query pool RAID information */

} lsm_capability_type;

diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt_plug_interface.h b/c_binding/include/libstoragemgmt/libstoragemgmt_plug_interface.h
index b36586c..259b631 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt_plug_interface.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt_plug_interface.h
@@ -827,6 +827,34 @@ typedef int (*lsm_plug_volume_raid_info)(lsm_plugin_ptr c, lsm_volume *volume,
uint32_t *disk_count, uint32_t *min_io_size, uint32_t *opt_io_size,
lsm_flag flags);

+/**
+ * Retrieves the RAID info of given pool. New in version 1.2.
+ * @param[in] c Valid connection
+ * @param[in] pool The lsm_pool ptr.
+ * @param[out] raid_type
+ * Enum of lsm_volume_raid_type.
+ * @param[out] member_type
+ * Enum of lsm_pool_member_type.
+ * @param[out] member_count
+ * Count of pool RAID members.
+ * @param[out] member_ids
+ * Array of string(char *).
+ * When 'member_type' is LSM_POOL_MEMBER_TYPE_POOL,
+ * the 'member_ids' will contain a list of parent Pool
+ * IDs.
+ * When 'member_type' is LSM_POOL_MEMBER_TYPE_DISK,
+ * the 'member_ids' will contain a list of disk IDs.
+ * When 'member_type' is LSM_POOL_MEMBER_TYPE_OTHER or
+ * LSM_POOL_MEMBER_TYPE_UNKNOWN, the member_ids should
+ * be NULL and member_count should be 0.
+ * @param[in] flags Reserved, set to 0
+ * @return LSM_ERR_OK on success else error reason.
+ */
+typedef int (*lsm_plug_pool_raid_info)(
+ lsm_plugin_ptr c, lsm_pool *pool, lsm_volume_raid_type *raid_type,
+ lsm_pool_member_type *member_type, uint32_t *member_count,
+ char **member_ids[], lsm_flag flags);
+
/** \struct lsm_ops_v1_2
* \brief Functions added in version 1.2
* NOTE: This structure will change during the developement util version 1.2
@@ -835,6 +863,7 @@ typedef int (*lsm_plug_volume_raid_info)(lsm_plugin_ptr c, lsm_volume *volume,
struct lsm_ops_v1_2 {
lsm_plug_volume_raid_info vol_raid_info;
/**^ Query volume RAID information*/
+ lsm_plug_pool_raid_info pool_raid_info;
};

/**
diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt_types.h b/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
index c5607c1..115ec5a 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt_types.h
@@ -169,6 +169,23 @@ typedef enum {
/**^ Vendor specific RAID type */
} lsm_volume_raid_type;

+/**< \enum lsm_pool_member_type Different types of Pool member*/
+typedef enum {
+ LSM_POOL_MEMBER_TYPE_UNKNOWN = 0,
+ /**^ Plugin failed to detect the RAID member type. */
+ LSM_POOL_MEMBER_TYPE_OTHER = 1,
+ /**^ Vendor specific RAID member type. */
+ LSM_POOL_MEMBER_TYPE_DISK = 2,
+ /**^ Pool is created from RAID group using whole disks. */
+ LSM_POOL_MEMBER_TYPE_POOL = 3,
+ /**^
+ * Current pool(also known as sub-pool) is allocated from other
+ * pool(parent pool).
+ * The 'raid_type' will set to RAID_TYPE_OTHER unless certain RAID system
+ * support RAID using space of parent pools.
+ */
+} lsm_pool_member_type;
+
#define LSM_VOLUME_STRIP_SIZE_UNKNOWN 0
#define LSM_VOLUME_DISK_COUNT_UNKNOWN 0
#define LSM_VOLUME_MIN_IO_SIZE_UNKNOWN 0
diff --git a/c_binding/lsm_mgmt.cpp b/c_binding/lsm_mgmt.cpp
index e6a254f..3dc0755 100644
--- a/c_binding/lsm_mgmt.cpp
+++ b/c_binding/lsm_mgmt.cpp
@@ -802,6 +802,62 @@ int lsm_pool_list(lsm_connect *c, char *search_key, char *search_value,
return rc;
}

+int lsm_pool_raid_info(lsm_connect *c, lsm_pool *pool,
+ lsm_volume_raid_type * raid_type,
+ lsm_pool_member_type *member_type,
+ uint32_t *member_count, char **member_ids[],
+ lsm_flag flags)
+{
+ if( LSM_FLAG_UNUSED_CHECK(flags) ) {
+ return LSM_ERR_INVALID_ARGUMENT;
+ }
+
+ int rc = LSM_ERR_OK;
+ CONN_SETUP(c);
+
+ if( !LSM_IS_POOL(pool) ) {
+ return LSM_ERR_INVALID_ARGUMENT;
+ }
+
+ if( !raid_type || !member_type || !member_count || !member_ids) {
+ return LSM_ERR_INVALID_ARGUMENT;
+ }
+
+ std::map<std::string, Value> p;
+ p["pool"] = pool_to_value(pool);
+ p["flags"] = Value(flags);
+ Value parameters(p);
+ try {
+
+ Value response;
+
+ rc = rpc(c, "pool_raid_info", parameters, response);
+ if( LSM_ERR_OK == rc ) {
+ std::vector<Value> j = response.asArray();
+ *raid_type = (lsm_volume_raid_type) j[0].asInt32_t();
+ *member_type = (lsm_pool_member_type) j[1].asInt32_t();
+ if (Value::array_t == j[2].valueType()){
+ std::vector<Value> member_ids_value = j[2].asArray();
+ *member_count = member_ids_value.size();
+ if (*member_count){
+ uint32_t i;
+ *member_ids = (char **) malloc(
+ *member_count * sizeof(char *));
+ for(i = 0; i < *member_count; ++i ) {
+ (*member_ids)[i] = strdup(
+ member_ids_value[i].asString().c_str());
+ }
+ }
+ }
+ }
+ } catch( const ValueException &ve ) {
+ rc = logException(c, LSM_ERR_LIB_BUG, "Unexpected type",
+ ve.what());
+ }
+ return rc;
+
+}
+
int lsm_target_port_list(lsm_connect *c, const char *search_key,
const char *search_value,
lsm_target_port **target_ports[],
diff --git a/c_binding/lsm_plugin_ipc.cpp b/c_binding/lsm_plugin_ipc.cpp
index d2a43d4..1b608e6 100644
--- a/c_binding/lsm_plugin_ipc.cpp
+++ b/c_binding/lsm_plugin_ipc.cpp
@@ -1015,6 +1015,51 @@ static int handle_volume_raid_info(lsm_plugin_ptr p, Value &params,
return rc;
}

+static int handle_pool_raid_info(lsm_plugin_ptr p, Value &params,
+ Value &response)
+{
+ int rc = LSM_ERR_NO_SUPPORT;
+ if( p && p->ops_v1_2 && p->ops_v1_2->pool_raid_info) {
+ Value v_pool = params["pool"];
+
+ if(IS_CLASS_POOL(v_pool) &&
+ LSM_FLAG_EXPECTED_TYPE(params) ) {
+ lsm_pool *pool = value_to_pool(v_pool);
+ std::vector<Value> result;
+
+ if( pool ) {
+ lsm_volume_raid_type raid_type;
+ lsm_pool_member_type member_type;
+ uint32_t member_count;
+ char **member_ids;
+
+ rc = p->ops_v1_2->pool_raid_info(
+ p, pool, &raid_type, &member_type, &member_count,
+ &member_ids, LSM_FLAG_GET_VALUE(params));
+
+ if( LSM_ERR_OK == rc ) {
+ result.push_back(Value((int32_t)raid_type));
+ result.push_back(Value((int32_t)member_type));
+ std::vector<Value> v_member_ids;
+ for (uint32_t i = 0; i < member_count; i++){
+ v_member_ids.push_back(Value(member_ids[i]));
+ }
+ result.push_back(v_member_ids);
+ response = Value(result);
+ }
+
+ lsm_pool_record_free(pool);
+ } else {
+ rc = LSM_ERR_NO_MEMORY;
+ }
+
+ } else {
+ rc = LSM_ERR_TRANSPORT_INVALID_ARG;
+ }
+ }
+ return rc;
+}
+
static int ag_list(lsm_plugin_ptr p, Value &params, Value &response)
{
int rc = LSM_ERR_NO_SUPPORT;
@@ -2213,7 +2258,8 @@ static std::map<std::string,handler> dispatch = static_map<std::string,handler>
("volume_resize", handle_volume_resize)
("volumes_accessible_by_access_group", vol_accessible_by_ag)
("volumes", handle_volumes)
- ("volume_raid_info", handle_volume_raid_info);
+ ("volume_raid_info", handle_volume_raid_info)
+ ("pool_raid_info", handle_pool_raid_info);

static int process_request(lsm_plugin_ptr p, const std::string &method, Value &request,
Value &response)
diff --git a/python_binding/lsm/_client.py b/python_binding/lsm/_client.py
index a641b1d..1ed6e1e 100644
--- a/python_binding/lsm/_client.py
+++ b/python_binding/lsm/_client.py
@@ -1074,3 +1074,88 @@ def volume_raid_info(self, volume, flags=FLAG_RSVD):
No support.
"""
return self._tp.rpc('volume_raid_info', _del_self(locals()))
+
+ @_return_requires([int, int, [unicode]])
+ def pool_raid_info(self, pool, flags=FLAG_RSVD):
+ """Query the RAID information of certain pool.
+
+ New in version 1.2.
+
+ Query the RAID type, RAID member type, RAID member ids
+
+ This method requires this capability:
+ lsm.Capabilities.POOL_RAID_INFO
+
+ Args:
+ pool (lsm.Pool object): Pool to query
+ flags (int): Reserved for future use. Should be set as
+ lsm.Client.FLAG_RSVD
+ Returns:
+ [raid_type, member_type, member_ids]
+
+ raid_type (int): RAID Type of requested pool.
+ Could be one of these values:
+ Volume.RAID_TYPE_RAID0
+ Stripe
+ Volume.RAID_TYPE_RAID1
+ Two disks Mirror
+ Volume.RAID_TYPE_RAID3
+ Byte-level striping with dedicated parity
+ Volume.RAID_TYPE_RAID4
+ Block-level striping with dedicated parity
+ Volume.RAID_TYPE_RAID5
+ Block-level striping with distributed parity
+ Volume.RAID_TYPE_RAID6
+ Block-level striping with two distributed parities,
+ aka, RAID-DP
+ Volume.RAID_TYPE_RAID10
+ Stripe of mirrors
+ Volume.RAID_TYPE_RAID15
+ Parity of mirrors
+ Volume.RAID_TYPE_RAID16
+ Dual parity of mirrors
+ Volume.RAID_TYPE_RAID50
+ Stripe of parities Volume.RAID_TYPE_RAID60
+ Stripe of dual parities
+ Volume.RAID_TYPE_RAID51
+ Mirror of parities
+ Volume.RAID_TYPE_RAID61
+ Mirror of dual parities
+ Volume.RAID_TYPE_JBOD
+ Just bunch of disks, no parity, no striping.
+ Volume.RAID_TYPE_UNKNOWN
+ The plugin failed to detect the volume's RAID type.
+ Volume.RAID_TYPE_MIXED
+ This volume contains multiple RAID settings.
+ Volume.RAID_TYPE_OTHER
+ Vendor specific RAID type
+ member_type(int):
+ Could be one of these values:
+ Pool.MEMBER_TYPE_POOL
+ # Current pool(also known as sub-pool) is allocated
+ # from other pool(parent pool).
+ # The 'raid_type' will set to RAID_TYPE_OTHER
+ # unless certain RAID system support RAID using space
+ # of parent pools.
+ Pool.MEMBER_TYPE_DISK
+ # Pool is created from RAID group using whole disks.
+ Pool.MEMBER_TYPE_OTHER
+ # Vendor specific RAID member type.
+ Pool.MEMBER_TYPE_UNKNOWN
+ # Plugin failed to detect the RAID member type.
+ member_ids(list(string)):
+ When 'member_type' is Pool.MEMBER_TYPE_POOL,
+ the 'member_ids' will contain a list of parent Pool IDs.
+ When 'member_type' is Pool.MEMBER_TYPE_DISK,
+ the 'member_ids' will contain a list of disk IDs.
+ When 'member_type' is Pool.MEMBER_TYPE_OTHER or
+ Pool.MEMBER_TYPE_UNKNOWN, the member_ids should be an
+ empty list.
+ Raises:
+ LsmError:
+ ErrorNumber.NO_SUPPORT
+ No support.
+ ErrorNumber.NOT_FOUND_POOL
+ Pool not found.
+ """
+ return self._tp.rpc('pool_raid_info', _del_self(locals()))
diff --git a/python_binding/lsm/_data.py b/python_binding/lsm/_data.py
index 23681dd..2d60562 100644
--- a/python_binding/lsm/_data.py
+++ b/python_binding/lsm/_data.py
@@ -412,6 +412,11 @@ class Pool(IData):
STATUS_INITIALIZING = 1 << 14
STATUS_GROWING = 1 << 15

+ MEMBER_TYPE_UNKNOWN = 0
+ MEMBER_TYPE_OTHER = 1
+ MEMBER_TYPE_DISK = 2
+ MEMBER_TYPE_POOL = 3
+
def __init__(self, _id, _name, _element_type, _unsupported_actions,
_total_space, _free_space,
_status, _status_info, _system_id, _plugin_data=None):
@@ -754,6 +759,7 @@ class Capabilities(IData):
TARGET_PORTS_QUICK_SEARCH = 217

DISKS = 220
+ POOL_RAID_INFO = 221

def _to_dict(self):
return {'class': self.__class__.__name__,
--
1.8.3.1
Gris Ge
2015-03-20 15:18:24 UTC
Permalink
* New command 'pool-raid-info' to utilize lsm.Client.pool_raid_info() method.

* Manpage updated.

* New alias 'pri' for 'pool-raid-info' command.

Signed-off-by: Gris Ge <***@redhat.com>
---
doc/man/lsmcli.1.in | 9 +++++++++
tools/lsmcli/cmdline.py | 19 ++++++++++++++++++-
tools/lsmcli/data_display.py | 41 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 68 insertions(+), 1 deletion(-)

diff --git a/doc/man/lsmcli.1.in b/doc/man/lsmcli.1.in
index e2af14f..df82f5d 100644
--- a/doc/man/lsmcli.1.in
+++ b/doc/man/lsmcli.1.in
@@ -351,6 +351,13 @@ Query RAID information for given volume.
\fB--vol\fR \fI<VOL_ID>\fR
Required. The ID of volume to query.

+.SS pool-raid-info
+.TP 15
+Query RAID information for given pool.
+.TP
+\fB--pool\fR \fI<POOL_ID>\fR
+Required. The ID of pool to query.
+
.SS access-group-create
.TP 15
Create an access group.
@@ -589,6 +596,8 @@ Alias of 'volume-mask'
Alias of 'volume-unmask'
.SS vri
Alias of 'volume-raid-info'
+.SS pri
+Alias of 'pool-raid-info'
.SS ac
Alias of 'access-group-create'
.SS aa
diff --git a/tools/lsmcli/cmdline.py b/tools/lsmcli/cmdline.py
index 980b3a0..cd687df 100644
--- a/tools/lsmcli/cmdline.py
+++ b/tools/lsmcli/cmdline.py
@@ -39,7 +39,8 @@

from lsm.lsmcli.data_display import (
DisplayData, PlugData, out,
- vol_provision_str_to_type, vol_rep_type_str_to_type, VolumeRAIDInfo)
+ vol_provision_str_to_type, vol_rep_type_str_to_type, VolumeRAIDInfo,
+ PoolRAIDInfo)


## Wraps the invocation to the command line
@@ -376,6 +377,14 @@ def _get_item(l, the_id, friendly_name='item', raise_error=True):
),

dict(
+ name='pool-raid-info',
+ help='Query Pool RAID infomation',
+ args=[
+ dict(pool_id_opt),
+ ],
+ ),
+
+ dict(
name='access-group-create',
help='Create an access group',
args=[
@@ -637,6 +646,7 @@ def _get_item(l, the_id, friendly_name='item', raise_error=True):
['ar', 'access-group-remove'],
['ad', 'access-group-delete'],
['vri', 'volume-raid-info'],
+ ['pri', 'pool-raid-info'],
)


@@ -1334,6 +1344,13 @@ def volume_raid_info(self, args):
VolumeRAIDInfo(
lsm_vol.id, *self.c.volume_raid_info(lsm_vol))])

+ def pool_raid_info(self, args):
+ lsm_pool = _get_item(self.c.pools(), args.pool, "Pool")
+ self.display_data(
+ [
+ PoolRAIDInfo(
+ lsm_pool.id, *self.c.pool_raid_info(lsm_pool))])
+
## Displays file system dependants
def fs_dependants(self, args):
fs = _get_item(self.c.fs(), args.fs, "File System")
diff --git a/tools/lsmcli/data_display.py b/tools/lsmcli/data_display.py
index 19f7114..115f15a 100644
--- a/tools/lsmcli/data_display.py
+++ b/tools/lsmcli/data_display.py
@@ -279,6 +279,26 @@ def raid_type_to_str(raid_type):
return _enum_type_to_str(raid_type, VolumeRAIDInfo._RAID_TYPE_MAP)


+class PoolRAIDInfo(object):
+ _MEMBER_TYPE_MAP = {
+ Pool.MEMBER_TYPE_UNKNOWN: 'Unknown',
+ Pool.MEMBER_TYPE_OTHER: 'Unknown',
+ Pool.MEMBER_TYPE_POOL: 'Pool',
+ Pool.MEMBER_TYPE_DISK: 'Disk',
+ }
+
+ def __init__(self, pool_id, raid_type, member_type, member_ids):
+ self.pool_id = pool_id
+ self.raid_type = raid_type
+ self.member_type = member_type
+ self.member_ids = member_ids
+
+ @staticmethod
+ def member_type_to_str(member_type):
+ return _enum_type_to_str(
+ member_type, PoolRAIDInfo._MEMBER_TYPE_MAP)
+
+
class DisplayData(object):

def __init__(self):
@@ -557,6 +577,27 @@ def __init__(self):
'value_conv_human': VOL_RAID_INFO_VALUE_CONV_HUMAN,
}

+ POOL_RAID_INFO_HEADER = OrderedDict()
+ POOL_RAID_INFO_HEADER['pool_id'] = 'Pool ID'
+ POOL_RAID_INFO_HEADER['raid_type'] = 'RAID Type'
+ POOL_RAID_INFO_HEADER['member_type'] = 'Member Type'
+ POOL_RAID_INFO_HEADER['member_ids'] = 'Member IDs'
+
+ POOL_RAID_INFO_COLUMN_SKIP_KEYS = []
+
+ POOL_RAID_INFO_VALUE_CONV_ENUM = {
+ 'raid_type': VolumeRAIDInfo.raid_type_to_str,
+ 'member_type': PoolRAIDInfo.member_type_to_str,
+ }
+ POOL_RAID_INFO_VALUE_CONV_HUMAN = []
+
+ VALUE_CONVERT[PoolRAIDInfo] = {
+ 'headers': POOL_RAID_INFO_HEADER,
+ 'column_skip_keys': POOL_RAID_INFO_COLUMN_SKIP_KEYS,
+ 'value_conv_enum': POOL_RAID_INFO_VALUE_CONV_ENUM,
+ 'value_conv_human': POOL_RAID_INFO_VALUE_CONV_HUMAN,
+ }
+
@staticmethod
def _get_man_pro_value(obj, key, value_conv_enum, value_conv_human,
flag_human, flag_enum):
--
1.8.3.1
Gris Ge
2015-03-20 15:18:26 UTC
Permalink
* Add lsm.Client.pool_raid_info() support.

* Use lsm.Pool.MEMBER_TYPE_XXX to replace PoolRAID.MEMBER_TYPE_XXX.

* Removed unused disk_type_to_member_type() and member_type_is_disk()
methods.

* Data version bumped to 3.2.

Signed-off-by: Gris Ge <***@redhat.com>
---
plugin/sim/simarray.py | 98 ++++++++++++++++---------------------------------
plugin/sim/simulator.py | 3 ++
2 files changed, 35 insertions(+), 66 deletions(-)

diff --git a/plugin/sim/simarray.py b/plugin/sim/simarray.py
index ae14848..b03a146 100644
--- a/plugin/sim/simarray.py
+++ b/plugin/sim/simarray.py
@@ -67,54 +67,6 @@ def _random_vpd():


class PoolRAID(object):
- MEMBER_TYPE_UNKNOWN = 0
- MEMBER_TYPE_DISK = 1
- MEMBER_TYPE_DISK_MIX = 10
- MEMBER_TYPE_DISK_ATA = 11
- MEMBER_TYPE_DISK_SATA = 12
- MEMBER_TYPE_DISK_SAS = 13
- MEMBER_TYPE_DISK_FC = 14
- MEMBER_TYPE_DISK_SOP = 15
- MEMBER_TYPE_DISK_SCSI = 16
- MEMBER_TYPE_DISK_NL_SAS = 17
- MEMBER_TYPE_DISK_HDD = 18
- MEMBER_TYPE_DISK_SSD = 19
- MEMBER_TYPE_DISK_HYBRID = 110
- MEMBER_TYPE_DISK_LUN = 111
-
- MEMBER_TYPE_POOL = 2
-
- _MEMBER_TYPE_2_DISK_TYPE = {
- MEMBER_TYPE_DISK: Disk.TYPE_UNKNOWN,
- MEMBER_TYPE_DISK_MIX: Disk.TYPE_UNKNOWN,
- MEMBER_TYPE_DISK_ATA: Disk.TYPE_ATA,
- MEMBER_TYPE_DISK_SATA: Disk.TYPE_SATA,
- MEMBER_TYPE_DISK_SAS: Disk.TYPE_SAS,
- MEMBER_TYPE_DISK_FC: Disk.TYPE_FC,
- MEMBER_TYPE_DISK_SOP: Disk.TYPE_SOP,
- MEMBER_TYPE_DISK_SCSI: Disk.TYPE_SCSI,
- MEMBER_TYPE_DISK_NL_SAS: Disk.TYPE_NL_SAS,
- MEMBER_TYPE_DISK_HDD: Disk.TYPE_HDD,
- MEMBER_TYPE_DISK_SSD: Disk.TYPE_SSD,
- MEMBER_TYPE_DISK_HYBRID: Disk.TYPE_HYBRID,
- MEMBER_TYPE_DISK_LUN: Disk.TYPE_LUN,
- }
-
- @staticmethod
- def member_type_is_disk(member_type):
- """
- Returns True if defined 'member_type' is disk.
- False when else.
- """
- return member_type in PoolRAID._MEMBER_TYPE_2_DISK_TYPE
-
- @staticmethod
- def disk_type_to_member_type(disk_type):
- for m_type, d_type in PoolRAID._MEMBER_TYPE_2_DISK_TYPE.items():
- if disk_type == d_type:
- return m_type
- return PoolRAID.MEMBER_TYPE_UNKNOWN
-
_RAID_DISK_CHK = {
Volume.RAID_TYPE_JBOD: lambda x: x > 0,
Volume.RAID_TYPE_RAID0: lambda x: x > 0,
@@ -171,7 +123,7 @@ def data_disk_count(raid_type, disk_count):


class BackStore(object):
- VERSION = "3.1"
+ VERSION = "3.2"
VERSION_SIGNATURE = 'LSM_SIMULATOR_DATA_%s_%s' % (VERSION, md5(VERSION))
JOB_DEFAULT_DURATION = 1
JOB_DATA_TYPE_VOL = 1
@@ -916,6 +868,12 @@ def sim_syss(self):
"""
return self._get_table('systems', BackStore.SYS_KEY_LIST)

+ def sim_disk_ids_of_pool(self, sim_pool_id):
+ return list(
+ d['id']
+ for d in self._data_find(
+ 'disks', 'owner_pool_id="%s"' % sim_pool_id, ['id']))
+
def sim_disks(self):
"""
Return a list of sim_disk dict.
@@ -935,20 +893,6 @@ def sim_pool_of_id(self, sim_pool_id):

def sim_pool_create_from_disk(self, name, sim_disk_ids, raid_type,
element_type, unsupported_actions=0):
- # Detect disk type
- disk_type = None
- for sim_disk in self.sim_disks():
- if sim_disk['id'] not in sim_disk_ids:
- continue
- if disk_type is None:
- disk_type = sim_disk['disk_type']
- elif disk_type != sim_disk['disk_type']:
- disk_type = None
- break
- member_type = PoolRAID.MEMBER_TYPE_DISK
- if disk_type is not None:
- member_type = PoolRAID.disk_type_to_member_type(disk_type)
-
self._data_add(
'pools',
{
@@ -958,7 +902,7 @@ def sim_pool_create_from_disk(self, name, sim_disk_ids, raid_type,
'element_type': element_type,
'unsupported_actions': unsupported_actions,
'raid_type': raid_type,
- 'member_type': member_type,
+ 'member_type': Pool.MEMBER_TYPE_DISK,
})

data_disk_count = PoolRAID.data_disk_count(
@@ -991,7 +935,7 @@ def sim_pool_create_sub_pool(self, name, parent_pool_id, size,
'element_type': element_type,
'unsupported_actions': unsupported_actions,
'raid_type': Volume.RAID_TYPE_OTHER,
- 'member_type': PoolRAID.MEMBER_TYPE_POOL,
+ 'member_type': Pool.MEMBER_TYPE_POOL,
'parent_pool_id': parent_pool_id,
'total_space': size,
})
@@ -2240,7 +2184,7 @@ def volume_raid_info(self, lsm_vol):
opt_io_size = Volume.OPT_IO_SIZE_UNKNOWN
disk_count = Volume.DISK_COUNT_UNKNOWN

- if sim_pool['member_type'] == PoolRAID.MEMBER_TYPE_POOL:
+ if sim_pool['member_type'] == Pool.MEMBER_TYPE_POOL:
parent_sim_pool = self.bs_obj.sim_pool_of_id(
sim_pool['parent_pool_id'])
raid_type = parent_sim_pool['raid_type']
@@ -2278,3 +2222,25 @@ def volume_raid_info(self, lsm_vol):
opt_io_size = int(data_disk_count * BackStore.STRIP_SIZE)

return [raid_type, strip_size, disk_count, min_io_size, opt_io_size]
+
+ @_handle_errors
+ def pool_raid_info(self, lsm_pool):
+ sim_pool = self.bs_obj.sim_pool_of_id(
+ SimArray._lsm_id_to_sim_id(
+ lsm_pool.id,
+ LsmError(ErrorNumber.NOT_FOUND_POOL, "Pool not found")))
+ member_type = sim_pool['member_type']
+ member_ids = []
+ if member_type == Pool.MEMBER_TYPE_POOL:
+ member_ids = [
+ SimArray._sim_id_to_lsm_id(
+ sim_pool['parent_pool_id'], 'POOL')]
+ elif member_type == Pool.MEMBER_TYPE_DISK:
+ member_ids = list(
+ SimArray._sim_id_to_lsm_id(sim_disk_id, 'DISK')
+ for sim_disk_id in self.bs_obj.sim_disk_ids_of_pool(
+ sim_pool['id']))
+ else:
+ member_type = Pool.MEMBER_TYPE_UNKNOWN
+
+ return sim_pool['raid_type'], member_type, member_ids
diff --git a/plugin/sim/simulator.py b/plugin/sim/simulator.py
index d562cd6..4638778 100644
--- a/plugin/sim/simulator.py
+++ b/plugin/sim/simulator.py
@@ -292,3 +292,6 @@ def target_ports(self, search_key=None, search_value=None, flags=0):

def volume_raid_info(self, volume, flags=0):
return self.sim_array.volume_raid_info(volume)
+
+ def pool_raid_info(self, pool, flags=0):
+ return self.sim_array.pool_raid_info(pool)
--
1.8.3.1
Gris Ge
2015-03-20 15:18:27 UTC
Permalink
* Add simply lsm_pool_raid_info() by return unknown data.

* Set LSM_CAP_POOL_RAID_INFO.

Signed-off-by: Gris Ge <***@redhat.com>
---
plugin/simc/simc_lsmplugin.c | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/plugin/simc/simc_lsmplugin.c b/plugin/simc/simc_lsmplugin.c
index 422a064..aebcd4b 100644
--- a/plugin/simc/simc_lsmplugin.c
+++ b/plugin/simc/simc_lsmplugin.c
@@ -392,6 +392,7 @@ static int cap(lsm_plugin_ptr c, lsm_system *system,
LSM_CAP_EXPORT_FS,
LSM_CAP_EXPORT_REMOVE,
LSM_CAP_VOLUME_RAID_INFO,
+ LSM_CAP_POOL_RAID_INFO,
-1
);

@@ -980,8 +981,29 @@ static int volume_raid_info(lsm_plugin_ptr c, lsm_volume *volume,
return rc;
}

+static int pool_raid_info(
+ lsm_plugin_ptr c, lsm_pool *pool,
+ lsm_volume_raid_type *raid_type, lsm_pool_member_type *member_type,
+ uint32_t *member_count, char **member_ids[], lsm_flag flags)
+{
+ int rc = LSM_ERR_OK;
+ struct plugin_data *pd = (struct plugin_data*)lsm_private_data_get(c);
+ lsm_pool *p = find_pool(pd, lsm_pool_id_get(pool));
+
+ if( !p) {
+ rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_POOL,
+ "Pool not found!");
+ }
+
+ *raid_type = LSM_VOLUME_RAID_TYPE_UNKNOWN;
+ *member_type = LSM_POOL_MEMBER_TYPE_UNKNOWN;
+ *member_count = 0;
+ return rc;
+}
+
static struct lsm_ops_v1_2 ops_v1_2 = {
- volume_raid_info
+ volume_raid_info,
+ pool_raid_info,
};

static int volume_enable_disable(lsm_plugin_ptr c, lsm_volume *v,
--
1.8.3.1
Gris Ge
2015-03-20 15:18:25 UTC
Permalink
* cmdtest.py: Test lsmcli 'pool-raid-info' command.
* plugin_test.py: Capability based python API test.
* tester.c: C API test for both simulator plugin and simulator C plugin.

Signed-off-by: Gris Ge <***@redhat.com>
---
test/cmdtest.py | 20 ++++++++++++++++++++
test/plugin_test.py | 10 ++++++++++
test/tester.c | 32 ++++++++++++++++++++++++++++++++
3 files changed, 62 insertions(+)

diff --git a/test/cmdtest.py b/test/cmdtest.py
index e80e027..97c5b88 100755
--- a/test/cmdtest.py
+++ b/test/cmdtest.py
@@ -696,6 +696,24 @@ def volume_raid_info_test(cap, system_id):
exit(10)
return

+def pool_raid_info_test(cap, system_id):
+ if cap['POOL_RAID_INFO']:
+ out = call([cmd, '-t' + sep, 'list', '--type', 'POOLS'])[1]
+ pool_list = parse(out)
+ for pool in pool_list:
+ out = call(
+ [cmd, '-t' + sep, 'pool-raid-info', '--pool', pool[0]])[1]
+ r = parse(out)
+ if len(r[0]) != 4:
+ print "pool-raid-info got expected output: %s" % out
+ exit(10)
+ if r[0][0] != pool[0]:
+ print "pool-raid-info output pool ID is not requested " \
+ "pool ID %s" % out
+ exit(10)
+ return
+
+
def run_all_tests(cap, system_id):
test_display(cap, system_id)
test_plugin_list(cap, system_id)
@@ -709,6 +727,8 @@ def run_all_tests(cap, system_id):

volume_raid_info_test(cap, system_id)

+ pool_raid_info_test(cap,system_id)
+
if __name__ == "__main__":
parser = OptionParser()
parser.add_option("-c", "--command", action="store", type="string",
diff --git a/test/plugin_test.py b/test/plugin_test.py
index 69a45b7..895bec3 100755
--- a/test/plugin_test.py
+++ b/test/plugin_test.py
@@ -1283,6 +1283,16 @@ def test_create_delete_exports(self):
self.c.export_remove(exp)
self._fs_delete(fs)

+ def test_pool_raid_info(self):
+ for s in self.systems:
+ cap = self.c.capabilities(s)
+ if supported(cap, [Cap.POOL_RAID_INFO]):
+ for pool in self.c.pools():
+ (raid_type, member_type, member_ids) = \
+ self.c.pool_raid_info(pool)
+ self.assertTrue(type(raid_type) is int)
+ self.assertTrue(type(member_type) is int)
+ self.assertTrue(type(member_ids) is list)

def dump_results():
"""
diff --git a/test/tester.c b/test/tester.c
index 1622a75..9301804 100644
--- a/test/tester.c
+++ b/test/tester.c
@@ -2887,6 +2887,37 @@ START_TEST(test_volume_raid_info)
}
END_TEST

+START_TEST(test_pool_raid_info)
+{
+ int rc;
+ lsm_pool **pools = NULL;
+ uint32_t poolCount = 0;
+ printf("querying pools\n");
+ G(rc, lsm_pool_list, c, NULL, NULL, &pools, &poolCount,
+ LSM_CLIENT_FLAG_RSVD);
+ printf("got pools\n");
+
+ lsm_volume_raid_type raid_type;
+ lsm_pool_member_type member_type;
+ uint32_t member_count;
+ char **member_ids = NULL;
+
+ int i;
+ int y;
+ for (i = 0; i < poolCount; i++) {
+ printf("Pool: %s\n", lsm_pool_id_get(pools[i]));
+ G(
+ rc, lsm_pool_raid_info, c, pools[i], &raid_type, &member_type,
+ &member_count, &member_ids, LSM_CLIENT_FLAG_RSVD);
+ for(y = 0; y < member_count; y++){
+ free(member_ids[y]);
+ }
+ free(member_ids);
+ G(rc, lsm_pool_record_free, pools[i]);
+ }
+}
+END_TEST
+
Suite * lsm_suite(void)
{
Suite *s = suite_create("libStorageMgmt");
@@ -2923,6 +2954,7 @@ Suite * lsm_suite(void)
tcase_add_test(basic, test_nfs_exports);
tcase_add_test(basic, test_invalid_input);
tcase_add_test(basic, test_volume_raid_info);
+ tcase_add_test(basic, test_pool_raid_info);

suite_add_tcase(s, basic);
return s;
--
1.8.3.1
Gris Ge
2015-03-20 15:18:28 UTC
Permalink
* Add lsm.Client.pool_raid_info() support:
* Treat NetApp ONTAP aggregate as disk RAID group.
Use na_disk['aggregate'] property to determine disk ownership.
* Treat NetApp ONTAP volume as sub-pool.
Use na_vol['containing-aggregate'] property to determine sub-pool
ownership.

* Set lsm.Capabilities.POOL_RAID_INFO.

Signed-off-by: Gris Ge <***@redhat.com>
---
plugin/ontap/ontap.py | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)

diff --git a/plugin/ontap/ontap.py b/plugin/ontap/ontap.py
index f9f1f56..c3fe2e2 100644
--- a/plugin/ontap/ontap.py
+++ b/plugin/ontap/ontap.py
@@ -545,6 +545,7 @@ def capabilities(self, system, flags=0):
cap.set(Capabilities.TARGET_PORTS)
cap.set(Capabilities.DISKS)
cap.set(Capabilities.VOLUME_RAID_INFO)
+ cap.set(Capabilities.POOL_RAID_INFO)
return cap

@handle_ontap_errors
@@ -1330,3 +1331,23 @@ def volume_raid_info(self, volume, flags=0):
return [
raid_type, Ontap._STRIP_SIZE, disk_count, Ontap._STRIP_SIZE,
Ontap._OPT_IO_SIZE]
+
+ @handle_ontap_errors
+ def pool_raid_info(self, pool, flags=0):
+ if pool.element_type & Pool.ELEMENT_TYPE_VOLUME:
+ # We got a NetApp volume
+ raid_type = Volume.RAID_TYPE_OTHER
+ member_type = Pool.MEMBER_TYPE_POOL
+ na_vol = self.f.volumes(volume_name=pool.name)[0]
+ disk_ids = [na_vol['containing-aggregate']]
+ else:
+ # We got a NetApp aggregate
+ member_type = Pool.MEMBER_TYPE_DISK
+ na_aggr = self.f.aggregates(aggr_name=pool.name)[0]
+ raid_type = Ontap._raid_type_of_na_aggr(na_aggr)
+ disk_ids = list(
+ Ontap._disk_id(d)
+ for d in self.f.disks()
+ if 'aggregate' in d and d['aggregate'] == pool.name)
+
+ return raid_type, member_type, disk_ids
--
1.8.3.1
Gris Ge
2015-03-20 15:18:29 UTC
Permalink
* Add lsm.Client.pool_raid_info() support:
* Use command 'storcli /c0/d0 show all J'.
* Use 'DG Drive LIST' section of output for disk_ids.
* Use 'TOPOLOGY' section of output for raid_type.
Since the command used here is not sharing the same data layout with
command "storcli /c0/v0 show all J" which is used by 'volume_raid_info()'
method, we now have two set of codes for detecting RAID type.

* Set lsm.Capabilities.POOL_RAID_INFO.

Signed-off-by: Gris Ge <***@redhat.com>
---
plugin/megaraid/megaraid.py | 54 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)

diff --git a/plugin/megaraid/megaraid.py b/plugin/megaraid/megaraid.py
index 78603fc..ff861b3 100644
--- a/plugin/megaraid/megaraid.py
+++ b/plugin/megaraid/megaraid.py
@@ -259,6 +259,7 @@ def capabilities(self, system, flags=Client.FLAG_RSVD):
cap.set(Capabilities.DISKS)
cap.set(Capabilities.VOLUMES)
cap.set(Capabilities.VOLUME_RAID_INFO)
+ cap.set(Capabilities.POOL_RAID_INFO)
return cap

def _storcli_exec(self, storcli_cmds, flag_json=True):
@@ -546,3 +547,56 @@ def volume_raid_info(self, volume, flags=Client.FLAG_RSVD):
return [
raid_type, strip_size, disk_count, strip_size,
strip_size * strip_count]
+
+ @_handle_errors
+ def pool_raid_info(self, pool, flags=Client.FLAG_RSVD):
+ lsi_dg_path = pool.plugin_data
+ # Check whether pool exists.
+ try:
+ dg_show_all_output = self._storcli_exec(
+ [lsi_dg_path , "show", "all"])
+ except ExecError as exec_error:
+ try:
+ json_output = json.loads(exec_error.stdout)
+ detail_error = json_output[
+ 'Controllers'][0]['Command Status']['Detailed Status']
+ except Exception:
+ raise exec_error
+
+ if detail_error and detail_error[0]['Status'] == 'Not found':
+ raise LsmError(
+ ErrorNumber.NOT_FOUND_POOL,
+ "Pool not found")
+ raise
+
+ ctrl_num = lsi_dg_path.split('/')[1][1:]
+ lsm_disk_map = {}
+ disk_ids = []
+ for lsm_disk in self.disks():
+ lsm_disk_map[lsm_disk.plugin_data] = lsm_disk.id
+
+ for dg_disk_info in dg_show_all_output['DG Drive LIST']:
+ cur_lsi_disk_path = "/c%s" % ctrl_num + "/e%s/s%s" % tuple(
+ dg_disk_info['EID:Slt'].split(':'))
+ if cur_lsi_disk_path in lsm_disk_map.keys():
+ disk_ids.append(lsm_disk_map[cur_lsi_disk_path])
+ else:
+ raise LsmError(
+ ErrorNumber.PLUGIN_BUG,
+ "pool_raid_info(): Failed to find disk id of %s" %
+ cur_lsi_disk_path)
+
+ raid_type = Volume.RAID_TYPE_UNKNOWN
+ dg_num = lsi_dg_path.split('/')[2][1:]
+ for dg_top in dg_show_all_output['TOPOLOGY']:
+ if dg_top['Arr'] == '-' and \
+ dg_top['Row'] == '-' and \
+ int(dg_top['DG']) == int(dg_num):
+ raid_type = _RAID_TYPE_MAP.get(
+ dg_top['Type'], Volume.RAID_TYPE_UNKNOWN)
+ break
+
+ if raid_type == Volume.RAID_TYPE_RAID1 and len(disk_ids) >= 4:
+ raid_type = Volume.RAID_TYPE_RAID10
+
+ return raid_type, Pool.MEMBER_TYPE_DISK, disk_ids
--
1.8.3.1
Gris Ge
2015-03-20 15:18:30 UTC
Permalink
* Add lsm.Client.pool_raid_info() support:
* Base on 'hpssacli ctrl slot=0 show config detail' command.

* Set lsm.Capabilities.POOL_RAID_INFO.

Signed-off-by: Gris Ge <***@redhat.com>
---
plugin/hpsa/hpsa.py | 39 +++++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)

diff --git a/plugin/hpsa/hpsa.py b/plugin/hpsa/hpsa.py
index 721b64b..f338d7f 100644
--- a/plugin/hpsa/hpsa.py
+++ b/plugin/hpsa/hpsa.py
@@ -278,6 +278,7 @@ def capabilities(self, system, flags=Client.FLAG_RSVD):
cap.set(Capabilities.VOLUMES)
cap.set(Capabilities.DISKS)
cap.set(Capabilities.VOLUME_RAID_INFO)
+ cap.set(Capabilities.POOL_RAID_INFO)
return cap

def _sacli_exec(self, sacli_cmds, flag_convert=True):
@@ -525,3 +526,41 @@ def volume_raid_info(self, volume, flags=Client.FLAG_RSVD):
"Volume not found")

return [raid_type, strip_size, disk_count, strip_size, stripe_size]
+
+ @_handle_errors
+ def pool_raid_info(self, pool, flags=Client.FLAG_RSVD):
+ """
+ Depend on command:
+ hpssacli ctrl slot=0 show config detail
+ """
+ if not pool.plugin_data:
+ raise LsmError(
+ ErrorNumber.INVALID_ARGUMENT,
+ "Ilegal input volume argument: missing plugin_data property")
+
+ (ctrl_num, array_num) = pool.plugin_data.split(":")
+ ctrl_data = self._sacli_exec(
+ ["ctrl", "slot=%s" % ctrl_num, "show", "config", "detail"]
+ ).values()[0]
+
+ disk_ids = []
+ raid_type = Volume.RAID_TYPE_UNKNOWN
+ for key_name in ctrl_data.keys():
+ if key_name == "Array: %s" % array_num:
+ for array_key_name in ctrl_data[key_name].keys():
+ if array_key_name.startswith("Logical Drive: ") and \
+ raid_type == Volume.RAID_TYPE_UNKNOWN:
+ raid_type = _hp_raid_type_to_lsm(
+ ctrl_data[key_name][array_key_name])
+ elif array_key_name.startswith("physicaldrive"):
+ hp_disk = ctrl_data[key_name][array_key_name]
+ if hp_disk['Drive Type'] == 'Data Drive':
+ disk_ids.append(hp_disk['Serial Number'])
+ break
+
+ if len(disk_ids) == 0:
+ raise LsmError(
+ ErrorNumber.NOT_FOUND_POOL,
+ "Pool not found")
+
+ return raid_type, Pool.MEMBER_TYPE_DISK, disk_ids
--
1.8.3.1
Tony Asleson
2015-03-20 17:33:05 UTC
Permalink
Post by Gris Ge
* I am new for manipulating array of string in C, not sure this is a correct
way to do so in libstoragemgmt. Please kindly pay extra care when reviewing
C API codes. Thank you very much in advance.
The library has an abstraction for this, lsm_string_list please use.

Thanks,
Tony
Tony Asleson
2015-03-20 17:46:41 UTC
Permalink
Post by Gris Ge
[PATCH V2 0/6] New HP SmartArray Plugin.
* RAID type.
* Member type(disk RAID group or sub-pool).
* Member IDs(disk ids or parent pool ids).
* This is preparation for coming HW RAID dedicate API volume_create_raid().
# I intend to make sure every changes made by any API is queryable.
Gris,

I think it would be useful to myself and others if you sent out some
design details about what you are looking to add for allowing the user
to create a logical unit on these external RAID adapters and how each of
the library calls fits into the use cases.

The other call you added for a volume_raid_info allows the user to query
properties pertaining to it. Adding the flag to the disks object allows
the user to locate disks that are available for use etc.

At the moment I'm wondering how adding this pool_raid_info fits into the
dedicated function to create a volume on a raid adapter. What it's use
case?

Thanks,
Tony
Gris Ge
2015-03-25 13:53:14 UTC
Permalink
Post by Tony Asleson
Post by Gris Ge
[PATCH V2 0/6] New HP SmartArray Plugin.
* RAID type.
* Member type(disk RAID group or sub-pool).
* Member IDs(disk ids or parent pool ids).
* This is preparation for coming HW RAID dedicate API volume_create_raid().
# I intend to make sure every changes made by any API is queryable.
Gris,
I think it would be useful to myself and others if you sent out some
design details about what you are looking to add for allowing the user
to create a logical unit on these external RAID adapters and how each of
the library calls fits into the use cases.
The other call you added for a volume_raid_info allows the user to query
properties pertaining to it. Adding the flag to the disks object allows
the user to locate disks that are available for use etc.
At the moment I'm wondering how adding this pool_raid_info fits into the
dedicated function to create a volume on a raid adapter. What it's use
case?
Let me combine pool_raid_info() patch set with volume_raid_create()
patch set, then detail design and implementation could be discussed
base on real code.
Post by Tony Asleson
Thanks,
Tony
------------------------------------------------------------------------------
Dive into the World of Parallel Programming The Go Parallel Website, sponsored
by Intel and developed in partnership with Slashdot Media, is your hub for all
things parallel software development, from weekly thought leadership blogs to
news, videos, case studies, tutorials and more. Take a look and join the
conversation now. http://goparallel.sourceforge.net/
_______________________________________________
Libstoragemgmt-devel mailing list
https://lists.sourceforge.net/lists/listinfo/libstoragemgmt-devel
--
Gris Ge
Loading...