Ejemplo n.º 1
0
def build_netmap_layer2_graph(topology_without_metadata,
                              vlan_by_interface,
                              vlan_by_netbox,
                              load_traffic=False,
                              view=None):
    """
    Builds a netmap layer 2 graph, based on nav's build_layer2_graph method.
    Reduces a topology graph from nav.topology.vlan, but retains it's
     directional (MultiDiGraph) properties as metadata under the key 'metadata'

    This is done as the visualization in Netmap won't ever be drawing multiple
    spines between edges as it will turn into a mess, instead we want to access
    such data as metadata.

    :param topology_without_metadata: nav.topology.vlan.build*_graph networkx
     graph
    :param vlan_by_interface: dictionary to lookup up vlan's attached to given
     interface
    :param vlan_by_netbox: dictonary to lookup up vlan's, keyed by netbox.
    :param view A NetMapView for getting node positions according to saved
     netmap view.
    :type topology_without_metadata: networkx.MultiDiGraph
    :type vlan_by_interface: dict
    :type vlan_by_netbox: dict
    :type view: nav.modeles.profiles.NetmapView
    :return NetworkX Graph with attached metadata for edges and nodes
    """
    _LOGGER.debug("_build_netmap_layer2_graph()")
    netmap_graph = nx.Graph()

    # basically loops over the whole MultiDiGraph from nav.topology and make
    # sure we fetch all 'loose' ends and makes sure they get attached as
    # metadata into netmap_graph
    for source, neighbors_dict in topology_without_metadata.adjacency_iter():
        for target, connected_interfaces_at_source_for_target in (
                six.iteritems(neighbors_dict)):
            for interface in connected_interfaces_at_source_for_target:
                # fetch existing metadata that might have been added already
                existing_metadata = netmap_graph.get_edge_data(source,
                                                               target) or {}
                port_pairs = existing_metadata.setdefault('port_pairs', set())
                port_pair = frozenset((interface, interface.to_interface))
                if len(port_pair) < 2:
                    _LOGGER.warning("Wonky self-loop at %r", port_pair)
                    continue  # ignore wonk!
                port_pairs.add(port_pair)

                netmap_graph.add_edge(target,
                                      source,
                                      attr_dict=existing_metadata)

    _LOGGER.debug(
        "build_netmap_layer2_graph() graph reduced.Port_pair metadata attached"
    )

    empty_traffic = Traffic()
    for source, target, metadata_dict in netmap_graph.edges_iter(data=True):
        for interface_a, interface_b in metadata_dict.get('port_pairs'):
            traffic = get_traffic_data(
                (interface_a, interface_b)) if load_traffic else empty_traffic
            additional_metadata = edge_metadata_layer2(
                (source, target), interface_a, interface_b, vlan_by_interface,
                traffic)

            metadata = metadata_dict.setdefault('metadata', list())
            metadata.append(additional_metadata)

    _LOGGER.debug("build_netmap_layer2_graph() netmap metadata built")

    for node, data in netmap_graph.nodes_iter(data=True):
        if node in vlan_by_netbox:
            data['metadata'] = {
                'vlans':
                sorted(six.iteritems(vlan_by_netbox[node]),
                       key=lambda x: x[1].vlan.vlan)
            }

    _LOGGER.debug("build_netmap_layer2_graph() vlan metadata for _nodes_ done")

    if view:
        saved_views = view.node_position_set.all()
        netmap_graph = _attach_node_positions(netmap_graph, saved_views)
    _LOGGER.debug("build_netmap_layer2_graph() view positions and graph done")

    return netmap_graph
Ejemplo n.º 2
0
def build_netmap_layer2_graph(topology_without_metadata, vlan_by_interface,
                              vlan_by_netbox, load_traffic=False, view=None):
    """
    Builds a netmap layer 2 graph, based on nav's build_layer2_graph method.
    Reduces a topology graph from nav.topology.vlan, but retains it's
     directional (MultiDiGraph) properties as metadata under the key 'metadata'

    This is done as the visualization in Netmap won't ever be drawing multiple
    spines between edges as it will turn into a mess, instead we want to access
    such data as metadata.

    :param topology_without_metadata: nav.topology.vlan.build*_graph networkx
     graph
    :param vlan_by_interface: dictionary to lookup up vlan's attached to given
     interface
    :param vlan_by_netbox: dictonary to lookup up vlan's, keyed by netbox.
    :param view A NetMapView for getting node positions according to saved
     netmap view.
    :type topology_without_metadata: networkx.MultiDiGraph
    :type vlan_by_interface: dict
    :type vlan_by_netbox: dict
    :type view: nav.modeles.profiles.NetmapView
    :return NetworkX Graph with attached metadata for edges and nodes
    """
    _LOGGER.debug(
        "_build_netmap_layer2_graph()")
    netmap_graph = nx.Graph()

    interfaces = set()

    # basically loops over the whole MultiDiGraph from nav.topology and make
    # sure we fetch all 'loose' ends and makes sure they get attached as
    # metadata into netmap_graph
    for source, neighbors_dict in topology_without_metadata.adjacency_iter():
        for target, connected_interfaces_at_source_for_target in (
            neighbors_dict.iteritems()):
            for interface in connected_interfaces_at_source_for_target:
                # fetch existing metadata that might have been added already
                existing_metadata = netmap_graph.get_edge_data(
                    source,
                    target
                ) or {}
                port_pairs = existing_metadata.setdefault('port_pairs', set())
                port_pair = tuple(
                    sorted(
                        (interface, interface.to_interface),
                        key=lambda
                                interfjes: interfjes and interfjes.pk or None
                    )
                )
                port_pairs.add(port_pair)
                if port_pair[0] is not None:
                    interfaces.add(port_pair[0])
                if port_pair[1] is not None:
                    interfaces.add(port_pair[1])

                netmap_graph.add_edge(source, target,
                                      attr_dict=existing_metadata)

    _LOGGER.debug(
        "build_netmap_layer2_graph() graph reduced.Port_pair metadata attached")

    empty_traffic = Traffic()
    for source, target, metadata_dict in netmap_graph.edges_iter(data=True):
        for interface_a, interface_b in metadata_dict.get('port_pairs'):
            traffic = get_traffic_data(
                (interface_a, interface_b)) if load_traffic else empty_traffic
            additional_metadata = edge_metadata_layer2((source, target),
                                                       interface_a,
                                                       interface_b,
                                                       vlan_by_interface,
                                                       traffic)

            metadata = metadata_dict.setdefault('metadata', list())
            metadata.append(additional_metadata)

    _LOGGER.debug(
        "build_netmap_layer2_graph() netmap metadata built")


    for node, data in netmap_graph.nodes_iter(data=True):
        if node in vlan_by_netbox:
            data['metadata'] = {
                'vlans': sorted(vlan_by_netbox[node].iteritems(),
                    key=lambda x: x[1].vlan.vlan)}
    _LOGGER.debug("build_netmap_layer2_graph() vlan metadata for _nodes_ done")

    if view:
        saved_views = view.node_position_set.all()
        netmap_graph = _attach_node_positions(netmap_graph,
                                              saved_views)
    _LOGGER.debug("build_netmap_layer2_graph() view positions and graph done")

    return netmap_graph