* The _parse_hpssacli_output() method will fail if got free disks detected. This fix is removing list used in _parse_hpssacli_output(), every line will be stored as an dictionary key. If current line is not 'key: value' format, the value will be set as None. Also skipped the incorrect indented 'Physical Drives' line, in the seek of avoiding duplication dictionary key.
* Also fix the incorrect 'flag_free' argument used for SmartArray._hp_disk_to_lsm_disk() when facing free disks. * Tested on HP P410i with one free disk, hence updated the TODO line about free disks. Signed-off-by: Gris Ge <f...@redhat.com> --- plugin/hpsa/hpsa.py | 72 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 58 insertions(+), 14 deletions(-) diff --git a/plugin/hpsa/hpsa.py b/plugin/hpsa/hpsa.py index 60d87cc..743cbcc 100644 --- a/plugin/hpsa/hpsa.py +++ b/plugin/hpsa/hpsa.py @@ -75,9 +75,20 @@ def _sys_status_of(hp_ctrl_status): def _parse_hpssacli_output(output): """ Got a output string of hpssacli to dictionary(nested). + Skipped these line: + 1. Starts with 'Note:' + This is just a message right after controller. We don't neet it + yet. + 2. The 'Physical Drives' line. + It should indented after 'Internal Drive Cage' like. + If not ignored, we might got duplication line error. + After ignored, it's phsycial disks will directly stored as + key of 'Internal Drive Cage' dictionary. """ output_lines = [ - l for l in output.split("\n") if l and not l.startswith('Note:')] + l for l in output.split("\n") + if l and not l.startswith('Note:') and + not l.strip() == 'Physical Drives'] data = {} @@ -108,24 +119,19 @@ def _parse_hpssacli_output(output): if nxt_indent_count > cur_indent_count: nxt_line_splitted = nxt_line.split(": ") - if len(nxt_line_splitted) == 1: - new_data = [] - else: - new_data = {} + new_data = {} if cur_line.lstrip() not in cur_data_pointer: cur_data_pointer[cur_line.lstrip()] = new_data indent_2_data[nxt_indent_count] = new_data - elif type(cur_data_pointer[cur_line.lstrip()]) != type(new_data): + else: raise LsmError( ErrorNumber.PLUGIN_BUG, - "_parse_hpssacli_output(): Unexpected line '%s%s\n'" % - (cur_line, nxt_line)) + "_parse_hpssacli_output(): Found duplicate line %s" % + cur_line) else: if len(cur_line_splitted) == 1: - if type(indent_2_data[cur_indent_count]) != list: - raise Exception("not a list: '%s'" % cur_line) - cur_data_pointer.append(cur_line.lstrip()) + cur_data_pointer[cur_line.lstrip()] = None else: cur_data_pointer[cur_line_splitted[0].lstrip()] = \ ": ".join(cur_line_splitted[1:]).strip() @@ -279,6 +285,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): @@ -450,8 +457,7 @@ def disks(self, search_key=None, search_value=None, Depend on command: hpssacli ctrl all show config detail """ - # TODO(Gris Ge): Need real test on spare disk and free disk. - # The free disks is purely base on HP document. + # TODO(Gris Ge): Need real test on spare disk. rc_lsm_disks = [] ctrl_all_conf = self._sacli_exec( ["ctrl", "all", "show", "config", "detail"]) @@ -475,7 +481,7 @@ def disks(self, search_key=None, search_value=None, SmartArray._hp_disk_to_lsm_disk( ctrl_data[key_name][array_key_name], sys_id, ctrl_num, array_key_name, - flag_free=False)) + flag_free=True)) return search_property(rc_lsm_disks, search_key, search_value) @@ -526,3 +532,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 ------------------------------------------------------------------------------ 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 Libstoragemgmt-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/libstoragemgmt-devel