def jsonify_anm(anm): """ Returns a dictionary of json-ified overlay graphs""" anm_json = {} for overlay_id in anm.overlays(): NmGraph = anm[overlay_id]._graph.copy() for n in NmGraph: try: del NmGraph.node[n]['id'] except KeyError: pass anm_json[overlay_id] = ank_json_dumps(NmGraph) return json.dumps(anm_json)
def rebind_interfaces(anm): for overlay_id in anm.overlays(): overlay = anm[overlay_id] #for edge in overlay.edges(): #unbound_interfaces = edge._interfaces ## map nodes -> node objects, values to integers (not strings) #interfaces = {overlay.node(key): val for key, val in unbound_interfaces.items()} #edge._interfaces = interfaces # store with remapped node for node in overlay.nodes(): unbound_interfaces = node._interfaces if len(unbound_interfaces): # is list if none set interfaces = {int(key): val for key, val in unbound_interfaces.items()} node._interfaces = interfaces
def jsonify_anm_with_graphics(anm): """ Returns a dictionary of json-ified overlay graphs, with graphics data appended to each overlay""" anm_json = {} graphics_graph = anm["graphics"]._graph.copy() for overlay_id in anm.overlays(): OverlayGraph = anm[overlay_id]._graph.copy() #TODO: only update, don't over write if already set for n in OverlayGraph: OverlayGraph.node[n].update( { 'x': graphics_graph.node[n]['x'], 'y': graphics_graph.node[n]['y'], 'asn': graphics_graph.node[n]['asn'], 'device_type': graphics_graph.node[n]['device_type'], 'device_subtype': graphics_graph.node[n].get('device_subtype'), 'pop': graphics_graph.node[n].get('pop'), }) try: del OverlayGraph.node[n]['id'] except KeyError: pass #TODO: combine these, and round as necessary x = (OverlayGraph.node[n]['x'] for n in OverlayGraph) y = (OverlayGraph.node[n]['y'] for n in OverlayGraph) try: x_min = min(x) except ValueError: x_min = 0 try: y_min = min(y) except ValueError: y_min = 0 for n in OverlayGraph: OverlayGraph.node[n]['x'] += - x_min OverlayGraph.node[n]['y'] += - y_min anm_json[overlay_id] = ank_json_dumps(OverlayGraph) return anm_json
def jsonify_anm_with_graphics(anm, nidb=None): """ Returns a dictionary of json-ified overlay graphs, with graphics data appended to each overlay""" from collections import defaultdict import math anm_json = {} test_anm_data = {} graphics_graph = anm["graphics"]._graph.copy() phy_graph = anm["phy"]._graph # to access ASNs """simple layout of deps - more advanced layout could export to dot and import to omnigraffle, etc """ g_deps = anm['_dependencies'] nm_graph = g_deps._graph # build tree layers = defaultdict(list) if len(nm_graph) > 0: topo_sort = nx.topological_sort(nm_graph) # trim out any nodes with no sucessors tree_root = topo_sort[0] #Note: topo_sort ensures that once reach node, would have reached its predecessors # start at first element after root for node in topo_sort: preds = nm_graph.predecessors(node) if len(preds): pred_level = max(nm_graph.node[p].get('level') for p in preds) else: # a root node pred_level = -1 # this node becomes level 0 level = pred_level + 1 nm_graph.node[node]['level'] = level layers[level].append(node) data = nm_graph.node[node] data['y'] = 100 * data['level'] data['device_type'] = "ank_internal" MIDPOINT = 50 # assign either side of for nodes in layers.values(): #TODO: since sort is stable, first sort by parent x (avoids zig-zags) nodes = sorted(nodes, reverse=True, key=lambda x: nm_graph.degree(x)) for index, node in enumerate(nodes): #TODO: work out why weird offset due to the math.pow * #node_x = MIDPOINT + 125*index * math.pow(-1, index) node_x = MIDPOINT + 125 * index nm_graph.node[node]['x'] = node_x import random attribute_cache = defaultdict(dict) # the attributes to copy # TODO: check behaviour for None if explicitly set #TODO: need to check if attribute is set in overlay..... using API copy_attrs = ["x", "y", "asn", "label", "device_type", "device_subtype"] for node, in_data in phy_graph.nodes(data=True): out_data = { key: in_data.get(key) for key in copy_attrs if key in in_data } attribute_cache[node].update(out_data) # Update for graphics (over-rides phy) for node, in_data in graphics_graph.nodes(data=True): out_data = { key: in_data.get(key) for key in copy_attrs if key in in_data } attribute_cache[node].update(out_data) # append label from function for node in anm['phy']: attribute_cache[node.id]['label'] = str(node) for overlay_id in anm.overlays(): nm_graph = anm[overlay_id]._graph.copy() if overlay_id == "_dependencies": nm_graph = nx.Graph( nm_graph) #convert to undirected for visual clarify for node in nm_graph: node_data = dict(attribute_cache.get(node, {})) # update with node data from this overlay #TODO: check is not None won't clobber specifically set in overlay... graph_node_data = nm_graph.node[node] overlay_node_data = { key: graph_node_data.get(key) for key in graph_node_data } node_data.update(overlay_node_data) # check for any non-set properties if node_data.get("x") is None: new_x = random.randint(0, 800) node_data['x'] = new_x # store for other graphs to use log.debug("Allocated random x %s to node %s in overlay %s" % (new_x, node, overlay_id)) attribute_cache[node]['x'] = new_x if node_data.get("y") is None: new_y = random.randint(0, 800) node_data['y'] = new_y # store for other graphs to use attribute_cache[node]['y'] = new_y log.debug("Allocated random y %s to node %s in overlay %s" % (new_y, node, overlay_id)) if node_data.get("label") == node: # try from cache node_data['label'] = attribute_cache.get(node, {}).get("label") if node_data.get("label") is None: node_data['label'] = str(node) # don't need to cache # store on graph nm_graph.node[node] = node_data if nm_graph.is_multigraph(): for u, v, k in nm_graph.edges(keys=True): # Store key: nx node_link_data ignores it #anm_graph[u][v][k]['_key'] = k pass # is this needed? as key itself holds no value? try: del nm_graph.node[node]['id'] except KeyError: pass if nidb: nidb_graph = nidb.raw_graph() if node in nidb: DmNode_data = nidb_graph.node[node] try: #TODO: check why not all nodes have _ports initialised overlay_interfaces = nm_graph.node[node]["_ports"] except KeyError: continue # skip copying interface data for this node for interface_id in overlay_interfaces.keys(): #TODO: use raw_interfaces here try: nidb_interface_id = DmNode_data['_ports'][ interface_id]['id'] except KeyError: #TODO: check why arrive here - something not initialised? continue nm_graph.node[node]['_ports'][interface_id][ 'id'] = nidb_interface_id id_brief = shortened_interface(nidb_interface_id) nm_graph.node[node]['_ports'][interface_id][ 'id_brief'] = id_brief anm_json[overlay_id] = ank_json_dumps(nm_graph) test_anm_data[overlay_id] = nm_graph if nidb: test_anm_data['nidb'] = prepare_nidb(nidb) result = json.dumps(test_anm_data, cls=AnkEncoder, indent=4, sort_keys=True) return result
def jsonify_anm_with_graphics(anm, nidb=None): """ Returns a dictionary of json-ified overlay graphs, with graphics data appended to each overlay""" anm_json = {} test_anm_data = {} graphics_graph = anm["graphics"]._graph.copy() for overlay_id in anm.overlays(): OverlayGraph = anm[overlay_id]._graph.copy() #TODO: only update, don't over write if already set for n in OverlayGraph: OverlayGraph.node[n].update({ 'x': graphics_graph.node[n]['x'], 'y': graphics_graph.node[n]['y'], 'asn': graphics_graph.node[n]['asn'], 'device_type': graphics_graph.node[n]['device_type'], 'device_subtype': graphics_graph.node[n].get('device_subtype'), 'pop': graphics_graph.node[n].get('pop'), }) try: del OverlayGraph.node[n]['id'] except KeyError: pass if nidb: nidb_graph = nidb._graph if n in nidb: nidb_node_data = nidb_graph.node[n] try: #TODO: check why not all nodes have _interfaces initialised overlay_interfaces = OverlayGraph.node[n][ "_interfaces"] except KeyError: continue # skip copying interface data for this node for interface_id in overlay_interfaces.keys(): try: nidb_interface_id = nidb_node_data['_interfaces'][ interface_id]['id'] except KeyError: #TODO: check why arrive here - something not initialised? continue OverlayGraph.node[n]['_interfaces'][interface_id][ 'id'] = nidb_interface_id id_brief = shortened_interface(nidb_interface_id) OverlayGraph.node[n]['_interfaces'][interface_id][ 'id_brief'] = id_brief #TODO: combine these, and round as necessary x = (OverlayGraph.node[n]['x'] for n in OverlayGraph) y = (OverlayGraph.node[n]['y'] for n in OverlayGraph) try: x_min = min(x) except ValueError: x_min = 0 try: y_min = min(y) except ValueError: y_min = 0 for n in OverlayGraph: OverlayGraph.node[n]['x'] += -x_min OverlayGraph.node[n]['y'] += -y_min anm_json[overlay_id] = ank_json_dumps(OverlayGraph) test_anm_data[overlay_id] = OverlayGraph if nidb: test_anm_data['nidb'] = prepare_nidb(nidb) result = json.dumps(test_anm_data, cls=AnkEncoder, indent=4, sort_keys=True) return result
def jsonify_anm_with_graphics(anm, nidb = None): """ Returns a dictionary of json-ified overlay graphs, with graphics data appended to each overlay""" anm_json = {} test_anm_data = {} graphics_graph = anm["graphics"]._graph.copy() phy_graph = anm["phy"]._graph # to access ASNs import random from collections import defaultdict attribute_cache = defaultdict(dict) # the attributes to copy # TODO: check behaviour for None if explicitly set #TODO: need to check if attribute is set in overlay..... using API copy_attrs = ["x", "y", "asn", "label", "device_type", "device_subtype"] for node, in_data in phy_graph.nodes(data=True): out_data = {key: in_data.get(key) for key in copy_attrs if key in in_data} attribute_cache[node].update(out_data) # Update for graphics (over-rides phy) for node, in_data in graphics_graph.nodes(data=True): out_data = {key: in_data.get(key) for key in copy_attrs if key in in_data} attribute_cache[node].update(out_data) for overlay_id in anm.overlays(): NmGraph = anm[overlay_id]._graph.copy() for node in NmGraph: node_data = dict(attribute_cache.get(node, {})) # update with node data from this overlay #TODO: check is not None won't clobber specifically set in overlay... graph_node_data = NmGraph.node[node] overlay_node_data = {key: graph_node_data.get(key) for key in copy_attrs if key in graph_node_data} node_data.update(overlay_node_data) # check for any non-set properties if node_data.get("x") is None: new_x = random.randint(0,800) node_data['x'] = new_x # store for other graphs to use log.debug("Allocated random x %s to node %s in overlay %s" % (new_x, node, overlay_id)) attribute_cache[node]['x'] = new_x if node_data.get("y") is None: new_y = random.randint(0,800) node_data['y'] =new_y # store for other graphs to use attribute_cache[node]['y'] =new_y log.debug("Allocated random y %s to node %s in overlay %s" % (new_y, node, overlay_id)) if node_data.get("label") is None: node_data['label'] = str(node) # don't need to cache # store on graph NmGraph.node[node] = node_data try: del NmGraph.node[node]['id'] except KeyError: pass if nidb: nidb_graph = nidb.raw_graph() if node in nidb: DmNode_data = nidb_graph.node[node] try: #TODO: check why not all nodes have _interfaces initialised overlay_interfaces = NmGraph.node[node]["_interfaces"] except KeyError: continue # skip copying interface data for this node for interface_id in overlay_interfaces.keys(): try: nidb_interface_id = DmNode_data['_interfaces'][interface_id]['id'] except KeyError: #TODO: check why arrive here - something not initialised? continue NmGraph.node[node]['_interfaces'][interface_id]['id'] = nidb_interface_id id_brief = shortened_interface(nidb_interface_id) NmGraph.node[node]['_interfaces'][interface_id]['id_brief'] = id_brief anm_json[overlay_id] = ank_json_dumps(NmGraph) test_anm_data[overlay_id] = NmGraph if nidb: test_anm_data['nidb'] = prepare_nidb(nidb) result = json.dumps(test_anm_data, cls=AnkEncoder, indent = 4, sort_keys = True) return result
def jsonify_anm_with_graphics(anm, nidb = None): """ Returns a dictionary of json-ified overlay graphs, with graphics data appended to each overlay""" anm_json = {} test_anm_data = {} graphics_graph = anm["graphics"]._graph.copy() phy_graph = anm["phy"]._graph # to access ASNs for overlay_id in anm.overlays(): OverlayGraph = anm[overlay_id]._graph.copy() #TODO: only update, don't over write if already set for n in OverlayGraph: OverlayGraph.node[n].update( { 'x': graphics_graph.node[n]['x'], 'y': graphics_graph.node[n]['y'], 'asn': graphics_graph.node[n]['asn'], 'label': graphics_graph.node[n]['label'], 'device_type': graphics_graph.node[n]['device_type'], 'device_subtype': graphics_graph.node[n].get('device_subtype'), 'pop': graphics_graph.node[n].get('pop'), }) if n in phy_graph: # use ASN from physical graph OverlayGraph.node[n]['asn'] = phy_graph.node[n]['asn'] try: del OverlayGraph.node[n]['id'] except KeyError: pass if nidb: nidb_graph = nidb._graph if n in nidb: nidb_node_data = nidb_graph.node[n] try: #TODO: check why not all nodes have _interfaces initialised overlay_interfaces = OverlayGraph.node[n]["_interfaces"] except KeyError: continue # skip copying interface data for this node for interface_id in overlay_interfaces.keys(): try: nidb_interface_id = nidb_node_data['_interfaces'][interface_id]['id'] except KeyError: #TODO: check why arrive here - something not initialised? continue OverlayGraph.node[n]['_interfaces'][interface_id]['id'] = nidb_interface_id id_brief = shortened_interface(nidb_interface_id) OverlayGraph.node[n]['_interfaces'][interface_id]['id_brief'] = id_brief #TODO: combine these, and round as necessary x = (OverlayGraph.node[n]['x'] for n in OverlayGraph) y = (OverlayGraph.node[n]['y'] for n in OverlayGraph) try: x_min = min(x) except ValueError: x_min = 0 try: y_min = min(y) except ValueError: y_min = 0 for n in OverlayGraph: OverlayGraph.node[n]['x'] += - x_min OverlayGraph.node[n]['y'] += - y_min anm_json[overlay_id] = ank_json_dumps(OverlayGraph) test_anm_data[overlay_id] = OverlayGraph if nidb: test_anm_data['nidb'] = prepare_nidb(nidb) result = json.dumps(test_anm_data, cls=AnkEncoder, indent = 4, sort_keys = True) return result
def jsonify_anm_with_graphics(anm, nidb=None): """ Returns a dictionary of json-ified overlay graphs, with graphics data appended to each overlay""" from collections import defaultdict import math anm_json = {} test_anm_data = {} graphics_graph = anm["graphics"]._graph.copy() phy_graph = anm["phy"]._graph # to access ASNs """simple layout of deps - more advanced layout could export to dot and import to omnigraffle, etc """ g_deps = anm['_dependencies'] nm_graph = g_deps._graph # build tree layers = defaultdict(list) nodes_by_layer = {} if len(nm_graph) > 0: topo_sort = nx.topological_sort(nm_graph) # trim out any nodes with no sucessors tree_root = topo_sort[0] # Note: topo_sort ensures that once reach node, would have reached its predecessors # start at first element after root for node in topo_sort: preds = nm_graph.predecessors(node) if len(preds): pred_level = max(nm_graph.node[p].get('level') for p in preds) else: # a root node pred_level = -1 # this node becomes level 0 level = pred_level + 1 nm_graph.node[node]['level'] = level layers[level].append(node) data = nm_graph.node[node] data['y'] = 100 * data['level'] data['device_type'] = "ank_internal" MIDPOINT = 50 # assign either side of for layer, nodes in layers.items(): # TODO: since sort is stable, first sort by parent x (avoids # zig-zags) nodes = sorted(nodes, reverse=True, key=lambda x: nm_graph.degree(x)) for index, node in enumerate(nodes): # TODO: work out why weird offset due to the math.pow * #node_x = MIDPOINT + 125*index * math.pow(-1, index) node_x = MIDPOINT + 125 * index nm_graph.node[node]['x'] = node_x nodes_by_layer[node] = layer import random attribute_cache = defaultdict(dict) # the attributes to copy # TODO: check behaviour for None if explicitly set # TODO: need to check if attribute is set in overlay..... using API copy_attrs = ["x", "y", "asn", "label", "device_type", "device_subtype"] for node, in_data in phy_graph.nodes(data=True): out_data = {key: in_data.get(key) for key in copy_attrs if key in in_data} attribute_cache[node].update(out_data) # Update for graphics (over-rides phy) for node, in_data in graphics_graph.nodes(data=True): out_data = {key: in_data.get(key) for key in copy_attrs if key in in_data} attribute_cache[node].update(out_data) # append label from function for node in anm['phy']: attribute_cache[node.id]['label'] = str(node) overlay_ids = sorted(anm.overlays(), key=lambda x: nodes_by_layer.get(x, 0)) for overlay_id in overlay_ids: nm_graph = anm[overlay_id]._graph.copy() if overlay_id == "_dependencies": # convert to undirected for visual clarify nm_graph = nx.Graph(nm_graph) for node in nm_graph: node_data = dict(attribute_cache.get(node, {})) # update with node data from this overlay # TODO: check is not None won't clobber specifically set in # overlay... graph_node_data = nm_graph.node[node] overlay_node_data = {key: graph_node_data.get(key) for key in graph_node_data} node_data.update(overlay_node_data) # check for any non-set properties if node_data.get("x") is None: new_x = random.randint(0, 800) node_data['x'] = new_x # store for other graphs to use log.debug("Allocated random x %s to node %s in overlay %s" % (new_x, node, overlay_id)) attribute_cache[node]['x'] = new_x else: # cache for next time, such as vswitch in l2 for l2_bc attribute_cache[node]['x'] = node_data['x'] if node_data.get("y") is None: new_y = random.randint(0, 800) node_data['y'] = new_y # store for other graphs to use attribute_cache[node]['y'] = new_y log.debug("Allocated random y %s to node %s in overlay %s" % (new_y, node, overlay_id)) else: attribute_cache[node]['y'] = node_data['y'] # TODO: may want to re-introduce graphics to store cross-layer data for virtual nodes # and cache device type and device subtype # TODO: catch for each, if node not in cache try: attribute_cache[node]['device_type'] = node_data['device_type'] except KeyError: pass # not set try: attribute_cache[node][ 'device_subtype'] = node_data['device_subtype'] except KeyError: pass # not set if node_data.get("label") == node: # try from cache node_data['label'] = attribute_cache.get(node, {}).get("label") if node_data.get("label") is None: node_data['label'] = str(node) # don't need to cache # store on graph nm_graph.node[node] = node_data if nm_graph.is_multigraph(): for u, v, k in nm_graph.edges(keys=True): # Store key: nx node_link_data ignores it #anm_graph[u][v][k]['_key'] = k pass # is this needed? as key itself holds no value? try: del nm_graph.node[node]['id'] except KeyError: pass if nidb: nidb_graph = nidb.raw_graph() if node in nidb: DmNode_data = nidb_graph.node[node] try: # TODO: check why not all nodes have _ports initialised overlay_interfaces = nm_graph.node[node]["_ports"] except KeyError: continue # skip copying interface data for this node for interface_id in overlay_interfaces.keys(): # TODO: use raw_interfaces here try: nidb_interface_id = DmNode_data[ '_ports'][interface_id]['id'] except KeyError: # TODO: check why arrive here - something not # initialised? continue nm_graph.node[node]['_ports'][ interface_id]['id'] = nidb_interface_id id_brief = shortened_interface(nidb_interface_id) nm_graph.node[node]['_ports'][ interface_id]['id_brief'] = id_brief anm_json[overlay_id] = ank_json_dumps(nm_graph) test_anm_data[overlay_id] = nm_graph if nidb: test_anm_data['nidb'] = prepare_nidb(nidb) result = json.dumps( test_anm_data, cls=AnkEncoder, indent=4, sort_keys=True) return result
def jsonify_anm_with_graphics(anm, nidb = None): """ Returns a dictionary of json-ified overlay graphs, with graphics data appended to each overlay""" anm_json = {} test_anm_data = {} graphics_graph = anm["graphics"]._graph.copy() phy_graph = anm["phy"]._graph # to access ASNs for overlay_id in anm.overlays(): OverlayGraph = anm[overlay_id]._graph.copy() #TODO: don't regen x,y for each overlay - persist (possibly across all layers?) # for speed/clarity, get the graphics data to a dict and then set x,y if not set # then read from this #TODO: only update, don't over write if already set for n in OverlayGraph: if n in graphics_graph: OverlayGraph.node[n].update( { 'x': graphics_graph.node[n].get('x'), 'y': graphics_graph.node[n].get('y'), 'asn': graphics_graph.node[n]['asn'], 'label': graphics_graph.node[n]['label'], 'device_type': graphics_graph.node[n]['device_type'], 'device_subtype': graphics_graph.node[n].get('device_subtype'), 'pop': graphics_graph.node[n].get('pop'), }) #TODO: if no label set, then use node if elif n in phy_graph: #TODO: if in phy but x/y not set, then fall through to setting random #TODO: tidy by moving x/y to higher up before each overlay # try to copy x/y from phy OverlayGraph.node[n].update( { 'x': phy_graph.node[n].get('x'), 'y': phy_graph.node[n].get('y'), 'asn': phy_graph.node[n]['asn'], 'label': phy_graph.node[n]['label'], 'device_type': phy_graph.node[n]['device_type'], 'device_subtype': phy_graph.node[n].get('device_subtype'), 'pop': phy_graph.node[n].get('pop'), }) else: import random log.debug("Converting to graphics JSON format: node %s not in graphics overlay" % n) #TODO: see if can key off node hash - so doesn't move nodes around if OverlayGraph.node[n].get("x") is None: OverlayGraph.node[n]['x'] = random.randint(0,800) if OverlayGraph.node[n].get("y") is None: OverlayGraph.node[n]['y'] =random.randint(0,800) if OverlayGraph.node[n].get("label") is None: OverlayGraph.node[n]['label'] = n # set to node ID if OverlayGraph.node[n].get("device_type") is None: OverlayGraph.node[n]['device_type'] = None # set to node ID if n in phy_graph: # use ASN from physical graph OverlayGraph.node[n]['asn'] = phy_graph.node[n].get("asn") try: del OverlayGraph.node[n]['id'] except KeyError: pass if nidb: nidb_graph = nidb._graph if n in nidb: nidb_node_data = nidb_graph.node[n] try: #TODO: check why not all nodes have _interfaces initialised overlay_interfaces = OverlayGraph.node[n]["_interfaces"] except KeyError: continue # skip copying interface data for this node for interface_id in overlay_interfaces.keys(): try: nidb_interface_id = nidb_node_data['_interfaces'][interface_id]['id'] except KeyError: #TODO: check why arrive here - something not initialised? continue OverlayGraph.node[n]['_interfaces'][interface_id]['id'] = nidb_interface_id id_brief = shortened_interface(nidb_interface_id) OverlayGraph.node[n]['_interfaces'][interface_id]['id_brief'] = id_brief #TODO: combine these, and round as necessary x = (OverlayGraph.node[n]['x'] for n in OverlayGraph) y = (OverlayGraph.node[n]['y'] for n in OverlayGraph) try: x_min = min(x) except ValueError: x_min = 0 try: y_min = min(y) except ValueError: y_min = 0 border_offset = 20 # so don't plot right at edge for n in OverlayGraph: #TODO: do this once per node, rather than each time OverlayGraph.node[n]['x'] += - x_min + border_offset OverlayGraph.node[n]['y'] += - y_min + border_offset #TODO: make scale to graph size: if size is <100 dont apply #OverlayGraph.node[n]['x'] = round(OverlayGraph.node[n]['x']/25) * 25 #OverlayGraph.node[n]['y'] = round(OverlayGraph.node[n]['y']/25) * 25 # and round to the nearest grid size # for now round to nearest 10 anm_json[overlay_id] = ank_json_dumps(OverlayGraph) test_anm_data[overlay_id] = OverlayGraph if nidb: test_anm_data['nidb'] = prepare_nidb(nidb) result = json.dumps(test_anm_data, cls=AnkEncoder, indent = 4, sort_keys = True) return result