def start_routing_protocol(protocol, rmap, ids, ignore_error=False): beg_count = count_instances(protocol, rmap) beg_ms = millis() for id in ids: remote = rmap[id] interface_up(remote, id, 'uplink', ignore_error) if protocol == 'babel': start_babel_instances(ids, rmap) elif protocol == 'batman-adv': start_batmanadv_instances(ids, rmap) elif protocol == 'bmx6': start_bmx6_instances(ids, rmap) elif protocol == 'cjdns': start_cjdns_instances(ids, rmap) elif protocol == 'olsr1': start_olsr1_instances(ids, rmap) elif protocol == 'olsr2': start_olsr2_instances(ids, rmap) elif protocol == 'ospf': start_ospf_instances(ids, rmap) elif protocol == 'yggdrasil': start_yggdrasil_instances(ids, rmap) elif protocol == 'none': return else: eprint(f'Error: unknown routing protocol: {protocol}') exit(1) wait_for_completion() # wait for last started process to fork # otherwise we might have one extra counted instance time.sleep(0.5) end_ms = millis() end_count = count_instances(protocol, rmap) count = end_count - beg_count if count != len(ids): eprint( f'Error: Failed to start {protocol} instances: {count}/{len(ids)} started' ) stop_all_terminals() exit(1) if verbosity != 'quiet': print('Started {} {} instances in {}'.format( count, protocol, format_duration(end_ms - beg_ms)))
def stop_routing_protocol(protocol, rmap, ids, ignore_error=False): beg_count = count_instances(protocol, rmap) beg_ms = millis() if protocol == 'babel': stop_babel_instances(ids, rmap) elif protocol == 'batman-adv': stop_batmanadv_instances(ids, rmap) elif protocol == 'bmx6': stop_bmx6_instances(ids, rmap) elif protocol == 'cjdns': stop_cjdns_instances(ids, rmap) elif protocol == 'olsr1': stop_olsr1_instances(ids, rmap) elif protocol == 'olsr2': stop_olsr2_instances(ids, rmap) elif protocol == 'ospf': stop_ospf_instances(ids, rmap) elif protocol == 'yggdrasil': stop_yggdrasil_instances(ids, rmap) elif protocol == 'none': pass else: eprint('Error: unknown routing protocol: {}'.format(protocol)) exit(1) for id in ids: remote = rmap[id] interface_down(remote, id, 'uplink', ignore_error=ignore_error) wait_for_completion() # wait for last stopped process to disappear # otherwise we might have one extra counted instance time.sleep(0.5) end_ms = millis() end_count = count_instances(protocol, rmap) count = beg_count - end_count if count != len(ids): eprint( f'Error: Failed to stop {protocol} instances: {count}/{len(ids)} left' ) exit(1) if not ignore_error and verbosity != 'quiet': print('Stopped {} {} instances in {}'.format( len(ids), protocol, format_duration(end_ms - beg_ms)))
def clear(remotes): base = os.path.dirname(os.path.realpath(__file__)) names = [] for name in os.listdir(f'{base}/protocols/'): if name.endswith('_stop.sh'): names.append(name) for remote in remotes: for name in names: label = remote.address or 'local' cmd = f'sh -s {label} < {base}/protocols/{name}' _exec_verbose(remote, cmd, ignore_error=True) wait_for_completion()
def _stop_protocol(protocol, rmap, ids): base = os.path.dirname(os.path.realpath(__file__)) path = f'{base}/protocols/{protocol}_stop.sh' if not os.path.isfile(path): eprint(f'File does not exist: {path}') stop_all_terminals() exit(1) for id in ids: remote = rmap[id] label = remote.address or 'local' cmd = f'ip netns exec ns-{id} sh -s {label} {id} < {path}' _exec_verbose(remote, cmd) wait_for_completion()
def apply(state={}, node_command=None, link_command=None, remotes=default_remotes): check_access(remotes) new_state = state (cur_state, cur_state_rmap) = get_current_state(remotes) # handle different new_state types if isinstance(new_state, str): if new_state == 'none': new_state = {} else: if not os.path.isfile(new_state): eprint(f'File not found: {new_state}') stop_all_terminals() exit(1) with open(new_state) as file: new_state = json.load(file) # map each node to a remote or local computer # distribute evenly with minimized interconnects rmap = _get_remote_mapping(cur_state, new_state, remotes, cur_state_rmap) data = _get_task(cur_state, new_state) beg_ms = millis() # add "switch" namespace if state_empty(cur_state): for remote in remotes: # add switch if it does not exist yet exec(remote, 'ip netns add "switch" || true') # disable IPv6 in switch namespace (no need, less overhead) exec( remote, 'ip netns exec "switch" sysctl -q -w net.ipv6.conf.all.disable_ipv6=1' ) for node in data.nodes_update: update_node(node, node_command, rmap) for link in data.links_update: update_link(link, link_command, rmap) for node in data.nodes_create: create_node(node, node_command, rmap) for link in data.links_create: create_link(link, link_command, rmap) for link in data.links_remove: remove_link(link, rmap) for node in data.nodes_remove: remove_node(node, rmap) # remove "switch" namespace if state_empty(new_state): for remote in remotes: exec(remote, 'ip netns del "switch" || true') # wait for tasks to complete wait_for_completion() end_ms = millis() if verbosity != 'quiet': print('Network setup in {}:'.format(format_duration(end_ms - beg_ms))) print( f' nodes: {len(data.nodes_create)} created, {len(data.nodes_remove)} removed, {len(data.nodes_update)} updated' ) print( f' links: {len(data.links_create)} created, {len(data.links_remove)} removed, {len(data.links_update)} updated' ) return new_state