* Treating HP SmartArray logical drive as LSM volume. * Depend on output of command "hpssacli ctrl all show config detail".
* New method of utils.py: * file_read() # Simply use 'cat' command to do file read which provide better # error handling using ExecError. * The block size and block count is read from linux sysfs as hpssacli provide the sdX name for each logical drive. Faillback to 512 and calculated from other output entry. * Include sdX name if found in Volume.name. * Set Capabilities.VOLUMES. Signed-off-by: Gris Ge <f...@redhat.com> --- plugin/hpsa/hpsa.py | 69 +++++++++++++++++++++++++++++++++++++++++++++++++--- plugin/hpsa/utils.py | 8 ++++++ 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/plugin/hpsa/hpsa.py b/plugin/hpsa/hpsa.py index e04134d..715d28e 100644 --- a/plugin/hpsa/hpsa.py +++ b/plugin/hpsa/hpsa.py @@ -21,9 +21,9 @@ from lsm import ( IPlugin, Client, Capabilities, VERSION, LsmError, ErrorNumber, uri_parse, - System, Pool, size_human_2_size_bytes, search_property) + System, Pool, size_human_2_size_bytes, search_property, Volume) -from lsm.plugin.hpsa.utils import cmd_exec, ExecError +from lsm.plugin.hpsa.utils import cmd_exec, ExecError, file_read def _handle_errors(method): @@ -222,7 +222,14 @@ def time_out_get(self, flags=Client.FLAG_RSVD): @_handle_errors def capabilities(self, system, flags=Client.FLAG_RSVD): - return Capabilities() + cur_lsm_syss = self.systems() + if system.id not in list(s.id for s in cur_lsm_syss): + raise LsmError( + ErrorNumber.NOT_FOUND_SYSTEM, + "System not found") + cap = Capabilities() + cap.set(Capabilities.VOLUMES) + return cap def _sacli_exec(self, sacli_cmds, flag_convert=True): """ @@ -313,3 +320,59 @@ def pools(self, search_key=None, search_value=None, ctrl_data[key_name], key_name, sys_id, ctrl_num)) return search_property(lsm_pools, search_key, search_value) + + @staticmethod + def _hp_ld_to_lsm_vol(hp_ld, pool_id, sys_id, ctrl_num, array_num, + hp_ld_name): + ld_num = hp_ld_name[len("Logical Drive: "):] + vpd83 = hp_ld['Unique Identifier'].lower() + # No document or command output indicate block size + # of volume. So we try to read from linux kernel, if failed + # try 512 and roughly calculate the sector count. + regex_match = re.compile("/dev/(sd[a-z]+)").search(hp_ld['Disk Name']) + vol_name = hp_ld_name + if regex_match: + sd_name = regex_match.group(1) + block_size = int(file_read( + "/sys/block/%s/queue/logical_block_size" % sd_name)) + num_of_blocks = int(file_read("/sys/block/%s/size" % sd_name)) + vol_name += ": /dev/%s" % sd_name + else: + block_size = 512 + num_of_blocks = int(_hp_size_to_lsm(hp_ld['Size']) / block_size) + + plugin_data = "%s:%s:%s" % (ctrl_num, array_num, ld_num) + + # HP SmartArray does not allow disabling volume. + return Volume( + vpd83, vol_name, vpd83, block_size, num_of_blocks, + Volume.ADMIN_STATE_ENABLED, sys_id, pool_id, plugin_data) + + @_handle_errors + def volumes(self, search_key=None, search_value=None, + flags=Client.FLAG_RSVD): + """ + Depend on command: + hpssacli ctrl all show config detail + """ + lsm_vols = [] + ctrl_all_conf = self._sacli_exec( + ["ctrl", "all", "show", "config", "detail"]) + for ctrl_data in ctrl_all_conf.values(): + ctrl_num = ctrl_data['Slot'] + sys_id = ctrl_data['Serial Number'] + for key_name in ctrl_data.keys(): + if not key_name.startswith("Array:"): + continue + pool_id = _pool_id_of(sys_id, key_name) + array_num = key_name[len('Array: '):] + for array_key_name in ctrl_data[key_name].keys(): + if not array_key_name.startswith("Logical Drive"): + continue + lsm_vols.append( + SmartArray._hp_ld_to_lsm_vol( + ctrl_data[key_name][array_key_name], + pool_id, sys_id, ctrl_num, array_num, + array_key_name)) + + return search_property(lsm_vols, search_key, search_value) diff --git a/plugin/hpsa/utils.py b/plugin/hpsa/utils.py index 67734b0..52670a0 100644 --- a/plugin/hpsa/utils.py +++ b/plugin/hpsa/utils.py @@ -35,6 +35,14 @@ def cmd_exec(cmds): return str_stdout +def file_read(file_path): + """ + Read file and return string of file content. + Use 'cat' command to better utilize the ExecError. + """ + return cmd_exec(['cat', file_path]) + + class ExecError(Exception): def __init__(self, cmd, errno, stdout, stderr, *args, **kwargs): Exception.__init__(self, *args, **kwargs) -- 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