Ejemplo n.º 1
0
def setup(agent_config, network, service, sim_config, seed, steps, weights,
          verbose, DATETIME, test, append_test, best, test_episodes, sim_seed,
          gen_scenario):
    """Overall setup for the rl variables"""
    if best:
        assert not (test or append_test or weights
                    ), "Cannot run 'best' with test, append_test, or weights"
        result_dir = f"results/{get_base_path(agent_config, network, service, sim_config)}"
        test = select_best_agent(result_dir)
    # Create the AgentHelper data class
    agent_helper = AgentHelper(agent_config, network, service, sim_config,
                               seed, steps, weights, verbose, DATETIME, test,
                               append_test, test_episodes, sim_seed,
                               gen_scenario)

    # Setup the files and paths required for the agent
    setup_files(agent_helper, best)
    set_random_seed(seed, agent_helper)
    agent_helper.config = get_config(agent_helper.agent_config_path)
    agent_helper.result.steps = agent_helper.steps
    # Get number of ingress nodes in the network
    no_of_ingress = num_ingress(network)
    # Create an input file with num_of_ingress and Algorithm used as attributes in the results directory
    create_input_file(agent_helper.config_dir, no_of_ingress,
                      agent_helper.config.get('agent_type'))
    return agent_helper
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}")
Ejemplo n.º 3
0
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}")