Skip to content

Commit

Permalink
add close_mbr_net() and a helper func, update tests
Browse files Browse the repository at this point in the history
Signed-off-by: Stephen Arnold <nerdboy@gentoo.org>
  • Loading branch information
sarnold committed Jun 9, 2020
1 parent 74f052b commit d384098
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 11 deletions.
67 changes: 67 additions & 0 deletions node_tools/async_funcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,73 @@ async def bootstrap_mbr_node(client, ctlr_id, node_id, deque, ex=False):
# logger.debug('TRIE: id_trie has items: {}'.format(ct.id_trie.items()))


async def close_mbr_net(client, node_lst, boot_lst, min_nodes=5):
"""
Wrapper for closing the bootstrap chain or adding it to an existing
(closed) network. This should run in the ctlr state runner *after*
the other handlers.
: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 find_exit_net
from node_tools.trie_funcs import get_neighbor_ids
from node_tools.trie_funcs import get_target_node_id

head_id = boot_lst[-1]
tail_id = boot_lst[0]
head_exit_net = find_exit_net(ct.id_trie)[0]
head_src_net, _, _, _ = get_neighbor_ids(ct.net_trie, head_id)
tail_exit_net = find_dangling_nets(ct.id_trie)[0]
deauth = unset_network_cfg()

# if true, we only have a boot list
if len(node_lst) - len(boot_lst) == 1:
# check if we have enough nodes for a network
if len(boot_lst) >= min_nodes:
logger.debug('CLOSURE: creating network from boot_list {}'.format(boot_lst))
# detach and connect head to tail
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))

await connect_mbr_node(client, head_id, head_src_net, tail_exit_net, tail_id)
publish_cfg_msg(ct.id_trie, head_id, addr='127.0.0.1')
else:
logger.debug('CLOSURE: not enough bootstrap nodes to wrap')
else:
logger.debug('CLOSURE: adding bootstrap nodes {} 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))

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')

# 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))

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')


async def connect_mbr_node(client, node_id, src_net, exit_net, gw_node):
"""
Wrapper to reconnect an existing member node; needs the (upstream)
Expand Down
12 changes: 3 additions & 9 deletions node_tools/netstate.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from node_tools import ctlr_data as ct

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 update_state_tries
from node_tools.cache_funcs import handle_node_status
Expand All @@ -26,7 +27,6 @@
from node_tools.network_funcs import publish_cfg_msg
from node_tools.trie_funcs import get_active_nodes
from node_tools.trie_funcs import get_bootstrap_list
from node_tools.trie_funcs import get_target_node_id


logger = logging.getLogger('netstate')
Expand Down Expand Up @@ -93,14 +93,8 @@ async def main():
boot_list = get_bootstrap_list(ct.net_trie, ct.id_trie)
logger.debug('{} nodes in boot_list: {}'.format(len(boot_list), boot_list))

# if true, we only have a boot list
if len(node_list) - len(boot_list) == 1:
# check if we have enough nodes for a network
if len(boot_list) >= 3:
# detach and connect
logger.debug('Creating network from boot_list {}'.format(boot_list))
else:
logger.debug('Adding bootstrap nodes {} to network'.format(boot_list))
if len(boot_list) != 0:
await close_mbr_net(client, node_list, boot_list, min_nodes=3)

except Exception as exc:
logger.error('netstate exception was: {}'.format(exc))
Expand Down
2 changes: 1 addition & 1 deletion node_tools/nodestate.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ async def main():

# check for reconfiguration events
for net in netStatus:
if net['status'] == 'NOT_FOUND':
if net['status'] == 'NOT_FOUND' or net['status'] == 'ACCESS_DENIED':
run_ztcli_cmd(action='leave', extra=net['identity'])
net_id_handler(None, net['identity'], old=True)
nsState.cfg_ref = None
Expand Down
14 changes: 14 additions & 0 deletions node_tools/trie_funcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,20 @@ def find_dangling_nets(trie):
return net_list


def find_exit_net(trie):
"""
Find the network attached to the exit node (search the ID trie).
:param trie: ID state trie
:return: network ID for the (only) network on the exit node
"""
net_list = []

for node in [x for x in list(trie) if len(x) == 10]:
if trie[node][1] == [False, False] and len(trie[node][0]) == 1:
net_list = trie[node][0]
return net_list


def get_active_nodes(id_trie):
"""
Find all the currently active nodes (search the ID trie).
Expand Down
9 changes: 8 additions & 1 deletion test/test_node_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
from node_tools.sched_funcs import check_return_status
from node_tools.trie_funcs import cleanup_state_tries
from node_tools.trie_funcs import create_state_trie
from node_tools.trie_funcs import find_exit_net
from node_tools.trie_funcs import get_active_nodes
from node_tools.trie_funcs import get_bootstrap_list
from node_tools.trie_funcs import get_dangling_net_data
Expand Down Expand Up @@ -762,6 +763,12 @@ def test_load_id_from_net_trie():
assert ct.id_trie['beefea68e6'] == (['beafde52b4296ea5'], [False, False])
assert ct.id_trie['beafde52b4a5f7ba'] == (['ee2eedb2e1', 'ff2ffdb2e1'], [False, False])
assert ct.id_trie['beafde52b4a5e8ab'] == (['ff2ffdb2e1'], [False, True])

res = find_exit_net(ct.id_trie)
assert isinstance(res, list)
assert res == ['beafde52b4296ea5']
exit_net = find_exit_net(ct.id_trie)[0]
assert exit_net == res[0]
# print(ct.id_trie.items())

node_id = 'beefea68e6'
Expand Down Expand Up @@ -811,7 +818,7 @@ def test_get_bootstrap_list():

boot_list = get_bootstrap_list(ct.net_trie, ct.id_trie)
assert exit_id not in boot_list
assert node_id == boot_list[1]
assert node_id == boot_list[-1]
assert tail_id == boot_list[0]
# print(boot_list)
NODE_SETTINGS['use_exitnode'].clear()
Expand Down

0 comments on commit d384098

Please sign in to comment.