Exemple #1
0
def connect_to_leader(cert=None, name=None, leader=None):
    global currentleader
    global follower
    if leader is None:
        leader = currentleader
    log.log({
        'info': 'Attempting connection to leader {0}'.format(leader),
        'subsystem': 'collective'
    })
    try:
        remote = connect_to_collective(cert, leader)
    except socket.error as e:
        log.log({
            'error':
            'Collective connection attempt to {0} failed: {1}'
            ''.format(leader, str(e)),
            'subsystem':
            'collective'
        })
        return False
    with connecting:
        with cfm._initlock:
            banner = tlvdata.recv(remote)  # the banner
            vers = banner.split()[2]
            if vers != b'v2':
                raise Exception(
                    'This instance only supports protocol 2, synchronize versions between collective members'
                )
            tlvdata.recv(remote)  # authpassed... 0..
            if name is None:
                name = get_myname()
            tlvdata.send(
                remote, {
                    'collective': {
                        'operation': 'connect',
                        'name': name,
                        'txcount': cfm._txcount
                    }
                })
            keydata = tlvdata.recv(remote)
            if not keydata:
                return False
            if 'error' in keydata:
                if 'backoff' in keydata:
                    log.log({
                        'info':
                        'Collective initialization in progress on '
                        '{0}'.format(leader),
                        'subsystem':
                        'collective'
                    })
                    return False
                if 'leader' in keydata:
                    log.log({
                        'info':
                        'Prospective leader {0} has redirected this '
                        'member to {1}'.format(leader, keydata['leader']),
                        'subsystem':
                        'collective'
                    })
                    ldrc = cfm.get_collective_member_by_address(
                        keydata['leader'])
                    if ldrc and ldrc['name'] == name:
                        raise Exception("Redirected to self")
                    return connect_to_leader(name=name,
                                             leader=keydata['leader'])
                if 'txcount' in keydata:
                    log.log({
                        'info':
                        'Prospective leader {0} has inferior '
                        'transaction count, becoming leader'
                        ''.format(leader),
                        'subsystem':
                        'collective',
                        'subsystem':
                        'collective'
                    })
                    return become_leader(remote)
                return False
                follower.kill()
                cfm.stop_following()
                follower = None
            if follower:
                follower.kill()
                cfm.stop_following()
                follower = None
            log.log({
                'info': 'Following leader {0}'.format(leader),
                'subsystem': 'collective'
            })
            colldata = tlvdata.recv(remote)
            # the protocol transmits global data, but for now we ignore it
            globaldata = tlvdata.recv(remote)
            dbi = tlvdata.recv(remote)
            dbsize = dbi['dbsize']
            dbjson = b''
            while (len(dbjson) < dbsize):
                ndata = remote.recv(dbsize - len(dbjson))
                if not ndata:
                    try:
                        remote.close()
                    except Exception:
                        pass
                    raise Exception("Error doing initial DB transfer")
                dbjson += ndata
            cfm.clear_configuration()
            try:
                cfm._restore_keys(keydata, None, sync=False)
                for c in colldata:
                    cfm._true_add_collective_member(c,
                                                    colldata[c]['address'],
                                                    colldata[c]['fingerprint'],
                                                    sync=False)
                #for globvar in globaldata:
                #    cfm.set_global(globvar, globaldata[globvar], False)
                cfm._txcount = dbi.get('txcount', 0)
                cfm.ConfigManager(tenant=None)._load_from_json(dbjson,
                                                               sync=False)
                cfm.commit_clear()
            except Exception:
                cfm.stop_following()
                cfm.rollback_clear()
                raise
            currentleader = leader
        #spawn this as a thread...
        follower = eventlet.spawn(follow_leader, remote, leader)
    return True
Exemple #2
0
def connect_to_leader(cert=None, name=None, leader=None):
    global currentleader
    global cfginitlock
    global follower
    if cfginitlock is None:
        cfginitlock = threading.RLock()
    if leader is None:
        leader = currentleader
    try:
        remote = connect_to_collective(cert, leader)
    except socket.error:
        return False
    with connecting:
        with cfginitlock:
            tlvdata.recv(remote)  # the banner
            tlvdata.recv(remote)  # authpassed... 0..
            if name is None:
                name = get_myname()
            tlvdata.send(
                remote, {
                    'collective': {
                        'operation': 'connect',
                        'name': name,
                        'txcount': cfm._txcount
                    }
                })
            keydata = tlvdata.recv(remote)
            if not keydata:
                return False
            if 'error' in keydata:
                if 'backoff' in keydata:
                    eventlet.spawn_after(random.random(), connect_to_leader,
                                         cert, name, leader)
                    return True
                if 'leader' in keydata:
                    ldrc = cfm.get_collective_member_by_address(
                        keydata['leader'])
                    if ldrc and ldrc['name'] == name:
                        raise Exception("Redirected to self")
                    return connect_to_leader(name=name,
                                             leader=keydata['leader'])
                if 'txcount' in keydata:
                    return become_leader(remote)
                print(keydata['error'])
                return False
            if follower is not None:
                follower.kill()
                cfm.stop_following()
                follower = None
            colldata = tlvdata.recv(remote)
            globaldata = tlvdata.recv(remote)
            dbi = tlvdata.recv(remote)
            dbsize = dbi['dbsize']
            dbjson = ''
            while (len(dbjson) < dbsize):
                ndata = remote.recv(dbsize - len(dbjson))
                if not ndata:
                    try:
                        remote.close()
                    except Exception:
                        pass
                    raise Exception("Error doing initial DB transfer")
                dbjson += ndata
            cfm.clear_configuration()
            try:
                cfm._restore_keys(keydata, None, sync=False)
                for c in colldata:
                    cfm._true_add_collective_member(c,
                                                    colldata[c]['address'],
                                                    colldata[c]['fingerprint'],
                                                    sync=False)
                for globvar in globaldata:
                    cfm.set_global(globvar, globaldata[globvar], False)
                cfm._txcount = dbi.get('txcount', 0)
                cfm.ConfigManager(tenant=None)._load_from_json(dbjson,
                                                               sync=False)
                cfm.commit_clear()
            except Exception:
                cfm.stop_following()
                cfm.rollback_clear()
                raise
            currentleader = leader
        #spawn this as a thread...
        follower = eventlet.spawn(follow_leader, remote)
    return True