• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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