wingo - in flumotion/trunk: . flumotion/admin flumotion/common flumotion/test

flumotion-commit at lists.fluendo.com flumotion-commit at lists.fluendo.com
Wed Jun 27 12:37:19 CEST 2007


Author: wingo
Date: Wed Jun 27 12:37:15 2007
New Revision: 5264

Modified:
   flumotion/trunk/ChangeLog
   flumotion/trunk/flumotion/admin/admin.py
   flumotion/trunk/flumotion/common/errors.py
   flumotion/trunk/flumotion/test/test_admin_admin.py
Log:
2007-06-27  Andy Wingo  <wingo at pobox.com>

	* flumotion/admin/admin.py (AdminModel.connectToManager): Some
	fixes to the deferred connection interface such that it respects
	keepTrying. The bit about keepTrying=True doesn't have tests yet
	though. See #621.
	(AdminModel.shutdown): Cancel the pending deferred connect, if
	there is one.

	* flumotion/common/errors.py (ConnectionCancelledError): New
	error.

	* flumotion/test/test_admin_admin.py (TestCaseWithManager.setUp)
	(TestCaseWithManager.tearDown): Add foo such that twisted
	exceptions don't cause errors. A better solution would be nice.
	(AdminTest.testConnectSuccess, AdminTest.testConnectFailure): New
	tests for the deferred connection interface.



Modified: flumotion/trunk/ChangeLog
==============================================================================
--- flumotion/trunk/ChangeLog	(original)
+++ flumotion/trunk/ChangeLog	Wed Jun 27 12:37:15 2007
@@ -1,5 +1,21 @@
 2007-06-27  Andy Wingo  <wingo at pobox.com>
 
+	* flumotion/admin/admin.py (AdminModel.connectToManager): Some
+	fixes to the deferred connection interface such that it respects
+	keepTrying. The bit about keepTrying=True doesn't have tests yet
+	though. See #621.
+	(AdminModel.shutdown): Cancel the pending deferred connect, if
+	there is one.
+
+	* flumotion/common/errors.py (ConnectionCancelledError): New
+	error.
+
+	* flumotion/test/test_admin_admin.py (TestCaseWithManager.setUp)
+	(TestCaseWithManager.tearDown): Add foo such that twisted
+	exceptions don't cause errors. A better solution would be nice.
+	(AdminTest.testConnectSuccess, AdminTest.testConnectFailure): New
+	tests for the deferred connection interface.
+
 	* flumotion/test/Makefile.am (EXTRA_DIST): 
 	* flumotion/test/test_admin_admin.py: New test, not quite fleshed
 	out yet.

Modified: flumotion/trunk/flumotion/admin/admin.py
==============================================================================
--- flumotion/trunk/flumotion/admin/admin.py	(original)
+++ flumotion/trunk/flumotion/admin/admin.py	Wed Jun 27 12:37:15 2007
@@ -182,6 +182,8 @@
         self.state = 'disconnected'
         self.clientFactory = None
 
+        self._deferredConnect = None
+
         self._components = {} # dict of components
         self.planet = None
         self._workerHeavenState = None
@@ -214,38 +216,48 @@
             reactor.connectTCP(connectionInfo.host, connectionInfo.port,
                                self.clientFactory)
 
-        def connected(model, d, ids):
-            map(model.disconnect, ids)
+        def connected(model, d):
+            # model is really "self". yay gobject?
             d.callback(model)
 
-        def disconnected(model, d, ids):
+        def disconnected(model, d):
             # can happen after setRemoteReference but before
             # getPlanetState or getWorkerHeavenState returns
-            map(model.disconnect, ids)
-            d.errback(errors.ConnectionFailedError('Lost connection'))
+            if not keepTrying:
+                d.errback(errors.ConnectionFailedError('Lost connection'))
 
-        def connection_refused(model, d, ids):
-            map(model.disconnect, ids)
-            d.errback(errors.ConnectionRefusedError())
-
-        def connection_failed(model, reason, d, ids):
-            map(model.disconnect, ids)
-            d.errback(errors.ConnectionFailedError(reason))
-
-        def connection_error(model, exception, d, ids):
-            map(model.disconnect, ids)
-            d.errback(exception)
+        def connection_refused(model, d):
+            if not keepTrying:
+                d.errback(errors.ConnectionRefusedError())
+
+        def connection_failed(model, reason):
+            if not keepTrying:
+                d.errback(errors.ConnectionFailedError(reason))
+
+        def connection_error(model, exception):
+            if not keepTrying:
+                d.errback(exception)
 
         d = defer.Deferred()
         ids = []
-        ids.append(self.connect('connected', connected, d, ids))
-        ids.append(self.connect('disconnected', disconnected, d, ids))
-        ids.append(self.connect('connection-refused',
-                                connection_refused, d, ids))
-        ids.append(self.connect('connection-failed',
-                                connection_failed, d, ids))
-        ids.append(self.connect('connection-error',
-                                connection_error, d, ids))
+        ids.append(self.connect('connected', connected, d))
+        ids.append(self.connect('disconnected', disconnected, d))
+        ids.append(self.connect('connection-refused', connection_refused, d))
+        ids.append(self.connect('connection-failed', connection_failed, d))
+        ids.append(self.connect('connection-error', connection_error, d))
+
+        def success(model):
+            map(self.disconnect, ids)
+            self._deferredConnect = None
+            return model
+
+        def failure(f):
+            map(self.disconnect, ids)
+            self._deferredConnect = None
+            return f
+
+        d.addCallbacks(success, failure)
+        self._deferredConnect = d
         return d
 
     def shutdown(self):
@@ -257,6 +269,11 @@
             self.clientFactory.disconnect()
             self.clientFactory = None
 
+        if self._deferredConnect is not None:
+            # this can happen with keepTrying=True
+            self.debug('cancelling connection attempt')
+            self._deferredConnect.errback(errors.ConnectionCancelledError())
+
     def reconnect(self, keepTrying=False):
         """Close any existing connection to the manager and
         reconnect."""

Modified: flumotion/trunk/flumotion/common/errors.py
==============================================================================
--- flumotion/trunk/flumotion/common/errors.py	(original)
+++ flumotion/trunk/flumotion/common/errors.py	Wed Jun 27 12:37:15 2007
@@ -55,6 +55,9 @@
 class ConnectionFailedError(ConnectionError):
     "Connection failed"
 
+class ConnectionCancelledError(ConnectionError):
+    "Connection attempt cancelled"
+
 class ManagerNotConnectedError(NotConnectedError):
     "Manager not connected"
 

Modified: flumotion/trunk/flumotion/test/test_admin_admin.py
==============================================================================
--- flumotion/trunk/flumotion/test/test_admin_admin.py	(original)
+++ flumotion/trunk/flumotion/test/test_admin_admin.py	Wed Jun 27 12:37:15 2007
@@ -19,12 +19,17 @@
 
 # Headers in this file shall remain intact.
 
+import common
+
 from StringIO import StringIO
 
+from twisted.cred import error
 from twisted.trial import unittest
 from twisted.internet import reactor
+from twisted.python import log as tlog
 
-from flumotion.common import config, server
+from flumotion.common import config, server, connection, log
+from flumotion.twisted import pb
 from flumotion.manager import manager
 from flumotion.admin import admin
 
@@ -47,6 +52,14 @@
 
 class TestCaseWithManager(unittest.TestCase):
     def setUp(self):
+        # This bit about log flushing is repeated in various tests;
+        # would be good to see about making it unnecessary. Perhaps
+        # returning a pb.Error subclass instead of UnauthorizedLogin
+        # would do the trick.
+
+        # don't output Twisted tracebacks for PB errors we will trigger
+        log._getTheFluLogObserver().ignoreErrors(error.UnauthorizedLogin)
+
         conf = config.ManagerConfigParser(StringIO(managerConf)).manager
         self.vishnu = manager.Vishnu(conf.name,
                                      unsafeTracebacks=True)
@@ -59,8 +72,19 @@
             p = s.startTCP(conf.host, conf.port)
         self.tport = p
         self.port = p.getHost().port
+        i = connection.PBConnectionInfo('localhost', self.port,
+                                        conf.transport == 'ssl',
+                                        pb.Authenticator(username='user',
+                                                         password='test'))
+        self.connectionInfo = i
         
     def tearDown(self):
+        try:
+            self.flushLoggedErrors(error.UnauthorizedLogin)
+        except AttributeError:
+            tlog.flushErrors(error.UnauthorizedLogin)
+        log._getTheFluLogObserver().clearIgnores()
+
         d = self.vishnu.shutdown()
         d.addCallback(lambda _: self.tport.stopListening())
         return d
@@ -69,3 +93,34 @@
 class AdminTest(TestCaseWithManager):
     def testConstructor(self):
         model = admin.AdminModel()
+
+    def testConnectSuccess(self):
+        def connected(_):
+            self.failUnless(a.planet is not None)
+            self.assertEqual(len(self.vishnu.adminHeaven.avatars),
+                             1)
+            a.shutdown()
+
+        a = admin.AdminModel()
+        d = a.connectToManager(self.connectionInfo)
+        d.addCallback(connected)
+        return d
+
+    def testConnectFailure(self):
+        def connected(_):
+            self.fail('should not have connected')
+
+        def failure(f):
+            # ok!
+            a.shutdown()
+
+        a = admin.AdminModel()
+        # create a connectionInfo that will not succeed
+        i = connection.PBConnectionInfo(self.connectionInfo.host,
+                                        self.connectionInfo.port,
+                                        self.connectionInfo.use_ssl,
+                                        pb.Authenticator(username='user',
+                                                         password='pest'))
+        d = a.connectToManager(i)
+        d.addCallbacks(connected, failure)
+        return d


More information about the flumotion-commit mailing list