diff options
author | Jenkins <jenkins@review.openstack.org> | 2015-02-06 18:37:37 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2015-02-06 18:37:37 +0000 |
commit | cb3d079343d1bd1d0adbf0fb3d5350c00d42a1b7 (patch) | |
tree | 28daaf83f3d57f0d48cc5aad80eb66c2c754d987 /nova | |
parent | 8969b92a78519f5e0cbf65f097afd11b7ff498d5 (diff) | |
parent | afe86b6f29033a472cab1b52dd0724bb3c6dfb82 (diff) | |
download | nova-cb3d079343d1bd1d0adbf0fb3d5350c00d42a1b7.tar.gz |
Merge "Fix conductor servicegroup joining when zk driver is used"
Diffstat (limited to 'nova')
-rw-r--r-- | nova/servicegroup/drivers/zk.py | 38 | ||||
-rw-r--r-- | nova/tests/unit/servicegroup/test_zk_driver.py | 17 |
2 files changed, 48 insertions, 7 deletions
diff --git a/nova/servicegroup/drivers/zk.py b/nova/servicegroup/drivers/zk.py index b391d173f5..6a06bf24b6 100644 --- a/nova/servicegroup/drivers/zk.py +++ b/nova/servicegroup/drivers/zk.py @@ -59,21 +59,47 @@ class ZooKeeperDriver(base.Driver): """Create the zk session object.""" if not all([evzookeeper, membership, zookeeper]): raise ImportError('zookeeper module not found') + self._memberships = {} + self._monitors = {} + super(ZooKeeperDriver, self).__init__() + self._cached_session = None + + @property + def _session(self): + """Creates zookeeper session in lazy manner. + + Session is created in lazy manner to mitigate lock problem + in zookeeper. + + Lock happens when many processes try to use the same zk handle. + Lazy creation allows to deffer initialization of session until + is really required by worker (child process). + + :returns: ZKSession -- new or created earlier + """ + if self._cached_session is None: + self._cached_session = self._init_session() + return self._cached_session + + def _init_session(self): + """Initializes new session. + + Optionally creates required servicegroup prefix. + + :returns ZKSession - newly created session + """ null = open(os.devnull, "w") - self._session = evzookeeper.ZKSession(CONF.zookeeper.address, + session = evzookeeper.ZKSession(CONF.zookeeper.address, recv_timeout= CONF.zookeeper.recv_timeout, zklog_fd=null) - self._memberships = {} - self._monitors = {} # Make sure the prefix exists try: - self._session.create(CONF.zookeeper.sg_prefix, "", + session.create(CONF.zookeeper.sg_prefix, "", acl=[evzookeeper.ZOO_OPEN_ACL_UNSAFE]) except zookeeper.NodeExistsException: pass - - super(ZooKeeperDriver, self).__init__() + return session def join(self, member_id, group, service=None): """Join the given service with its group.""" diff --git a/nova/tests/unit/servicegroup/test_zk_driver.py b/nova/tests/unit/servicegroup/test_zk_driver.py index 08121c8290..ddd3073b97 100644 --- a/nova/tests/unit/servicegroup/test_zk_driver.py +++ b/nova/tests/unit/servicegroup/test_zk_driver.py @@ -29,6 +29,7 @@ import os import eventlet from nova import servicegroup +from nova.servicegroup.drivers import zk from nova import test @@ -37,7 +38,6 @@ class ZKServiceGroupTestCase(test.NoDBTestCase): def setUp(self): super(ZKServiceGroupTestCase, self).setUp() servicegroup.API._driver = None - from nova.servicegroup.drivers import zk self.flags(servicegroup_driver='zk') self.flags(address='localhost:2181', group="zookeeper") try: @@ -85,3 +85,18 @@ class ZKServiceGroupTestCase(test.NoDBTestCase): None) # expected existing "process id" node self.assertTrue(session.get(path)) + + def test_lazy_session(self): + """Session object (contains zk handle) should be created in + lazy manner, because handle cannot be shared by forked processes. + """ + # insied import because this test runs conditionaly (look at setUp) + import evzookeeper + driver = zk.ZooKeeperDriver() + # check that internal private attribute session is empty + self.assertIsNone(driver.__dict__['_ZooKeeperDriver__session']) + # after first use of property ... + driver._session + # check that internal private session attribute is ready + self.assertIsInstance(driver.__dict__['_ZooKeeperDriver__session'], + evzookeeper.ZKSession) |