PageRenderTime 57ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/cablemodem_check.py

https://gitlab.com/mikeos2/Nagios_Plugins
Python | 223 lines | 121 code | 39 blank | 63 comment | 32 complexity | 794239fc949bcab64b6a29626785920a MD5 | raw file
  1. #!/usr/bin/python
  2. # cablemodem_check.py - A Python plugin for Nagious to retrieve data from a
  3. # Motorola SB6121 Cable Modem
  4. # Copyright (C) 2016 Michael Greene <mikeos2@gmail.com>
  5. #
  6. # This program is free software: you can redistribute it and/or modify it
  7. # under the terms of the GNU General Public License version 3, as published
  8. # by the Free Software Foundation.
  9. #
  10. # This program is distributed in the hope that it will be useful, but
  11. # WITHOUT ANY WARRANTY; without even the implied warranties of
  12. # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
  13. # PURPOSE. See the GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License along
  16. # with this program. If not, see <http://www.gnu.org/licenses/>.
  17. #
  18. # My modem info:
  19. # Model Name: SB6121
  20. # Vendor Name: Motorola
  21. # Firmware Name: SB_KOMODO-1.0.6.14-SCM03-NOSH
  22. # Boot Version: PSPU-Boot(25CLK) 1.0.12.18m3
  23. # Hardware Version: 5.0
  24. # Firmware Build Time: Jan 22 2015 14:31:03
  25. import sys
  26. import argparse
  27. import socket
  28. import urllib2
  29. # Nagios Plugin Return Codes
  30. # https://nagios-plugins.org/doc/guidelines.html#PLUGOUTPUT
  31. Nagios_OK = 0 # define the exit code if status is OK
  32. Nagios_WARNING = 1 # define the exit code if status is Warning
  33. Nagios_CRITICAL = 2 # define the exit code if status is Critical
  34. Nagios_UNKNOWN = 3 # define the exit code if status is Unknown
  35. try:
  36. from bs4 import BeautifulSoup
  37. except ImportError:
  38. print "Error: (" + str(Nagios_UNKNOWN) + ") install BeautifulSoup!"
  39. sys.exit(Nagios_UNKNOWN)
  40. class SnmpCalls:
  41. def __init__(self, host, oprtype):
  42. self.opr_type = oprtype
  43. # modem info pages
  44. self.modem_page_status = "http://" + host + "/indexData.htm"
  45. self.modem_page_logs = "http://" + host + "/cmLogsData.htm"
  46. self.current_status = Nagios_OK
  47. self.error_msg = "None"
  48. # Pull page and return, I think all errors are covered
  49. def _get_page(self, url):
  50. try:
  51. page = urllib2.urlopen(url, timeout = 2).read()
  52. except socket.timeout, error:
  53. self.current_status = Nagios_CRITICAL
  54. self.error_msg = str(error)
  55. return "Error"
  56. except urllib2.URLError, error:
  57. self.current_status = Nagios_CRITICAL
  58. self.error_msg = str(error)
  59. return "Error"
  60. return BeautifulSoup(page)
  61. # get tables from page
  62. def _get_pagetables(self, _page):
  63. # get the status page from the modem
  64. soup = self._get_page(_page)
  65. # if there was an error getting the page then
  66. # just get out and return the error
  67. if self.current_status != Nagios_OK:
  68. return self.current_status, self.error_msg
  69. page_list = list()
  70. for table_rows in soup.find_all('tr'):
  71. table_cell = table_rows.find_all('td')
  72. if self.opr_type < 3:
  73. # skips the format stuff and throw everything into a list
  74. if len(table_cell) != 0:
  75. page_list.append(table_cell[0].text)
  76. page_list.append(table_cell[1].text)
  77. # At this point all the items and status are in the list
  78. # of 20 elements with the items in the following order:
  79. # [index, description]
  80. #
  81. # 0 DOCSIS Downstream Channel Acquisition
  82. # 2 DOCSIS Ranging
  83. # 4 Establish IP Connectivity using DHCP
  84. # 6 Establish Time Of Day
  85. # 8 Transfer Operational Parameters through TFTP
  86. # 10 Register Connection
  87. # 12 Cable Modem Status
  88. # 14 Initialize Baseline Privacy
  89. # 16 Current Time and Date
  90. # 18 System Up Time
  91. # Get logs
  92. elif self.opr_type == 3:
  93. if len(table_cell) != 0:
  94. for temp in range(4):
  95. page_list.append(table_cell[temp].text)
  96. return page_list
  97. # Get modem status + misc info
  98. def modem_status(self):
  99. page_list = self._get_pagetables(self.modem_page_status)
  100. # Element 13 is the operational status, set Nagios
  101. # return to Crit if not operational otherwise
  102. # leave it OK
  103. if page_list[13] != "Operational":
  104. self.current_status = Nagios_CRITICAL
  105. # Set up the return message in the correct order
  106. modem_status = list()
  107. modem_status.append(page_list[12] + ": " + page_list[13])
  108. modem_status.append(page_list[0] + ": " + page_list[1])
  109. modem_status.append(page_list[2] + ": " + page_list[3])
  110. modem_status.append(page_list[4] + ": " + page_list[5])
  111. modem_status.append(page_list[6] + ": " + page_list[7])
  112. modem_status.append(page_list[8] + ": " + page_list[9])
  113. modem_status.append(page_list[10] + ": " + page_list[11])
  114. modem_status.append(page_list[14] + ": " + page_list[15])
  115. return self.current_status, modem_status
  116. # Get modem uptime
  117. def modem_uptime(self):
  118. page_list = self._get_pagetables(self.modem_page_status)
  119. # Uptime is elements 18 and 19 in the list
  120. ret_msg = page_list[18] + ": " + page_list[19]
  121. return self.current_status, ret_msg
  122. # Not sure what I will do with this but it pulls the
  123. # modem logs
  124. def modem_logs(self):
  125. page_list = self._get_pagetables(self.modem_page_logs)
  126. modem_logs = list()
  127. for temp in range(0, (len(page_list) - 1), 4):
  128. modem_logs.append(page_list[temp] +
  129. " " + '{0: <10}'.format(page_list[temp+1]) +
  130. " " + '{0: <6}'.format(page_list[temp+2]) +
  131. " " + page_list[temp+3])
  132. return self.current_status, modem_logs
  133. # ********** Main Entry **********
  134. #
  135. def main(snmpcalls):
  136. if snmpcalls.opr_type == 0 or snmpcalls.opr_type == 1:
  137. ret_status, ret_type = snmpcalls.modem_uptime()
  138. # Assume no errors can happen if we have got here so
  139. # no error checking - bad assumption?
  140. if snmpcalls.opr_type == 0:
  141. print str(ret_status) + " " + ret_type
  142. else:
  143. print ret_type
  144. return ret_status
  145. if snmpcalls.opr_type == 0 or snmpcalls.opr_type == 2:
  146. ret_status, ret_type = snmpcalls.modem_status()
  147. if snmpcalls.opr_type == 0:
  148. print "****** Return code: " + str(ret_status) + "******"
  149. for temp in range(len(ret_type)):
  150. print ret_type[temp]
  151. else:
  152. for temp in range(len(ret_type)):
  153. print ret_type[temp]
  154. return ret_status
  155. if snmpcalls.opr_type == 3:
  156. ret_status, ret_type = snmpcalls.modem_logs()
  157. for temp in range(len(ret_type)):
  158. print ret_type[temp]
  159. return ret_status
  160. if __name__ == "__main__":
  161. parser = argparse.ArgumentParser(
  162. description='Nagios command to retrieve Motorola SB6121 Cable Modem data.',
  163. usage='%(prog)s host type',
  164. epilog="Types: uptime, status")
  165. parser.add_argument('host', help='hostname')
  166. parser.add_argument('type', help='Type to check')
  167. args = parser.parse_args()
  168. # Just use brut force option selection
  169. if args.type == "debug":
  170. opr_type = 0 # do everything
  171. # no range checks for all
  172. args.warn = -1
  173. args.critical = -1
  174. elif args.type == "uptime":
  175. opr_type = 1 # uptime
  176. elif args.type == "status":
  177. opr_type = 2 # status and info
  178. elif args.type == "logs":
  179. opr_type = 3 # status and info
  180. else:
  181. print "Error: Bad operation type (" + args.type + ")." # bad operation
  182. sys.exit(Nagios_UNKNOWN)
  183. options = SnmpCalls(args.host, opr_type)
  184. sys.exit(main(options))