diff options
-rwxr-xr-x | plugins/network.py | 151 | ||||
-rwxr-xr-x | plugins/sadf.py | 1 | ||||
-rwxr-xr-x | rfc.sh | 2 | ||||
-rw-r--r-- | tests/Makefile.am | 1 | ||||
-rw-r--r-- | tests/test_network.py | 184 | ||||
-rw-r--r-- | tests/test_network_dataFile.py | 162 |
6 files changed, 231 insertions, 270 deletions
diff --git a/plugins/network.py b/plugins/network.py index d25c848..c740514 100755 --- a/plugins/network.py +++ b/plugins/network.py @@ -16,71 +16,122 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA # -import sadf +import sys import argparse +import ethtool +import logging + +import sadf from glusternagios import utils +_description = "Network plugin for Nagios provides status and performance " \ + "data of network interfaces. By default, it provides " \ + "details of all the interfaces having IP addresses" _sadfNetCommand = ["sadf", "-x", "--", "-n", "DEV"] +_defaultExcludeList = ['lo'] + +class InterfaceStatus: + UP = 'UP' + DOWN = 'DOWN' + + +def parse_cmdargs(): + parser = argparse.ArgumentParser(description=_description) + sadf.add_common_args(parser) -def parse_input(): - parser = argparse.ArgumentParser() group = parser.add_mutually_exclusive_group() group.add_argument("-e", "--exclude", action="append", - help="Parameters to be excluded") + help="exclude given interface") group.add_argument("-i", "--include", action="append", - help="Parameters to be included") - sadf.add_common_args(parser) + help="add given interface for monitoring") + group.add_argument("-a", "--all", action="store_true", default=False, + help="get status of all interfaces") + args = parser.parse_args() return args -def showNetStat(s, iface_list=None, list_type=None): - pl_op = {} - if not s: - pl_op["message"] = ("IFACE UNKNOWN") - pl_op['exit_status'] = utils.PluginStatusCode.UNKNOWN - return pl_op +def _getNetworkInterfaces(interfaces=()): + if interfaces: + devices = interfaces + else: + devices = ethtool.get_active_devices() + + info = {} + for dev in devices: + try: + info[dev] = {'ipaddr': ethtool.get_ipaddr(dev), + 'flags': ethtool.get_flags(dev)} + except IOError as e: + logging.error("unable to get ipaddr/flags for %s: %s" % (dev, e)) + info[dev] = {'ipaddr': None, + 'flags': None} + + return info + + +def _getStatMessage(stat, all=False, includes=(), excludes=()): + excludeList = _defaultExcludeList + if excludes: + excludeList += excludes + + rc = utils.PluginStatus.OK + interfaces = _getNetworkInterfaces() devNames = [] perfLines = [] - try: - for dev in s['network']['net-dev']: - if list_type == "exclude": - if dev['iface'] in iface_list: - continue - elif list_type == "include": - if dev['iface'] not in iface_list: - continue - devNames.append(dev['iface']) - perfLines.append("%s.rxpck=%s %s.txpck=%s %s.rxkB=%s %s.txkB=%s" - % (dev['iface'], dev['rxpck'], - dev['iface'], dev['txpck'], - dev['iface'], dev['rxkB'], - dev['iface'], dev['txkB'])) - except (KeyError, ValueError, TypeError) as e: - pl_op["message"] = "key: %s not found" % str(e) - pl_op["exit_status"] = utils.PluginStatusCode.UNKNOWN - return pl_op - - pl_op["message"] = ("IFACE OK: %s |%s" % (", ".join(devNames), - " ".join(perfLines))) - pl_op['exit_status'] = utils.PluginStatusCode.OK - return pl_op -if __name__ == '__main__': - args = parse_input() + for info in stat['network']['net-dev']: + ipaddr = interfaces.get(info['iface'], {}).get('ipaddr') + flags = interfaces.get(info['iface'], {}).get('flags') + if flags and (flags & ethtool.IFF_UP): + status = InterfaceStatus.UP + else: + status = InterfaceStatus.DOWN + + if includes: + if info['iface'] not in includes: + continue + elif not all: + if not ipaddr: + continue + elif info['iface'] in excludeList: + continue + + if includes and (status == InterfaceStatus.DOWN): + rc = utils.PluginStatus.WARNING + + devNames.append("%s:%s" % (info['iface'], status)) + perfLines.append("%s.rxpck=%s %s.txpck=%s %s.rxkB=%s %s.txkB=%s" + % (info['iface'], info['rxpck'], + info['iface'], info['txpck'], + info['iface'], info['rxkB'], + info['iface'], info['txkB'])) + + return (getattr(utils.PluginStatusCode, rc), + "%s: %s |%s" % (rc, + ",".join(devNames), + " ".join(perfLines))) + + +def main(): + args = parse_cmdargs() + try: - st = sadf.getLatestStat(sadf.sadfExecCmd(_sadfNetCommand), - args.interval if args.interval else 1) + stat = sadf.getLatestStat(sadf.sadfExecCmd(_sadfNetCommand), + args.interval) + (rc, msg) = _getStatMessage(stat, all=args.all, + includes=args.include, + excludes=args.exclude) + print msg + sys.exit(rc) except (sadf.SadfCmdExecFailedException, - sadf.SadfXmlErrorException) as e: - print str(e) - exit(utils.PluginStatusCode.UNKNOWN) - if args.exclude: - d = showNetStat(st, args.exclude, "exclude") - elif args.include: - d = showNetStat(st, args.include, "include") - else: - d = showNetStat(st) - print d["message"] - exit(d['exit_status']) + sadf.SadfXmlErrorException, + KeyError) as e: + logging.error("unable to get network status: %s" % e) + print "UNKNOWN" + sys.exit(utils.PluginStatusCode.UNKNOWN) + + +if __name__ == '__main__': + main() diff --git a/plugins/sadf.py b/plugins/sadf.py index 5ac1ed0..c7caee8 100755 --- a/plugins/sadf.py +++ b/plugins/sadf.py @@ -98,5 +98,6 @@ def getLatestStat(root, interval=1): def add_common_args(parser): parser.add_argument("-t", "--interval", action="store", type=int, + default=1, help="Interval of time(min) older than" " which sadf output in considered stale") @@ -112,7 +112,7 @@ add_hook_commit_msg() assert_python_check() { - pyfiles=$(git diff --name-only origin/$branch..HEAD 2>/dev/null | grep -e '\.py$' -e '\.py\.in$') + pyfiles=$(git diff --diff-filter=ACMRT --name-only origin/$branch..HEAD 2>/dev/null | grep -e '\.py$' -e '\.py\.in$') if [ -z "$pyfiles" ]; then return fi diff --git a/tests/Makefile.am b/tests/Makefile.am index 0777a27..cdf62d4 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -28,7 +28,6 @@ test_modules = \ test_memory.py \ test_memory_dataFile.py \ test_network.py \ - test_network_dataFile.py \ test_sadf.py \ test_swap.py \ test_swap_dataFile.py \ diff --git a/tests/test_network.py b/tests/test_network.py index 8cb4552..13a5925 100644 --- a/tests/test_network.py +++ b/tests/test_network.py @@ -18,69 +18,141 @@ # Refer to the README and COPYING files for full details of the license # +import mock + from testrunner import PluginsTestCase as TestCaseBase -from plugins import network -import test_network_dataFile +import plugins + + +stat = {'date': '2014-04-17', + 'interval': '60', + 'network': {'net-dev': [{'iface': 'tun0', + 'rxcmp': '0.00', + 'rxkB': '0.01', + 'rxmcst': '0.00', + 'rxpck': '0.10', + 'txcmp': '0.00', + 'txkB': '0.01', + 'txpck': '0.08'}, + {'iface': 'wlp3s0', + 'rxcmp': '0.00', + 'rxkB': '0.00', + 'rxmcst': '0.00', + 'rxpck': '0.00', + 'txcmp': '0.00', + 'txkB': '0.00', + 'txpck': '0.00'}, + {'iface': 'lo', + 'rxcmp': '0.00', + 'rxkB': '0.00', + 'rxmcst': '0.00', + 'rxpck': '0.00', + 'txcmp': '0.00', + 'txkB': '0.00', + 'txpck': '0.00'}, + {'iface': 'virbr0-nic', + 'rxcmp': '0.00', + 'rxkB': '0.00', + 'rxmcst': '0.00', + 'rxpck': '0.00', + 'txcmp': '0.00', + 'txkB': '0.00', + 'txpck': '0.00'}, + {'iface': 'virbr0', + 'rxcmp': '0.00', + 'rxkB': '0.00', + 'rxmcst': '0.00', + 'rxpck': '0.00', + 'txcmp': '0.00', + 'txkB': '0.00', + 'txpck': '0.00'}, + {'iface': 'enp0s29u1u2', + 'rxcmp': '0.00', + 'rxkB': '0.09', + 'rxmcst': '0.00', + 'rxpck': '1.15', + 'txcmp': '0.00', + 'txkB': '0.25', + 'txpck': '1.65'}, + {'iface': 'em1', + 'rxcmp': '0.00', + 'rxkB': '0.00', + 'rxmcst': '0.00', + 'rxpck': '0.00', + 'txcmp': '0.00', + 'txkB': '0.00', + 'txpck': '0.00'}], + 'per': 'second'}, + 'time': '02:36:01', + 'utc': '1'} + +interfaces = {'em1': {'flags': None, 'ipaddr': None}, + 'enp0s29u1u2': {'flags': 4163, 'ipaddr': '192.168.42.182'}, + 'lo': {'flags': 73, 'ipaddr': '127.0.0.1'}, + 'tun0': {'flags': 4305, 'ipaddr': '10.10.63.201'}, + 'virbr0': {'flags': 4099, 'ipaddr': '192.168.122.1'}, + 'wlp3s0': {'flags': None, 'ipaddr': None}} class networkTests(TestCaseBase): + @mock.patch('plugins.network._getNetworkInterfaces') + def test_network_default(self, _getNetworkInterfaces_mock): + expected = (0, "OK: tun0:UP,virbr0:UP,enp0s29u1u2:UP |" + "tun0.rxpck=0.10 tun0.txpck=0.08 " + "tun0.rxkB=0.01 tun0.txkB=0.01 " + "virbr0.rxpck=0.00 virbr0.txpck=0.00 " + "virbr0.rxkB=0.00 virbr0.txkB=0.00 " + "enp0s29u1u2.rxpck=1.15 enp0s29u1u2.txpck=1.65 " + "enp0s29u1u2.rxkB=0.09 enp0s29u1u2.txkB=0.25") + _getNetworkInterfaces_mock.return_value = interfaces + + actual = plugins.network._getStatMessage(stat) + self.assertEquals(expected, actual) - def _showNetStatus_unknown_test(self): - actual = network.showNetStat( - test_network_dataFile.SHOW_NETWORK_STATUS_UNKNOWN_IP - ) - self.assertEquals( - actual, - test_network_dataFile.SHOW_NETWORK_STATUS_UNKNOWN_OP - ) + @mock.patch('plugins.network._getNetworkInterfaces') + def test_network_all(self, _getNetworkInterfaces_mock): + expected = (0, "OK: tun0:UP,wlp3s0:DOWN,lo:UP,virbr0-nic:DOWN," + "virbr0:UP,enp0s29u1u2:UP,em1:DOWN |" + "tun0.rxpck=0.10 tun0.txpck=0.08 " + "tun0.rxkB=0.01 tun0.txkB=0.01 " + "wlp3s0.rxpck=0.00 wlp3s0.txpck=0.00 " + "wlp3s0.rxkB=0.00 wlp3s0.txkB=0.00 " + "lo.rxpck=0.00 lo.txpck=0.00 lo.rxkB=0.00 lo.txkB=0.00 " + "virbr0-nic.rxpck=0.00 virbr0-nic.txpck=0.00 " + "virbr0-nic.rxkB=0.00 virbr0-nic.txkB=0.00 " + "virbr0.rxpck=0.00 virbr0.txpck=0.00 " + "virbr0.rxkB=0.00 virbr0.txkB=0.00 " + "enp0s29u1u2.rxpck=1.15 enp0s29u1u2.txpck=1.65 " + "enp0s29u1u2.rxkB=0.09 enp0s29u1u2.txkB=0.25 " + "em1.rxpck=0.00 em1.txpck=0.00 " + "em1.rxkB=0.00 em1.txkB=0.00") + _getNetworkInterfaces_mock.return_value = interfaces - def _showNetStatus_ok_test(self): - actual = network.showNetStat( - test_network_dataFile.SHOW_NETWORK_STATUS_OK_IP - ) - self.assertEquals( - actual, - test_network_dataFile.SHOW_NETWORK_STATUS_OK_OP - ) + actual = plugins.network._getStatMessage(stat, all=True) + self.assertEquals(expected, actual) - def _showNetStatus_include_test(self): - in_list = ["lo"] - list_type = "include" - actual = network.showNetStat( - test_network_dataFile.SHOW_NETWORK_STATUS_INCLUDE_IP, - in_list, - list_type - ) - self.assertEquals( - actual, - test_network_dataFile.SHOW_NETWORK_STATUS_INCLUDE_OP - ) + @mock.patch('plugins.network._getNetworkInterfaces') + def test_network_includes(self, _getNetworkInterfaces_mock): + expected = (1, "WARNING: tun0:UP,em1:DOWN |" + "tun0.rxpck=0.10 tun0.txpck=0.08 " + "tun0.rxkB=0.01 tun0.txkB=0.01 " + "em1.rxpck=0.00 em1.txpck=0.00 " + "em1.rxkB=0.00 em1.txkB=0.00") + _getNetworkInterfaces_mock.return_value = interfaces - def _showNetStatus_exclude_test(self): - ex_list = ["lo"] - list_type = "exclude" - actual = network.showNetStat( - test_network_dataFile.SHOW_NETWORK_STATUS_EXCLUDE_IP, - ex_list, - list_type - ) - self.assertEquals( - actual, - test_network_dataFile.SHOW_NETWORK_STATUS_EXCLUDE_OP - ) + actual = plugins.network._getStatMessage(stat, + includes=('tun0', 'em1')) + self.assertEquals(expected, actual) - def _showNetStatus_exception_test(self): - actual = network.showNetStat( - test_network_dataFile.SHOW_NETWORK_STATUS_EXCEPTION_IP - ) - self.assertEquals( - actual, - test_network_dataFile.SHOW_NETWORK_STATUS_EXCEPTION_OP - ) + @mock.patch('plugins.network._getNetworkInterfaces') + def test_network_excludes(self, _getNetworkInterfaces_mock): + expected = (0, "OK: virbr0:UP,enp0s29u1u2:UP |" + "virbr0.rxpck=0.00 virbr0.txpck=0.00 " + "virbr0.rxkB=0.00 virbr0.txkB=0.00 " + "enp0s29u1u2.rxpck=1.15 enp0s29u1u2.txpck=1.65 " + "enp0s29u1u2.rxkB=0.09 enp0s29u1u2.txkB=0.25") + _getNetworkInterfaces_mock.return_value = interfaces - def test_showNetStatus(self): - self._showNetStatus_unknown_test() - self._showNetStatus_ok_test() - self._showNetStatus_include_test() - self._showNetStatus_exclude_test() - self._showNetStatus_exception_test() + actual = plugins.network._getStatMessage(stat, + excludes=('tun0', )) + self.assertEquals(expected, actual) diff --git a/tests/test_network_dataFile.py b/tests/test_network_dataFile.py deleted file mode 100644 index f74157c..0000000 --- a/tests/test_network_dataFile.py +++ /dev/null @@ -1,162 +0,0 @@ -# -# Copyright 2014 Red Hat, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -# -# Refer to the README and COPYING files for full details of the license -# - -SHOW_NETWORK_STATUS_UNKNOWN_IP = {} - -SHOW_NETWORK_STATUS_UNKNOWN_OP = \ - {'message': "IFACE UNKNOWN", 'exit_status': 3} - -SHOW_NETWORK_STATUS_OK_IP = \ - {'date': '2014-03-11', - 'utc': '1', 'interval': '60', - 'network': - {'net-dev': - [{'rxmcst': '0.00', - 'iface': 'tun0', 'rxkB': '11.44', - 'rxpck': '13.28', 'txpck': '13.51', - 'txkB': '1.28', 'txcmp': '0.00', - 'rxcmp': '0.00'}, - {'rxmcst': '0.00', 'iface': 'wlp3s0', - 'rxkB': '12.60', 'rxpck': '13.73', - 'txpck': '13.60', 'txkB': '2.72', - 'txcmp': '0.00', 'rxcmp': '0.00'}, - {'rxmcst': '0.00', 'iface': 'lo', - 'rxkB': '0.04', 'rxpck': '0.12', - 'txpck': '0.12', 'txkB': '0.04', - 'txcmp': '0.00', 'rxcmp': '0.00'}, - {'rxmcst': '0.00', 'iface': 'virbr0-nic', - 'rxkB': '0.00', 'rxpck': '0.00', - 'txpck': '0.00', 'txkB': '0.00', - 'txcmp': '0.00', 'rxcmp': '0.00'}, - {'rxmcst': '0.00', 'iface': 'virbr0', - 'rxkB': '0.00', 'rxpck': '0.00', - 'txpck': '0.00', 'txkB': '0.00', - 'txcmp': '0.00', 'rxcmp': '0.00'}, - {'rxmcst': '0.02', 'iface': 'em1', - 'rxkB': '0.21', 'rxpck': '2.23', - 'txpck': '0.40', 'txkB': '0.03', - 'txcmp': '0.00', 'rxcmp': '0.00'}], - 'per': 'second'}, - 'time': '07:00:01'} - -SHOW_NETWORK_STATUS_OK_OP = \ - {'message': "IFACE OK: tun0, wlp3s0, lo, " - "virbr0-nic, virbr0, em1 |tun0.rxpck=13.28 " - "tun0.txpck=13.51 tun0.rxkB=11.44 tun0.txkB=" - "1.28 wlp3s0.rxpck=13.73 wlp3s0.txpck=13.60 " - "wlp3s0.rxkB=12.60 wlp3s0.txkB=2.72 lo.rxpck=" - "0.12 lo.txpck=0.12 lo.rxkB=0.04 lo.txkB=0.04" - " virbr0-nic.rxpck=0.00 virbr0-nic.txpck=0.00" - " virbr0-nic.rxkB=0.00 virbr0-nic.txkB=0.00 " - "virbr0.rxpck=0.00 virbr0.txpck=0.00 " - "virbr0.rxkB=0.00 virbr0.txkB=0.00 em1.rxpck=" - "2.23 em1.txpck=0.40 em1.rxkB=0.21 em1.txkB=" - "0.03", 'exit_status': 0} - -SHOW_NETWORK_STATUS_INCLUDE_IP = \ - {'date': '2014-03-11', - 'utc': '1', 'interval': '60', - 'network': - {'net-dev': - [{'rxmcst': '0.00', - 'iface': 'tun0', 'rxkB': '11.44', - 'rxpck': '13.28', 'txpck': '13.51', - 'txkB': '1.28', 'txcmp': '0.00', - 'rxcmp': '0.00'}, - {'rxmcst': '0.00', 'iface': 'wlp3s0', - 'rxkB': '12.60', 'rxpck': '13.73', - 'txpck': '13.60', 'txkB': '2.72', - 'txcmp': '0.00', 'rxcmp': '0.00'}, - {'rxmcst': '0.00', 'iface': 'lo', - 'rxkB': '0.04', 'rxpck': '0.12', - 'txpck': '0.12', 'txkB': '0.04', - 'txcmp': '0.00', 'rxcmp': '0.00'}, - {'rxmcst': '0.00', 'iface': 'virbr0-nic', - 'rxkB': '0.00', 'rxpck': '0.00', - 'txpck': '0.00', 'txkB': '0.00', - 'txcmp': '0.00', 'rxcmp': '0.00'}, - {'rxmcst': '0.00', 'iface': 'virbr0', - 'rxkB': '0.00', 'rxpck': '0.00', - 'txpck': '0.00', 'txkB': '0.00', - 'txcmp': '0.00', 'rxcmp': '0.00'}, - {'rxmcst': '0.02', 'iface': 'em1', - 'rxkB': '0.21', 'rxpck': '2.23', - 'txpck': '0.40', 'txkB': '0.03', - 'txcmp': '0.00', 'rxcmp': '0.00'}], - 'per': 'second'}, - 'time': '07:00:01'} - -SHOW_NETWORK_STATUS_INCLUDE_OP = \ - {'message': "IFACE OK: lo |lo.rxpck=0.12 " - "lo.txpck=0.12 lo.rxkB=0.04 lo.txkB=0.04", - 'exit_status': 0} - -SHOW_NETWORK_STATUS_EXCLUDE_IP = \ - {'date': '2014-03-11', - 'utc': '1', 'interval': '60', - 'network': - {'net-dev': - [{'rxmcst': '0.00', - 'iface': 'tun0', 'rxkB': '11.44', - 'rxpck': '13.28', 'txpck': '13.51', - 'txkB': '1.28', 'txcmp': '0.00', - 'rxcmp': '0.00'}, - {'rxmcst': '0.00', 'iface': 'wlp3s0', - 'rxkB': '12.60', 'rxpck': '13.73', - 'txpck': '13.60', 'txkB': '2.72', - 'txcmp': '0.00', 'rxcmp': '0.00'}, - {'rxmcst': '0.00', 'iface': 'lo', - 'rxkB': '0.04', 'rxpck': '0.12', - 'txpck': '0.12', 'txkB': '0.04', - 'txcmp': '0.00', 'rxcmp': '0.00'}, - {'rxmcst': '0.00', 'iface': 'virbr0-nic', - 'rxkB': '0.00', 'rxpck': '0.00', - 'txpck': '0.00', 'txkB': '0.00', - 'txcmp': '0.00', 'rxcmp': '0.00'}, - {'rxmcst': '0.00', 'iface': 'virbr0', - 'rxkB': '0.00', 'rxpck': '0.00', - 'txpck': '0.00', 'txkB': '0.00', - 'txcmp': '0.00', 'rxcmp': '0.00'}, - {'rxmcst': '0.02', 'iface': 'em1', - 'rxkB': '0.21', 'rxpck': '2.23', - 'txpck': '0.40', 'txkB': '0.03', - 'txcmp': '0.00', 'rxcmp': '0.00'}], - 'per': 'second'}, - 'time': '07:00:01'} - -SHOW_NETWORK_STATUS_EXCLUDE_OP = \ - {'message': "IFACE OK: tun0, wlp3s0, virbr0-nic" - ", virbr0, em1 |tun0.rxpck=13.28 tun0.txpck=13.51" - " tun0.rxkB=11.44 tun0.txkB=1.28 wlp3s0.rxpck=13.73" - " wlp3s0.txpck=13.60 wlp3s0.rxkB=12.60 wlp3s0.txkB=" - "2.72 virbr0-nic.rxpck=0.00 virbr0-nic.txpck=0.00 " - "virbr0-nic.rxkB=0.00 virbr0-nic.txkB=0.00 " - "virbr0.rxpck=0.00 virbr0.txpck=0.00 virbr0.rxkB=" - "0.00 virbr0.txkB=0.00 em1.rxpck=2.23 em1.txpck=" - "0.40 em1.rxkB=0.21 em1.txkB=0.03", 'exit_status': 0} - -SHOW_NETWORK_STATUS_EXCEPTION_IP = \ - {'date': '2014-03-11', - 'utc': '1', 'interval': '60', - 'network': "test"} - -SHOW_NETWORK_STATUS_EXCEPTION_OP = \ - {'message': 'key: string indices must be integers' - ', not str not found', 'exit_status': 3} |