def rescue_cluster(host, port, subst_host, subst_port): failed_slots = set(xrange(SLOT_COUNT)) with Talker(host, port) as t: _ensure_cluster_status_set(t) for node in _list_masters(t)[0]: failed_slots -= set(node.assigned_slots) if len(failed_slots) == 0: logging.info('No need to rescue cluster at %s:%d', host, port) return with Talker(subst_host, subst_port) as s: _ensure_cluster_status_unset(s) m = s.talk('cluster', 'meet', host, port) logging.debug('Ask `cluster meet` Rsp %s', m) if m.lower() != 'ok': raise RedisStatusError('Unexpected reply after MEET: %s' % m) m = s.talk('cluster', 'addslots', *failed_slots) logging.debug('Ask `cluster addslots` Rsp %s', m) if m.lower() != 'ok': raise RedisStatusError('Unexpected reply after ADDSLOTS: %s' % m) _poll_check_status(s) logging.info( 'Instance at %s:%d serves %d slots to rescue the cluster', subst_host, subst_port, len(failed_slots))
def _poll_check_status(t): m = t.talk_raw(CMD_CLUSTER_INFO) logging.debug('Ask `cluster info` Rsp %s', m) cluster_state = PAT_CLUSTER_STATE.findall(m) cluster_slot_assigned = PAT_CLUSTER_SLOT_ASSIGNED.findall(m) if cluster_state[0] != 'ok' or int(cluster_slot_assigned[0]) != SLOT_COUNT: raise RedisStatusError('Unexpected status: %s' % m)
def _check_slave(slave_host, slave_port, t): slave_addr = '%s:%d' % (slave_host, slave_port) for line in t.talk('cluster', 'nodes').split('\n'): if slave_addr in line: if 'slave' in line: return raise RedisStatusError('%s not switched to a slave' % slave_addr)
def shutdown_cluster(host, port): with Talker(host, port) as t: _ensure_cluster_status_set(t) myself = None m = t.talk_raw(CMD_CLUSTER_NODES) logging.debug('Ask `cluster nodes` Rsp %s', m) nodes_info = filter(None, m.split('\n')) if len(nodes_info) > 1: raise RedisStatusError('More than 1 nodes in cluster.') try: m = t.talk('cluster', 'reset') except hiredis.ReplyError, e: if 'containing keys' in e.message: raise RedisStatusError('Cluster containing keys') raise logging.debug('Ask `cluster delslots` Rsp %s', m)
def replicate(master_host, master_port, slave_host, slave_port): master_talker = None t = Talker(slave_host, slave_port) try: master_talker = Talker(master_host, master_port) _ensure_cluster_status_set(master_talker) myself = _list_nodes(master_talker)[1] myid = (myself.node_id if myself.role_in_cluster == 'master' else myself.master_id) _join_to_cluster(master_host, master_port, t) logging.info('Instance at %s:%d has joined %s:%d; now set replica', slave_host, slave_port, master_host, master_port) m = t.talk('cluster', 'replicate', myid) logging.debug('Ask `cluster replicate` Rsp %s', m) if m.lower() != 'ok': raise RedisStatusError('Unexpected reply after REPCLIATE: %s' % m) _check_slave(slave_host, slave_port, master_talker) logging.info('Instance at %s:%d set as replica to %s', slave_host, slave_port, myid) finally: t.close() if master_talker is not None: master_talker.close()
def expect_talk_ok(m, slot): if m.lower() != 'ok': raise RedisStatusError('\n'.join([ 'Error while moving slot [ %d ] between' % slot, 'Source node - %s:%d' % (source_node.host, source_node.port), 'Target node - %s:%d' % (target_node.host, target_node.port), 'Got %s' % m]))
def _join_to_cluster(clst, new): _ensure_cluster_status_set(clst) _ensure_cluster_status_unset(new) m = clst.talk('cluster', 'meet', new.host, new.port) logging.debug('Ask `cluster meet` Rsp %s', m) if m.lower() != 'ok': raise RedisStatusError('Unexpected reply after MEET: %s' % m) _poll_check_status(new)
def start_cluster(host, port): with Talker(host, port) as t: _ensure_cluster_status_unset(t) m = t.talk('cluster', 'addslots', *xrange(SLOT_COUNT)) logging.debug('Ask `cluster addslots` Rsp %s', m) if m.lower() != 'ok': raise RedisStatusError('Unexpected reply after ADDSLOTS: %s' % m) _poll_check_status(t) logging.info('Instance at %s:%d started as a standalone cluster', host, port)
def raise_(self, message): raise RedisStatusError(message, self.host, self.port)
def addslots(t, begin, end): m = t.talk('cluster', 'addslots', *xrange(begin, end)) logging.debug('Ask `cluster addslots` Rsp %s', m) if m.lower() != 'ok': raise RedisStatusError('Unexpected reply after ADDSLOTS: %s' % m)