|
@@ -0,0 +1,123 @@
|
|
|
+#!/usr/bin/python
|
|
|
+
|
|
|
+import datetime, collectd, os.path, ipaddress
|
|
|
+
|
|
|
+def parse_leases(lease_file):
|
|
|
+ validKeys = ['lease', 'starts', 'ends', '}']
|
|
|
+ leases = {}
|
|
|
+ lease = {}
|
|
|
+ for line in lease_file:
|
|
|
+ tokens = line.split()
|
|
|
+
|
|
|
+ if len(tokens) == 0 or tokens[0].startswith('#'):
|
|
|
+ continue
|
|
|
+
|
|
|
+ key = tokens[0].lower()
|
|
|
+
|
|
|
+ if key in validKeys:
|
|
|
+ if key == 'lease':
|
|
|
+ lease = {'id' : tokens[1]}
|
|
|
+
|
|
|
+ elif key == '}':
|
|
|
+ if lease['id'] in leases:
|
|
|
+ if leases[lease['id']]['ends'] < lease['ends']:
|
|
|
+ leases[lease['id']] = lease
|
|
|
+ else:
|
|
|
+ leases[lease['id']] = lease
|
|
|
+
|
|
|
+ else:
|
|
|
+ lease[key] = tokens[2]+' '+tokens[3].rstrip(';')
|
|
|
+
|
|
|
+ return leases
|
|
|
+
|
|
|
+def parse_dhcpd_conf(config_file):
|
|
|
+ subnet = {}
|
|
|
+ subnets = {}
|
|
|
+ for line in config_file:
|
|
|
+ line = line.strip().rstrip(';')
|
|
|
+ tokens = line.split()
|
|
|
+
|
|
|
+ if len(tokens) == 0 or tokens[0].startswith('#'):
|
|
|
+ continue
|
|
|
+ key = tokens[0].lower()
|
|
|
+
|
|
|
+ if key == 'subnet':
|
|
|
+ net = ipaddress.ip_network(unicode(tokens[1]+'/'+tokens[3]))
|
|
|
+ subnet = {'netaddr_str' : tokens[1], 'netaddr_int' : int(net.network_address), 'netmask_str' : tokens[3], 'netmask_int' : int(net.netmask)}
|
|
|
+
|
|
|
+ elif key == 'interface':
|
|
|
+ subnet['interface'] = tokens[1]
|
|
|
+
|
|
|
+ elif key == '}':
|
|
|
+ subnet_add(subnets, subnet)
|
|
|
+ subnet = {}
|
|
|
+
|
|
|
+ return subnets
|
|
|
+
|
|
|
+def subnet_add(subnets, subnet):
|
|
|
+ if 'interface' not in subnet:
|
|
|
+ subnet['interface'] = 'global'
|
|
|
+ sub_name = subnet['interface']
|
|
|
+ if sub_name not in subnets:
|
|
|
+ subnets[sub_name] = subnet
|
|
|
+ else:
|
|
|
+ pass #needs to be implemented
|
|
|
+
|
|
|
+def count_active_leases(all_leases, now, subnets):
|
|
|
+ count_active = 0
|
|
|
+ count_all = 0
|
|
|
+ subnet_counter = {}
|
|
|
+ for interface in subnets.iterkeys():
|
|
|
+ subnet_counter[interface] = {'count_active': 0, 'count_all': 0, 'count_touch': 0}
|
|
|
+
|
|
|
+ for lease in all_leases.itervalues():
|
|
|
+ addr = int(ipaddress.ip_address(unicode(lease['id'])))
|
|
|
+ for subnet in subnets.itervalues():
|
|
|
+ if (addr & subnet['netmask_int']) == subnet['netaddr_int']:
|
|
|
+ subnc = subnet_counter[subnet['interface']]
|
|
|
+ subnc['count_all'] += 1
|
|
|
+ count_all += 1
|
|
|
+ if timestamp_inbetween(now, lease['starts'], lease['ends']):
|
|
|
+ subnc['count_active'] += 1
|
|
|
+ count_active += 1
|
|
|
+ break
|
|
|
+
|
|
|
+ for subnet in subnet_counter.itervalues():
|
|
|
+ subnet['count_touch'] = subnet['count_all'] - subnet['count_active']
|
|
|
+ count_touch = count_all - count_active
|
|
|
+
|
|
|
+ return count_active, count_touch, subnet_counter
|
|
|
+
|
|
|
+
|
|
|
+def timestamp_inbetween(now, start, end):
|
|
|
+ return start < now < end
|
|
|
+
|
|
|
+def read(data=None):
|
|
|
+ configfile = '/etc/dhcp/dhcpd.conf'
|
|
|
+ if os.path.isfile(configfile):
|
|
|
+ cfile = open(configfile, 'r')
|
|
|
+ config = parse_dhcpd_conf(cfile)
|
|
|
+ leasefile = '/var/lib/dhcp/dhcpd.leases'
|
|
|
+ if os.path.isfile(leasefile):
|
|
|
+ lfile = open(leasefile, 'r')
|
|
|
+ all_leases = parse_leases(lfile)
|
|
|
+ lfile.close()
|
|
|
+ count_active, count_touch, subnet_counter = count_active_leases(all_leases, datetime.datetime.utcnow().strftime("%Y/%m/%d %H:%M:%S"), config)
|
|
|
+ vl = collectd.Values(type='dhcp_leases')
|
|
|
+ vl.plugin='dhcp'
|
|
|
+ vl.type_instance = 'all_interfaces'
|
|
|
+ vl.dispatch(values=[count_active, count_touch])
|
|
|
+ for k, v in subnet_counter.iteritems():
|
|
|
+ vl = collectd.Values(type='dhcp_leases')
|
|
|
+ vl.plugin='dhcp'
|
|
|
+ vl.type_instance = k
|
|
|
+ vl.dispatch(values=[v['count_active'], v['count_touch']])
|
|
|
+ vl = collectd.Values(type='dhcp_leases')
|
|
|
+
|
|
|
+
|
|
|
+def write(vl, data=None):
|
|
|
+ for i in vl.values:
|
|
|
+ print "%s (%s): %f" % (vl.plugin, vl.type, i)
|
|
|
+
|
|
|
+collectd.register_read(read)
|
|
|
+collectd.register_write(write);
|