diff --git a/node_tools/async_funcs.py b/node_tools/async_funcs.py index a331664..e6df46d 100644 --- a/node_tools/async_funcs.py +++ b/node_tools/async_funcs.py @@ -133,17 +133,15 @@ async def close_mbr_net(client, node_lst, boot_lst, min_nodes=5): else: logger.debug('CLOSURE: not enough bootstrap nodes to wrap') else: - logger.debug('CLOSURE: adding bootstrap nodes {} to network'.format(boot_lst)) + logger.debug('CLOSURE: adding bootstrap list {} to network'.format(boot_lst)) tgt_id = get_target_node_id(node_lst, boot_lst) tgt_net, tgt_exit_net, tgt_src_node, tgt_exit_node = get_neighbor_ids(ct.net_trie, tgt_id) - tgt_nets = [tgt_net, tgt_exit_net] - logger.debug('CLOSURE: got tgt_nets {}'.format(tgt_nets)) tgt_src_net, _, _, _ = get_neighbor_ids(ct.net_trie, tgt_src_node) # detach and connect tgt to tail await config_network_object(client, deauth, tgt_exit_net, tgt_id) cleanup_state_tries(ct.net_trie, ct.id_trie, tgt_exit_net, tgt_id, mbr_only=True) - logger.debug('CLOSURE: deauthed node id {} from exit net {}'.format(tgt_id, tgt_exit_net)) + logger.debug('CLOSURE: deauthed node id {} from tgt exit net {}'.format(tgt_id, tgt_exit_net)) await connect_mbr_node(client, tgt_id, tgt_src_net, tail_exit_net, tail_id) publish_cfg_msg(ct.id_trie, tgt_id, addr='127.0.0.1') @@ -151,7 +149,7 @@ async def close_mbr_net(client, node_lst, boot_lst, min_nodes=5): # detach and connect head to tgt exit net await config_network_object(client, deauth, head_exit_net, head_id) cleanup_state_tries(ct.net_trie, ct.id_trie, head_exit_net, head_id, mbr_only=True) - logger.debug('CLOSURE: deauthed node id {} from exit net {}'.format(head_id, head_exit_net)) + logger.debug('CLOSURE: deauthed node id {} from head exit net {}'.format(head_id, head_exit_net)) await connect_mbr_node(client, head_id, head_src_net, tgt_exit_net, tgt_exit_node) publish_cfg_msg(ct.id_trie, head_id, addr='127.0.0.1') @@ -276,6 +274,47 @@ async def update_state_tries(client, net_trie, id_trie): logger.debug('member key suffixes: {}'.format(net_trie.suffixes(net_id))) +async def unwrap_mbr_net(client, node_lst, boot_lst, min_nodes=5): + """ + Wrapper for unwrapping the (closed) network when it gets too small. + This should run in the ctlr state runner *after* the other handlers + (and when there are not enough nodes to keep a closed network). + :param client: ztcli_api client object + :param node_lst: list of all active nodes + :param boot_lst: list of bootstrap nodes + :param min_nodes: minimum number of nodes for a closed network + """ + from node_tools import ctlr_data as ct + from node_tools import state_data as st + + from node_tools.ctlr_funcs import unset_network_cfg + from node_tools.network_funcs import publish_cfg_msg + from node_tools.trie_funcs import cleanup_state_tries + from node_tools.trie_funcs import find_dangling_nets + from node_tools.trie_funcs import get_neighbor_ids + from node_tools.trie_funcs import get_target_node_id + + if len(node_lst) <= min_nodes and len(node_lst) > 1: + logger.debug('UNWRAP: creating bootstrap list from network {}'.format(node_lst)) + tgt_id = get_target_node_id(node_lst, boot_lst) + tgt_net, tgt_exit_net, _, _ = get_neighbor_ids(ct.net_trie, tgt_id) + # tgt_src_net, _, _, _ = get_neighbor_ids(ct.net_trie, tgt_src_node) + data_list = find_dangling_nets(ct.id_trie) + exit_net = data_list[0] + exit_node = data_list[1] + deauth = unset_network_cfg() + + # detach and connect tgt node back to exit node + await config_network_object(client, deauth, tgt_exit_net, tgt_id) + cleanup_state_tries(ct.net_trie, ct.id_trie, tgt_exit_net, tgt_id, mbr_only=True) + logger.debug('UNWRAP: deauthed node id {} from tgt exit net {}'.format(tgt_id, tgt_exit_net)) + + await connect_mbr_node(client, tgt_id, tgt_net, exit_net, exit_node) + publish_cfg_msg(ct.id_trie, tgt_id, addr='127.0.0.1') + else: + logger.debug('UNWRAP: num nodes greater than {} so not unwrapping'.format(min_nodes)) + + async def add_network_object(client, net_id=None, mbr_id=None, ctlr_id=None): """ Command wrapper for creating ZT objects under the `controller` endpoint. diff --git a/node_tools/netstate.py b/node_tools/netstate.py index 559e937..6f87dfe 100644 --- a/node_tools/netstate.py +++ b/node_tools/netstate.py @@ -15,6 +15,7 @@ from node_tools.async_funcs import bootstrap_mbr_node from node_tools.async_funcs import close_mbr_net from node_tools.async_funcs import offline_mbr_node +from node_tools.async_funcs import unwrap_mbr_net from node_tools.async_funcs import update_state_tries from node_tools.cache_funcs import handle_node_status from node_tools.ctlr_funcs import is_exit_node @@ -90,11 +91,14 @@ async def main(): node_list = get_active_nodes(ct.id_trie) logger.debug('{} nodes in node_list: {}'.format(len(node_list), node_list)) - 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) + 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) + elif len(boot_list) == 0 and len(node_list) > 1: + await unwrap_mbr_net(client, node_list, boot_list, min_nodes=3) except Exception as exc: logger.error('netstate exception was: {}'.format(exc)) diff --git a/setup.py b/setup.py index b6795cc..10e317a 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ from distutils.core import setup -__version__ = '0.8.6' +__version__ = '0.8.7' # make setuptools happy with PEP 440-compliant post version # (enable this for patch releases)