pvl.wlan-syslog: split out separate KeyTimestampDatabase
authorTero Marttila <terom@paivola.fi>
Fri, 05 Jul 2013 01:17:51 +0300
changeset 240 8b55ca43e076
parent 239 198dc3a19f54
child 241 97a0a66e2211
pvl.wlan-syslog: split out separate KeyTimestampDatabase
bin/pvl.wlan-syslog
--- 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) :