Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Site diagram #45

Merged
merged 3 commits into from
Jul 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions netdoc/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class DiagramModeChoices(ChoiceSet):
CHOICES = [
("l2", "L2"),
("l3", "L3"),
("site", "Site connections"),
# ("stp", "STP"),
]

Expand Down
Binary file added netdoc/static/netdoc/img/site.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
129 changes: 129 additions & 0 deletions netdoc/topologies.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,21 @@
</table>
"""

SITE_TEMPLATE = """
<table>
<tbody>
<tr>
<th>From: </th>
<td>[{{ from_interface.device.site.name }}] {{ from_interface.device.name }}:{{ from_interface.name }}</td>
</tr>
<tr>
<th>To: </th>
<td>[{{ to_interface.device.site.name }}] {{ to_interface.device.name }}:{{ to_interface.name }}</td>
</tr>
</tbody>
</table>
"""

NETWORK_TEMPLATE = """
<table>
<tbody>
Expand Down Expand Up @@ -347,3 +362,117 @@ def get_l3_drawio_topology(queryset, diagram):
)

return drawio_o.dump_xml()


def get_site_topology_data(queryset, details):
"""Create a site vis.js topology data from an Interface queryset."""
sites = {}
links = {}

# Filter out unconnected interfaces
queryset = queryset.filter(cable__isnull=False)

for interface_o in queryset:
# Create link
cable_o = interface_o.cable
from_interface_o = cable_o.terminations.first().interface.first()
from_interface_id = from_interface_o.id
to_interface_o = cable_o.terminations.last().interface.first()
to_interface_id = to_interface_o.id
from_site_o = from_interface_o.device.site
from_site_id = from_site_o.id
to_site_o = to_interface_o.device.site
to_site_id = to_site_o.id
link_id = (
f"{from_interface_id}-{to_interface_id}"
if from_interface_id <= to_interface_id
else f"{to_interface_id}-{from_interface_id}"
)

if link_id not in links and from_site_id != to_site_id:
# Add link only if intra-site
links[link_id] = {
"id": link_id,
"from": from_site_id,
"from_label": f"{from_interface_o.device.name}:{from_interface_o.label}",
"to": to_site_id,
"to_label": f"{to_interface_o.device.name}:{to_interface_o.label}",
"title": Template(SITE_TEMPLATE, autoescape=JINJA_AUTOESCAPE).render(
from_interface=from_interface_o, to_interface=to_interface_o
),
}

# Add source site
if from_site_id not in sites:
sites[from_site_id] = {
"id": from_site_id,
"label": from_site_o.name,
"image": "/static/netdoc/img/site.png",
"shape": "image",
"title": from_site_o.name,
}
# Set position
if "positions" in sites and str(from_site_o.id) in details["positions"]:
sites[from_site_id]["x"] = details["positions"][str(from_site_id)].get(
"x"
)
sites[from_site_id]["y"] = details["positions"][str(from_site_id)].get(
"y"
)

# Add destination site
if to_site_id not in sites:
sites[to_site_id] = {
"id": to_site_id,
"label": to_site_o.name,
"image": "/static/netdoc/img/site.png",
"shape": "image",
"title": to_site_o.name,
}
# Set position
if "positions" in details and str(from_site_o.id) in details["positions"]:
sites[to_site_id]["x"] = details["positions"][str(to_site_id)].get("x")
sites[to_site_id]["y"] = details["positions"][str(to_site_id)].get("y")

return {
"nodes": list(sites.values()),
"edges": list(links.values()),
}


def get_site_drawio_topology(queryset, diagram):
"""Create a site DrawIO topology data from an Interface queryset."""
data = get_site_topology_data(queryset, diagram.details)
nodes = data.get("nodes")
links = data.get("edges")

# Transform node list into dict using id a key
nodes_dict = {item["id"]: item for item in nodes}

# Create diagram
drawio_o = drawio_diagram()
drawio_o.add_diagram("Page-1")

for node in nodes:
# Add node
node_label = node.get("label")
node_style = "site"
drawio_o.add_node(
id=node_label,
url="Page-1",
x_pos=node.get("x") if node.get("x") else None,
y_pos=node.get("y") if node.get("x") else None,
**DRAWIO_ROLE_MAP[node_style],
)

for link in links:
# Add link (using node labels)
drawio_o.add_link(
nodes_dict[link["from"]]["label"],
nodes_dict[link["to"]]["label"],
src_label=link["from_label"],
trgt_label=link["to_label"],
link_id=link["id"],
)

return drawio_o.dump_xml()
9 changes: 9 additions & 0 deletions netdoc/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,15 @@
"width": 50,
"height": 50,
},
"site": {
"style": "points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[1,0.25,0],[1,0.5,0],"
+ "[1,0.75,0],[1,1,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,1,0],[0,0.75,0],[0,0.5,0],"
+ "[0,0.25,0]];verticalLabelPosition=bottom;sketch=0;html=1;verticalAlign=top;"
+ "aspect=fixed;align=center;pointerEvents=1;shape=mxgraph.cisco19.branch;"
+ "fillColor=#005073;strokeColor=none;",
"width": 50,
"height": 50,
},
"storage": {
"style": "sketch=0;points=[[0.015,0.015,0],[0.985,0.015,0],[0.985,0.985,0],[0.015,0.985,0],"
+ "[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],"
Expand Down