def main(): # Parse arguments args = parse_args() if not args.seed: args.seed = random.randint(1, 9999) logging.basicConfig(level=logging.INFO) logging.getLogger("coordsim").setLevel(logging.WARNING) # Creating the results directory variable where the simulator result files will be written network_stem = os.path.splitext(os.path.basename(args.network))[0] service_function_stem = os.path.splitext( os.path.basename(args.service_functions))[0] simulator_config_stem = os.path.splitext(os.path.basename(args.config))[0] results_dir = f"{PROJECT_ROOT}/results/{network_stem}/{service_function_stem}/{simulator_config_stem}" \ f"/{DATETIME}_seed{args.seed}" # creating the simulator simulator = Simulator(os.path.abspath(args.network), os.path.abspath(args.service_functions), os.path.abspath(args.config), test_mode=True, test_dir=results_dir) init_state = simulator.init(args.seed) log.info("Network Stats after init(): %s", init_state.network_stats) nodes_list = [node['id'] for node in init_state.network.get('nodes')] nodes_with_capacity = [] for node in simulator.network.nodes(data=True): if node[1]['cap'] > 0: nodes_with_capacity.append(node[0]) sf_list = list(init_state.service_functions.keys()) sfc_list = list(init_state.sfcs.keys()) ingress_nodes = get_ingress_nodes_and_cap(simulator.network) # we place every sf on each node of the network with some capacity, so placement is calculated only once placement = get_placement(nodes_with_capacity, sf_list) # Uniformly distributing the schedule for all Nodes with some capacity schedule = get_schedule(nodes_list, nodes_with_capacity, sf_list, sfc_list) # Since the placement and the schedule are fixed , the action would also be the same throughout action = SimulatorAction(placement, schedule) # iterations define the number of time we wanna call apply() log.info(f"Running for {args.iterations} iterations...") for i in tqdm(range(args.iterations)): _ = simulator.apply(action) # We copy the input files(network, simulator config....) to the results directory copy_input_files(results_dir, os.path.abspath(args.network), os.path.abspath(args.service_functions), os.path.abspath(args.config)) # Creating the input file in the results directory containing the num_ingress and the Algo used attributes create_input_file(results_dir, len(ingress_nodes), "LB") log.info(f"Saved results in {results_dir}")
def main(): args = parse_args() if not args.seed: args.seed = random.randint(1, 9999) # os.makedirs("logs", exist_ok=True) # logging.basicConfig(filename="logs/{}_{}_{}.log".format(os.path.basename(args.network), # DATETIME, args.seed), level=logging.INFO) # logging.getLogger("coordsim").setLevel(logging.WARNING) # logging.getLogger("bjointsp").setLevel(logging.INFO) # Creating the results directory variable where the simulator result files will be written network_stem = os.path.splitext(os.path.basename(args.network))[0] service_function_stem = os.path.splitext( os.path.basename(args.service_functions))[0] simulator_config_stem = os.path.splitext(os.path.basename(args.config))[0] results_dir = f"{PROJECT_ROOT}/results/{network_stem}/{service_function_stem}/{simulator_config_stem}" \ f"/{DATETIME}_seed{args.seed}" # creating the simulator # initializing the simulator with absolute paths to the network, service_functions and the config. files. simulator = Simulator(os.path.abspath(args.network), os.path.abspath(args.service_functions), os.path.abspath(args.config), test_mode=True, test_dir=results_dir) init_state = simulator.init(args.seed) # log.info("Network Stats after init(): %s", init_state.network_stats) # assuming for now that there is only one SFC. sfc_name = list(init_state.sfcs.keys())[0] sf_list = list(init_state.sfcs.get(sfc_name)) sf_delays_dict = init_state.service_functions nodes_list = [node['id'] for node in init_state.network.get('nodes')] ingress_nodes, node_cap = get_ingress_nodes_and_cap(simulator.network) # Getting the Mean Flow Data rate and flow size from the simulator_config.yaml file with open(args.config, "r") as f: conf = yaml.load(f, yaml.SafeLoader) flow_dr_mean = conf.get('flow_dr_mean') flow_size = conf.get('flow_size_shape') run_duration = conf.get('run_duration') inter_arrival_mean = conf.get('inter_arrival_mean') flow_duration = (float(flow_size) / float(flow_dr_mean) ) * 1000 # Converted flow duration to ms # Getting Processing delay from Service_functions file with open(args.service_functions, "r") as f: service_func = yaml.load(f, yaml.SafeLoader) processing_delay = service_func['sf_list'][ sf_list[0]]['processing_delay_mean'] # The template object is fixed, so it is created just once and used throughout for the 'place' fx of BJointSP template = create_template(sfc_name, sf_list, sf_delays_dict) # Since after the init() call to Simulator we don't get any traffic info back # we can't create the source needed for 'place' function of BJointSP, # So we for just the first 'place' call to BJointSP create a source with just ingress nodes having * # *vnf_source as the vnf in it and date_rate of flow_dr_mean from the config file num_flows = run_duration / inter_arrival_mean overlapping_flows = math.ceil( (num_flows * (processing_delay + flow_duration)) / run_duration) source_list = [] j = 1 for i in range(len(ingress_nodes)): flows = [] for _ in range(int(overlapping_flows / flow_dr_mean)): flows.append({"id": "f" + str(j), "data_rate": flow_dr_mean}) j += 1 source_list.append({ 'node': ingress_nodes[i], 'vnf': "vnf_source", 'flows': flows }) # Since the simulator right now does not have any link_dr , we are using a high value = 1000 for now. first_result = bjointsp_place(os.path.abspath(args.network), template, source_list, source_template_object=True, cpu=node_cap, mem=node_cap, networkx=simulator.network, write_result=False, logging_level=None) # creating the schedule and placement for the simulator from the first result file that BJointSP returns. placement, schedule = get_placement_and_schedule(first_result, nodes_list, sfc_name, sf_list) # We run the simulator iterations number of times to get the Traffic info from the SimulatorAction object # We generate new source file for the BJointSP from the traffic info we get from the simulator for each iteration # Using this source file and the already generated Template file we call the 'place' fx of BJointSP # In-case no source exists, we use the previous placement and schedule for _ in tqdm(range(args.iterations)): action = SimulatorAction(placement, schedule) apply_state = simulator.apply(action) source, source_exists = create_source_object( apply_state.traffic, sf_list, sfc_name, ingress_nodes, flow_dr_mean, processing_delay, flow_duration, run_duration) if source_exists: result = bjointsp_place(os.path.abspath(args.network), template, source, source_template_object=True, cpu=node_cap, mem=node_cap, networkx=simulator.network, write_result=False, logging_level=None) placement, schedule = get_placement_and_schedule( result, nodes_list, sfc_name, sf_list) copy_input_files(results_dir, os.path.abspath(args.network), os.path.abspath(args.service_functions), os.path.abspath(args.config)) create_input_file(results_dir, len(ingress_nodes), "BJointSP-Fixed") print(f"Saved results in {results_dir}")
def main(): args = parse_args() timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") os.makedirs("logs", exist_ok=True) logging.basicConfig(filename="logs/{}_{}_{}.log".format(os.path.basename(args.network), timestamp, args.seed), level=logging.INFO) logging.getLogger("coordsim").setLevel(logging.WARNING) logging.getLogger("bjointsp").setLevel(logging.INFO) # creating the simulator # initializing the simulator with absolute paths to the network, service_functions and the config. files. simulator = Simulator(os.path.abspath(args.network), os.path.abspath(args.service_functions), os.path.abspath(args.config), test_mode=True) init_state = simulator.init(args.seed) log.info("Network Stats after init(): %s", init_state.network_stats) # assuming for now that there is only one SFC. sfc_name = list(init_state.sfcs.keys())[0] sf_list = list(init_state.sfcs.get(sfc_name)) sf_delays_dict = init_state.service_functions nodes_list = [node['id'] for node in init_state.network.get('nodes')] ingress_nodes, node_cap = get_ingress_nodes_and_cap(simulator.network) # Getting the Mean Flow Data rate from the sim_config.yaml file with open(args.config, "r") as f: conf = yaml.load(f, yaml.SafeLoader) flow_dr_mean = conf.get('flow_dr_mean') # The template file is fixed, so it is created just once and used throughout for the 'place' fx of BJointSP template = create_template(sfc_name, sf_list, sf_delays_dict) # Since after the init() call to Simulator we don't get any traffic info back # we can't create the source file needed for 'place' function of BJointSP, # So we for just the first 'place' call to BJointSP create a source file with just ingress nodes having * # *vnf_source as the vnf in it and date_rate of flow_dr_mean from the config file with open(BJOINTSP_FIRST_SRC_LOCATION, "w") as f: source_list = [] for i in range(len(ingress_nodes)): source_list.append({'node': ingress_nodes[i], 'vnf': "vnf_source", 'flows': [{"id": "f" + str(i + 1), "data_rate": flow_dr_mean} ]}) yaml.safe_dump(source_list, f, default_flow_style=False) # Since the simulator right now does not have any link_dr , we are using a high value = 1000 for now. first_result = bjointsp_place(os.path.abspath(args.network), os.path.abspath(template), os.path.abspath(BJOINTSP_FIRST_SRC_LOCATION), cpu=node_cap, mem=node_cap, dr=1000, networkx=simulator.network) # creating the schedule and placement for the simulator from the first result file that BJointSP returns. placement, schedule = get_placement_and_schedule(os.path.abspath(first_result), nodes_list, sfc_name, sf_list) # We run the simulator iterations number of times to get the Traffic info from the SimulatorAction object # We generate new source file for the BJointSP from the traffic info we get from the simulator for each iteration # Using this source file and the already generated Template file we call the 'place' fx of BJointSP # Incase no source exists, we use the previous placement and schedule for i in range(args.iterations): action = SimulatorAction(placement, schedule) apply_state = simulator.apply(action) log.info("Network Stats after apply() # %s: %s", i + 1, apply_state.network_stats) source, source_exists = create_source_file(apply_state.traffic, sf_list, sfc_name, flow_dr_mean) if source_exists: result = bjointsp_place(os.path.abspath(args.network), os.path.abspath(template), os.path.abspath(source), cpu=node_cap, mem=node_cap, dr=1000, networkx=simulator.network) placement, schedule = get_placement_and_schedule(os.path.abspath(result), nodes_list, sfc_name, sf_list) simulator.params.adapter.writer.write_results(simulator.params.adapter.metrics.metrics)