diff adslstats.py @ 23:4b6c811e77df

Save & load session cookie so we don't have to reauth every time. It seems even successful auth attemps are rate limited and get a 503.
author Daniel O'Connor <darius@dons.net.au>
date Sat, 17 Jun 2017 15:59:23 +0930
parents a53f90508a06
children 806b1ed7f1b5
line wrap: on
line diff
--- a/adslstats.py	Thu Jun 15 15:07:01 2017 +0930
+++ b/adslstats.py	Sat Jun 17 15:59:23 2017 +0930
@@ -39,6 +39,7 @@
 import mysrp as srp
 import optparse
 import os
+import os.path
 import re
 import requests
 import rrdtool
@@ -51,6 +52,7 @@
 conf.set('global', 'username', 'admin')
 conf.set('global', 'password', 'admin')
 conf.set('global', 'name', '10.0.2.14')
+conf.set('global', 'cookiejar', os.path.expanduser('~/.adslstats.cj'))
 
 conflist = ['adslstats.ini']
 if ('HOME' in os.environ):
@@ -100,15 +102,32 @@
     stats = DSLStats()
     parser = ConfigParser.ConfigParser()
     base = 'http://%s' % (conf.get('global', 'name'))
+    br = mechanize.Browser()
+    #br.set_debug_http(True)
+    #br.set_debug_responses(True)
+    #br.set_debug_redirects(True)
+    cj = mechanize.LWPCookieJar()
+    if os.path.exists(conf.get('global', 'cookiejar')):
+        cj.load(conf.get('global', 'cookiejar'), ignore_discard = True)
+    br.set_cookiejar(cj)
+    if not fillstats(br, base, stats):
+        if not authenticate(br, base, conf.get('global', 'username'), conf.get('global', 'password')):
+            print('login failed')
+            return None
+        print('login succeeded, getting stats')
+        fillstats(br, base, stats)
 
+    cj.save(conf.get('global', 'cookiejar'), ignore_discard = True)
+    return stats
+
+def authenticate(br, base, username, password):
     # Connect and authenticate
-    br = mechanize.Browser()
     r = br.open(base)
     bs = bs4.BeautifulSoup(r)
     token = bs.head.find(lambda tag: tag.has_attr('name') and tag['name'] == 'CSRFtoken')['content']
     #print('Got CSRF token ' + token)
 
-    usr = srp.User(conf.get('global', 'username'), conf.get('global', 'password'), hash_alg = srp.SHA256, ng_type = srp.NG_2048)
+    usr = srp.User(username, password, hash_alg = srp.SHA256, ng_type = srp.NG_2048)
     uname, A = usr.start_authentication()
 
     req = mechanize.Request(base + '/authenticate', data = urllib.urlencode({'CSRFtoken' : token, 'I' : uname, 'A' : binascii.hexlify(A)}))
@@ -125,11 +144,15 @@
     usr.verify_session(binascii.unhexlify(j['M']))
     if not usr.authenticated():
         print('Failed to authenticate')
-        return None
+        return False
+    return True
 
+def fillstats(br, base, stats):
     # Fetch stats and parse
     r = br.open(base + '/modals/broadband-bridge-modal.lp')
     bs = bs4.BeautifulSoup(r)
+    if bs.find('div', 'login') != None:
+        return False
 
     # Helper function to extract data
     def getvals(bs, text):
@@ -161,7 +184,7 @@
     else:
         stats.uptime = reduce(lambda a, b: a + b, map(lambda a: int(a[0]) * a[1], zip(uptime, mults)))
 
-    return stats
+    return True
 
 # Setup RRD
 # We expect data to be logged every 5 minutes