| #!/usr/bin/python2 |
| |
| """ |
| usage: |
| ./dhcp_failed_machines.py /var/log/dhcp.log |
| |
| You can also run it directly on the gzip'd logs. |
| |
| This script basically expects to run from the dhcp machine, as it looks at |
| /etc/dhcp/dhcpd.conf to be able to do reverse DNS lookups. It also expects the |
| dhcp log to be copied to some local file. |
| |
| If you're lucky, there might still be a copy of this script already on the dhcp |
| server at /tmp/looky.py. |
| """ |
| |
| import gzip |
| import itertools |
| import pprint |
| import re |
| import sys |
| |
| lookups = {} |
| |
| with open('/etc/dhcp/dhcpd.conf', 'r') as f: |
| for line in f: |
| if line.startswith('#'): |
| continue |
| if line.split() and line.split()[0] == 'host': |
| hostconf = list(itertools.takewhile(lambda x: x.strip() != '}', f)) |
| d = dict([h.strip().split()[-2:] for h in hostconf]) |
| hostname = d['ddns-hostname'].replace('"', '').replace(';', '') |
| lookups[d['fixed-address'].replace(';', '')] = hostname |
| |
| |
| offers = {} |
| offenders = set() |
| restarts = [] |
| |
| rgx = re.compile( |
| r'(?P<command>[A-Z]+) (?:from|on|for) (?P<host>\d+.\d+.\d+.\d+)') |
| server_restart_str = 'Internet Systems Consortium' |
| |
| |
| def open_file(f): |
| if f.endswith('.gz'): |
| return gzip.open(f, 'r') |
| else: |
| return open(f, 'r') |
| |
| with open_file(sys.argv[1]) as f: |
| for line in f: |
| if server_restart_str in line: |
| restarts.append(line) |
| continue |
| m = rgx.search(line) |
| if m: |
| command = m.group('command') |
| host = m.group('host') |
| if command == 'DHCPOFFER': |
| offers[host] = offers.get(host, 0) + 1 |
| if offers[host] > 2: |
| offenders.add(host) |
| if command == 'DHCPREQUEST': |
| offers[host] = 0 |
| |
| if restarts: |
| print 'DHCP restarts:\n %s' % ''.join(restarts) |
| |
| def lookup(h): |
| return lookups.get(h, h) |
| |
| hosts = sorted([lookup(h) for h in offenders]) |
| if len(sys.argv) == 2: |
| pprint.pprint(hosts) |
| else: |
| warning = int(sys.argv[2]) |
| critical = int(sys.argv[3]) |
| if len(offenders) > critical: |
| print ('DHCP Critical, number of duts with DHCP failure is %d: %s' % |
| (len(hosts), ', '.join(hosts))) |
| sys.exit(2) |
| elif len(offenders) > warning: |
| print ('DHCP Warning, number of duts with DHCP failure is %d: %s' % |
| (len(hosts), ', '.join(hosts))) |
| sys.exit(1) |
| else: |
| print ('DHCP OK, number of duts with DHCP failure is %d: %s' % |
| (len(hosts), ', '.join(hosts))) |
| sys.exit(0) |