[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[or-cvs] r21936: {weather} Add user-selected grace time that will be waited until the u (in weather/trunk: . lib/weather)
Author: kaner
Date: 2010-03-13 20:13:07 +0000 (Sat, 13 Mar 2010)
New Revision: 21936
Added:
weather/trunk/LICENSE
Modified:
weather/trunk/Weather.py
weather/trunk/lib/weather/config.py
weather/trunk/lib/weather/constants.py
weather/trunk/lib/weather/poller.py
weather/trunk/lib/weather/queries.py
Log:
Add user-selected grace time that will be waited until the user is notified, add copyright notice
Added: weather/trunk/LICENSE
===================================================================
--- weather/trunk/LICENSE (rev 0)
+++ weather/trunk/LICENSE 2010-03-13 20:13:07 UTC (rev 21936)
@@ -0,0 +1,31 @@
+gettor is distributed under this license:
+
+Copyright (c) 2008, The Tor Project, Inc.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+
+ * Neither the names of the copyright owners nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Modified: weather/trunk/Weather.py
===================================================================
--- weather/trunk/Weather.py 2010-03-13 18:41:34 UTC (rev 21935)
+++ weather/trunk/Weather.py 2010-03-13 20:13:07 UTC (rev 21936)
@@ -1,5 +1,11 @@
#!/usr/bin/python
+__program__ = 'Weather.py'
+__url__ = 'https://svn.torproject.org/svn/weather/'
+__author__ = 'Jacob Appelbaum <jacob@xxxxxxxxxxxxx>, Christian Fromme <kaner@xxxxxxxxxx>'
+__copyright__ = 'Copyright (c) 2009, 2010 The Tor Project'
+__license__ = 'See LICENSE for licensing information'
+
import os
import re
import sys
@@ -11,7 +17,7 @@
from weather.constants import PAGE_TEMPLATE, PAGE_SIGNUP, CONFIRMATION_MAIL, THANKS_OUT, PAGE_SUB_FIN
from weather.queries import CHECK_SUBS_Q, INSERT_SUBS_Q, CHECK_SUBS_AUTH_Q, ACK_SUB_Q, UNSUBSCRIBE_Q
from weather.poller import WeatherPoller
-from weather.config import pollPeriod, URLbase, mailFrom
+from weather.config import pollPeriod, URLbase, mailFrom, databaseName
import weather.utils as utils
class WeatherIndex(resource.Resource):
@@ -27,6 +33,12 @@
self.request = request
self.email = request.args['email'][0]
self.node = request.args['node'][0]
+ self.downtime = int(request.args['downtime'][0])
+ # Don't accept downtime grace values longer than 8760 hours = 1 year
+ if self.downtime > 8760:
+ self.downtime = 8760
+ if self.downtime < 1:
+ self.downtime = 1
if not utils.checkMail(self.email):
return "Error: Bad email address '%s'" % self.email
@@ -54,7 +66,7 @@
def _runSaveQuery(self):
dbQuery = INSERT_SUBS_Q % (self.email, self.node, \
- self.subs_auth, self.unsubs_auth)
+ self.subs_auth, self.unsubs_auth, self.downtime)
q = self.dbConn.runOperation(dbQuery)
q.addCallback(self._saved)
q.addErrback(self._errback)
@@ -111,7 +123,8 @@
def _checkRet(self, result, request):
if len(result) is 0:
request.setResponseCode(http.OK)
- request.write(utils.pageOut("Error: No subscription with your auth code"))
+ text = "Error: No subscription with your auth code"
+ request.write(utils.pageOut(text))
request.finish()
else:
self.unsubs_auth = str(result[0][0])
@@ -177,7 +190,7 @@
def main():
# Set up database connection
- dbConn = utils.setupDBConn("subscriptions.db")
+ dbConn = utils.setupDBConn(databaseName)
# Set up polling timer
weatherPoller = WeatherPoller(dbConn)
pollTimer = LoopingCall(weatherPoller.poller)
Modified: weather/trunk/lib/weather/config.py
===================================================================
--- weather/trunk/lib/weather/config.py 2010-03-13 18:41:34 UTC (rev 21935)
+++ weather/trunk/lib/weather/config.py 2010-03-13 20:13:07 UTC (rev 21936)
@@ -13,4 +13,6 @@
failureThreshold = 4 # this number of failures in a row counts as being
# down
-pollPeriod = 10 # try to wait this number of seconds in between polling
+pollPeriod = 10 # Check every hour
+
+databaseName = "subscriptions.db"
Modified: weather/trunk/lib/weather/constants.py
===================================================================
--- weather/trunk/lib/weather/constants.py 2010-03-13 18:41:34 UTC (rev 21935)
+++ weather/trunk/lib/weather/constants.py 2010-03-13 20:13:07 UTC (rev 21936)
@@ -84,7 +84,12 @@
</p><p>
Node fingerprint:<br>
<input type="text" name="node" size="50" maxlength="255" value="Enter one Tor node ID" onclick="if (this.value == 'Enter one Tor node ID') {this.value = ''}" />
-</p><p>
+</p>
+<p>
+How many hours of downtime until we send a notification:<br>
+<input type="text" name="downtime" size="50" maxlength="255" value="Default is 1 hour, enter up to 8760 (1 year)" onclick="if (this.value == 'Default is 1 hour, enter up to 8760 (1 year)') {this.value = ''}" />
+</p>
+<p>
<input type="submit" class="submit" value="Subscribe to Tor Weather" name="sa"/>
</p>
<hr>
Modified: weather/trunk/lib/weather/poller.py
===================================================================
--- weather/trunk/lib/weather/poller.py 2010-03-13 18:41:34 UTC (rev 21935)
+++ weather/trunk/lib/weather/poller.py 2010-03-13 20:13:07 UTC (rev 21936)
@@ -2,8 +2,8 @@
import smtplib
+import weather.queries as queries
from twisted.web import server
-from weather.queries import GETALL_SUBS_Q
from weather.torping import TorPing
from weather.config import URLbase, mailFrom
from weather.constants import REPORT_MAIL
@@ -18,7 +18,7 @@
return server.NOT_DONE_YET
def _checkAll(self):
- dbQuery = GETALL_SUBS_Q
+ dbQuery = queries.GETALL_SUBS_Q
q = self.dbConn.runQuery(dbQuery)
q.addCallback(self._checkRet)
q.addErrback(self._errBack)
@@ -32,8 +32,11 @@
self._handleOfflineNode(result)
else:
print "Server %s is ok" % checkHost
+ # Reset possible seen_down counter
+ self._resetSeendown(result)
def _errBack(self, failure):
+ # XXX: Log
print "Error: ", failure.getErrorMessage()
def _checkHost(self, hostID):
@@ -41,17 +44,56 @@
return torPing.ping(hostID)
def _handleOfflineNode(self, dbRow):
- # Log, mail
- if self._decideNotice(dbRow):
- self._sendNotice(dbRow)
+ self._getDowntimes(dbRow[0])
+ self._updateDowntime(dbRow[0])
- def _decideNotice(self, dbRow):
- # This is just a placeholder for now. We'll decide later what
- # conditions we want to check
- return True
+ def _getDowntimes(self, id):
+ dbQuery = queries.ALL_BY_ID_Q % id
+ q = self.dbConn.runQuery(dbQuery)
+ q.addCallback(self._decideNotice)
+ q.addErrback(self._errBack)
- def _sendNotice(self, dbRow):
- nodeId = dbRow[2]
- unsubsURL = URLbase + "/unsubscribe?auth=" + str(dbRow[4])
- mailText = REPORT_MAIL % (nodeId, unsubsURL)
- utils.sendMail(mailFrom, dbRow[1], mailText)
+ def _decideNotice(self, result):
+ downGrace = result[0][6]
+ seenDown = result[0][7]
+ email = result[0][1]
+ node = result[0][2]
+ id = result[0][0]
+ noticed = result[0][8]
+ unsubs_auth = result[0][4]
+ if noticed is 0 and (seenDown + 1) >= downGrace:
+ # XXX: Log
+ self._sendNotice(email, node, id, unsubs_auth)
+
+ def _sendNotice(self, email, node, id, unsubs_auth):
+ unsubsURL = URLbase + "/unsubscribe?auth=" + str(unsubs_auth)
+ mailText = REPORT_MAIL % (node, unsubsURL)
+ try:
+ utils.sendMail(mailFrom, email, mailText)
+ except:
+ # XXX: Log
+ print "Error, exception!"
+ else:
+ # Set 'noticed' flag so we don't bother that user again
+ self._setNoticed(id)
+
+ def _setNoticed(self, id):
+ dbQuery = queries.UPDATE_NOTICED_Q % id
+ q = self.dbConn.runQuery(dbQuery)
+ q.addCallback(self._updateDone)
+ q.addErrback(self._errBack)
+
+ def _updateDowntime(self, id):
+ dbQuery = queries.UPDATE_DOWN_Q % id
+ q = self.dbConn.runQuery(dbQuery)
+ q.addCallback(self._updateDone)
+ q.addErrback(self._errBack)
+
+ def _updateDone(self, result):
+ print "Query ok"
+
+ def _resetSeendown(self, dbRow):
+ dbQuery = queries.RESET_COUNT_Q % dbRow[0]
+ q = self.dbConn.runQuery(dbQuery)
+ q.addCallback(self._updateDone)
+ q.addErrback(self._errBack)
Modified: weather/trunk/lib/weather/queries.py
===================================================================
--- weather/trunk/lib/weather/queries.py 2010-03-13 18:41:34 UTC (rev 21935)
+++ weather/trunk/lib/weather/queries.py 2010-03-13 20:13:07 UTC (rev 21936)
@@ -3,12 +3,16 @@
# Query strings
CHECK_SUBS_Q = "SELECT id FROM subscriptions WHERE email='%s' and node='%s'"
INSERT_SUBS_Q = """
- INSERT INTO subscriptions (email, node, subs_auth, unsubs_auth, subscribed) VALUES ('%s', '%s', '%s', '%s', 0)
+ INSERT INTO subscriptions (email, node, subs_auth, unsubs_auth, subscribed, downtime_grace, seen_down, noticed) VALUES ('%s', '%s', '%s', '%s', 0, '%s', 0, 0)
"""
CHECK_SUBS_AUTH_Q = "SELECT unsubs_auth FROM subscriptions WHERE subs_auth='%s'"
ACK_SUB_Q = "UPDATE subscriptions SET subscribed=1 WHERE subs_auth='%s'"
UNSUBSCRIBE_Q = "DELETE from subscriptions where unsubs_auth='%s'"
GETALL_SUBS_Q = "SELECT * from subscriptions WHERE subscribed=1"
CREATE_TABLE_Q = """
- CREATE TABLE IF NOT EXISTS %s (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, email VARCHAR(255) NOT NULL, node VARCHAR(255) NOT NULL, subs_auth VARCHAR(255) NOT NULL, unsubs_auth VARCHAR(255) NOT NULL, subscribed INTEGER NOT NULL)
+ CREATE TABLE IF NOT EXISTS '%s' (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, email VARCHAR(255) NOT NULL, node VARCHAR(255) NOT NULL, subs_auth VARCHAR(255) NOT NULL, unsubs_auth VARCHAR(255) NOT NULL, subscribed INTEGER NOT NULL, downtime_grace INTEGER NOT NULL, seen_down INTEGER NOT NULL, noticed INTEGER NOT NULL)
"""
+ALL_BY_ID_Q = "SELECT * from subscriptions WHERE id = '%s'"
+UPDATE_DOWN_Q = "UPDATE subscriptions SET seen_down = seen_down + 1 WHERE id = '%s'"
+UPDATE_NOTICED_Q = "UPDATE subscriptions SET noticed = 1 WHERE id = '%s'"
+RESET_COUNT_Q = "UPDATE subscriptions SET seen_down = 0, noticed = 0 WHERE (id = '%s') AND (seen_down > 0) AND (noticed > 0)"