terom@184: from pvl.verkko import web, db, table terom@184: from pvl.verkko.utils import parse_timedelta, format_timedelta terom@184: terom@184: from pvl.web import html terom@184: terom@184: import datetime terom@184: terom@184: import logging; log = logging.getLogger('pvl.verkko.leases') terom@184: terom@184: class DHCPLease (object) : terom@184: """ terom@184: A DHCP lease with ip/mac and starts/ends terom@184: """ terom@184: terom@184: DATE_FMT = '%Y%m%d %H:%M' terom@184: TIME_FMT = '%H:%M:%S' terom@184: terom@184: @classmethod terom@184: def format_datetime (cls, dt) : terom@184: if dt.date() == datetime.date.today() : terom@184: return dt.strftime(cls.TIME_FMT) terom@184: else : terom@184: return dt.strftime(cls.DATE_FMT) terom@184: terom@184: def render_starts (self) : terom@184: return self.format_datetime(self.starts) terom@184: terom@184: def render_ends (self) : terom@184: if self.ends : terom@184: return self.format_datetime(self.ends) terom@184: else : terom@184: return None terom@184: terom@184: def ends_class (self) : terom@186: if self.ends and self.ends > datetime.datetime.now() : terom@184: return 'active' terom@184: else : terom@184: return None terom@184: terom@184: @property terom@184: def length (self) : terom@184: if self.ends : terom@184: return self.ends - self.starts terom@184: else : terom@184: return datetime.datetime.now() - self.starts terom@184: terom@184: def render_length (self) : terom@184: return format_timedelta(self.length) terom@184: terom@184: db.mapper(DHCPLease, db.dhcp_leases, properties=dict( terom@184: terom@184: )) terom@184: terom@184: class LeasesTable (table.Table) : terom@184: """ terom@186: of leases. terom@184: """ terom@184: terom@184: ITEMS = "Leases" terom@184: COLUMNS = ( terom@184: table.Column('ip', "IP", DHCPLease.ip, terom@184: rowfilter = True, terom@184: ), terom@184: table.Column('mac', "MAC", DHCPLease.mac, terom@184: rowfilter = True, terom@184: ), terom@184: table.Column('hostname', "Hostname", DHCPLease.hostname), terom@184: table.Column('starts', "Starts", DHCPLease.starts, DHCPLease.render_starts), terom@184: table.Column('ends', "Ends", DHCPLease.ends, DHCPLease.render_ends, terom@184: rowcss = DHCPLease.ends_class terom@184: ), terom@184: table.Column('length', "Lease", DHCPLease.ends - DHCPLease.starts, DHCPLease.render_length), terom@184: ) terom@184: terom@184: # XXX: have to set again terom@184: ATTRS = dict((col.attr, col) for col in COLUMNS) terom@184: terom@184: # default terom@184: SORT = DHCPLease.starts.desc() terom@184: PAGE = 20 terom@184: terom@184: class LeasesHandler (table.TableHandler, web.DatabaseHandler) : terom@184: """ terom@184: Combined database +
terom@184: """ terom@184: terom@184: CSS = web.DatabaseHandler.CSS + table.TableHandler.CSS + ( terom@184: "/static/dhcp/hosts.css", terom@184: ) terom@184: terom@186: # view terom@184: TABLE = LeasesTable terom@184: terom@184: def query (self) : terom@184: """ terom@184: Database SELECT query. terom@184: """ terom@184: terom@184: return self.db.query(DHCPLease) terom@184: terom@184: def filter_starts (self, value) : terom@184: return ((db.func.now() - DHCPLease.starts) < parse_timedelta(value)) terom@184: terom@184: def filter_ends (self, value) : terom@184: return ((DHCPLease.ends - db.func.now()) > parse_timedelta(value)) terom@184: terom@184: def filter_length (self, value) : terom@184: """ terom@184: Filter by leases valid on given date. terom@184: """ terom@184: terom@184: dt = datetime.datetime.strptime(value, DHCPLease.DATE_FMT) terom@184: terom@184: return db.between(dt, DHCPLease.starts, DHCPLease.ends) terom@184: terom@184: def filter_ip (self, value) : terom@184: # column is IPv4 string literal format... terom@184: if '/' in value : terom@184: return (db.func.inet(DHCPLease.ip).op('<<')(db.func.cidr(value))) terom@184: else : terom@184: return (db.func.inet(DHCPLease.ip) == db.func.inet(value)) terom@184: terom@184: terom@184: class ListHandler (LeasesHandler) : terom@184: """ terom@184: List of DHCP leases, using table.TableHandler -> LeasesTable. terom@184: """ terom@184: terom@184: #TABLE_ITEM_URL = ItemHandler terom@184: terom@184: def process (self) : terom@184: # super terom@184: table.TableHandler.process(self) terom@184: terom@184: def title (self) : terom@184: if self.filters : terom@184: return "DHCP Leases: {filters}".format(filters=self.filters_title()) terom@184: else : terom@184: return "DHCP Leases" terom@184: terom@184: def render (self) : terom@184: return ( terom@184: self.render_table(self.query, filters=self.filters, sort=self.sorts, page=self.page), terom@184: terom@184: #html.a(href=self.url())(html('«'), 'Back') if self.filters else None, terom@184: ) terom@184: terom@184: terom@184: