pvl/verkko/leases.py
author Tero Marttila <terom@paivola.fi>
Sat, 21 Dec 2013 22:57:44 +0200
changeset 329 b3778c190aa5
parent 186 0bfb34281141
permissions -rw-r--r--
version 0..0:

pvl.rrd: api.report()
pvl.wlan-syslog: track openwrt hostapd syslog wlan sta activity
pvl.verkko.wlan: basic Table view
pvl.dns-serial
pvl.dns-zone
pvl.dhcp.config: nested blocks
pvl.hosts-import: import hosts from dns/dhcp
pvl.hosts-dns: generate --forward-zone=paivola.fi and --reverse-zone=194.197.235
pvl.hosts-dhcp: generate dhcp hosts conf
from pvl.verkko import web, db, table
from pvl.verkko.utils import parse_timedelta, format_timedelta

from pvl.web import html

import datetime

import logging; log = logging.getLogger('pvl.verkko.leases')

class DHCPLease (object) :
    """
        A DHCP lease with ip/mac and starts/ends
    """

    DATE_FMT = '%Y%m%d %H:%M'
    TIME_FMT = '%H:%M:%S'

    @classmethod
    def format_datetime (cls, dt) :
        if dt.date() == datetime.date.today() :
            return dt.strftime(cls.TIME_FMT)
        else :
            return dt.strftime(cls.DATE_FMT)
    
    def render_starts (self) :
        return self.format_datetime(self.starts)

    def render_ends (self) :
        if self.ends :
            return self.format_datetime(self.ends)
        else :
            return None
    
    def ends_class (self) :
        if self.ends and self.ends > datetime.datetime.now() :
            return 'active'
        else :
            return None

    @property
    def length (self) :
        if self.ends :
            return self.ends - self.starts
        else :
            return datetime.datetime.now() - self.starts

    def render_length (self) :
        return format_timedelta(self.length)

db.mapper(DHCPLease, db.dhcp_leases, properties=dict(

))

class LeasesTable (table.Table) :
    """
        <table> of leases.
    """

    ITEMS   = "Leases"
    COLUMNS = (
        table.Column('ip',          "IP",       DHCPLease.ip,        
            rowfilter   = True,
        ),
        table.Column('mac',         "MAC",      DHCPLease.mac,
            rowfilter   = True,
        ),
        table.Column('hostname',    "Hostname", DHCPLease.hostname),
        table.Column('starts',      "Starts",   DHCPLease.starts,       DHCPLease.render_starts),
        table.Column('ends',        "Ends",     DHCPLease.ends,         DHCPLease.render_ends,
            rowcss  = DHCPLease.ends_class
        ),
        table.Column('length',      "Lease",    DHCPLease.ends - DHCPLease.starts,  DHCPLease.render_length),
    )
    
    # XXX: have to set again
    ATTRS = dict((col.attr, col) for col in COLUMNS)

    # default
    SORT = DHCPLease.starts.desc()
    PAGE = 20

class LeasesHandler (table.TableHandler, web.DatabaseHandler) :
    """
        Combined database + <table>
    """

    CSS = web.DatabaseHandler.CSS + table.TableHandler.CSS + (
        "/static/dhcp/hosts.css", 
    )
    
    # view
    TABLE = LeasesTable

    def query (self) :
        """
            Database SELECT query.
        """

        return self.db.query(DHCPLease)

    def filter_starts (self, value) :
        return ((db.func.now() - DHCPLease.starts) < parse_timedelta(value))

    def filter_ends (self, value) :
        return ((DHCPLease.ends - db.func.now()) > parse_timedelta(value))

    def filter_length (self, value) :
        """
            Filter by leases valid on given date.
        """

        dt = datetime.datetime.strptime(value, DHCPLease.DATE_FMT)

        return db.between(dt, DHCPLease.starts, DHCPLease.ends)

    def filter_ip (self, value) :
        # column is IPv4 string literal format...
        if '/' in value :
            return (db.func.inet(DHCPLease.ip).op('<<')(db.func.cidr(value)))
        else :
            return (db.func.inet(DHCPLease.ip) == db.func.inet(value))


class ListHandler (LeasesHandler) :
    """
        List of DHCP leases, using table.TableHandler -> LeasesTable.
    """

    #TABLE_ITEM_URL = ItemHandler

    def process (self) :
        # super
        table.TableHandler.process(self)
 
    def title (self) :
        if self.filters :
            return "DHCP Leases: {filters}".format(filters=self.filters_title())
        else :
            return "DHCP Leases"

    def render (self) :
        return (
            self.render_table(self.query, filters=self.filters, sort=self.sorts, page=self.page),

            #html.a(href=self.url())(html('&laquo;'), 'Back') if self.filters else None,
        )