#!/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);