|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
# Get topologies
|
|
|
|
|
|
|
|
import sys
|
|
|
|
from birdvisu.providers import BirdSocketTopologyProvider, OspfFileTopologyProvider
|
|
|
|
|
|
|
|
|
|
|
|
ref_topo_file = 'reference.ospf'
|
|
|
|
if len(sys.argv) > 1:
|
|
|
|
ref_topo_file = sys.argv[1]
|
|
|
|
|
|
|
|
ref_topo = OspfFileTopologyProvider(ref_topo_file).get_topology()
|
|
|
|
|
|
|
|
try:
|
|
|
|
cur_topo = BirdSocketTopologyProvider(instance='ospf1', area=0).get_topology()
|
|
|
|
except OSError as e:
|
|
|
|
raise NotImplementedError('Cannot create a mock topology atm') from e
|
|
|
|
|
|
|
|
# Create combined topology
|
|
|
|
|
|
|
|
from birdvisu.topo_v3 import TopologyV3
|
|
|
|
|
|
|
|
combined_topology = TopologyV3.combine_topologies(reference=ref_topo, current=cur_topo)
|
|
|
|
combined_topology.freeze()
|
|
|
|
|
|
|
|
# Annotate it
|
|
|
|
|
|
|
|
from birdvisu.topo_v3 import VertexID
|
|
|
|
from birdvisu.annotations import AnnotatedTopology, AnnotatorID
|
|
|
|
from birdvisu.annotations.analysis import TopologyDifference, ShortestPathTree
|
|
|
|
from ipaddress import IPv4Address
|
|
|
|
|
|
|
|
annot_topo = AnnotatedTopology(combined_topology)
|
|
|
|
annotators = [
|
|
|
|
AnnotatorID(TopologyDifference),
|
|
|
|
AnnotatorID(ShortestPathTree, (VertexID(
|
|
|
|
family=None,
|
|
|
|
is_router=True,
|
|
|
|
address=None,
|
|
|
|
router_id=int(IPv4Address('172.23.100.10')),
|
|
|
|
dr_id=None,
|
|
|
|
discriminator=None
|
|
|
|
), 'current')),
|
|
|
|
]
|
|
|
|
for ann_id in annotators:
|
|
|
|
annot_topo.run_annotator(ann_id)
|
|
|
|
|
|
|
|
# ---
|
|
|
|
|
|
|
|
# Show it
|
|
|
|
|
|
|
|
#from birdvisu.visualisation import annotators
|
|
|
|
#from birdvisu import maps_new
|
|
|
|
|
|
|
|
# annotators.create_qgritems does not like being run without Qt initialization.
|
|
|
|
from PySide6 import QtCore, QtGui, QtWidgets
|
|
|
|
app = QtWidgets.QApplication([])
|
|
|
|
|
|
|
|
#annotated_topology = maps_new.annotate_topology(combined_topology,
|
|
|
|
# # A semi-canonical set of annotators:
|
|
|
|
# [
|
|
|
|
# annotators.extract_positions,
|
|
|
|
# annotators.random_position,
|
|
|
|
# annotators.assign_brushes,
|
|
|
|
# annotators.create_qgritems,
|
|
|
|
# ]
|
|
|
|
# )
|
|
|
|
|
|
|
|
from random import randint
|
|
|
|
from collections import defaultdict
|
|
|
|
|
|
|
|
shapes = dict()
|
|
|
|
nei = defaultdict(lambda: [])
|
|
|
|
|
|
|
|
class MyGraphicsRectItem(QtWidgets.QGraphicsRectItem):
|
|
|
|
#def __init__(self, *a, **kwa):
|
|
|
|
# return super().__init__(*a, **kwa)
|
|
|
|
#def itemChange(self, change, val):
|
|
|
|
# return super().itemChange(change, val)
|
|
|
|
def mouseMoveEvent(self, evt):
|
|
|
|
vtxid = self.data(0)
|
|
|
|
for e in nei[vtxid]:
|
|
|
|
x1 = self.x()
|
|
|
|
y1 = self.y()
|
|
|
|
other = e.source if e.source != vtxid else e.target
|
|
|
|
x2 = shapes[other].x()
|
|
|
|
y2 = shapes[other].y()
|
|
|
|
qlinef = QtCore.QLineF(x1, y1, x2, y2)
|
|
|
|
shapes[e].setLine(qlinef)
|
|
|
|
return super().mouseMoveEvent(evt)
|
|
|
|
|
|
|
|
for k, v in annot_topo.topology.vertices.items():
|
|
|
|
size = 30 if k.is_router else 10
|
|
|
|
x, y = randint(0, 1920), randint(0, 1080)
|
|
|
|
shape = MyGraphicsRectItem(-size/2, -size/2, size, size)
|
|
|
|
shape.setPos(x,y)
|
|
|
|
# TODO:brush
|
|
|
|
label_text = str(IPv4Address(k.router_id)) if k.is_router else str(k.address) # Surprisingly works for all the possible addresses.
|
|
|
|
label = QtWidgets.QGraphicsSimpleTextItem(label_text, parent=shape)
|
|
|
|
label.setY(size*0.8)
|
|
|
|
text_width = label.boundingRect().width()
|
|
|
|
label.setX(-text_width/2)
|
|
|
|
shape.setData(0, k)
|
|
|
|
shape.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable | QtWidgets.QGraphicsItem.ItemIsSelectable)
|
|
|
|
shapes[k] = shape
|
|
|
|
|
|
|
|
for e in annot_topo.topology.edges:
|
|
|
|
start = shapes[e.source].pos()
|
|
|
|
end = shapes[e.target].pos()
|
|
|
|
qlinef = QtCore.QLineF(start, end)
|
|
|
|
line = QtWidgets.QGraphicsLineItem(qlinef)
|
|
|
|
line.setData(0, e)
|
|
|
|
nei[e.source].append(e)
|
|
|
|
nei[e.target].append(e)
|
|
|
|
shapes[e] = line
|
|
|
|
|
|
|
|
# Render the widget
|
|
|
|
|
|
|
|
scene = QtWidgets.QGraphicsScene()
|
|
|
|
|
|
|
|
#for tagsrc in [
|
|
|
|
# annotated_topology.router_annotations.values(),
|
|
|
|
# annotated_topology.network_annotations.values(),
|
|
|
|
# annotated_topology.link_annotations.values(),
|
|
|
|
# ]:
|
|
|
|
# for taglist in tagsrc:
|
|
|
|
# assert len(taglist) > 0
|
|
|
|
# assert isinstance(taglist[-1], QtWidgets.QGraphicsItem)
|
|
|
|
# scene.addItem(taglist[-1])
|
|
|
|
|
|
|
|
for sh in shapes.values(): scene.addItem(sh)
|
|
|
|
|
|
|
|
view = QtWidgets.QGraphicsView(scene)
|
|
|
|
#view.show()
|
|
|
|
|
|
|
|
|
|
|
|
main_window = QtWidgets.QMainWindow()
|
|
|
|
main_window.setCentralWidget(view)
|
|
|
|
|
|
|
|
menu = main_window.menuBar().addMenu('Hello')
|
|
|
|
act = QtGui.QAction('Hi')
|
|
|
|
#act.setToolTip('Howdy')
|
|
|
|
menu.addAction(act)
|
|
|
|
main_window.show()
|
|
|
|
|
|
|
|
app.exec()
|