This commit is contained in:
2026-03-11 15:32:40 +03:00
parent 1ef63d9513
commit 35cf7d4dd7
6 changed files with 18 additions and 7 deletions
@@ -1,10 +1,10 @@
Name,Role,Adapter,Interface,Master Interface,Network,VLAN,Network IP,Mask,Device IP,Default Gateway
PC1,Host,Adapter1,eth1,vlan7,A,,,,,,
PC1,Host,Adapter1,eth1,vlan7,A,,,,,
PC1,Host,,vlan7,,7,10.10.10.0,/24,10.10.10.7,0.0.0.0,
PC2,Host,Adapter1,eth1,vlan9,B,,,,,,
PC2,Host,Adapter1,eth1,vlan9,B,,,,,
PC2,Host,,vlan9,,9,10.10.10.0,/24,10.10.10.9,0.0.0.0,
com,Switch,Adapter1,eth2,vlan7,A,7,,,,,
com,Switch,Adapter2,eth3,vlan9,B,9,,,,,
com,Switch,Adapter1,eth2,vlan7,A,7,,,,
com,Switch,Adapter2,eth3,vlan9,B,9,,,,
com,Switch,,vlan7,bridge,,,,,,
com,Switch,,vlan9,bridge,,,,,,
com,Switch,,bridge,,,,,,,
1 Name,Role,Adapter,Interface,Master Interface,Network,VLAN,Network IP,Mask,Device IP,Default Gateway Name Role Adapter Interface Master Interface Network VLAN Network IP Mask Device IP Default Gateway
2 PC1,Host,Adapter1,eth1,vlan7,A,,,,,, PC1 Host Adapter1 eth1 vlan7 A
3 PC1,Host,,vlan7,,7,10.10.10.0,/24,10.10.10.7,0.0.0.0, PC1 Host vlan7 7 10.10.10.0 /24 10.10.10.7 0.0.0.0
4 PC2,Host,Adapter1,eth1,vlan9,B,,,,,, PC2 Host Adapter1 eth1 vlan9 B
5 PC2,Host,,vlan9,,9,10.10.10.0,/24,10.10.10.9,0.0.0.0, PC2 Host vlan9 9 10.10.10.0 /24 10.10.10.9 0.0.0.0
6 com,Switch,Adapter1,eth2,vlan7,A,7,,,,, com Switch Adapter1 eth2 vlan7 A 7
7 com,Switch,Adapter2,eth3,vlan9,B,9,,,,, com Switch Adapter2 eth3 vlan9 B 9
8 com,Switch,,vlan7,bridge,,,,,, com Switch vlan7 bridge
9 com,Switch,,vlan9,bridge,,,,,, com Switch vlan9 bridge
10 com,Switch,,bridge,,,,,,, com Switch bridge
+2 -2
View File
@@ -21,9 +21,9 @@ def run(argv: list[str] | None = None) -> None:
raw_devices = parse_csv(Path(args.input))
topology = convert_raw_topology(raw_devices)
generate_diagram(topology, Path(args.output) / "diagram.png")
# generate_diagram(topology, Path(args.output) / "diagram.png")
make_yaml(topology, Path(args.output) / "topology.yaml")
# generate_d2_diagram(topology, Path(args.output) / "diagram.d2")
generate_d2_diagram(topology, Path(args.output) / "diagram.d2")
logging.info("All tasks completed successfully.")
+8
View File
@@ -16,6 +16,8 @@ class Interface:
def __init__(
self,
name: str,
adapter: Optional[str] = None,
master_interface: Optional[str] = None,
ip_address: Optional[str] = None,
network: Optional[str] = None,
default_gateway: Optional[str] = None,
@@ -28,11 +30,17 @@ class Interface:
raise ValueError("Interface 'network' must be a string or None")
if default_gateway is not None and not isinstance(default_gateway, str):
raise ValueError("Interface 'default_gateway' must be a string or None")
if adapter is not None and not isinstance(adapter, str):
raise ValueError("Interface 'adapter' must be a string or None")
if master_interface is not None and not isinstance(master_interface, str):
raise ValueError("Interface 'master_interface' must be a string or None")
self.name = name
self.ip_address = ip_address
self.network = network
self.default_gateway = default_gateway
self.adapter = adapter
self.master_interface = master_interface
def __repr__(self) -> str:
return f"Interface(name={self.name}, ip_address={self.ip_address}, network={self.network}, default_gateway={self.default_gateway})"
+3 -1
View File
@@ -6,6 +6,7 @@ from ..domain.models import VirtualInterface
from pathlib import Path
from py_d2 import D2Diagram, D2Shape, D2Connection
from py_d2.shape import Shape
from py_d2.connection import Direction
# https://d2lang.com/tour/themes/
THEME_NUMBER = 200
@@ -71,6 +72,7 @@ def generate_d2_diagram(topology: Topology, output_path: Path) -> None:
connection = D2Connection(
shape_1=f"{device.name}.{interface.adapter}",
shape_2=interface.network,
direction=Direction("--"),
)
connections.append(connection)
@@ -102,7 +104,7 @@ def _generate_picture(diagram: Path, output_path: Path) -> None:
)
res = subprocess.run(
["d2", f"--theme={THEME_NUMBER}", str(diagram), str(output_path)],
["d2", f"--theme={THEME_NUMBER}", str(diagram)],
check=True,
capture_output=True,
)
+1
View File
@@ -14,6 +14,7 @@ class RawDevices:
if not isinstance(fields, dict):
raise ValueError("RawDevices 'fields' must be a dictionary")
if any(not isinstance(k, str) for k in fields.keys()):
print(fields.keys())
raise ValueError("RawDevices 'fields' keys must be strings")
self.id = id