get-devs.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. #!/usr/bin/env python2.7
  2. #
  3. # Copyright (c) 2017-2019 Joe Clarke <jclarke@cisco.com>
  4. # All rights reserved.
  5. #
  6. # Redistribution and use in source and binary forms, with or without
  7. # modification, are permitted provided that the following conditions
  8. # are met:
  9. # 1. Redistributions of source code must retain the above copyright
  10. # notice, this list of conditions and the following disclaimer.
  11. # 2. Redistributions in binary form must reproduce the above copyright
  12. # notice, this list of conditions and the following disclaimer in the
  13. # documentation and/or other materials provided with the distribution.
  14. #
  15. # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  16. # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  19. # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  21. # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  22. # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  23. # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  24. # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  25. # SUCH DAMAGE.
  26. import requests
  27. from requests.packages.urllib3.exceptions import InsecureRequestWarning
  28. requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
  29. import json
  30. import sys
  31. import time
  32. import os
  33. from subprocess import call
  34. from sparker import Sparker
  35. import pprint
  36. import re
  37. from multiprocessing import Pool
  38. import socket
  39. import CLEUCreds
  40. TOOL = 'tool.ciscolive.network'
  41. CACHE_FILE = '/home/jclarke/cached_devs.dat'
  42. PING_DEVS_FILE = '/home/jclarke/ping-devs.json'
  43. TEXT_BAD = "**DANGER! DANGER!**: Pinger detected that device %s (IP: %s)%s is no longer reachable"
  44. TEXT_GOOD = "_RELAX_: Pinger has detected that device %s (IP: %s)%s is now reachable again"
  45. ROOM_NAME = 'Device Alarms'
  46. TEAM_NAME = 'CL19 NOC Team'
  47. excluded_devices = [r'^VHS-']
  48. additional_devices = []
  49. def check_prev(dev_dic, prev_devs, pstate='REACHABLE'):
  50. send_msg = False
  51. for pd in prev_devs:
  52. if pd['name'] == dev_dic['name']:
  53. if pd['reachability'] != pstate:
  54. send_msg = True
  55. break
  56. return send_msg
  57. def know_device(dev_dic, prev_devs):
  58. for pd in prev_devs:
  59. if pd['name'] == dev_dic['name']:
  60. return True
  61. return False
  62. def ping_device(dev):
  63. global TEAM_NAME, ROOM_NAME, TEXT_BAD, TEXT_GOOD, prev_devs, spark, excluded_devices
  64. dev_dic = {}
  65. dev_dic['name'] = dev['Hostname']
  66. dev_dic['ip'] = dev['IPAddress']
  67. if dev_dic['ip'] == '0.0.0.0':
  68. return None
  69. for exc in excluded_devices:
  70. if re.search(exc, dev_dic['name']) or re.search(exc, dev_dic['ip']):
  71. return None
  72. #print('Pinging {}'.format(dev_dic['name']))
  73. msg_text = TEXT_BAD
  74. send_msg = True
  75. if not dev['Reachable']:
  76. send_msg = know_device(dev_dic, prev_devs)
  77. for i in range(2):
  78. res = call(["/usr/local/sbin/fping",
  79. "-q", "-r0", dev_dic['ip']])
  80. time.sleep(.5)
  81. if res != 0:
  82. dev_dic['reachability'] = 'UNREACHABLE'
  83. send_msg = check_prev(dev_dic, prev_devs, 'UNREACHABLE')
  84. else:
  85. dev_dic['reachability'] = 'REACHABLE'
  86. msg_text = TEXT_GOOD
  87. send_msg = check_prev(dev_dic, prev_devs)
  88. if send_msg:
  89. loc = ''
  90. if 'LocationDetail' in dev:
  91. loc = ' (Location: {})'.format(dev['LocationDetail'])
  92. message = msg_text % (dev_dic['name'], dev_dic['ip'], loc)
  93. spark.post_to_spark(TEAM_NAME, ROOM_NAME, message)
  94. return dev_dic
  95. def get_devs(p):
  96. global TOOL, additional_devices
  97. url = "http://{}/get/switches/json".format(TOOL)
  98. devices = []
  99. # response = requests.request('GET', url)
  100. code = 200
  101. # code = response.status_code
  102. if code == 200:
  103. #j = json.loads(response.text)
  104. j = []
  105. for dev in additional_devices:
  106. ip = dev
  107. try:
  108. ip = socket.gethostbyname(dev)
  109. except:
  110. pass
  111. j.append({'Hostname': dev, 'IPAddress': ip, 'Reachable': True})
  112. results = [pool.apply_async(ping_device, [d]) for d in j]
  113. for res in results:
  114. retval = res.get()
  115. if retval is not None:
  116. devices.append(retval)
  117. return devices
  118. if __name__ == '__main__':
  119. prev_devs = []
  120. if os.path.exists(CACHE_FILE):
  121. fd = open(CACHE_FILE, 'r')
  122. prev_devs = json.load(fd)
  123. fd.close()
  124. spark = Sparker(token=CLEUCreds.SPARK_TOKEN)
  125. try:
  126. fd = open(PING_DEVS_FILE, 'r')
  127. additional_devices = json.load(fd)
  128. fd.close()
  129. except:
  130. pass
  131. pool = Pool(20)
  132. devs = get_devs(pool)
  133. fd = open(CACHE_FILE, 'w')
  134. json.dump(devs, fd, ensure_ascii=False, indent=4)
  135. fd.close()