Merge pull request #38 from zalando/bugfix/zookeeper

Bugfix/zookeeper
This commit is contained in:
Alexander Kukushkin
2015-09-15 09:29:18 +02:00
3 changed files with 31 additions and 14 deletions
+8 -6
View File
@@ -108,14 +108,15 @@ class ZooKeeper(AbstractDCS):
def get_node(self, key, watch=None):
try:
return self.client.get(key, watch)
ret = self.client.get(key, watch)
return (ret[0].decode('utf-8'), ret[1])
except NoNodeError:
return None
@staticmethod
def member(name, value, znode):
conn_url, api_url = parse_connection_string(value)
return Member(znode.mzxid, name, conn_url, api_url, None, None)
return Member(znode.version, name, conn_url, api_url, None, None)
def get_children(self, key, watch=None):
try:
@@ -153,7 +154,7 @@ class ZooKeeper(AbstractDCS):
if leader:
member = Member(-1, leader[0], None, None, None, None)
member = ([m for m in members if m.name == leader[0]] or [member])[0]
leader = Leader(leader[1].mzxid, None, None, member)
leader = Leader(leader[1].version, None, None, member)
self.fetch_cluster = member.index == -1
# get last leader operation
@@ -176,7 +177,7 @@ class ZooKeeper(AbstractDCS):
def _create(self, path, value, **kwargs):
try:
self.client.retry(self.client.create, path, value, **kwargs)
self.client.retry(self.client.create, path, value.encode('utf-8'), **kwargs)
return True
except:
return False
@@ -193,6 +194,7 @@ class ZooKeeper(AbstractDCS):
if self.cluster and any(m.name == self._name for m in self.cluster.members):
return True
path = self.member_path
connection_string = connection_string.encode('utf-8')
try:
self.client.retry(self.client.create, path, connection_string, makepath=True, ephemeral=True)
return True
@@ -209,7 +211,7 @@ class ZooKeeper(AbstractDCS):
return self.attempt_to_acquire_leader()
def update_leader(self, state_handler):
last_operation = state_handler.last_operation()
last_operation = state_handler.last_operation().encode('utf-8')
if last_operation != self.last_leader_operation:
self.last_leader_operation = last_operation
path = self.leader_optime_path
@@ -231,7 +233,7 @@ class ZooKeeper(AbstractDCS):
def _cancel_initialization(self):
node = self.get_node(self.initialize_path)
if node and node[0] == self._name:
self.client.delete(self.initialize_path, version=node[1].mzxid)
self.client.delete(self.initialize_path, version=node[1].version)
def cancel_initialization(self):
try:
+1 -1
View File
@@ -44,7 +44,7 @@ class MockPostgresql:
name = ''
def last_operation(self):
return 0
return '0'
def requests_get(url, **kwargs):
+22 -7
View File
@@ -1,5 +1,6 @@
import patroni.zookeeper
import requests
import six
import unittest
from patroni.dcs import Leader
@@ -56,41 +57,55 @@ class MockKazooClient:
func(*args, **kwargs)
def get(self, path, watch=None):
if not isinstance(path, six.string_types):
raise TypeError("Invalid type for 'path' (string expected)")
if path == '/no_node':
raise NoNodeError
elif '/members/' in path:
return (
'postgres://repuser:rep-pass@localhost:5434/postgres?application_name=http://127.0.0.1:8009/patroni',
b'postgres://repuser:rep-pass@localhost:5434/postgres?application_name=http://127.0.0.1:8009/patroni',
ZnodeStat(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
)
elif path.endswith('/optime/leader'):
return '1'
return (b'1', ZnodeStat(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
elif path.endswith('/leader'):
if self.leader:
return ('foo', ZnodeStat(0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0))
return ('foo', ZnodeStat(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
return (b'foo', ZnodeStat(0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0))
return (b'foo', ZnodeStat(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
elif path.endswith('/initialize'):
return ('foo', ZnodeStat(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
return (b'foo', ZnodeStat(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
def get_children(self, path, watch=None, include_data=False):
if not isinstance(path, six.string_types):
raise TypeError("Invalid type for 'path' (string expected)")
if path == '/no_node':
raise NoNodeError
elif path in ['/service/bla/', '/service/test/']:
return ['initialize', 'leader', 'members', 'optime']
return ['foo', 'bar', 'buzz']
def create(self, path, value="", acl=None, ephemeral=False, sequence=False, makepath=False):
def create(self, path, value=b"", acl=None, ephemeral=False, sequence=False, makepath=False):
if not isinstance(path, six.string_types):
raise TypeError("Invalid type for 'path' (string expected)")
if not isinstance(value, (six.binary_type,)):
raise TypeError("Invalid type for 'value' (must be a byte string)")
if path.endswith('/initialize') or path == '/service/test/optime/leader':
raise Exception
elif value == 'retry' or (value == 'exists' and self.exists):
elif value == b'retry' or (value == b'exists' and self.exists):
raise NodeExistsError
def set(self, path, value, version=-1):
if not isinstance(path, six.string_types):
raise TypeError("Invalid type for 'path' (string expected)")
if not isinstance(value, (six.binary_type,)):
raise TypeError("Invalid type for 'value' (must be a byte string)")
if path == '/service/bla/optime/leader':
raise Exception
raise NoNodeError
def delete(self, path, version=-1, recursive=False):
if not isinstance(path, six.string_types):
raise TypeError("Invalid type for 'path' (string expected)")
self.exists = False
if path == '/service/test/leader':
if self.leader: