[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] r22489: {weather} Be a good Weather and reconnect if the local Tor instance is (in weather/trunk: . lib/weather)



Author: kaner
Date: 2010-06-07 17:26:07 +0000 (Mon, 07 Jun 2010)
New Revision: 22489

Modified:
   weather/trunk/Weather.py
   weather/trunk/lib/weather/poller.py
   weather/trunk/lib/weather/torping.py
Log:
Be a good Weather and reconnect if the local Tor instance is offline, maybe because of some weasels


Modified: weather/trunk/Weather.py
===================================================================
--- weather/trunk/Weather.py	2010-06-07 17:21:11 UTC (rev 22488)
+++ weather/trunk/Weather.py	2010-06-07 17:26:07 UTC (rev 22489)
@@ -15,7 +15,6 @@
 from twisted.internet import reactor
 from twisted.internet.task import LoopingCall 
 
-from weather.torping import TorPing
 import weather.constants as constants
 import weather.queries as queries
 from weather.poller import WeatherPoller
@@ -265,9 +264,7 @@
     # Set up database connection
     dbConn = utils.setupDBConn(config.databaseName)
     # Set up polling timer
-    # XXX Have one main TorPing instance until TotCtl fixes its thread leak
-    torPing = TorPing()
-    weatherPoller = WeatherPoller(dbConn, torPing)
+    weatherPoller = WeatherPoller(dbConn)
     pollTimer = LoopingCall(weatherPoller.poller)
     pollTimer.start(config.pollPeriod)
     # Set up webserver

Modified: weather/trunk/lib/weather/poller.py
===================================================================
--- weather/trunk/lib/weather/poller.py	2010-06-07 17:21:11 UTC (rev 22488)
+++ weather/trunk/lib/weather/poller.py	2010-06-07 17:26:07 UTC (rev 22489)
@@ -7,16 +7,16 @@
 import smtplib
 from twisted.web import server
 
-from weather.torping import TorPing
+import weather.torping as torping
 import weather.config as config
 import weather.constants as constants
 import weather.queries as queries
 import weather.utils as utils
 
 class WeatherPoller():
-    def __init__(self, dbConn, torPing):
+    def __init__(self, dbConn):
         self.dbConn = dbConn
-        self.torPing = torPing
+        self.torPing = torping.TorPing()
 
     def poller(self):
         self._checkAll()
@@ -25,26 +25,41 @@
     def _checkAll(self):
         dbQuery = queries.GETALL_SUBS_Q
         self.dbConn.runQuery(dbQuery).addCallback(
-            self._checkRet).addErrback(
+            self._checkHosts).addErrback(
             self._errBack)
 
-    def _checkRet(self, resultList):
+    def _checkHosts(self, resultList):
         # Loop through result list and check each node
         for result in resultList:
+            if not self.torPing.isConnected():
+                logging.error("Not connected to Tor, leaving loop")
+                break
             checkHost = result[2]
-            if not self._checkHost(checkHost):
+            ret = self._checkHost(checkHost)
+            if ret is torping.TORPING_OFFLINE:
                 logging.info("Server %s seems to be offline" % checkHost)
                 self._handleOfflineNode(result)
-            else:
+            elif ret == torping.TORPING_ONLINE:
                 logging.info("Server %s is ok" % checkHost)
                 # Reset possible seen_down counter
                 self._resetSeendown(result)
+            else:
+                logging.error("General error while checking %s" % checkHost)
+
+        # Try to reconnect..
+        if not self.torPing.isConnected():
+            logging.error("Trying to reconnect to local Tor instance..")
+            del self.torPing
+            self.torPing = torping.TorPing()
     
     def _errBack(self, failure):
         logging.error("Error: %s" % failure.getErrorMessage())
 
     def _checkHost(self, hostID):
-        return self.torPing.ping(hostID)
+        if self.torPing.isConnected():
+            return self.torPing.ping(hostID)
+        else:
+            return torping.GENERR
 
     def _handleOfflineNode(self, dbRow):
         self._getDowntimes(dbRow[0])

Modified: weather/trunk/lib/weather/torping.py
===================================================================
--- weather/trunk/lib/weather/torping.py	2010-06-07 17:21:11 UTC (rev 22488)
+++ weather/trunk/lib/weather/torping.py	2010-06-07 17:26:07 UTC (rev 22489)
@@ -12,43 +12,58 @@
 
 debugfile = open("debug", "w")
 
+TORPING_ONLINE = 0
+TORPING_OFFLINE = 1
+TORPING_GENERR = 2
+
 class TorPing:
   "Check to see if various tor nodes respond to SSL hanshakes"
   def __init__(self, control_host = "127.0.0.1", control_port = 9051):
     "Keep the connection to the control port lying around"
+    self.connected = False
+    self.control = None
     self.control_host = control_host
     self.control_port = control_port
     self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     try:
         self.sock.connect((control_host,control_port))
+        self.control = TorCtl.Connection(self.sock)
+        self.control.authenticate(weather.config.authenticator)
+        self.control.debug(debugfile)
+        self.connected = True
     except:
         errormsg = "Could not connect to Tor control port" + \
                    "Is Tor running on %s with its control port opened on %s?" \
                    % (control_host, control_port)
         logging.error(errormsg)
-        print >> sys.stderr, errormsg
-        raise
-    self.control = TorCtl.Connection(self.sock)
-    self.control.authenticate(weather.config.authenticator)
-    self.control.debug(debugfile)
 
   def __del__(self):
-    self.sock.close()
-    del self.sock
-    self.sock = None                # prevents double deletion exceptions
+    if self.sock is not None:
+        self.sock.close()
+        del self.sock
+        self.sock = None                # prevents double deletion exceptions
 
-    # it would be better to fix TorCtl!
-    try:
-      self.control.close()
-    except:
-      logging.error("Exception while closing TorCtl")
-      pass
+    if self.control is not None:
+        # it would be better to fix TorCtl!
+        try:
+          self.control.close()
+        except:
+          logging.error("Exception while closing TorCtl")
+          pass
 
-    del self.control
-    self.control = None
+        del self.control
+        self.control = None
 
+  def isConnected(self):
+      return self.connected
+
   def ping(self, nodeId):
-    "Let's see if this tor node is up by only asking Tor."
+    """Let's see if this tor node is up by only asking Tor."""
+
+    # If we're not connected (yet) to Tor, don't even try to ping
+    if not self.connected:
+        return TORPING_GENERR
+
     try:
        info = self.control.get_info(str("ns/id/" + nodeId))
     except TorCtl.ErrorReply, e:
@@ -56,11 +71,12 @@
         # ErrorReply: 552 Unrecognized key "ns/id/46D9..."
         # This means that the node isn't recognized by 
         logging.error("ErrorReply: %s" % str(e))
-        return False
+        return TORPING_OFFLINE
 
     except:
         logging.error("Unknown exception in ping()")
-        return False
+        self.connected = False 
+        return TORPING_GENERR
 
     # If we're here, we were able to fetch information about the router
-    return True
+    return TORPING_ONLINE