timerdb-info.py 2.74 KB
Newer Older
1
#!/usr/bin/env python
2 3 4 5 6
# vim: et ts=4 sw=4 sts=4
#
# Dump content of zone timers database in user readable format.
#

7 8
from __future__ import print_function

9 10 11 12 13 14 15 16 17
import datetime
import lmdb
import struct
import sys

class TimerDBInfo:
    def __init__(self, path):
        self._path = path

18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
    @classmethod
    def format_timestamp(cls, timestamp):
        if timestamp == 0:
            return "never"
        else:
            return datetime.datetime.fromtimestamp(timestamp).isoformat()

    @classmethod
    def format_seconds(cls, value):
        return "%d" % value

    @classmethod
    def format_value(cls, id, value):
        timers = {
                # knot >= 1.6
                0x01: ("legacy_refresh", cls.format_timestamp),
                0x02: ("legacy_expire",  cls.format_timestamp),
                0x03: ("legacy_flush",   cls.format_timestamp),
                # knot >= 2.4
                0x80: ("soa_expire",   cls.format_seconds),
                0x81: ("last_flush",   cls.format_timestamp),
                0x82: ("last_refresh", cls.format_timestamp),
                0x83: ("next_refresh", cls.format_timestamp),
41 42 43
                # knot >= 2.6
                0x84: ("last_resalt",      cls.format_timestamp),
                0x85: ("next_parent_ds_q", cls.format_timestamp),
44 45 46 47 48
        }
        if id in timers:
            return (timers[id][0], timers[id][1](value))
        else:
            return ("%02x" % id, "%08x" % value)
49 50 51 52

    @classmethod
    def parse_dname(cls, dname):
        labels = []
53 54
        while ord(dname[0]) != 0:
            llen = ord(dname[0])
55 56 57 58 59 60 61 62 63 64 65 66
            label = dname[1:llen+1].decode("utf-8")
            dname = dname[llen+1:]
            labels.append(label)
        return ".".join(labels)

    @classmethod
    def parse_timers(cls, binary):
        timers = {}
        while len(binary) > 0:
            chunk = binary[:9]
            binary = binary[9:]
            id, value = struct.unpack("!BQ", chunk)
67
            timers[id] = value
68 69 70 71 72
        return timers

    @classmethod
    def format_line(cls, zone, timers):
        parts = [zone]
73 74
        for id, value in timers.items():
            parts.append("%s %s" % cls.format_value(id, value))
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
        return " | ".join(parts)

    def run(self):
        with lmdb.open(self._path, readonly=True) as db:
            with db.begin() as txn:
                cursor = txn.cursor()
                for key, value in cursor:
                    zone = self.parse_dname(key)
                    timers = self.parse_timers(value)
                    print(self.format_line(zone, timers))

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("usage: %s <timerdb-path>" % sys.argv[0], file=sys.stderr)
        sys.exit(1)
    path = sys.argv[1]
    app = TimerDBInfo(path)
    app.run()