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: