Exemple #1
0
def test_is_exit_node():
    NODE_SETTINGS['use_exitnode'].append('beefea68e6')
    res = is_exit_node('beefea68e6')
    assert res is True
    NODE_SETTINGS['use_exitnode'].remove('beefea68e6')
    res = is_exit_node('beefea68e6')
    assert res is False
Exemple #2
0
def get_target_node_id(node_lst, boot_lst):
    """
    Return a target node ID from the active network to use as an
    insertion point for all the nodes in the bootstrap list.
    :notes: choice of tgt node is random; this may change
    :param trie: net data trie
    :param node_lst: list of all active nodes
    :param boot_lst: list of bootstrap nodes
    :return: <str> node ID
    """
    import random
    from node_tools.ctlr_funcs import is_exit_node

    return random.choice(
        [x for x in node_lst if x not in boot_lst and not is_exit_node(x)])
Exemple #3
0
def get_neighbor_ids(trie, node_id):
    """
    Given the node ID, get the payloads from the net trie and return
    the attached network and neighbor node IDs.
    :param trie: net data trie
    :param node_id: node ID to lookup
    :return: tuple of net and node IDs
    """
    from node_tools.ctlr_funcs import ipnet_get_netcfg
    from node_tools.ctlr_funcs import is_exit_node
    from node_tools.ctlr_funcs import netcfg_get_ipnet
    from node_tools.helper_funcs import find_ipv4_iface

    node_list = []
    key_list = []
    src_net = None
    exit_net = None
    src_node = None
    exit_node = None

    for key in trie:
        if node_id in key:
            key_list.append(key[0:16])
            node_list.append(trie[key])

    if len(key_list) != 2 and (len(key_list) == 1
                               and not is_exit_node(node_id)):
        raise AssertionError('Node {} keys {} are invalid!'.format(
            node_id, key_list))
    else:
        for key, data in zip(key_list, node_list):
            node_ip = data['ipAssignments'][0]
            ipnet = netcfg_get_ipnet(node_ip)
            netcfg = ipnet_get_netcfg(ipnet)
            gw_ip = find_ipv4_iface(netcfg.gateway[0])
            if node_ip == gw_ip:
                src_net = key
                for node in trie.suffixes(src_net)[1:]:
                    if node_id != node:
                        src_node = node
            else:
                exit_net = key
                for node in trie.suffixes(exit_net)[1:]:
                    if node_id != node:
                        exit_node = node
    return src_net, exit_net, src_node, exit_node
Exemple #4
0
def handle_wedged_nodes(trie, wdg_q, off_q):
    """
    Use node ID in wedged queue to lookup the corresponding exit node ID
    and add it to the offline queue.  This is the only way we currently
    have to remove a wedged neighbor (exit) node.
    """
    from node_tools.ctlr_funcs import is_exit_node
    from node_tools.trie_funcs import get_wedged_node_id

    deduped = list(set(list(wdg_q)))
    for node_id in deduped:
        with wdg_q.transact():
            clean_from_queue(node_id, wdg_q)
        wedged_node = get_wedged_node_id(trie, node_id)
        if wedged_node is not None:
            if not is_exit_node(wedged_node):
                with off_q.transact():
                    add_one_only(wedged_node, off_q)
Exemple #5
0
def get_active_nodes(id_trie):
    """
    Find all the currently active nodes except the exit node (search the
    ID trie).
    :notes: In this case the answer depends on when this runs (relative
            to the cmds in `netstate` runner).
    :param id_trie: ID state trie
    :return: list of node IDs (empty list if None)
    """
    from node_tools.ctlr_funcs import is_exit_node

    node_list = []

    for node in [
            x for x in list(id_trie) if len(x) == 10 and not is_exit_node(x)
    ]:
        node_list.append(node)
    return node_list
Exemple #6
0
def find_orphans(net_trie, id_trie):
    """
    Find orphaned nodes/empty nets based on current trie data from ZT api.
    In this context, an orphan is:
    * an empty net ID
    * a node ID with a single net ID (except the exit node)
    * a node ID without any networks
    :param net_trie: datrie trie object
    :param id_trie: datrie trie object
    :return: tuple of lists (orphan net list, orphan node list)
    """
    from node_tools.ctlr_funcs import is_exit_node

    orphan_nets = []
    orphan_nodes = []

    for net_id in [x for x in list(id_trie) if len(x) == 16]:
        mbr_list = net_trie.suffixes(net_id)[1:]
        if mbr_list == []:
            orphan_nets.append(net_id)
            logger.warning('CLEANUP: found empty net: {}'.format(net_id))
    for node_id in [
            x for x in list(id_trie) if len(x) == 10 and not is_exit_node(x)
    ]:
        net_list = []
        for key in list(net_trie):
            if node_id in key:
                net_list.append((key[0:16], node_id))
        if len(net_list) == 1:
            orphan_nets.append(net_list[0])
            logger.warning('CLEANUP: found orphan net {}'.format(net_list))
        elif len(net_list) == 0:
            orphan_nodes.append(node_id)
            logger.warning('CLEANUP: found orphan node {}'.format(node_id))

    return orphan_nets, orphan_nodes
Exemple #7
0
async def main():
    """State cache updater to retrieve data from a local ZeroTier node."""
    async with aiohttp.ClientSession() as session:
        ZT_API = get_token()
        client = ZeroTier(ZT_API, loop, session)

        try:
            # handle offline/wedged nodes
            handle_wedged_nodes(ct.net_trie, wdg_q, off_q)
            pre_off = list(off_q)
            logger.debug('{} nodes in offline queue: {}'.format(
                len(pre_off), pre_off))
            for node_id in pre_off:
                await offline_mbr_node(client, node_id)
            for node_id in [x for x in off_q if x in pre_off]:
                off_q.remove(node_id)
            logger.debug('{} nodes in offline queue: {}'.format(
                len(off_q), list(off_q)))

            # get ID and status details of ctlr node
            await client.get_data('status')
            ctlr_id = handle_node_status(client.data, cache)

            # update ctlr state tries
            await update_state_tries(client, ct.net_trie, ct.id_trie)
            logger.debug('net_trie has keys: {}'.format(list(ct.net_trie)))
            # for key in list(ct.net_trie):
            #     logger.debug('net key {} has paylod: {}'.format(key, ct.net_trie[key]))
            # for key in list(ct.id_trie):
            #     logger.debug('id key {} has payload: {}'.format(key, ct.id_trie[key]))
            logger.debug('id_trie has keys: {}'.format(list(ct.id_trie)))

            # handle node queues and publish messages
            logger.debug('{} nodes in node queue: {}'.format(
                len(node_q), list(node_q)))
            if len(node_q) > 0:
                handle_node_queues(node_q, staging_q)
                logger.debug('{} nodes in node queue: {}'.format(
                    len(node_q), list(node_q)))
            logger.debug('{} nodes in staging queue: {}'.format(
                len(staging_q), list(staging_q)))

            for mbr_id in [x for x in staging_q if x not in list(ct.id_trie)]:
                if is_exit_node(mbr_id):
                    await bootstrap_mbr_node(client,
                                             ctlr_id,
                                             mbr_id,
                                             netobj_q,
                                             ex=True)
                else:
                    await bootstrap_mbr_node(client, ctlr_id, mbr_id, netobj_q)
                st.wait_cache.set(mbr_id, True, 90)
                publish_cfg_msg(ct.id_trie, mbr_id, addr='127.0.0.1')

            for mbr_id in [x for x in staging_q if x in list(ct.id_trie)]:
                publish_cfg_msg(ct.id_trie, mbr_id, addr='127.0.0.1')
                staging_q.remove(mbr_id)
            logger.debug('{} nodes in staging queue: {}'.format(
                len(staging_q), list(staging_q)))

            # refresh ctlr state tries again
            await update_state_tries(client, ct.net_trie, ct.id_trie)

            node_list = get_active_nodes(ct.id_trie)
            logger.debug('{} nodes in node_list: {}'.format(
                len(node_list), node_list))
            if len(node_list) > 0:
                boot_list = get_bootstrap_list(ct.net_trie, ct.id_trie)
                logger.debug('{} nodes in boot_list: {}'.format(
                    len(boot_list), boot_list))

                if len(boot_list) != 0:
                    await close_mbr_net(client,
                                        node_list,
                                        boot_list,
                                        min_nodes=3)
                else:
                    await unwrap_mbr_net(client,
                                         node_list,
                                         boot_list,
                                         min_nodes=3)

        except Exception as exc:
            logger.error('netstate exception was: {}'.format(exc))
            await cleanup_orphans(client)
            if list(ct.net_trie) == [] and list(ct.id_trie) != []:
                ct.id_trie.clear()
            raise exc