Skip to content

Instantly share code, notes, and snippets.

@bockor
Last active March 8, 2020 15:10
Show Gist options
  • Save bockor/2be1ff0a730c5f64bda50b09f1ff498e to your computer and use it in GitHub Desktop.
Save bockor/2be1ff0a730c5f64bda50b09f1ff498e to your computer and use it in GitHub Desktop.
net_centric_yed-ip
#!/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