--- a/bin/pvl.wlan-syslog Fri Jul 05 01:01:14 2013 +0300
+++ b/bin/pvl.wlan-syslog Fri Jul 05 01:17:51 2013 +0300
@@ -53,26 +53,29 @@
import re
from pvl.verkko import db
-class WlanStaDatabase (object) :
- HOSTAPD_STA_RE = re.compile(r'(?P<wlan>.+?): STA (?P<sta>.+?) (?P<msg>.+)')
-
- DB_TABLE = db.wlan_sta
- DB_LAST_SEEN = db.wlan_sta.c.last_seen
- DB_SELECT = (db.dhcp_hosts.c.gw, db.dhcp_hosts.c.ip)
+class KeyTimestampDatabase (object) :
+ """
+ A pvl.verkko.db table that tracks events by key/timestamp.
+ """
- def __init__ (self, db, interface_map=None) :
- """
- interface_map - {(hostname, interface): (nodename, wlan)}
+ DB_TABLE = None
+ DB_LAST_SEEN = None
+ DB_COUNT = None
+ DB_DISTINCT = None
+
+ def __init__ (self, db) :
"""
+ db - pvl.verkko.db.Database
+ """
+
self.db = db
- self.interface_map = interface_map
- def select (self, distinct=DB_SELECT, interval=None) :
+ def select (self, interval=None) :
"""
SELECT unique gw/ip hosts, for given interval.
"""
- query = db.select(distinct, distinct=True)
+ query = db.select(self.DB_DISTINCT, distinct=True)
if interval :
# timedelta
@@ -80,9 +83,9 @@
return self.db.select(query)
- def insert (self, key, update, timestamp, count=True) :
+ def insert (self, key, timestamp, update) :
"""
- INSERT new host
+ INSERT new row.
"""
query = self.DB_TABLE.insert().values(**key).values(**update).values(
@@ -90,15 +93,15 @@
last_seen = timestamp,
)
- if count :
+ if self.DB_COUNT :
query = query.values(count=1)
# -> id
return self.db.insert(query)
- def update (self, key, update, timestamp, count=True) :
+ def update (self, key, timestamp, update) :
"""
- UPDATE existing host, or return False if not found.
+ UPDATE existing row, or return False if not found.
"""
table = self.DB_TABLE
@@ -109,21 +112,38 @@
query = query.values(last_seen=timestamp)
- if count :
- query = query.values(count=db.func.coalesce(table.c.count, 0) + 1)
+ if self.DB_COUNT is not None :
+ query = query.values(count=db.func.coalesce(self.DB_COUNT, 0) + 1)
query = query.values(**update)
# -> any matched rows?
return self.db.update(query)
- def touch (self, key, update, timestamp, **opts) :
+ def touch (self, key, timestamp, update, **opts) :
# update existing?
- if self.update(key, update, timestamp, **opts) :
- log.info("Update: %s: %s: %s", key, update, timestamp)
+ if self.update(key, timestamp, update, **opts) :
+ log.info("Update: %s: %s: %s", key, timestamp, update)
else :
- log.info("Insert: %s: %s: %s", key, update, timestamp)
- self.insert(key, update, timestamp, **opts)
+ log.info("Insert: %s: %s: %s", key, timestamp, update)
+ self.insert(key, timestamp, update, **opts)
+
+
+class WlanStaDatabase (KeyTimestampDatabase) :
+ HOSTAPD_STA_RE = re.compile(r'(?P<wlan>.+?): STA (?P<sta>.+?) (?P<msg>.+)')
+
+ DB_TABLE = db.wlan_sta
+ DB_LAST_SEEN = db.wlan_sta.c.last_seen
+ DB_COUNT = db.wlan_sta.c.count
+
+ DB_DISTINCT = (db.wlan_sta.c.sta, )
+
+ def __init__ (self, db, interface_map=None) :
+ """
+ interface_map - {(hostname, interface): (nodename, wlan)}
+ """
+ KeyTimestampDatabase.__init__(self, db)
+ self.interface_map = interface_map
def parse (self, item) :
"""
@@ -137,6 +157,21 @@
return match.groupdict()
+ def lookup_wlan (self, host, iface) :
+ """
+ Lookup ap/ssid by host/iface.
+ """
+ mapping = None
+ if self.interface_map :
+ mapping = self.interface_map.get((host, iface))
+
+ if mapping :
+ return mapping
+ else :
+ # as-is
+ log.warning("Unknown host/iface: %s/%s", host, iface)
+ return host, iface
+
def __call__ (self, item) :
match = self.parse(item)
@@ -144,23 +179,13 @@
return
# lookup?
- ap, wlan = item['host'], match['wlan']
-
- if self.interface_map :
- mapping = self.interface_map.get((ap, wlan))
-
- if mapping :
- ap, wlan = mapping
+ ap, ssid = self.lookup_wlan(item['host'], match['wlan'])
# update/insert
self.touch(
- dict(
- ap = ap,
- wlan = wlan,
- sta = match['sta'],
- ), dict(
- msg = match['msg'],
- ), item['timestamp']
+ dict(ap=ap, wlan=ssid, sta=match['sta']),
+ item['timestamp'],
+ dict(msg=match['msg']),
)
def main (argv) :