diff --git a/zaqar/storage/base.py b/zaqar/storage/base.py index f69cb898a..e467cc25a 100644 --- a/zaqar/storage/base.py +++ b/zaqar/storage/base.py @@ -128,6 +128,11 @@ class DataDriverBase(DriverBase): """Return the health status based on different backends.""" raise NotImplementedError + @abc.abstractmethod + def close(self): + """Close connections to the backend.""" + raise NotImplementedError + def _get_operation_status(self): op_status = {} status_template = lambda s, t, r: {'succeeded': s, @@ -276,6 +281,11 @@ class ControlDriverBase(DriverBase): """Returns the driver's queue controller.""" raise NotImplementedError + @abc.abstractmethod + def close(self): + """Close connections to the backend.""" + raise NotImplementedError + class ControllerBase(object): """Top-level class for controllers. diff --git a/zaqar/storage/mongodb/driver.py b/zaqar/storage/mongodb/driver.py index 8a0191daf..0243d8379 100644 --- a/zaqar/storage/mongodb/driver.py +++ b/zaqar/storage/mongodb/driver.py @@ -123,6 +123,9 @@ class DataDriver(storage.DataDriverBase): except pymongo.errors.PyMongoError: return False + def close(self): + self.connection.close() + def _health(self): KPI = {} KPI['storage_reachable'] = self.is_alive() @@ -212,6 +215,9 @@ class ControlDriver(storage.ControlDriverBase): self.mongodb_conf = self.conf[options.MANAGEMENT_MONGODB_GROUP] + def close(self): + self.connection.close() + @decorators.lazy_property(write=False) def connection(self): """MongoDB client connection instance.""" diff --git a/zaqar/storage/pipeline.py b/zaqar/storage/pipeline.py index ca2f2b6ba..d7df0fa42 100644 --- a/zaqar/storage/pipeline.py +++ b/zaqar/storage/pipeline.py @@ -126,6 +126,9 @@ class DataDriver(base.DataDriverBase): def capabilities(self): return self._storage.capabilities() + def close(self): + self._storage.close() + def is_alive(self): return self._storage.is_alive() diff --git a/zaqar/storage/pooling.py b/zaqar/storage/pooling.py index 931deb17d..dd0c80152 100644 --- a/zaqar/storage/pooling.py +++ b/zaqar/storage/pooling.py @@ -86,6 +86,13 @@ class DataDriver(storage.DataDriverBase): # is neither used for pools creation nor flavor creation. return self.BASE_CAPABILITIES + def close(self): + cursor = self._pool_catalog._pools_ctrl.list(limit=0) + # Messages of each pool + for pool in next(cursor): + driver = self._pool_catalog.get_driver(pool['name']) + driver.close() + def is_alive(self): cursor = self._pool_catalog._pools_ctrl.list(limit=0) pools = next(cursor) diff --git a/zaqar/storage/redis/driver.py b/zaqar/storage/redis/driver.py index aa3f81b51..e0fac6e36 100644 --- a/zaqar/storage/redis/driver.py +++ b/zaqar/storage/redis/driver.py @@ -174,6 +174,9 @@ class DataDriver(storage.DataDriverBase): except redis.exceptions.ConnectionError: return False + def close(self): + self.connection.close() + def _health(self): KPI = {} KPI['storage_reachable'] = self.is_alive() @@ -218,6 +221,9 @@ class ControlDriver(storage.ControlDriverBase): self.redis_conf = self.conf[options.MANAGEMENT_REDIS_GROUP] + def close(self): + self.connection.close() + @decorators.lazy_property(write=False) def connection(self): """Redis client connection instance.""" diff --git a/zaqar/storage/sqlalchemy/driver.py b/zaqar/storage/sqlalchemy/driver.py index 21968fae5..1f1c784df 100644 --- a/zaqar/storage/sqlalchemy/driver.py +++ b/zaqar/storage/sqlalchemy/driver.py @@ -75,7 +75,7 @@ class ControlDriver(storage.ControlDriverBase): def run(self, *args, **kwargs): return self.connection.execute(*args, **kwargs) - def close_connection(self): + def close(self): self.connection.close() @property diff --git a/zaqar/tests/faulty_storage.py b/zaqar/tests/faulty_storage.py index b51742d74..e09131b87 100644 --- a/zaqar/tests/faulty_storage.py +++ b/zaqar/tests/faulty_storage.py @@ -28,6 +28,9 @@ class DataDriver(storage.DataDriverBase): def __init__(self, conf, cache, control_driver): super(DataDriver, self).__init__(conf, cache, control_driver) + def close(self): + pass + @property def default_options(self): return {} @@ -64,6 +67,9 @@ class ControlDriver(storage.ControlDriverBase): def __init__(self, conf, cache): super(ControlDriver, self).__init__(conf, cache) + def close(self): + pass + @property def queue_controller(self): return QueueController(self) diff --git a/zaqar/tests/functional/base.py b/zaqar/tests/functional/base.py index 339d42517..01c47c044 100644 --- a/zaqar/tests/functional/base.py +++ b/zaqar/tests/functional/base.py @@ -92,8 +92,10 @@ class FunctionalTestBase(testing.TestBase): self.mconf.pooling = True self.mconf.admin_mode = True - self.client = http.WSGIClient( - bootstrap.Bootstrap(self.mconf).transport.app) + boot = bootstrap.Bootstrap(self.mconf) + self.addCleanup(boot.storage.close) + self.addCleanup(boot.control.close) + self.client = http.WSGIClient(boot.transport.app) self.headers = helpers.create_zaqar_headers(self.cfg) diff --git a/zaqar/tests/unit/transport/websocket/base.py b/zaqar/tests/unit/transport/websocket/base.py index 3792eae08..5b283fe5e 100644 --- a/zaqar/tests/unit/transport/websocket/base.py +++ b/zaqar/tests/unit/transport/websocket/base.py @@ -43,6 +43,8 @@ class TestBase(testing.TestBase): self.conf.unreliable = True self.conf.admin_mode = True self.boot = bootstrap.Bootstrap(self.conf) + self.addCleanup(self.boot.storage.close) + self.addCleanup(self.boot.control.close) self.transport = self.boot.transport self.api = self.boot.api diff --git a/zaqar/tests/unit/transport/wsgi/base.py b/zaqar/tests/unit/transport/wsgi/base.py index 4b78210e9..4fd7bea71 100644 --- a/zaqar/tests/unit/transport/wsgi/base.py +++ b/zaqar/tests/unit/transport/wsgi/base.py @@ -46,6 +46,8 @@ class TestBase(testing.TestBase): self.conf.unreliable = True self.conf.admin_mode = True self.boot = bootstrap.Bootstrap(self.conf) + self.addCleanup(self.boot.storage.close) + self.addCleanup(self.boot.control.close) self.app = self.boot.transport.app