From 77e53059239d959c3b02765a872e993e4f62103a Mon Sep 17 00:00:00 2001 From: Nathaniel Clark Date: Thu, 24 Sep 2020 08:48:06 -0400 Subject: [PATCH] Merge both SB6183 plugins Add more error handling for bad status from modem Signed-off-by: Nathaniel Clark --- plugins/router/arris-sb6183 | 122 +++++++++++++++++++------ plugins/router/arris-sb6183_uptime | 141 ----------------------------- 2 files changed, 95 insertions(+), 168 deletions(-) delete mode 100755 plugins/router/arris-sb6183_uptime diff --git a/plugins/router/arris-sb6183 b/plugins/router/arris-sb6183 index 7b6b9a74..aa912da3 100755 --- a/plugins/router/arris-sb6183 +++ b/plugins/router/arris-sb6183 @@ -27,6 +27,7 @@ This provides the following multigraphs: * upstream and downstream power levels * downstream signal to noise ratio * downstream error counts +* uptime The values are retrieved from the cable modem's status web pages at 192.168.100.1. So, this plugin must be installed on a munin node @@ -74,7 +75,8 @@ import sys from urllib import request HOSTNAME = os.getenv("hostname", None) -URL = "http://192.168.100.1/RgConnect.asp" +STATUS_URL = "http://192.168.100.1/RgConnect.asp" +INFO_URL = "http://192.168.100.1/RgSwInfo.asp" UPCOUNT = 4 DOWNCOUNT = 16 @@ -83,6 +85,22 @@ if len(sys.argv) == 2: if HOSTNAME: print("host_name {0}\n".format(HOSTNAME)) + # UPTIME + print( + """multigraph arris_uptime +graph_title Modem Uptime +graph_category system +graph_args --base 1000 -l 0 +graph_vlabel uptime in days +graph_scale no +graph_category system +graph_info This graph shows the number of days that the the host is up and running so far. +uptime.label uptime +uptime.info The system uptime itself in days. +uptime.draw AREA +""" + ) + # POWER print("multigraph arris_power") print("graph_title Arris Power (dBmV)") @@ -170,7 +188,7 @@ if len(sys.argv) == 2: try: from lxml import html - resp = request.urlopen(URL) + resp = request.urlopen(STATUS_URL) except ImportError: print("no (missing lxml module)") except OSError: @@ -188,26 +206,70 @@ rxblank = re.compile(r"[\x00\n\r\t ]+", re.MULTILINE) rxcomment = re.compile(r"") rxscript = re.compile(r"", re.MULTILINE) -resp = request.urlopen(URL) -data = rxscript.sub( - "", - rxcomment.sub( + +def process_url(url): + """ + Extract simpleTables from page at URL + """ + try: + resp = request.urlopen(url) + except OSError: + print("failed to contact router", file=sys.stderr) + return [] + if resp.status != 200: + print( + "failed to get status page %d: %s" % (resp.status, resp.reason), + file=sys.stderr, + ) + return [] + data = rxscript.sub( "", - rxblank.sub(" ", "".join(map(lambda x: x.decode("utf-8"), resp.readlines()))), - ), -) -dom = html.fromstring(data) + rxcomment.sub( + "", + rxblank.sub( + " ", "".join(map(lambda x: x.decode("utf-8"), resp.readlines())) + ), + ), + ) + dom = html.fromstring(data) -arr = dom.xpath('//table[contains(@class, "simpleTable")]') -downstream = arr[1] -upstream = arr[2] + return dom.xpath('//table[contains(@class, "simpleTable")]') -trs = downstream.findall("tr") -# drop title -trs.pop(0) -headings = ["".join(x.itertext()).strip() for x in trs.pop(0).findall("td")] -# ['Channel', 'Lock Status', 'Modulation', 'Channel ID', 'Frequency', 'Power', 'SNR', 'Corrected', 'Uncorrectables'] +print("multi_graph arris_uptime") +arr = process_url(INFO_URL) +if arr: + trs = arr[1].findall("tr") + # drop title + trs.pop(0) + + date = "".join(trs[0].findall("td")[1].itertext()).strip() + + arr = date.split(" ") + rx = re.compile(r"[hms]") + days = int(arr[0]) + hms = rx.sub("", arr[2]).split(":") + + seconds = ((days * 24 + int(hms[0])) * 60 + int(hms[1])) * 60 + int(hms[2]) + print("uptime.value {0}".format(seconds / 86400.0)) +else: + print("uptime.value U") + + +arr = process_url(STATUS_URL) +if arr: + downstream = arr[1] + upstream = arr[2] + + trs = downstream.findall("tr") + # drop title + trs.pop(0) + + headings = ["".join(x.itertext()).strip() for x in trs.pop(0).findall("td")] + # ['Channel', 'Lock Status', 'Modulation', 'Channel ID', 'Frequency', 'Power', 'SNR', 'Corrected', 'Uncorrectables'] +else: + trs = [] + headings = [] # Summation Graphs correct = 0 @@ -223,7 +285,7 @@ for row in trs: channel = int(data["Channel"]) - print("multigraph arris_power.down_{0}".format(channel)) + print("\nmultigraph arris_power.down_{0}".format(channel)) value = data["Power"].split(" ")[0] print("power.value {0}".format(value)) power["down"][channel - 1] = value @@ -239,7 +301,7 @@ for row in trs: # Fill missing for i in range(len(trs), DOWNCOUNT): - print("multigraph arris_power.down_{0}".format(i + 1)) + print("\nmultigraph arris_power.down_{0}".format(i + 1)) print("power.value U") print("multigraph arris_snr.down_{0}".format(i + 1)) @@ -250,19 +312,25 @@ for i in range(len(trs), DOWNCOUNT): print("uncr.value U") print("multigraph arris_error") -print("corr.value {0}".format(correct)) -print("uncr.value {0}".format(uncorr)) +if arr: + print("corr.value {0}".format(correct)) + print("uncr.value {0}".format(uncorr)) +else: + print("corr.value U") + print("uncr.value U") print("multigraph arris_snr") for i in range(0, DOWNCOUNT): print("down_{0}.value {1}".format(i + 1, snr[i])) -trs = upstream.findall("tr") -# drop title -trs.pop(0) +if arr: + trs = upstream.findall("tr") + # drop title + trs.pop(0) + + headings = ["".join(x.itertext()).strip() for x in trs.pop(0).findall("td")] + # ['Channel', 'Lock Status', 'US Channel Type', 'Channel ID', 'Symbol Rate', 'Frequency', 'Power'] -headings = ["".join(x.itertext()).strip() for x in trs.pop(0).findall("td")] -# ['Channel', 'Lock Status', 'US Channel Type', 'Channel ID', 'Symbol Rate', 'Frequency', 'Power'] for row in trs: data = dict( zip(headings, ["".join(x.itertext()).strip() for x in row.findall("td")]) diff --git a/plugins/router/arris-sb6183_uptime b/plugins/router/arris-sb6183_uptime deleted file mode 100755 index 7aac2318..00000000 --- a/plugins/router/arris-sb6183_uptime +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2020 Nathaniel Clark -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Library General Public License as published by -# the Free Software Foundation; version 2 only -# -# 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 Library General Public License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# - -""" -=head1 NAME - -arris-sb6183_uptime - Uptime monitoring for Arris SB6183 Cable Modem - -=head1 CONFIGURATION - -Make sure 192.168.100.1 is accessible through your firewall. - -To have this register with munin as it's own host set the "env.hostname" in config. -Also ensure that the hostname set is listed in munin.conf. - -[arris*] -env.hostname modem - -=head1 TESTING - -Developed and tested with: -firmware: D30CM-OSPREY-2.4.0.1-GA-02-NOSH -hardware version: 1 - -=head1 VERSION - -0.0.1 - -=head1 AUTHOR - -Nathaniel Clark - -=head1 LICENSE - -GPLv2 - -=head1 MAGIC MARKERS - - #%# family=contrib - #%# capabilities=autoconf - -=cut -""" -import re -import os -import sys -from urllib import request - - -HOSTNAME = os.getenv("hostname", None) -URL = "http://192.168.100.1/RgSwInfo.asp" - -if len(sys.argv) == 2: - if sys.argv[1] == "config": - if HOSTNAME: - print("host_name {0}".format(HOSTNAME)) - - # POWER - print( - """graph_title Modem Uptime -graph_category system -graph_args --base 1000 -l 0 -graph_vlabel uptime in days -graph_scale no -graph_category system -graph_info This graph shows the number of days that the the host is up and running so far. -uptime.label uptime -uptime.info The system uptime itself in days. -uptime.draw AREA -""" - ) - sys.exit(0) - - if sys.argv[1] == "autoconfig": - try: - from lxml import html - - resp = request.urlopen(URL) - except ImportError: - print("no (missing lxml module)") - except OSError: - print("no (no router)") - else: - if page.status_code == 200: - print("yes") - else: - print("no (Bad status code: %d)" % page.status_code) - sys.exit(0) - -from lxml import html - -rxblank = re.compile(r"[\x00\n\r\t ]+", re.MULTILINE) -rxcomment = re.compile(r"") -rxscript = re.compile(r"", re.MULTILINE) - -resp = request.urlopen(URL) -if resp.status != 200: - print( - "failed to get status page %d: %s" % (resp.status, resp.reason), file=sys.stderr - ) - print("uptime.value U") - sys.exit(0) - -data = rxscript.sub( - "", - rxcomment.sub( - "", - rxblank.sub(" ", "".join(map(lambda x: x.decode("utf-8"), resp.readlines()))), - ), -) -dom = html.fromstring(data) - -arr = dom.xpath('//table[contains(@class, "simpleTable")]') -trs = arr[1].findall("tr") -# drop title -trs.pop(0) - -date = "".join(trs[0].findall("td")[1].itertext()).strip() - -arr = date.split(" ") -rx = re.compile(r"[hms]") -days = int(arr[0]) -hms = rx.sub("", arr[2]).split(":") - -seconds = ((days * 24 + int(hms[0])) * 60 + int(hms[1])) * 60 + int(hms[2]) -print("uptime.value {0}".format(seconds / 86400.0))