From 2b612f07e72033f6dea61e26b13044bb5950fb36 Mon Sep 17 00:00:00 2001 From: Peng Lei Date: Tue, 5 Nov 2024 12:50:21 +0800 Subject: [PATCH] Resolve "cfg overwrite and missing interface" --- src/containernet/containernet_host.py | 5 +++++ src/core/network_mgr.py | 6 ++++-- src/core/runner.py | 17 ++++++++++------- src/interfaces/network.py | 6 ++++++ src/protosuites/bats/bats_protocol.py | 21 ++++++++++++++------- src/testsuites/test_scp.py | 2 +- src/tools/cfg_generator.py | 3 +++ 7 files changed, 43 insertions(+), 17 deletions(-) diff --git a/src/containernet/containernet_host.py b/src/containernet/containernet_host.py index 005ca66..ae90ff0 100644 --- a/src/containernet/containernet_host.py +++ b/src/containernet/containernet_host.py @@ -16,6 +16,11 @@ def cmd(self, command: str) -> str: """ return self.containernet_host.cmd(command) + def cmdPrint(self, command: str) -> str: + """Execute a command on the host and print the output. + """ + return self.containernet_host.cmdPrint(command) + def name(self) -> str: """Get the name of the host. """ diff --git a/src/core/network_mgr.py b/src/core/network_mgr.py index ac844ac..41e6001 100644 --- a/src/core/network_mgr.py +++ b/src/core/network_mgr.py @@ -67,8 +67,10 @@ def build_networks(self, node_config: NodeConfig, node_config.bind_port = False route_strategy = RoutingFactory().create_routing( route_string_to_enum[route]) - self.networks.append(ContainerizedNetwork( - node_config, topology, route_strategy)) + net = ContainerizedNetwork( + node_config, topology, route_strategy) + net.id = i + self.networks.append(net) elif cur_net_num > net_num: # stop the extra networks for i in range(net_num, cur_net_num): diff --git a/src/core/runner.py b/src/core/runner.py index c68ca50..ad84bda 100644 --- a/src/core/runner.py +++ b/src/core/runner.py @@ -388,8 +388,7 @@ def execute_tests(self): for i in range(self.net_num): p = multiprocessing.Process(target=self._perform_test_in_process, args=(networks[i], - test_name, - i, process_shared_dict)) + test_name, process_shared_dict)) processes.append(p) p.start() @@ -450,9 +449,11 @@ def handle_test_results(self, top_index): "Test %s results analysis not passed, and failure is ignored.", test_name) # 5.2 move results(logs, diagrams) to "{cur_results_path}/{top_index}" cur_results_path = f"{g_root_path}test_results/{test_name}/" - logging.info("cur_results_path %s", cur_results_path) archive_dir = f"{cur_results_path}topology-{top_index}" + logging.info("cur_results_path %s, archive_dir %s", + cur_results_path, archive_dir) if not os.path.exists(archive_dir): + logging.info("Create archive directory %s", archive_dir) os.makedirs(archive_dir) # move all files and folders to the archive directory except folder which start with "topology-*" for root, dirs, files in os.walk(cur_results_path): @@ -463,11 +464,15 @@ def handle_test_results(self, top_index): if dir_name.startswith("topology-"): continue os.system(f"mv {root}/{dir_name} {archive_dir}") + logging.info("Move %s to %s", dir_name, archive_dir) for file_name in files: os.system(f"mv {root}/{file_name} {archive_dir}") + logging.info("Move %s to %s", file_name, archive_dir) # 5.3 save top_description with open(f"{archive_dir}/topology_description.txt", 'w', encoding='utf-8') as f: f.write(f"{self.top_description}") + logging.debug("Save topology description to %s", + f"{archive_dir}/topology_description.txt") return True def cleanup(self): @@ -492,13 +497,11 @@ def _load_protocols(self): return False return True - def _perform_test_in_process(self, network, test_name, id, result_dict): + def _perform_test_in_process(self, network, test_name, result_dict): """Execute the test in a separate process, then store the results in the shared dictionary. - - Args: - id (int): The id of the process. """ + id = network.get_id() logging.info( "########## Oasis process %d Performing the test for %s", id, test_name) network.perform_test() diff --git a/src/interfaces/network.py b/src/interfaces/network.py index fa5469d..d723e07 100644 --- a/src/interfaces/network.py +++ b/src/interfaces/network.py @@ -11,6 +11,7 @@ class INetwork(ABC): def __init__(self): + self.id = 0 self.test_suites = [] self.proto_suites = [] self.test_results = {} @@ -20,6 +21,9 @@ def __init__(self): def is_accessible(self): return self.is_accessible_flag + def get_id(self): + return self.id + @abstractmethod def start(self): pass @@ -76,6 +80,8 @@ def perform_test(self): # Combination of protocol and test for proto in self.proto_suites: # start the protocol + logging.info("Starting protocol %s on network %s", + proto.get_config().name, self.get_id()) if proto.start(self) is False: logging.error("Protocol %s failed to start", proto.get_config().name) diff --git a/src/protosuites/bats/bats_protocol.py b/src/protosuites/bats/bats_protocol.py index 09e33ec..6c867c6 100644 --- a/src/protosuites/bats/bats_protocol.py +++ b/src/protosuites/bats/bats_protocol.py @@ -30,7 +30,9 @@ def pre_run(self, network: INetwork): # Init the license file for bats, otherwise it will not run. hosts = network.get_hosts() if hosts is None: + logging.error("No host found in the network") return False + net_id = network.get_id() host_num = len(hosts) # prepare the bats protocol config files hosts_ip_range = network.get_host_ip_range() @@ -43,17 +45,19 @@ def pre_run(self, network: INetwork): cfg_template_path = os.path.join( self.config.config_base_path, self.config.config_file) else: - logging.error("Config base path or config file is not set.") - logging.debug( - f"########################## BATSProtocol Source path: %s", self.source_path) + logging.error( + "%s Config base path or config file is not set.", net_id) + # configurations are separated by network + logging.info( + f"########################## BATSProtocol Source path: %s, %s", self.source_path, net_id) generate_cfg_files(host_num, hosts_ip_range, - self.virtual_ip_prefix, self.source_path, cfg_template_path) + self.virtual_ip_prefix, f'{self.source_path}/{net_id}', cfg_template_path) # generate some error log if the license file is not correct self._verify_license() for i in range(host_num): hosts[i].cmd(f'iptables -F -t nat') self._init_tun(hosts[i]) - self._init_config(hosts[i]) + self._init_config(hosts[i], net_id) logging.info( f"############### Oasis install bats protocol config files on " "%s ###############", @@ -88,6 +92,9 @@ def run(self, network: INetwork): res = hosts[host_idx].cmd(f'ls /tmp | grep "{running_flag}"') if res.find(running_flag) == -1: unready_idx.append(host_idx) + else: + logging.info("Bats protocol is running on %s", + hosts[host_idx].name()) host_range = unready_idx if len(host_range) > 0: @@ -140,7 +147,7 @@ def _verify_license(self) -> bool: return False return True - def _init_config(self, host: IHost): + def _init_config(self, host: IHost, id: int): # {host.name()} = h0, h1, h2, ... the last character is the index of the host host_idx = int(host.name()[-1]) host.cmd( @@ -150,7 +157,7 @@ def _init_config(self, host: IHost): host.cmd( f'mkdir -p /etc/bats-protocol') host.cmd( - f'cp {self.source_path}/h{host_idx}.ini /etc/bats-protocol/bats-protocol-settings.ini') + f'cp {self.source_path}/{id}/h{host_idx}.ini /etc/bats-protocol/bats-protocol-settings.ini') return True def _get_ip_from_host(self, host: IHost, dev: str) -> str: diff --git a/src/testsuites/test_scp.py b/src/testsuites/test_scp.py index a6e17fb..c702a41 100644 --- a/src/testsuites/test_scp.py +++ b/src/testsuites/test_scp.py @@ -47,7 +47,7 @@ def _run_test(self, network: INetwork, proto_info: IProtoInfo): for file in self.scp_files: scp_cmd += f' {file}' scp_cmd += f' root@{receiver_ip}:/tmp/' - hosts[i].cmdPrint( + hosts[i].cmd( f'script -c \'{scp_cmd}\' | tee {self.result.record} ') return True # Run ping test from client to server diff --git a/src/tools/cfg_generator.py b/src/tools/cfg_generator.py index 7ef6340..d3a7178 100644 --- a/src/tools/cfg_generator.py +++ b/src/tools/cfg_generator.py @@ -1,3 +1,4 @@ +import os import argparse import logging from mininet.util import ipStr, netParse @@ -189,6 +190,8 @@ def generate_cfg_files(num_nodes, node_ip_range="10.0.0.0/8", virtual_ip_prefix="1.0.0.", output_dir="/tmp", config_file_template=None): + if not os.path.exists(output_dir): + os.makedirs(output_dir) generator = ConfigGenerator( node_ip_range, output_dir, config_file_template) generator.generate_cfg(num_nodes, virtual_ip_prefix)