Last active
March 8, 2020 15:10
-
-
Save bockor/2be1ff0a730c5f64bda50b09f1ff498e to your computer and use it in GitHub Desktop.
net_centric_yed-ip
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
''' | |
[ | |
{ | |
"20S301": "SHAPE", | |
"20SU06": "SHAPE", | |
"77B301": "BRUNSSUM", | |
"77B302": "BRUNSSUM", | |
"77B402": "BRUNSSUM", | |
"H13FXX": "FRANCE", | |
"H21": "NETHERLANDS", | |
"H22": "POLAND", | |
"H23": "NETHERLANDS", | |
"H24": "NETHERLANDS", | |
"H31": "LUXEMBURG", | |
"H47": "GERMANY", | |
"H49": "CANADA", | |
"H51": "U.S.A.", | |
"H61": "U.S.A.", | |
"H79": "ITALY", | |
"H89": "ROMANIA" | |
} | |
] | |
NET,OCCUPANT | |
NETWORK,OCCUPANT | |
10.0.248.0/30,20S301 | |
10.0.248.0/30,77B301 | |
10.135.66.0/24,20S301 | |
10.35.166.0/24,20S301 | |
10.88.66.0/24,77B301 | |
10.88.166.0/24,77B302 | |
10.0.248.4/30,77B301 | |
10.0.248.4/30,77B302 | |
10.0.248.8/30,20S301 | |
10.0.248.8/30,77B302 | |
''' | |
''' | |
ABOUT: net centrics approach to automatise visualising IP networks in yEd | |
AUTHOR: bockor | |
DATE: 07 MAR 2020 | |
''' | |
import csv | |
import json | |
import re | |
from collections import defaultdict | |
# based on the pyyed module, adapted by the author | |
import nra_pyyed | |
# SPECIFY HERE THE INPUT AND OUTPUT FILES | |
file_in_csv = './net_centric.csv' | |
file_out_graphml = './net_centric_result.graphml' | |
# SPECIFY THE JSON FILE THAT MAPS CAST LOCIDS TO GEO PLACE | |
file_in_cast = './net_centric_places.json' | |
# DEFINE OCCUPANT COLORS AND SHAPES | |
color_rtr = '#FF0000' | |
color_ipz = '#FFFF00' | |
shape_rtr = 'ellipse' | |
shape_fw = 'octagon' | |
def get_occupant_shape(occupant): | |
# CHECK THE 4TH AND/OR THE 6TH CHARACTER FOR AN "F" | |
# E.G. BC2F OR 20SF55 | |
if re.search('^.{3}F(?:$|.{2}$)', occupant): | |
return shape_fw | |
else: | |
return shape_rtr | |
def get_occupant_color(occupant): | |
# CHECK IF THE 4TH CHARACTER IS A "4" | |
if re.search('^.{3}4', occupant): | |
return color_ipz | |
else: | |
return color_rtr | |
def get_occupants_from_csv(network): | |
# A SET OBJECT IS NEEDED TO GET "UNIQUE" ENTRIES | |
occupants = set() | |
for row in network: | |
if row[0] and row[1]: | |
occupants.add(row[1]) | |
else: | |
print('[ERROR] Need 2 nodes to construct an edge') | |
return (list(occupants)) | |
def get_network_placements(network, places): | |
''' | |
intra networks must be placed into a GroupNode | |
inter networks are standalone nodes | |
''' | |
inter_networks = [] | |
intra_networks = {} # key = network, value = geo location | |
''' | |
STEP 1: Group the OCCUPANTS by NETWORK | |
FROM: | |
NETWORK,OCCUPANT | |
10.0.248.0/30,20S301 | |
10.0.248.0/30,77B301 | |
10.135.66.0/24,20S301 | |
10.35.166.0/24,20S301 | |
10.88.66.0/24,77B301 | |
10.88.166.0/24,77B302 | |
10.0.248.4/30,77B301 | |
10.0.248.4/30,77B302 | |
10.0.248.8/30,20S301 | |
10.0.248.8/30,77B302 | |
INTO: | |
{'10.0.248.4/30': ['77B301', '77B302'], '10.35.166.0/24': ['20S301'], | |
'10.0.248.0/30': ['20S301', '77B301'], '10.88.66.0/24': ['77B301'], | |
'10.135.66.0/24': ['20S301'], '10.88.166.0/24': ['77B302'], | |
'10.0.248.8/30': ['20S301', '77B302']} | |
''' | |
occupants_by_network = defaultdict(list) | |
for net, occupant in network: | |
occupants_by_network[net].append(occupant) | |
#print ("Grouped dictionary is : " + str(dict(occupants_by_network))) | |
''' | |
STEP 2: Categorise the networks and append them to the relevant list or | |
dictionary | |
{'10.88.166.0/24': u'BRUNSSUM', '10.0.248.4/30': u'BRUNSSUM', | |
'10.135.66.0/24': u'SHAPE', '10.35.166.0/24': u'SHAPE', | |
'10.88.66.0/24': u'BRUNSSUM'} | |
['10.0.248.0/30', '10.0.248.8/30'] | |
''' | |
for k,v in occupants_by_network.items(): | |
#k=network, v=occupant | |
if len(v) == 1: | |
# LAN's here | |
intra_networks.update({k:places[v[0]]}) | |
elif places[v[0]] == places[v[1]]: | |
# connection within the same place | |
intra_networks.update({k:places[v[0]]}) | |
else: | |
inter_networks.append(k) | |
''' | |
STEP3 | |
''' | |
return (intra_networks, inter_networks) | |
def get_edges_from_csv(network): | |
edges = [] | |
for row in network: | |
if row[0] and row[1]: | |
edge = (row[0], row[1]) | |
edges.append(edge) | |
else: | |
print('[ERROR] Need 2 nodes to construct an edge') | |
return edges | |
def main(): | |
# INITIALISE THE GRAPH | |
g = nra_pyyed.Graph() | |
with open(file_in_csv) as fin: | |
reader = csv.reader(fin) | |
header = next(reader) | |
network = [row for row in reader] | |
with open(file_in_cast) as fcast: | |
places = json.load(fcast)[0] | |
# OCCUPANT PLACEMENTS | |
for occupant in get_occupants_from_csv(network): | |
try: | |
place = places[occupant] | |
if place == None: | |
place = 'NAUGHT BOYS ( NO PLACE FOUND IN CAST )' | |
except KeyError: | |
place = 'NAUGHT BOYS ( NO LOCID FOUND IN CAST )' | |
try: | |
g.groups[place].add_node(occupant, \ | |
shape=get_occupant_shape(occupant), \ | |
shape_fill=get_occupant_color(occupant)) | |
except: | |
new_group = g.add_group(place, shape="roundrectangle", \ | |
fill="#808000", edge_width="2.0") | |
new_group.add_node(occupant, shape=get_occupant_shape(occupant), \ | |
shape_fill=get_occupant_color(occupant)) | |
# NETWORK PLACEMENTS (INTER & INTRA NETWORKS) | |
intra_networks, inter_networks = get_network_placements(network,places) | |
for inter in inter_networks: | |
g.add_node(inter, shape="roundrectangle", shape_fill="#FFCC00", \ | |
height="30", width="100") | |
for k,v in intra_networks.items(): | |
#k=network, v=occupant | |
g.groups[v].add_node(k, shape="roundrectangle", shape_fill="#FFCC00", \ | |
height="30", width="100") | |
# INSTITUTE THE EDGES (UNDIRECTED CONNECTIONS) | |
for edge in get_edges_from_csv(network): | |
g.add_edge(edge[0], edge[1], arrowhead='none') | |
# WRITE TO GRAPHML FILE | |
with open(file_out_graphml, 'w') as fout: | |
fout.write(g.get_graph()) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment