1#!/usr/bin/python2 2 3""" 4usage: 5./dhcp_failed_machines.py /var/log/dhcp.log 6 7You can also run it directly on the gzip'd logs. 8 9This script basically expects to run from the dhcp machine, as it looks at 10/etc/dhcp/dhcpd.conf to be able to do reverse DNS lookups. It also expects the 11dhcp log to be copied to some local file. 12 13If you're lucky, there might still be a copy of this script already on the dhcp 14server at /tmp/looky.py. 15""" 16 17import gzip 18import itertools 19import pprint 20import re 21import sys 22 23lookups = {} 24 25with open('/etc/dhcp/dhcpd.conf', 'r') as f: 26 for line in f: 27 if line.startswith('#'): 28 continue 29 if line.split() and line.split()[0] == 'host': 30 hostconf = list(itertools.takewhile(lambda x: x.strip() != '}', f)) 31 d = dict([h.strip().split()[-2:] for h in hostconf]) 32 hostname = d['ddns-hostname'].replace('"', '').replace(';', '') 33 lookups[d['fixed-address'].replace(';', '')] = hostname 34 35 36offers = {} 37offenders = set() 38restarts = [] 39 40rgx = re.compile( 41 r'(?P<command>[A-Z]+) (?:from|on|for) (?P<host>\d+.\d+.\d+.\d+)') 42server_restart_str = 'Internet Systems Consortium' 43 44 45def open_file(f): 46 if f.endswith('.gz'): 47 return gzip.open(f, 'r') 48 else: 49 return open(f, 'r') 50 51with open_file(sys.argv[1]) as f: 52 for line in f: 53 if server_restart_str in line: 54 restarts.append(line) 55 continue 56 m = rgx.search(line) 57 if m: 58 command = m.group('command') 59 host = m.group('host') 60 if command == 'DHCPOFFER': 61 offers[host] = offers.get(host, 0) + 1 62 if offers[host] > 2: 63 offenders.add(host) 64 if command == 'DHCPREQUEST': 65 offers[host] = 0 66 67if restarts: 68 print 'DHCP restarts:\n %s' % ''.join(restarts) 69 70def lookup(h): 71 return lookups.get(h, h) 72 73hosts = sorted([lookup(h) for h in offenders]) 74if len(sys.argv) == 2: 75 pprint.pprint(hosts) 76else: 77 warning = int(sys.argv[2]) 78 critical = int(sys.argv[3]) 79 if len(offenders) > critical: 80 print ('DHCP Critical, number of duts with DHCP failure is %d: %s' % 81 (len(hosts), ', '.join(hosts))) 82 sys.exit(2) 83 elif len(offenders) > warning: 84 print ('DHCP Warning, number of duts with DHCP failure is %d: %s' % 85 (len(hosts), ', '.join(hosts))) 86 sys.exit(1) 87 else: 88 print ('DHCP OK, number of duts with DHCP failure is %d: %s' % 89 (len(hosts), ', '.join(hosts))) 90 sys.exit(0) 91