diff options
author | vuko <vuko@hackerspace.pl> | 2020-06-11 09:11:24 +0200 |
---|---|---|
committer | vuko <vuko@hackerspace.pl> | 2020-06-11 10:18:32 +0200 |
commit | 6f3ba0a61f7045985b911d48fa65e9ad27df3d5f (patch) | |
tree | 2a252d581c67ee990c5d109f29e81db3e308ce7c | |
parent | fa542ad1796c9fc42b779da025e1a994a50eee26 (diff) | |
download | checkinator-6f3ba0a61f7045985b911d48fa65e9ad27df3d5f.tar.gz checkinator-6f3ba0a61f7045985b911d48fa65e9ad27df3d5f.tar.bz2 checkinator-6f3ba0a61f7045985b911d48fa65e9ad27df3d5f.zip |
skip already parsed entries in dhcpd.leases
-rw-r--r-- | at.py | 56 |
1 files changed, 49 insertions, 7 deletions
@@ -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) |