diff --git a/helpers/dcs.py b/helpers/dcs.py index 63515e81..22c47e26 100644 --- a/helpers/dcs.py +++ b/helpers/dcs.py @@ -58,6 +58,10 @@ class Leader(namedtuple('Leader', 'index,expiration,ttl,member')): :param ttl: ttl of the leader key :param member: reference to a `Member` object which represents current leader (see `Cluster.members`)""" + @property + def name(self): + return self.member.name + class Cluster(namedtuple('Cluster', 'initialize,leader,last_leader_operation,members')): """Immutable object (namedtuple) which represents PostgreSQL cluster. @@ -69,7 +73,7 @@ class Cluster(namedtuple('Cluster', 'initialize,leader,last_leader_operation,mem :param members: list of Member object, all PostgreSQL cluster members including leader""" def is_unlocked(self): - return not (self.leader and self.leader.member.name) + return not (self.leader and self.leader.name) class AbstractDCS: @@ -83,7 +87,8 @@ class AbstractDCS: i.e.: `zookeeper` for zookeeper, `etcd` for etcd, etc... """ self._name = name - self._base_path = '/service/' + config['scope'] + self._scope = config['scope'] + self._base_path = '/service/' + self._scope def client_path(self, path): return self._base_path + path diff --git a/helpers/etcd.py b/helpers/etcd.py index 6bea59e7..d6739e2d 100644 --- a/helpers/etcd.py +++ b/helpers/etcd.py @@ -185,7 +185,8 @@ class Etcd(AbstractDCS): self.cluster = Cluster(initialize, leader, last_leader_operation, members) return self.cluster except etcd.EtcdKeyNotFound: - return Cluster(False, None, None, []) + self.cluster = Cluster(False, None, None, []) + return self.cluster except: logger.exception('get_cluster') @@ -226,14 +227,14 @@ class Etcd(AbstractDCS): def watch(self, timeout): # watch on leader key changes if it is defined and current node is not lock owner - if self.cluster and self.cluster.leader and self.cluster.leader.member.name != self._name: + if self.cluster and self.cluster.leader and self.cluster.leader.name != self._name: end_time = time.time() + timeout index = self.cluster.leader.index while index and timeout >= 1: # when timeout is too small urllib3 doesn't have enough time to connect try: res = self.client.watch(self.client_path('/leader'), index=index + 1, timeout=timeout) - if res.action not in ['set', 'compareAndSwap'] or res.value != self.cluster.leader.member.name: + if res.action not in ['set', 'compareAndSwap'] or res.value != self.cluster.leader.name: return index = res.modifiedIndex except urllib3.exceptions.TimeoutError: diff --git a/helpers/ha.py b/helpers/ha.py index ff67f0e0..8e283c55 100644 --- a/helpers/ha.py +++ b/helpers/ha.py @@ -31,7 +31,7 @@ class Ha: return self.dcs.update_leader(self.state_handler) def has_lock(self): - lock_owner = self.cluster.leader and self.cluster.leader.member.name + lock_owner = self.cluster.leader and self.cluster.leader.name logger.info('Lock owner: %s; I am %s', lock_owner, self.state_handler.name) return lock_owner == self.state_handler.name diff --git a/helpers/zookeeper.py b/helpers/zookeeper.py index bf8b281a..d1ccafa2 100644 --- a/helpers/zookeeper.py +++ b/helpers/zookeeper.py @@ -217,7 +217,7 @@ class ZooKeeper(AbstractDCS): return True def delete_leader(self): - if isinstance(self.leader, Leader) and self.leader.member.name == self._name: + if isinstance(self.leader, Leader) and self.leader.name == self._name: self.client.delete(self.client_path('/leader')) def watch(self, timeout):