summaryrefslogtreecommitdiff
path: root/nova
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2015-02-06 18:37:37 +0000
committerGerrit Code Review <review@openstack.org>2015-02-06 18:37:37 +0000
commitcb3d079343d1bd1d0adbf0fb3d5350c00d42a1b7 (patch)
tree28daaf83f3d57f0d48cc5aad80eb66c2c754d987 /nova
parent8969b92a78519f5e0cbf65f097afd11b7ff498d5 (diff)
parentafe86b6f29033a472cab1b52dd0724bb3c6dfb82 (diff)
downloadnova-cb3d079343d1bd1d0adbf0fb3d5350c00d42a1b7.tar.gz
Merge "Fix conductor servicegroup joining when zk driver is used"
Diffstat (limited to 'nova')
-rw-r--r--nova/servicegroup/drivers/zk.py38
-rw-r--r--nova/tests/unit/servicegroup/test_zk_driver.py17
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)