async def connect_mbr_node(client, node_id, src_net, exit_net, gw_node): """ Wrapper to reconnect an existing member node; needs the (upstream) exit net and node IDs as well as its own ID and src_net ID. :notes: uses both Tries (required by offline_mbr_node below) :param client: ztcli_api client object :param node_id: node ID :param node_net: src_net ID for node :param exit_net: network ID of the gateway net to connect :param gw_node: node ID of the gateway host """ from node_tools import ctlr_data as ct from node_tools.ctlr_funcs import set_network_cfg from node_tools.trie_funcs import get_dangling_net_data from node_tools.trie_funcs import update_id_trie await add_network_object(client, exit_net, node_id) logger.debug('CONNECT: added neighbor {} to exit net {}'.format( node_id, exit_net)) netcfg = get_dangling_net_data(ct.net_trie, exit_net) gw_cfg = set_network_cfg(netcfg.host) logger.debug('CONNECT: got cfg {} for exit net'.format(gw_cfg)) await config_network_object(client, gw_cfg, exit_net, node_id) logger.debug('CONNECT: net_trie keys: {}'.format(list(ct.net_trie))) logger.debug('CONNECT: id_trie keys: {}'.format(list(ct.id_trie))) update_id_trie(ct.id_trie, [exit_net], [node_id, gw_node], needs=[False, False], nw=True) update_id_trie(ct.id_trie, [src_net, exit_net], [node_id], needs=[False, False])
def test_update_id_trie_node(self): update_id_trie(self.trie, self.nets, self.node1) res = self.trie[self.node1[0]] self.assertIsInstance(res, tuple) self.assertEqual(len(res), 2) for thing in res: self.assertIsInstance(thing, list) self.assertEqual(res, (self.nets, []))
def test_update_id_trie_net(self): update_id_trie(self.trie, self.net1, [self.node2], nw=True) res = self.trie[self.net1[0]] self.assertIsInstance(res, tuple) self.assertEqual(len(res), 2) for thing in res: self.assertIsInstance(thing, list) self.assertEqual(res, ([self.node2], []))
def test_find_dangling_nets(self): update_id_trie(self.trie, self.net1, self.node1, [False, False]) update_id_trie(self.trie, self.net2, self.nodes, [False, False], nw=True) res = find_dangling_nets(self.trie) self.assertEqual(res, []) update_id_trie(self.trie, self.net1, self.node1, [False, True], nw=True) res = find_dangling_nets(self.trie) self.assertEqual(len(res), 2) self.assertEqual(res, [self.net1[0], self.node1[0]])
def test_update_id_trie_none(self): with self.assertRaises(AssertionError): update_id_trie(self.trie, self.net1, self.node1, needs=[True]) update_id_trie(self.trie, self.netss, self.node1) update_id_trie(self.trie, self.nets, self.node4)
async def bootstrap_mbr_node(client, ctlr_id, node_id, deque, ex=False): """ Wrapper for bootstrapping a new member node; adds one network for each node and adds each node to its (new) network. Updates net/id tries with new data. :notes: Since we *always* provide a new (ZT) network, we do *not* handle existing nodes here. The `deque` parameter is required for handle_net_cfg(). :param client: ztcli_api client object :param ctlr_id: node ID of controller node :param node_id: node ID :param deque: netobj queue :param ex: True if node is an exit node """ from node_tools import ctlr_data as ct from node_tools.ctlr_funcs import get_network_id from node_tools.ctlr_funcs import handle_net_cfg from node_tools.ctlr_funcs import set_network_cfg from node_tools.trie_funcs import find_dangling_nets from node_tools.trie_funcs import get_dangling_net_data from node_tools.trie_funcs import update_id_trie await add_network_object(client, ctlr_id=ctlr_id) net_id = get_network_id(client.data) logger.debug('BOOTSTRAP: added network id {}'.format(net_id)) net_rules = ct.rules await config_network_object(client, net_rules, net_id) logger.debug('BOOTSTRAP: added network rules {}'.format(net_rules)) await get_network_object_ids(client) logger.debug('BOOTSTRAP: got network list {}'.format(client.data)) net_list = client.data if net_id in net_list: # Get details about each network await get_network_object_data(client, net_id) logger.debug('BOOTSTRAP: got network data {}'.format(client.data)) trie_nets = [net_id] await add_network_object(client, net_id, node_id) logger.debug('BOOTSTRAP: added node id {} to gw net'.format(node_id)) await get_network_object_ids(client, net_id) member_dict = client.data logger.debug('BOOTSTRAP: got node dict {}'.format(member_dict)) await get_network_object_data(client, net_id, node_id) logger.debug('BOOTSTRAP: got node data {}'.format(client.data)) ipnet, _, gw = handle_net_cfg(deque) await config_network_object(client, ipnet, net_id) # A dedicated exit node is a special case, otherwise, each new node # gets a src_net here, and still *needs* a exit_net. We also need to # update the src net needs after linking the next mbr node. if not ex: data_list = find_dangling_nets(ct.id_trie) logger.debug('BOOTSTRAP: got exit net {}'.format(data_list)) if len(data_list) == 2: exit_net = data_list[0] exit_node = data_list[1] await add_network_object(client, exit_net, node_id) logger.debug( 'BOOTSTRAP: added node id {} to exit net {}'.format( node_id, exit_net)) netcfg = get_dangling_net_data(ct.net_trie, exit_net) gw_cfg = set_network_cfg(netcfg.host) logger.debug( 'BOOTSTRAP: got node addr {} for exit net'.format(gw_cfg)) await config_network_object(client, gw_cfg, exit_net, node_id) trie_nets = [net_id, exit_net] else: logger.error( 'BOOTSTRAP: malformed exit net data {}'.format(data_list)) await config_network_object(client, gw, net_id, node_id) logger.debug('BOOTSTRAP: set gw addr {} for src net {}'.format( gw, net_id)) await update_mbr_data(client, ct.net_trie, net_id, node_id) logger.debug('BOOTSTRAP: loaded net trie with {} and {} data'.format( node_id, net_id)) node_needs = [False, False] net_needs = [False, True] if not ex: update_id_trie(ct.id_trie, [exit_net], [node_id, exit_node], needs=[False, False], nw=True) update_id_trie(ct.id_trie, trie_nets, [node_id], needs=node_needs) update_id_trie(ct.id_trie, [net_id], [node_id], needs=net_needs, nw=True)