mirror of
https://github.com/munin-monitoring/contrib.git
synced 2025-07-30 12:54:50 +00:00
Merge both SB6183 plugins
Add more error handling for bad status from modem Signed-off-by: Nathaniel Clark <Nathaniel.Clark@misrule.us>
This commit is contained in:
parent
7b07874918
commit
77e5305923
2 changed files with 95 additions and 168 deletions
|
@ -27,6 +27,7 @@ This provides the following multigraphs:
|
||||||
* upstream and downstream power levels
|
* upstream and downstream power levels
|
||||||
* downstream signal to noise ratio
|
* downstream signal to noise ratio
|
||||||
* downstream error counts
|
* downstream error counts
|
||||||
|
* uptime
|
||||||
|
|
||||||
The values are retrieved from the cable modem's status web pages at
|
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
|
192.168.100.1. So, this plugin must be installed on a munin node
|
||||||
|
@ -74,7 +75,8 @@ import sys
|
||||||
from urllib import request
|
from urllib import request
|
||||||
|
|
||||||
HOSTNAME = os.getenv("hostname", None)
|
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
|
UPCOUNT = 4
|
||||||
DOWNCOUNT = 16
|
DOWNCOUNT = 16
|
||||||
|
|
||||||
|
@ -83,6 +85,22 @@ if len(sys.argv) == 2:
|
||||||
if HOSTNAME:
|
if HOSTNAME:
|
||||||
print("host_name {0}\n".format(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
|
# POWER
|
||||||
print("multigraph arris_power")
|
print("multigraph arris_power")
|
||||||
print("graph_title Arris Power (dBmV)")
|
print("graph_title Arris Power (dBmV)")
|
||||||
|
@ -170,7 +188,7 @@ if len(sys.argv) == 2:
|
||||||
try:
|
try:
|
||||||
from lxml import html
|
from lxml import html
|
||||||
|
|
||||||
resp = request.urlopen(URL)
|
resp = request.urlopen(STATUS_URL)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print("no (missing lxml module)")
|
print("no (missing lxml module)")
|
||||||
except OSError:
|
except OSError:
|
||||||
|
@ -188,26 +206,70 @@ rxblank = re.compile(r"[\x00\n\r\t ]+", re.MULTILINE)
|
||||||
rxcomment = re.compile(r"<!--.*?-->")
|
rxcomment = re.compile(r"<!--.*?-->")
|
||||||
rxscript = re.compile(r"<script.*?</script>", re.MULTILINE)
|
rxscript = re.compile(r"<script.*?</script>", re.MULTILINE)
|
||||||
|
|
||||||
resp = request.urlopen(URL)
|
|
||||||
data = rxscript.sub(
|
def process_url(url):
|
||||||
"",
|
"""
|
||||||
rxcomment.sub(
|
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()))),
|
rxcomment.sub(
|
||||||
),
|
"",
|
||||||
)
|
rxblank.sub(
|
||||||
dom = html.fromstring(data)
|
" ", "".join(map(lambda x: x.decode("utf-8"), resp.readlines()))
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
dom = html.fromstring(data)
|
||||||
|
|
||||||
arr = dom.xpath('//table[contains(@class, "simpleTable")]')
|
return dom.xpath('//table[contains(@class, "simpleTable")]')
|
||||||
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")]
|
print("multi_graph arris_uptime")
|
||||||
# ['Channel', 'Lock Status', 'Modulation', 'Channel ID', 'Frequency', 'Power', 'SNR', 'Corrected', 'Uncorrectables']
|
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
|
# Summation Graphs
|
||||||
correct = 0
|
correct = 0
|
||||||
|
@ -223,7 +285,7 @@ for row in trs:
|
||||||
|
|
||||||
channel = int(data["Channel"])
|
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]
|
value = data["Power"].split(" ")[0]
|
||||||
print("power.value {0}".format(value))
|
print("power.value {0}".format(value))
|
||||||
power["down"][channel - 1] = value
|
power["down"][channel - 1] = value
|
||||||
|
@ -239,7 +301,7 @@ for row in trs:
|
||||||
|
|
||||||
# Fill missing
|
# Fill missing
|
||||||
for i in range(len(trs), DOWNCOUNT):
|
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("power.value U")
|
||||||
|
|
||||||
print("multigraph arris_snr.down_{0}".format(i + 1))
|
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("uncr.value U")
|
||||||
|
|
||||||
print("multigraph arris_error")
|
print("multigraph arris_error")
|
||||||
print("corr.value {0}".format(correct))
|
if arr:
|
||||||
print("uncr.value {0}".format(uncorr))
|
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")
|
print("multigraph arris_snr")
|
||||||
for i in range(0, DOWNCOUNT):
|
for i in range(0, DOWNCOUNT):
|
||||||
print("down_{0}.value {1}".format(i + 1, snr[i]))
|
print("down_{0}.value {1}".format(i + 1, snr[i]))
|
||||||
|
|
||||||
trs = upstream.findall("tr")
|
if arr:
|
||||||
# drop title
|
trs = upstream.findall("tr")
|
||||||
trs.pop(0)
|
# 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:
|
for row in trs:
|
||||||
data = dict(
|
data = dict(
|
||||||
zip(headings, ["".join(x.itertext()).strip() for x in row.findall("td")])
|
zip(headings, ["".join(x.itertext()).strip() for x in row.findall("td")])
|
||||||
|
|
|
@ -1,141 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
# Copyright 2020 Nathaniel Clark <nathaniel.clark@misrule.us>
|
|
||||||
#
|
|
||||||
# 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 <nathaniel.clark@misrule.us>
|
|
||||||
|
|
||||||
=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"<script.*?</script>", 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))
|
|
Loading…
Add table
Add a link
Reference in a new issue