Ejemplo n.º 1
0
def read_prev_placement(networkx, templates):
    # create empty overlays for all templates
    prev_embedding = {}  # dict: template -> overlay
    for t in templates:
        prev_embedding[t] = Overlay(t, [], [])

    # only read and recreate placement (not edges or flows)
    for v in networkx.nodes.data():
        node_id = v[0]
        node_attr = v[1]
        for vnf in node_attr['available_sf']:
            # find component that matches the VNF name (in any of the templates)
            for t in templates:
                # use first matching component (assuming it's only in one template); here, "vnf" is the vnf's name
                component = get_component(t, vnf)
                if component is not None:
                    # add new instance to overlay of corresponding template (source components need src_flows being set)
                    if component.source:
                        prev_embedding[t].instances.append(
                            Instance(component, node_id, src_flows=[]))
                    else:
                        prev_embedding[t].instances.append(
                            Instance(component, node_id))
                    break

    return prev_embedding
Ejemplo n.º 2
0
def read_prev_embedding(file, templates, nodes, links):
    # create shortest paths
    shortest_paths = sp.all_pairs_shortest_paths(nodes, links)
    # create empty overlays for all templates
    prev_embedding = {}  # dict: template -> overlay
    for t in templates:
        prev_embedding[t] = Overlay(t, [], [])

    with open(file, "r") as f:
        yaml_file = yaml.load(f, yaml.SafeLoader)

        # read and create VNF instances of previous embedding
        for vnf in yaml_file["placement"]["vnfs"]:
            # find component that matches the VNF name (in any of the templates)
            for t in templates:
                # use first matching component (assuming it's only in one template)
                if vnf["name"] in [c.name for c in t.components]:
                    component = list(filter(lambda x: x.name == vnf["name"], t.components))[0]
                    # add new instance to overlay of corresponding template (source components need src_flows being set)
                    if component.source:
                        prev_embedding[t].instances.append(Instance(component, vnf["node"], src_flows=[]))
                    else:
                        prev_embedding[t].instances.append(Instance(component, vnf["node"]))
                    break

        # TODO: read and create flows. otherwise, adding edges really doesn't make a difference in the heuristic
        # read and create edges of previous embedding
        for edge in yaml_file["placement"]["vlinks"]:
            instances = [i for ol in prev_embedding.values() for i in ol.instances]

            # try to get source and dest instance from list of instances
            try:
                source = list(filter(lambda x: x.component.name == edge["src_vnf"] and x.location == edge["src_node"],
                                     instances))[0]
                dest = list(filter(lambda x: x.component.name == edge["dest_vnf"] and x.location == edge["dest_node"],
                                   instances))[0]
            # if the vnfs don't exist in prev_embedding (eg, through incorrect input), ignore the edge
            except IndexError:
                # print("No matching VNFs in prev_embedding for edge from {} to {}.
                #                                         Ignoring the edge.".format(source, dest))
                continue  # skip and continue with next edge

            # get arc from templates by matching against source and dest components
            for t in templates:
                if source.component in t.components and dest.component in t.components:
                    # assume t has an arc source->dest if both components are in t
                    arc = list(filter(lambda x: x.source == source.component and x.dest == dest.component, t.arcs))[0]
                    # add new edge to overlay of corresponding template
                    edge = Edge(arc, source, dest)
                    prev_embedding[t].edges.append(edge)
                    edge.paths.append(shortest_paths[(source.location, dest.location)][0])

    return prev_embedding
Ejemplo n.º 3
0
def solve(arg_nodes,
          arg_links,
          templates,
          prev_overlays,
          sources,
          fixed,
          arg_shortest_paths,
          tabu=set()):
    # print("Previous overlays:")
    # for ol in prev_overlays.values():
    #     ol.print()
    # tabu_string = ""
    # for i in tabu:
    #     tabu_string += "({},{}) ".format(i[0], i[1])
    #     print("Tabu list: {}".format(tabu_string))

    # write global variables
    global nodes, links, shortest_paths, overlays
    nodes = arg_nodes
    links = arg_links
    shortest_paths = arg_shortest_paths

    # keep previous overlays of templates that still exist
    overlays = {t: ol for t, ol in prev_overlays.items() if t in templates}

    # create empty overlays for new templates
    for t in templates:
        if t not in overlays.keys():
            overlays[t] = Overlay(t, [], [])
            # print("Created empty overlay for new template {}".format(t))
            logger.info("Created empty overlay for new template {}".format(t))

    # remove all instances of fixed components => curr fixed instances added again later; prev fixed instances removed
    fixed_components = {f.component for f in fixed}
    fixed_instances = {
        i
        for ol in overlays.values() for i in ol.instances
        if i.component in fixed_components
    }
    # print("Remove any existing fixed instances:", *fixed_instances, sep=" ")
    for i in fixed_instances:
        remove_instance(i)

    # embed templates sequentially in given order
    for t in templates:
        # print("\n-Embedding template: {}-".format(t))
        logger.info("-Embedding template: {}-".format(t))

        own_sources = [src for src in sources if src.component in t.components]
        update_sources(overlays[t], own_sources)

        # add fixed instances that match template t's components
        for f in fixed:
            if f.component in t.components:
                fixed_instance = Instance(f.component, f.location, fixed=True)
                if fixed_instance not in overlays[t].instances:
                    overlays[t].instances.append(fixed_instance)
                    # print("Added fixed instance of {} at {}".format(f.component, f.location))
                    logger.info("Added fixed instance of {} at {}".format(
                        f.component, f.location))

        # iterate over all instances in topological order; start in forward direction then switch to backward
        i = 0
        direction = "forward"
        while i < len(overlays[t].topological_order()):
            instance = overlays[t].topological_order()[i]
            # #print("Topological order:", *overlays[t].topological_order(), sep=" ")

            # remove unused instances (except fixed instances)
            if not instance.fixed:
                if not instance.used(direction, overlays[t]):
                    # print("Removed unused instance {} from overlay of {}".format(instance, t))
                    logger.info(
                        "Removed unused instance {} from overlay of {}".format(
                            instance, t))
                    remove_instance(instance, overlays[t])
                    continue

            # switch direction at the first instance of an end component (bc outgoing not ingoing direction considered)
            if instance.component.end:
                direction = "backward"

            # get outgoing flows (and their dr) for each output
            out_flows = instance.out_flows(direction)
            for k in range(len(out_flows)):
                arc = out_arc(t, instance.component, k, direction)
                # when a component is adapted for reuse, it has separate outputs for the arcs of different templates
                if arc is None:  # for output k, this template has no arc => skip to next output
                    # print("{}'s outgoing arc at output {} in {} direction belongs to a different template.
                    #        The output is skipped".format(instance, k, direction))
                    logger.debug(
                        "{}'s outgoing arc at output {} in {} direction belongs to a different template. "
                        "The output is skipped".format(instance, k, direction))
                    continue

                update_flow_mapping(overlays[t], instance, arc, out_flows[k],
                                    tabu)
                # print("Updated the flow mapping along arc {} at {}\n".format(arc, instance))
                logger.info(
                    "Updated the flow mapping along arc {} at {}\n".format(
                        arc, instance))

            i += 1

        # print()
        if overlays[t].empty():
            del overlays[t]
            # print("Deleted empty overlay of {}".format(t))
            logger.info("Deleted empty overlay of {}".format(t))
    # else:
    # overlays[t].print()
    # print("Topological order:", *overlays[t].topological_order(), sep=" ")
    # print()

    return overlays