123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- #!/usr/bin/env python2.7
- #
- # Copyright (c) 2017-2019 Joe Clarke <jclarke@cisco.com>
- # All rights reserved.
- #
- # Redistribution and use in source and binary forms, with or without
- # modification, are permitted provided that the following conditions
- # are met:
- # 1. Redistributions of source code must retain the above copyright
- # notice, this list of conditions and the following disclaimer.
- # 2. Redistributions in binary form must reproduce the above copyright
- # notice, this list of conditions and the following disclaimer in the
- # documentation and/or other materials provided with the distribution.
- #
- # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- # SUCH DAMAGE.
- import requests
- from requests.packages.urllib3.exceptions import InsecureRequestWarning
- requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
- import json
- import sys
- import time
- import os
- from subprocess import call
- from sparker import Sparker
- import pprint
- import re
- from multiprocessing import Pool
- import socket
- import CLEUCreds
- TOOL = 'tool.ciscolive.network'
- CACHE_FILE = '/home/jclarke/cached_devs.dat'
- PING_DEVS_FILE = '/home/jclarke/ping-devs.json'
- TEXT_BAD = "**DANGER! DANGER!**: Pinger detected that device %s (IP: %s)%s is no longer reachable"
- TEXT_GOOD = "_RELAX_: Pinger has detected that device %s (IP: %s)%s is now reachable again"
- ROOM_NAME = 'Device Alarms'
- TEAM_NAME = 'CL19 NOC Team'
- excluded_devices = [r'^VHS-']
- additional_devices = []
- def check_prev(dev_dic, prev_devs, pstate='REACHABLE'):
- send_msg = False
- for pd in prev_devs:
- if pd['name'] == dev_dic['name']:
- if pd['reachability'] != pstate:
- send_msg = True
- break
- return send_msg
- def know_device(dev_dic, prev_devs):
- for pd in prev_devs:
- if pd['name'] == dev_dic['name']:
- return True
- return False
- def ping_device(dev):
- global TEAM_NAME, ROOM_NAME, TEXT_BAD, TEXT_GOOD, prev_devs, spark, excluded_devices
- dev_dic = {}
- dev_dic['name'] = dev['Hostname']
- dev_dic['ip'] = dev['IPAddress']
- if dev_dic['ip'] == '0.0.0.0':
- return None
- for exc in excluded_devices:
- if re.search(exc, dev_dic['name']) or re.search(exc, dev_dic['ip']):
- return None
- #print('Pinging {}'.format(dev_dic['name']))
- msg_text = TEXT_BAD
- send_msg = True
- if not dev['Reachable']:
- send_msg = know_device(dev_dic, prev_devs)
- for i in range(2):
- res = call(["/usr/local/sbin/fping",
- "-q", "-r0", dev_dic['ip']])
- time.sleep(.5)
- if res != 0:
- dev_dic['reachability'] = 'UNREACHABLE'
- send_msg = check_prev(dev_dic, prev_devs, 'UNREACHABLE')
- else:
- dev_dic['reachability'] = 'REACHABLE'
- msg_text = TEXT_GOOD
- send_msg = check_prev(dev_dic, prev_devs)
- if send_msg:
- loc = ''
- if 'LocationDetail' in dev:
- loc = ' (Location: {})'.format(dev['LocationDetail'])
- message = msg_text % (dev_dic['name'], dev_dic['ip'], loc)
- spark.post_to_spark(TEAM_NAME, ROOM_NAME, message)
- return dev_dic
- def get_devs(p):
- global TOOL, additional_devices
- url = "http://{}/get/switches/json".format(TOOL)
- devices = []
- # response = requests.request('GET', url)
- code = 200
- # code = response.status_code
- if code == 200:
- #j = json.loads(response.text)
- j = []
- for dev in additional_devices:
- ip = dev
- try:
- ip = socket.gethostbyname(dev)
- except:
- pass
- j.append({'Hostname': dev, 'IPAddress': ip, 'Reachable': True})
- results = [pool.apply_async(ping_device, [d]) for d in j]
- for res in results:
- retval = res.get()
- if retval is not None:
- devices.append(retval)
- return devices
- if __name__ == '__main__':
- prev_devs = []
- if os.path.exists(CACHE_FILE):
- fd = open(CACHE_FILE, 'r')
- prev_devs = json.load(fd)
- fd.close()
- spark = Sparker(token=CLEUCreds.SPARK_TOKEN)
- try:
- fd = open(PING_DEVS_FILE, 'r')
- additional_devices = json.load(fd)
- fd.close()
- except:
- pass
- pool = Pool(20)
- devs = get_devs(pool)
- fd = open(CACHE_FILE, 'w')
- json.dump(devs, fd, ensure_ascii=False, indent=4)
- fd.close()
|