python.d/isc_dhcpd: add support for ip ranges (#9755)
Javier Pastor committed
Aug 17, 2020 at 10:32 UTC
5541187fcf745eb381c9cc90691b1265a37563d0
3 files changed
+74
-6
collectors/python.d.plugin/isc_dhcpd/README.md
+7
-3
@@ -12,6 +12,7 @@ Monitors the leases database to show all active leases for given pools.
12
13
- dhcpd leases file MUST BE readable by Netdata
14
- pools MUST BE in CIDR format
15
+- `python-ipaddress` package is needed in Python2
16
17
It produces:
18
@@ -41,11 +42,14 @@ Sample:
42
43
```yaml
44
local:
44
- leases_path : '/var/lib/dhcp/dhcpd.leases'
45
- pools : '192.168.3.0/24 192.168.4.0/24 192.168.5.0/24'
45
+ leases_path: '/var/lib/dhcp/dhcpd.leases'
46
+ pools:
47
+ office: '192.168.2.0/24' # name(dimension): pool in CIDR format
48
+ wifi: '192.168.3.10-192.168.3.20' # name(dimension): pool in IP Range format
49
+ 192.168.4.0/24: '192.168.4.0/24' # name(dimension): pool in CIDR format
50
+ wifi-guest: '192.168.5.0/24 192.168.6.10-192.168.6.20' # name(dimension): pool in CIDR + IP Range format
51
```
52
48
-In case of python2 you need to install `py2-ipaddress` to make plugin work.
53
The module will not work If no configuration is given.
54
55
---
collectors/python.d.plugin/isc_dhcpd/isc_dhcpd.chart.py
+63
@@ -45,6 +45,19 @@ CHARTS = {
45
}
46
}
47
48
+POOL_CIDR = "CIDR"
49
+POOL_IP_RANGE = "IP_RANGE"
50
+POOL_UNKNOWN = "UNKNOWN"
51
+
52
+def detect_ip_type(ip):
53
+ ip_type = ip.split("-")
54
+ if len(ip_type) == 1:
55
+ return POOL_CIDR
56
+ elif len(ip_type) == 2:
57
+ return POOL_IP_RANGE
58
+ else:
59
+ return POOL_UNKNOWN
60
+
61
62
class DhcpdLeasesFile:
63
def __init__(self, path):
@@ -86,6 +99,32 @@ class Pool:
99
def __init__(self, name, network):
100
self.id = re.sub(r'[:/.-]+', '_', name)
101
self.name = name
102
+
103
+ self.networks = list()
104
+ for network in network.split(" "):
105
+ if not network:
106
+ continue
107
+
108
+ ip_type = detect_ip_type(ip=network)
109
+ if ip_type == POOL_CIDR:
110
+ self.networks.append(PoolCIDR(network=network))
111
+ elif ip_type == POOL_IP_RANGE:
112
+ self.networks.append(PoolIPRange(ip_range=network))
113
+ else:
114
+ raise ValueError('Network ({0}) incorrect syntax, expect CIDR or IPRange format.'.format(network))
115
+
116
+ def num_hosts(self):
117
+ return sum([network.num_hosts() for network in self.networks])
118
+
119
+ def __contains__(self, item):
120
+ for network in self.networks:
121
+ if item in network:
122
+ return True
123
+ return False
124
+
125
+
126
+class PoolCIDR:
127
+ def __init__(self, network):
128
self.network = ipaddress.ip_network(address=u'%s' % network)
129
130
def num_hosts(self):
@@ -95,6 +134,30 @@ class Pool:
134
return item.address in self.network
135
136
137
+class PoolIPRange:
138
+ def __init__(self, ip_range):
139
+ ip_range = ip_range.split("-")
140
+ self.networks = list(self._summarize_address_range(ip_range[0], ip_range[1]))
141
+
142
+ @staticmethod
143
+ def ip_address(ip):
144
+ return ipaddress.ip_address(u'%s' % ip)
145
+
146
+ def _summarize_address_range(self, first, last):
147
+ address_first = self.ip_address(first)
148
+ address_last = self.ip_address(last)
149
+ return ipaddress.summarize_address_range(address_first, address_last)
150
+
151
+ def num_hosts(self):
152
+ return sum([network.num_addresses for network in self.networks])
153
+
154
+ def __contains__(self, item):
155
+ for network in self.networks:
156
+ if item.address in network:
157
+ return True
158
+ return False
159
+
160
+
161
class Lease:
162
def __init__(self, address, ends, state):
163
self.address = ipaddress.ip_address(address=u'%s' % address)
collectors/python.d.plugin/isc_dhcpd/isc_dhcpd.conf
+4
-3
@@ -63,9 +63,10 @@
63
#
64
# leases_path: 'PATH' # the path to dhcpd.leases file
65
# pools:
66
-# office: '192.168.2.0/24' # name(dimension): pool in CIDR format
67
-# wifi: '192.168.3.0/24' # name(dimension): pool in CIDR format
68
-# 192.168.4.0/24: '192.168.4.0/24' # name(dimension): pool in CIDR format
66
+# office: '192.168.2.0/24' # name(dimension): pool in CIDR format
67
+# wifi: '192.168.3.10-192.168.3.20' # name(dimension): pool in IP Range format
68
+# 192.168.4.0/24: '192.168.4.0/24' # name(dimension): pool in CIDR format
69
+# wifi-guest: '192.168.5.0/24 192.168.6.10-192.168.6.20' # name(dimension): pool in CIDR + IP Range format
70
#
71
#-----------------------------------------------------------------------
72
# IMPORTANT notes