0.1
This commit is contained in:
482
data/example-a.sections.json
Normal file
482
data/example-a.sections.json
Normal file
File diff suppressed because one or more lines are too long
BIN
data/example.log
Normal file
BIN
data/example.log
Normal file
Binary file not shown.
500
data/example.sections.json
Normal file
500
data/example.sections.json
Normal file
File diff suppressed because one or more lines are too long
10
main.py
10
main.py
@@ -1,8 +1,9 @@
|
|||||||
# main.py
|
# main.py
|
||||||
import json
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from utils.texttools import split_display_sections
|
from utils.texttools import split_display_sections
|
||||||
from models.hpe5130 import SwitchHPE5130
|
from models.hpe5130 import SwitchHPE5130
|
||||||
|
from output.export_json import export_switch_to_json
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def read_file_with_fallback(path: Path) -> str:
|
def read_file_with_fallback(path: Path) -> str:
|
||||||
@@ -14,7 +15,7 @@ def read_file_with_fallback(path: Path) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
log_path = Path("data/example-a.log")
|
log_path = Path("data/example.log")
|
||||||
if not log_path.exists():
|
if not log_path.exists():
|
||||||
print(f"Fichier non trouvé : {log_path}")
|
print(f"Fichier non trouvé : {log_path}")
|
||||||
return
|
return
|
||||||
@@ -27,10 +28,7 @@ def main():
|
|||||||
switch.parse_block(section["section"], section["content"])
|
switch.parse_block(section["section"], section["content"])
|
||||||
|
|
||||||
output_path = Path("data/switch_parsed.json")
|
output_path = Path("data/switch_parsed.json")
|
||||||
with open(output_path, "w", encoding="utf-8") as f:
|
export_switch_to_json(switch, output_path)
|
||||||
json.dump(switch.to_dict(), f, indent=2, ensure_ascii=False)
|
|
||||||
|
|
||||||
print(f"Switch exporté dans {output_path}")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
# models/base_switch.py
|
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
import re
|
||||||
|
|
||||||
|
def normalize_port_name(port: str) -> str:
|
||||||
|
port = port.upper()
|
||||||
|
port = port.replace("GE", "GIGABITETHERNET")
|
||||||
|
port = port.replace("XGE", "TEN-GIGABITETHERNET")
|
||||||
|
port = port.replace("BAGG", "BRIDGE-AGGREGATION")
|
||||||
|
return port
|
||||||
|
|
||||||
class PowerSupply:
|
class PowerSupply:
|
||||||
def __init__(self, id: int, state: str, mode: Optional[str] = None):
|
def __init__(self, id: int, state: str, mode: Optional[str] = None):
|
||||||
@@ -55,14 +62,20 @@ class Port:
|
|||||||
self.speed = None
|
self.speed = None
|
||||||
self.vlan = None
|
self.vlan = None
|
||||||
self.link_type = None
|
self.link_type = None
|
||||||
self.trunk_vlans = []
|
self.trunk_vlans: List[int] = []
|
||||||
self.bpdu_protection = False
|
self.bpdu_protection = False
|
||||||
self.portfast = False
|
self.portfast = False
|
||||||
self.loopback_detection = None
|
self.loopback_detection = None
|
||||||
self.mac_addresses = []
|
self.mac_addresses: List[str] = []
|
||||||
self.summary = ""
|
self.summary = ""
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
|
mac_count = len(self.mac_addresses)
|
||||||
|
mac_info = f", {mac_count} MAC" if mac_count else ""
|
||||||
|
vlan_info = f"TRUNK ({', '.join(map(str, sorted(self.trunk_vlans)))})" if self.link_type == "trunk" else f"VLAN {self.vlan or '?'}"
|
||||||
|
status = self.status.upper() if self.status else "INCONNU"
|
||||||
|
speed = self.speed or "vitesse inconnue"
|
||||||
|
self.summary = f"Port {self.name} est {status} à {speed}, {vlan_info}{mac_info}"
|
||||||
return {
|
return {
|
||||||
"object": "port",
|
"object": "port",
|
||||||
"name": self.name,
|
"name": self.name,
|
||||||
@@ -70,11 +83,11 @@ class Port:
|
|||||||
"speed": self.speed,
|
"speed": self.speed,
|
||||||
"vlan": self.vlan,
|
"vlan": self.vlan,
|
||||||
"link_type": self.link_type,
|
"link_type": self.link_type,
|
||||||
"trunk_vlans": self.trunk_vlans if self.link_type == "trunk" else None,
|
"trunk_vlans": ", ".join(map(str, self.trunk_vlans)) if self.link_type == "trunk" else None,
|
||||||
"bpdu_protection": self.bpdu_protection,
|
"bpdu_protection": self.bpdu_protection,
|
||||||
"portfast": self.portfast,
|
"portfast": self.portfast,
|
||||||
"loopback_detection": self.loopback_detection,
|
"loopback_detection": self.loopback_detection,
|
||||||
"mac_addresses": [m.to_dict() for m in self.mac_addresses],
|
"mac_addresses": self.mac_addresses,
|
||||||
"summary": self.summary,
|
"summary": self.summary,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# models/hpe5130.py
|
# models/hpe5130.py
|
||||||
from models.base_switch import Switch
|
from models.base_switch import Switch, normalize_port_name
|
||||||
from models.base_switch import Fan, PowerSupply, MACEntry, Port, VLAN
|
from models.base_switch import Fan, PowerSupply, MACEntry, Port, VLAN
|
||||||
import re
|
import re
|
||||||
|
|
||||||
@@ -78,7 +78,14 @@ class SwitchHPE5130(Switch):
|
|||||||
mac = match.group(1).replace("-", ":").lower()
|
mac = match.group(1).replace("-", ":").lower()
|
||||||
vlan = int(match.group(2))
|
vlan = int(match.group(2))
|
||||||
port = match.group(3)
|
port = match.group(3)
|
||||||
self.mac_table.append(MACEntry(mac, vlan, port, type_="dynamic"))
|
mac_entry = MACEntry(mac, vlan, port, type_="dynamic")
|
||||||
|
self.mac_table.append(mac_entry)
|
||||||
|
|
||||||
|
# 🔁 Ajout dans le bon port (nom normalisé)
|
||||||
|
normalized_port = normalize_port_name(port)
|
||||||
|
port_obj = next((p for p in self.ports if p.name.upper() == normalized_port), None)
|
||||||
|
if port_obj:
|
||||||
|
port_obj.mac_addresses.append(mac)
|
||||||
|
|
||||||
def _parse_display_interface(self, content: str):
|
def _parse_display_interface(self, content: str):
|
||||||
pattern = re.compile(r"^(Bridge-Aggregation\d+|\S*Ethernet\d+/\d+/\d+|InLoopBack\d+|NULL\d+)$", re.MULTILINE)
|
pattern = re.compile(r"^(Bridge-Aggregation\d+|\S*Ethernet\d+/\d+/\d+|InLoopBack\d+|NULL\d+)$", re.MULTILINE)
|
||||||
@@ -220,4 +227,5 @@ class SwitchHPE5130(Switch):
|
|||||||
block_lines.append(line)
|
block_lines.append(line)
|
||||||
|
|
||||||
if current_interface and block_lines:
|
if current_interface and block_lines:
|
||||||
self._apply_interface_config(current_interface, block_lines)
|
self._apply_interface_config(current_interface, block_lines)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
def export_switch_to_json(switch_obj, output_path: Path):
|
||||||
|
def compact(obj):
|
||||||
|
# sérialise en JSON sans indent, puis ré-indente les lignes manuellement
|
||||||
|
return json.dumps(
|
||||||
|
obj,
|
||||||
|
indent=None,
|
||||||
|
separators=(",", ": "),
|
||||||
|
ensure_ascii=False
|
||||||
|
)
|
||||||
|
|
||||||
|
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
||||||
|
with open(output_path, "w", encoding="utf-8") as f:
|
||||||
|
parsed = json.loads(compact(switch_obj.to_dict()))
|
||||||
|
json.dump(parsed, f, indent=2, separators=(",", ": "), ensure_ascii=False)
|
||||||
|
|||||||
Reference in New Issue
Block a user