summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvuko <vuko@hackerspace.pl>2020-06-11 09:11:24 +0200
committervuko <vuko@hackerspace.pl>2020-06-11 10:18:32 +0200
commit6f3ba0a61f7045985b911d48fa65e9ad27df3d5f (patch)
tree2a252d581c67ee990c5d109f29e81db3e308ce7c
parentfa542ad1796c9fc42b779da025e1a994a50eee26 (diff)
downloadcheckinator-6f3ba0a61f7045985b911d48fa65e9ad27df3d5f.tar.gz
checkinator-6f3ba0a61f7045985b911d48fa65e9ad27df3d5f.tar.bz2
checkinator-6f3ba0a61f7045985b911d48fa65e9ad27df3d5f.zip
skip already parsed entries in dhcpd.leases
-rw-r--r--at.py56
1 files changed, 49 insertions, 7 deletions
diff --git a/at.py b/at.py
index 0c5fb63..22bb220 100644
--- a/at.py
+++ b/at.py
@@ -167,36 +167,73 @@ class CapUpdater(Updater):
class MtimeUpdater(Updater):
def __init__(self, lease_file, *a, **kw):
self.lease_file = lease_file
+ self.position = 0
self.last_modified = 0
Updater.__init__(self, *a, **kw)
def file_changed(self, f):
- pass
+ """Callback on changed lease file
+
+ Args:
+ f: Lease file. File offset can be used to skip already parsed lines.
+
+ Returns: New byte offset pointing after last parsed byte.
+ """
+ return f.tell()
def _trigger_update(self):
app.logger.info('Lease file changed, updating')
with open(self.lease_file, 'r') as f:
- self.file_changed(f)
+ f.seek(self.position)
+ self.position = self.file_changed(f)
def run(self):
+ """Periodicaly check if file has changed
+
+ From ISC DHCPD manual:
+
+ New leases are appended to the end of the dhcpd.leases file. In
+ order to prevent the file from becoming arbitrarily large, from
+ time to time dhcpd creates a new dhcpd.leases file from its in-core
+ lease database. Once this file has been written to disk, the old
+ file is renamed dhcpd.leases~, and the new file is renamed
+ dhcpd.leases.
+ """
while True:
try:
- mtime = os.stat(self.lease_file).st_mtime
+ stat = os.stat(self.lease_file)
+ mtime = stat.st_mtime
+ size = stat.st_size
+ if size < self.position:
+ app.logger.info('leases file changed - reseting pointer')
+ self.position = 0
+ try:
+ # checking if DHCPD performed cleanup
+ # cleanup during operation seems to be currently broken
+ # on customs so this could never execute
+ purge_time = os.stat(self.lease_file + '~').st_mtime
+ if purge_time > self.last_modified:
+ app.logger.info('leases file purged - reseting pointer')
+ self.position = 0
+ except FileNotFoundError:
+ pass
if mtime > self.last_modified:
self._trigger_update()
self.last_modified = mtime
- sleep(3.0)
+ sleep(5.0)
except Exception as e:
- app.logger.error('Updater got an exception:\n' +
- traceback.format_exc(e))
+ app.logger.exception('Exception in updater')
sleep(10.0)
class DnsmasqUpdater(MtimeUpdater):
def file_changed(self, f):
+ raise NotImplementedError(
+ "This was not tested after adding differential update")
for line in f:
ts, hwaddr, ip, name, client_id = line.split(' ')
self.update(hwaddr, int(ts), ip, name)
+ return f.tell()
class DhcpdUpdater(MtimeUpdater):
@@ -206,7 +243,11 @@ class DhcpdUpdater(MtimeUpdater):
ip = None
hwaddr = None
atime = None
- for line in f:
+ while True:
+ # using readline because iter(file) blocks file.tell usage
+ line = f.readline()
+ if not f:
+ return offset
line = line.split('#')[0]
cmd = line.strip().split()
if not cmd:
@@ -222,6 +263,7 @@ class DhcpdUpdater(MtimeUpdater):
if(field == 'hardware'):
hwaddr = cmd[2][:-1]
if(field.startswith('}')):
+ offset = f.tell()
lease = False
if hwaddr is not None and atime is not None:
self.update(hwaddr, atime, ip, name)