* Using storcli(LSI binary tool).
* Currently only got 'systems()' and 'disks()' supported.
* This plugin require root privilege, plugin config file included.
* Autotools files updated.
* RPM SPEC updated with new sub package:
libstoragemgmt-megaraid-plugin (RHEL/Fedora/Centos)
or
libstoragemgmt1-megaraid-plugin (OpenSuSE)
* The URI for this plugin is:
megaraid://
or
megaraid://?storcli=<path_of_storcli>
* If SELinux enabled, please check SELinux logs to grant permission for this.
For exmaple:
grep storcli64 /var/log/audit/audit.log | audit2allow -M mypol
semodule -i mypol.pp
* Added new manpage: megaraid_lsmplugin(1).
* Tested on RHEL6 and RHEL7 for SAS and SATA disks.
Changes in V2:
* Update manpage megaraid_lsmplugin(1):
1. Fix incorrect spells.
2. Indicate SELinux might stop plugin accessing the hardware.
* Include disk ID in Disk.name. The disk ID is required to query SMART
information via command:
smartctl -a -d megaraid,10 /dev/sda
^^--> disk ID
* Improve disk type detecting base LSI engineer's feedback.
* Fix typo excutable -> executable.
* Add 'INVALID_ARGUMENT' error when plugin was not run as root.
* Change base class to inherit from IPlugin.
* Implement(as not supported) the abstract method defined by IPlugin:
* job_free
* job_status
* pools
* time_out_get
* time_out_set
* Add '--without-megaraid' option to configure to skip installing the
MegaRAID plugin.
* Add '--without megaraid' option to rpm SPEC to skip building the
MegaRAID plugin rpm.
* Change rpm package for megaraid plugin as noarch.
Signed-off-by: Gris Ge <***@redhat.com>
---
config/Makefile.am | 5 +
config/pluginconf.d/megaraid.conf | 1 +
configure.ac | 14 ++
doc/man/Makefile.am | 4 +
doc/man/megaraid_lsmplugin.1.in | 52 ++++++
packaging/libstoragemgmt.spec.in | 42 +++++
plugin/Makefile.am | 2 +-
plugin/megaraid/Makefile.am | 8 +
plugin/megaraid/__init__.py | 1 +
plugin/megaraid/megaraid.py | 323 +++++++++++++++++++++++++++++++++++++
plugin/megaraid/megaraid_lsmplugin | 37 +++++
plugin/megaraid/utils.py | 47 ++++++
12 files changed, 535 insertions(+), 1 deletion(-)
create mode 100644 config/pluginconf.d/megaraid.conf
create mode 100644 doc/man/megaraid_lsmplugin.1.in
create mode 100644 plugin/megaraid/Makefile.am
create mode 100644 plugin/megaraid/__init__.py
create mode 100644 plugin/megaraid/megaraid.py
create mode 100755 plugin/megaraid/megaraid_lsmplugin
create mode 100644 plugin/megaraid/utils.py
diff --git a/config/Makefile.am b/config/Makefile.am
index 71291ad..70ab97b 100644
--- a/config/Makefile.am
+++ b/config/Makefile.am
@@ -6,3 +6,8 @@ EXTRA_DIST= lsmd.conf pluginconf.d/sim.conf
pluginconfdir=$(sysconfdir)/lsm/pluginconf.d
pluginconf_DATA=pluginconf.d/sim.conf
+
+if WITH_MEGARAID
+pluginconf_DATA += pluginconf.d/megaraid.conf
+EXTRA_DIST += pluginconf.d/megaraid.conf
+endif
diff --git a/config/pluginconf.d/megaraid.conf b/config/pluginconf.d/megaraid.conf
new file mode 100644
index 0000000..35b52d4
--- /dev/null
+++ b/config/pluginconf.d/megaraid.conf
@@ -0,0 +1 @@
+require-root-privilege = true;
diff --git a/configure.ac b/configure.ac
index eeaa350..74e6811 100644
--- a/configure.ac
+++ b/configure.ac
@@ -181,6 +181,18 @@ fi
AM_CONDITIONAL([WITH_REST_API], [test "x$with_rest_api" = "xyes"])
dnl ==========================================================================
+dnl Add option '--without-megaraid' to exclude megaraid plugin.
+dnl ==========================================================================
+
+AC_ARG_WITH([megaraid],
+ [AS_HELP_STRING([--without-megaraid],
+ [Do not build the MegaRAID plugin])],
+ [],
+ [with_megaraid=yes])
+
+AM_CONDITIONAL([WITH_MEGARAID], [test "x$with_megaraid" = "xyes"])
+
+dnl ==========================================================================
dnl Check for libconfig as it is needed for lsmd daemon
dnl ==========================================================================
PKG_CHECK_MODULES(
@@ -208,6 +220,7 @@ AC_OUTPUT(libstoragemgmt.pc \
python_binding/lsm/version.py \
plugin/Makefile \
plugin/simc/Makefile \
+ plugin/megaraid/Makefile \
daemon/Makefile \
config/Makefile \
doc/Makefile \
@@ -215,6 +228,7 @@ AC_OUTPUT(libstoragemgmt.pc \
doc/man/lsmd.1 \
doc/doxygen.conf \
doc/man/lsmd.conf.5 \
+ doc/man/megaraid_lsmplugin.1 \
tools/Makefile \
tools/udev/Makefile \
tools/lsmcli/Makefile \
diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
index 18d8663..ccbcb38 100644
--- a/doc/man/Makefile.am
+++ b/doc/man/Makefile.am
@@ -1,3 +1,7 @@
notrans_dist_man1_MANS = lsmcli.1 lsmd.1
+if WITH_MEGARAID
+notrans_dist_man1_MANS += megaraid_lsmplugin.1
+endif
+
notrans_dist_man5_MANS = lsmd.conf.5.in
diff --git a/doc/man/megaraid_lsmplugin.1.in b/doc/man/megaraid_lsmplugin.1.in
new file mode 100644
index 0000000..27749b6
--- /dev/null
+++ b/doc/man/megaraid_lsmplugin.1.in
@@ -0,0 +1,52 @@
+.TH megaraid_lsmplugin "1" "Januray 2015" "megaraid_lsmplugin @VERSION@" "libStorageMgmt"
+.SH NAME
+megaraid_lsmplugin -- LibstorageMgmt MegaRAID plugin
+
+.SH DESCRIPTION
+LibstorageMgmt megaraid plugin allows user to manage LSI MegaRAID via vendor
+tool \fBstorcli\fR[1].
+The 'megaraid_lsmplugin' executable file is for libStorageMgmt
+daemon to execute when client user specifies megaraid plugin in the URI.
+
+Extra SELinux actions are required to allowing plugin access the hardware.
+
+.SH URI
+To use this plugin, users should set their URI to this format:
+.nf
+
+ \fBmegaraid://\fR
+ or
+ \fBmegaraid://?storcli=<path_of_storcli>\fR
+
+.fi
+
+.TP storcli
+The 'storcli' URI parameter is used to specified the path of storcli tool.
+By default, this plugin will try these paths used by storcli rpm:
+\fB/opt/MegaRAID/storcli/storcli64\fR and \fB/opt/MegaRAID/storcli/storcli\fR.
+
+.SH ROOT PRIVILEGE
+This plugin requires both \fBlsmd\fR daemon and API client running as root
+user. Please check manpage \fIlsmd.conf (5)\fR for detail.
+
+.SH SUPPORTED HARDWARES
+Please refer to LSI website for hardware support status of storcli.
+Detailed support status can be queried via:
+
+ * \fBlsm.Client.capabilities()\fR (Python API)
+ * \fBlsm_capabilities()\fR (C API)
+ * \fBlsmcli capabilities\fR (lsmcli command line).
+
+.SH FIREWALL RULES
+This plugin only execute \fBstorcli\fR on localhost. No network connection
+required.
+
+.SH SEE ALSO
+\fIlsmcli\fR(1), \fIlsmd\fR(1), [1] http://www.lsi.com
+
+.SH BUGS
+Please report bugs to
+\fI<libstoragemgmt-***@lists.sourceforge.net>\fR
+
+.SH AUTHOR
+Gris Ge \fI<***@redhat.com>\fR
diff --git a/packaging/libstoragemgmt.spec.in b/packaging/libstoragemgmt.spec.in
index a79bff5..34ef3f2 100644
--- a/packaging/libstoragemgmt.spec.in
+++ b/packaging/libstoragemgmt.spec.in
@@ -1,10 +1,14 @@
%bcond_with rest_api
+%bcond_without megaraid
# Use one-line macro for OBS workaround:
# https://bugzilla.novell.com/show_bug.cgi?id=864323
%{?_with_rest_api: %global with_rest_api 1 }
%{?_without_rest_api: %global with_rest_api 0 }
+%{?_with_megaraid: %global with_megaraid 1 }
+%{?_without_megaraid: %global with_megaraid 0 }
+
%define libsoname libstoragemgmt
%if 0%{?suse_version} || 0%{?fedora} >= 15 || 0%{?rhel} >= 7
@@ -207,6 +211,20 @@ the %{libstoragemgmt}-rest package contains the http daemon for
%{libstoragemgmt} rest api.
%endif
+
+%if 0%{?with_megaraid}
+%package -n %{libstoragemgmt}-megaraid-plugin
+Summary: Files for LSI MegaRAID support for %{libstoragemgmt}
+Group: System Environment/Libraries
+Requires: %{libstoragemgmt}%{?_isa} = %{version}-%{release}
+BuildArch: noarch
+
+%description -n %{libstoragemgmt}-megaraid-plugin
+The %{libstoragemgmt}-megaraid-plugin package contains the plugin for LSI
+MegaRAID storage management via storcli.
+%endif
+
+
%prep
%setup -q
@@ -217,6 +235,9 @@ the %{libstoragemgmt}-rest package contains the http daemon for
%if 0%{?with_rest_api} != 1
--without-rest-api \
%endif
+%if 0%{?with_megaraid} != 1
+ --without-megaraid \
+%endif
--disable-static
V=1 make %{?_smp_mflags}
@@ -413,6 +434,15 @@ if [ $1 -eq 0 ]; then
fi
+%if 0%{?with_megaraid}
+%postun -n %{libstoragemgmt}-megaraid-plugin
+if [ $1 -eq 0 ]; then
+ # Remove
+ /usr/bin/systemctl try-restart libstoragemgmt.service \
+ >/dev/null 2>&1 || :
+fi
+%endif
+
%files -n %{libstoragemgmt}
%defattr(-,root,root,-)
%doc README COPYING.LIB
@@ -507,6 +537,18 @@ fi
%{python_sitelib}/lsm/plugin/nstor/nstor.*
%{_bindir}/nstor_lsmplugin
+%if 0%{?with_megaraid}
+%files -n %{libstoragemgmt}-megaraid-plugin
+%defattr(-,root,root,-)
+%dir %{python_sitelib}/lsm/plugin/megaraid
+%{python_sitelib}/lsm/plugin/megaraid/__init__.*
+%{python_sitelib}/lsm/plugin/megaraid/megaraid.*
+%{python_sitelib}/lsm/plugin/megaraid/utils.*
+%{_bindir}/megaraid_lsmplugin
+%{_sysconfdir}/lsm/pluginconf.d/megaraid.conf
+%{_mandir}/man1/megaraid_lsmplugin.1*
+%endif
+
%files udev
%defattr(-,root,root,-)
%{udev_dir}/udev/scan-scsi-target
diff --git a/plugin/Makefile.am b/plugin/Makefile.am
index 78ceb36..f9146a8 100644
--- a/plugin/Makefile.am
+++ b/plugin/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS=simc
+SUBDIRS=simc megaraid
plugindir = $(pythondir)/lsm/plugin
diff --git a/plugin/megaraid/Makefile.am b/plugin/megaraid/Makefile.am
new file mode 100644
index 0000000..a4b6b1c
--- /dev/null
+++ b/plugin/megaraid/Makefile.am
@@ -0,0 +1,8 @@
+if WITH_MEGARAID
+plugindir = $(pythondir)/lsm/plugin
+megaraiddir = $(plugindir)/megaraid
+
+megaraid_PYTHON = __init__.py megaraid.py utils.py
+
+dist_bin_SCRIPTS= megaraid_lsmplugin
+endif
diff --git a/plugin/megaraid/__init__.py b/plugin/megaraid/__init__.py
new file mode 100644
index 0000000..8f4602c
--- /dev/null
+++ b/plugin/megaraid/__init__.py
@@ -0,0 +1 @@
+from lsm.plugin.megaraid.megaraid import MegaRAID
diff --git a/plugin/megaraid/megaraid.py b/plugin/megaraid/megaraid.py
new file mode 100644
index 0000000..e1e7e8d
--- /dev/null
+++ b/plugin/megaraid/megaraid.py
@@ -0,0 +1,323 @@
+# Copyright (C) 2015 Red Hat, Inc.
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# Author: Gris Ge <***@redhat.com>
+
+import os
+import json
+from string import strip
+import re
+import errno
+
+from lsm import (uri_parse, search_property, size_human_2_size_bytes,
+ Capabilities, LsmError, ErrorNumber, System, Client,
+ Disk, VERSION, search_property, IPlugin)
+
+from lsm.plugin.megaraid.utils import cmd_exec, ExecError
+
+_FLAG_RSVD = Client.FLAG_RSVD
+
+
+# Naming scheme
+# mega_sys_path /c0
+# mega_disk_path /c0/e64/s0
+
+
+def _handle_errors(method):
+ def _wrapper(*args, **kwargs):
+ try:
+ return method(*args, **kwargs)
+ except LsmError:
+ raise
+ except KeyError as key_error:
+ raise LsmError(
+ ErrorNumber.PLUGIN_BUG,
+ "Expected key missing from MegaRAID storcli output:%s" %
+ key_error)
+ except ExecError as exec_error:
+ raise LsmError(ErrorNumber.PLUGIN_BUG, str(exec_error))
+ except Exception as common_error:
+ raise LsmError(
+ ErrorNumber.PLUGIN_BUG,
+ "Got unexpected error %s" % common_error)
+
+ return _wrapper
+
+
+def _blk_count_of(mega_disk_size):
+ blk_count_regex = re.compile("(0x[0-9a-f]+) Sectors")
+ blk_count_search = blk_count_regex.search(mega_disk_size)
+ if blk_count_search:
+ return int(blk_count_search.group(1), 16)
+ return Disk.BLOCK_COUNT_NOT_FOUND
+
+
+def _disk_type_of(disk_show_basic_dict):
+ """
+ Return the 'Drive /c0/e64/s0' entry of '/c0/e64/s0 show all'
+ """
+ disk_media = disk_show_basic_dict['Med']
+ disk_interface = disk_show_basic_dict['Intf']
+ if disk_media == 'HDD':
+ if disk_interface == 'SATA':
+ return Disk.TYPE_SATA
+ elif disk_interface == 'SAS':
+ return Disk.TYPE_SAS
+ elif disk_interface == 'Parallel SCSI':
+ return Disk.TYPE_SCSI
+ elif disk_interface == 'FC':
+ return Disk.TYPE_FC
+ else:
+ return Disk.TYPE_HDD
+ elif disk_media == 'SSD':
+ return Disk.TYPE_SSD
+
+ return Disk.TYPE_UNKNOWN
+
+_DISK_STATE_MAP = {
+ 'Onln': Disk.STATUS_OK,
+ 'Offln': Disk.STATUS_ERROR,
+ 'GHS': Disk.STATUS_SPARE_DISK | Disk.STATUS_OK,
+ 'DHS': Disk.STATUS_SPARE_DISK | Disk.STATUS_OK,
+ 'UGood': Disk.STATUS_STOPPED | Disk.STATUS_OK,
+ 'UBad': Disk.STATUS_STOPPED | Disk.STATUS_ERROR,
+}
+
+
+def _disk_status_of(disk_show_basic_dict, disk_show_stat_dict):
+ if disk_show_stat_dict['Media Error Count'] or \
+ disk_show_stat_dict['Other Error Count'] or \
+ disk_show_stat_dict['S.M.A.R.T alert flagged by drive'] != 'No':
+ return Disk.STATUS_ERROR
+
+ if disk_show_stat_dict['Predictive Failure Count']:
+ return Disk.STATUS_PREDICTIVE_FAILURE
+
+ if disk_show_basic_dict['Sp'] == 'D':
+ return Disk.STATUS_STOPPED
+
+ if disk_show_basic_dict['Sp'] == 'F':
+ return Disk.STATUS_OTHER
+
+ return _DISK_STATE_MAP.get(
+ disk_show_basic_dict['State'], Disk.STATUS_UNKNOWN)
+
+
+class MegaRAID(IPlugin):
+ _DEFAULT_MDADM_BIN_PATHS = [
+ "/opt/MegaRAID/storcli/storcli64", "/opt/MegaRAID/storcli/storcli"]
+ _CMD_JSON_OUTPUT_SWITCH = 'J'
+
+ def __init__(self):
+ self._storcli_bin = None
+
+ def _find_storcli(self):
+ """
+ Try _DEFAULT_MDADM_BIN_PATHS
+ """
+ for cur_path in MegaRAID._DEFAULT_MDADM_BIN_PATHS:
+ if os.path.lexists(cur_path):
+ self._storcli_bin = cur_path
+
+ if not self._storcli_bin:
+ raise LsmError(
+ ErrorNumber.INVALID_ARGUMENT,
+ "MegaRAID storcli is not installed correctly")
+
+ @_handle_errors
+ def plugin_register(self, uri, password, timeout, flags=Client.FLAG_RSVD):
+ if os.geteuid() != 0:
+ raise LsmError(
+ ErrorNumber.INVALID_ARGUMENT,
+ "This plugin requires root privilege both daemon and client")
+ uri_parsed = uri_parse(uri)
+ self._storcli_bin = uri_parsed.get('parameters', {}).get('storcli')
+ if not self._storcli_bin:
+ self._find_storcli()
+
+ # change working dir to "/tmp" as storcli will create a log file
+ # named as 'MegaSAS.log'.
+ os.chdir("/tmp")
+ self._storcli_exec(['-v'], flag_json=False)
+
+ @_handle_errors
+ def plugin_unregister(self, flags=Client.FLAG_RSVD):
+ pass
+
+ @_handle_errors
+ def job_status(self, job_id, flags=Client.FLAG_RSVD):
+ raise LsmError(ErrorNumber.NO_SUPPORT, "Not supported yet")
+
+ @_handle_errors
+ def job_free(self, job_id, flags=Client.FLAG_RSVD):
+ pass
+
+ @_handle_errors
+ def plugin_info(self, flags=Client.FLAG_RSVD):
+ return "LSI MegaRAID Plugin", VERSION
+
+ @_handle_errors
+ def time_out_set(self, ms, flags=Client.FLAG_RSVD):
+ raise LsmError(ErrorNumber.NO_SUPPORT, "Not supported yet")
+
+ @_handle_errors
+ def time_out_get(self, flags=Client.FLAG_RSVD):
+ raise LsmError(ErrorNumber.NO_SUPPORT, "Not supported yet")
+
+ @_handle_errors
+ def capabilities(self, system, flags=_FLAG_RSVD):
+ 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.DISKS)
+ return cap
+
+ def _storcli_exec(self, storcli_cmds, flag_json=True):
+ storcli_cmds.insert(0, self._storcli_bin)
+ if flag_json:
+ storcli_cmds.append(MegaRAID._CMD_JSON_OUTPUT_SWITCH)
+ try:
+ output = cmd_exec(storcli_cmds)
+ except OSError as os_error:
+ if os_error.errno == errno.ENOENT:
+ raise LsmError(
+ ErrorNumber.INVALID_ARGUMENT,
+ "storcli binary '%s' is not exist or executable." %
+ self._storcli_bin)
+ else:
+ raise
+
+ if flag_json:
+ output_dict = json.loads(output)
+ ctrl_output = output_dict.get('Controllers')
+ if len(ctrl_output) != 1:
+ raise LsmError(
+ ErrorNumber.PLUGIN_BUG,
+ "_storcli_exec(): Unexpected output from MegaRAID "
+ "storcli: %s" % output_dict)
+
+ rc_status = ctrl_output[0].get('Command Status')
+ if rc_status.get('Status') != 'Success':
+ raise LsmError(
+ ErrorNumber.PLUGIN_BUG,
+ "MegaRAID storcli failed with error %d: %s" %
+ (rc_status['Status Code'], rc_status['Description']))
+ return ctrl_output[0].get('Response Data')
+ else:
+ return output
+
+ def _ctrl_count(self):
+ return self._storcli_exec(
+ ["show", "ctrlcount"]).get("Controller Count")
+
+ def _lsm_status_of_ctrl(self, ctrl_num):
+ ctrl_health_output = self._storcli_exec(
+ ["/c%d" % ctrl_num, 'show', 'health', 'all'])
+ health_info = ctrl_health_output['Controller Health Info']
+ # TODO(Gris Ge): Try pull a disk off to check whether this change.
+ if health_info['Overall Health'] == 'GOOD':
+ return System.STATUS_OK, ''
+
+ return System.STATUS_UNKNOWN, "%s reason code %s" % (
+ health_info['Overall Health'],
+ health_info['Reason Code'])
+
+ def _sys_id_of_ctrl_num(self, ctrl_num, ctrl_show_output=None):
+ if ctrl_show_output is None:
+ ctrl_show_output = self._storcli_exec(["/c%d" % ctrl_num, "show"])
+ sys_id = ctrl_show_output['Serial Number']
+ if not sys_id:
+ raise LsmError(
+ ErrorNumber.PLUGIN_BUG,
+ "_sys_id_of_ctrl_num(): Fail to get system id: %s" %
+ ctrl_show_output.items())
+ else:
+ return sys_id
+
+ @_handle_errors
+ def systems(self, flags=0):
+ rc_lsm_syss = []
+ for ctrl_num in range(self._ctrl_count()):
+ ctrl_show_output = self._storcli_exec(["/c%d" % ctrl_num, "show"])
+ sys_id = self._sys_id_of_ctrl_num(ctrl_num, ctrl_show_output)
+ sys_name = "%s %s %s:%s:%s" % (
+ ctrl_show_output['Product Name'],
+ ctrl_show_output['Host Interface'],
+ format(ctrl_show_output['Bus Number'], '02x'),
+ format(ctrl_show_output['Device Number'], '02x'),
+ format(ctrl_show_output['Function Number'], '02x'))
+ (status, status_info) = self._lsm_status_of_ctrl(ctrl_num)
+ plugin_data = "/c%d"
+ # Since PCI slot sequence might change.
+ # This string just stored for quick system verification.
+
+ rc_lsm_syss.append(
+ System(sys_id, sys_name, status, status_info, plugin_data))
+
+ return rc_lsm_syss
+
+ @_handle_errors
+ def disks(self, search_key=None, search_value=None, flags=_FLAG_RSVD):
+ rc_lsm_disks = []
+ mega_disk_path_regex = re.compile(
+ r"^Drive (\/c[0-9]+\/e[0-9]+\/s[0-9]+) - Detailed Information$")
+
+ for ctrl_num in range(self._ctrl_count()):
+ sys_id = self._sys_id_of_ctrl_num(ctrl_num)
+
+ disk_show_output = self._storcli_exec(
+ ["/c%d/eall/sall" % ctrl_num, "show", "all"])
+ for drive_name in disk_show_output.keys():
+ re_match = mega_disk_path_regex.match(drive_name)
+ if not re_match:
+ continue
+
+ mega_disk_path = re_match.group(1)
+ # Assuming only 1 disk attached to each slot.
+ disk_show_basic_dict = disk_show_output[
+ "Drive %s" % mega_disk_path][0]
+ disk_show_attr_dict = disk_show_output[drive_name][
+ 'Drive %s Device attributes' % mega_disk_path]
+ disk_show_stat_dict = disk_show_output[drive_name][
+ 'Drive %s State' % mega_disk_path]
+
+ disk_id = disk_show_attr_dict['SN'].strip()
+ disk_name = "Disk %s %s %s" % (
+ disk_show_basic_dict['DID'],
+ disk_show_attr_dict['Manufacturer Id'].strip(),
+ disk_show_attr_dict['Model Number'])
+ disk_type = _disk_type_of(disk_show_basic_dict)
+ blk_size = size_human_2_size_bytes(
+ disk_show_basic_dict['SeSz'])
+ blk_count = _blk_count_of(disk_show_attr_dict['Coerced size'])
+ status = _disk_status_of(
+ disk_show_basic_dict, disk_show_stat_dict)
+
+ plugin_data = mega_disk_path
+
+ rc_lsm_disks.append(
+ Disk(
+ disk_id, disk_name, disk_type, blk_size, blk_count,
+ status, sys_id, plugin_data))
+
+ return search_property(rc_lsm_disks, search_key, search_value)
+
+ @_handle_errors
+ def pools(self, search_key=None, search_value=None,
+ flags=Client.FLAG_RSVD):
+ raise LsmError(ErrorNumber.NO_SUPPORT, "Not supported yet")
diff --git a/plugin/megaraid/megaraid_lsmplugin b/plugin/megaraid/megaraid_lsmplugin
new file mode 100755
index 0000000..5aaa0e8
--- /dev/null
+++ b/plugin/megaraid/megaraid_lsmplugin
@@ -0,0 +1,37 @@
+#!/usr/bin/env python2
+
+# Copyright (C) 2011-2013 Red Hat, Inc.
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# Author: tasleson
+
+import sys
+import syslog
+import traceback
+
+try:
+ from lsm import PluginRunner
+ from lsm.plugin.megaraid import MegaRAID
+
+ if __name__ == '__main__':
+ PluginRunner(MegaRAID, sys.argv).run()
+except Exception:
+ #This should be quite rare, but when it does happen this is pretty
+ #key in understanding what happened, especially when it happens when
+ #running from the daemon.
+ msg = str(traceback.format_exc())
+ syslog.syslog(syslog.LOG_ERR, msg)
+ sys.stderr.write(msg)
+ sys.exit(1)
diff --git a/plugin/megaraid/utils.py b/plugin/megaraid/utils.py
new file mode 100644
index 0000000..4290b39
--- /dev/null
+++ b/plugin/megaraid/utils.py
@@ -0,0 +1,47 @@
+## Copyright (C) 2015 Red Hat, Inc.
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# Author: Gris Ge <***@redhat.com>
+
+import subprocess
+import os
+
+def cmd_exec(cmds):
+ """
+ Execute provided command and return the STDOUT as string.
+ Raise ExecError if command return code is not zero
+ """
+ cmd_popen = subprocess.Popen(
+ cmds, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+ env={"PATH": os.getenv("PATH")})
+ str_stdout = "".join(list(cmd_popen.stdout)).strip()
+ str_stderr = "".join(list(cmd_popen.stderr)).strip()
+ errno = cmd_popen.wait()
+ if errno != 0:
+ raise ExecError(" ".join(cmds), errno, str_stdout, str_stderr)
+ return str_stdout
+
+
+class ExecError(Exception):
+ def __init__(self, cmd, errno, stdout, stderr, *args, **kwargs):
+ Exception.__init__(self, *args, **kwargs)
+ self.cmd = cmd
+ self.errno = errno
+ self.stdout = stdout
+ self.stderr = stderr
+
+ def __str__(self):
+ return "cmd: '%s', errno: %d, stdout: '%s', stderr: '%s'" % \
+ (self.cmd, self.errno, self.stdout, self.stderr)
--
1.8.3.1