2026-05-20 13:56:08 +02:00
import os
import sys
import subprocess
from datetime import datetime
from threading import Thread
2026-01-14 14:15:06 +01:00
import tkinter as tk
from tkinter import ttk , filedialog , messagebox
2026-05-20 13:56:08 +02:00
from pathlib import Path
def make_scrollable ( parent ) :
canvas = tk . Canvas ( parent , highlightthickness = 0 )
scrollbar = ttk . Scrollbar ( parent , orient = " vertical " , command = canvas . yview )
scrollable_frame = ttk . Frame ( canvas )
scrollable_frame . bind (
" <Configure> " ,
lambda e : canvas . configure ( scrollregion = canvas . bbox ( " all " ) )
)
canvas . create_window ( ( 0 , 0 ) , window = scrollable_frame , anchor = " nw " )
def on_configure ( event ) :
canvas . itemconfig ( " frame " , width = canvas . winfo_width ( ) )
canvas . create_window ( ( 0 , 0 ) , window = scrollable_frame , anchor = " nw " , tags = " frame " )
canvas . bind ( " <Configure> " , on_configure )
canvas . configure ( yscrollcommand = scrollbar . set )
canvas . pack ( side = " left " , fill = " both " , expand = True )
scrollbar . pack ( side = " right " , fill = " y " )
canvas . bind_all ( " <MouseWheel> " , lambda e : canvas . yview_scroll ( int ( - 1 * ( e . delta / 120 ) ) , " units " ) )
return scrollable_frame
class ToolTip :
def __init__ ( self , widget , text ) :
self . widget = widget
self . text = text
self . tipwindow = None
widget . bind ( " <Enter> " , self . show )
widget . bind ( " <Leave> " , self . hide )
def show ( self , event = None ) :
if self . tipwindow or not self . text :
return
x = self . widget . winfo_rootx ( ) + 20
y = self . widget . winfo_rooty ( ) + 20
self . tipwindow = tw = tk . Toplevel ( self . widget )
tw . wm_overrideredirect ( True )
tw . wm_geometry ( f " + { x } + { y } " )
label = tk . Label (
tw ,
text = self . text ,
justify = " left " ,
background = " #ffffe0 " ,
relief = " solid " ,
borderwidth = 1 ,
font = ( " Arial " , 9 ) ,
padx = 8 ,
pady = 4
)
label . pack ( )
def hide ( self , event = None ) :
if self . tipwindow :
self . tipwindow . destroy ( )
self . tipwindow = None
# Contenu fenêtre Analyse Switch Multi
def open_switch_gui_multi ( app , OUTPUT_DIR , HELP_FILE_SW , SWITCH_DIR , SWITCH_MAIN ) :
app2 = tk . Toplevel ( app )
app2 . title ( " Analyse Configuration Switch - Plusieurs switch " )
app2 . geometry ( " 800x450 " )
app2 . resizable ( True , True )
rapport_uplink = tk . BooleanVar ( )
schema_infra = tk . BooleanVar ( )
rapport_stack = tk . BooleanVar ( )
rapport_interfaces = tk . BooleanVar ( )
content = make_scrollable ( app2 )
def open_output_folder ( ) :
if sys . platform == " win32 " :
os . startfile ( OUTPUT_DIR )
elif sys . platform == " darwin " :
subprocess . run ( [ " open " , OUTPUT_DIR ] )
else :
subprocess . run ( [ " xdg-open " , OUTPUT_DIR ] )
def open_help ( ) :
if not os . path . exists ( HELP_FILE_SW ) :
messagebox . showerror ( " Erreur " , " Le fichier d ' aide est introuvable. " )
return
if sys . platform == " win32 " :
os . startfile ( HELP_FILE_SW )
elif sys . platform == " darwin " :
subprocess . run ( [ " open " , HELP_FILE_SW ] )
else :
subprocess . run ( [ " xdg-open " , HELP_FILE_SW ] )
def get_selected_switch ( vars_dict ) :
for sw , var in vars_dict . items ( ) :
if var . get ( ) :
return sw
return None
def run_parser_multi ( ) :
selections = [ ]
for name , vars_dict in file_selections . items ( ) :
sw = get_selected_switch ( vars_dict )
if sw :
selections . append ( {
" type " : " file " ,
" name " : name ,
" switch " : sw
} )
# for name, vars_dict in dir_selections.items():
# sw = get_selected_switch(vars_dict)
# if sw:
# selections.append({
# "type": "dir",
# "name": name,
# "switch": sw
# })
if not selections :
messagebox . showwarning (
" Aucune sélection " ,
" Veuillez sélectionner au moins un fichier ou dossier. "
)
return
content . config ( cursor = " watch " )
progress_bar = ttk . Progressbar ( content , mode = " indeterminate " )
progress_bar . pack ( pady = 10 , fill = " x " , padx = 10 )
progress_bar . start ( 10 )
def process ( ) :
try :
for item in selections :
input_path = str ( INPUT_DIR / item [ " name " ] )
cmd = [
sys . executable ,
SWITCH_MAIN ,
item [ " switch " ] ,
input_path
]
if rapport_uplink . get ( ) :
cmd . append ( " -u " )
if schema_infra . get ( ) :
cmd . append ( " -d " )
if rapport_stack . get ( ) :
cmd . append ( " -s " )
if rapport_interfaces . get ( ) :
cmd . append ( " -i " )
cmd . append ( " -o " )
if item [ " type " ] == " file " :
base_name = os . path . splitext ( item [ " name " ] ) [ 0 ]
cmd . append ( base_name )
else :
cmd . append ( item [ " name " ] )
print ( " Commande exécutée : " , " " . join ( cmd ) )
subprocess . run ( cmd , cwd = SWITCH_DIR , check = True )
def on_success ( ) :
progress_bar . stop ( )
progress_bar . destroy ( )
content . config ( cursor = " " )
messagebox . showinfo ( " Succès " , " Tous les traitements sont terminés. " )
open_output_folder ( )
app2 . destroy ( )
app2 . after ( 0 , on_success )
except subprocess . CalledProcessError as e :
def on_error ( ) :
progress_bar . stop ( )
progress_bar . destroy ( )
content . config ( cursor = " " )
messagebox . showerror (
" Erreur " ,
f " Erreur lors de l ' exécution du traitement. \n \n { e } "
)
app2 . after ( 0 , on_error )
Thread ( target = process , daemon = True ) . start ( )
def create_table ( parent , title , items , mode ) :
"""
mode = ' file '
"""
style = ttk . Style ( )
style . configure (
" Table.TFrame " ,
background = " white " ,
borderwidth = 1 ,
relief = " solid "
)
style . configure (
" Table.TLabel " ,
background = " white "
)
style . configure (
" Table.TCheckbutton " ,
background = " white "
)
style . map (
" Table.TCheckbutton " ,
background = [ ( " disabled " , " #f0f0f0 " ) ] ,
foreground = [ ( " disabled " , " #a0a0a0 " ) ]
)
ttk . Label (
parent ,
text = title ,
font = ( " Arial " , 10 , " bold " )
) . pack ( anchor = " w " , padx = 10 , pady = ( 0 , 4 ) )
table = ttk . Frame ( parent , style = " Table.TFrame " )
table . pack ( fill = " x " , padx = 10 )
table . columnconfigure ( 0 , weight = 1 )
if mode == " file " : n = " Fichier source "
else : n = " Dossier source "
headers = [ n , " HPE " ]
for col , text in enumerate ( headers ) :
ttk . Label (
table ,
text = text ,
style = " Table.TLabel " ,
font = ( " Arial " , 9 , " bold " )
) . grid ( row = 0 , column = col , padx = 8 , pady = 6 , sticky = " e " if col > 0 else " w " )
ttk . Separator ( table , orient = " horizontal " ) . grid (
row = 1 , column = 0 , columnspan = 4 , sticky = " ew " , pady = ( 0 , 2 )
)
selections = { }
grid_row = 2
for name in items :
ttk . Label (
table ,
text = name ,
style = " Table.TLabel "
) . grid ( row = grid_row , column = 0 , sticky = " w " , padx = 8 , pady = 4 )
var_hpe = tk . BooleanVar ( )
# var_autre = tk.BooleanVar()
def make_command ( active , others ) :
def cmd ( ) :
if active . get ( ) :
for var in others :
var . set ( False )
return cmd
cb_hpe = ttk . Checkbutton (
table ,
variable = var_hpe ,
style = " Table.TCheckbutton " ,
command = make_command ( var_hpe , [ ] )
)
# cb_autre = ttk.Checkbutton(
# table,
# variable=var_autre,
# style="Table.TCheckbutton",
# command=make_command(var_autre, [var_hpe])
cb_hpe . grid ( row = grid_row , column = 1 , sticky = " n " , padx = 8 )
# cb_autre.grid(row=grid_row, column=2, sticky="n", padx=8)
# elif mode == "file":
# cb_autre.state(["disabled"])
if mode == " dir " :
cb_hpe . state ( [ " disabled " ] )
selections [ name ] = {
" HPE " : var_hpe ,
# "autre": var_autre
}
# Séparateur interligne
ttk . Separator ( table , orient = " horizontal " ) . grid (
row = grid_row + 1 ,
column = 0 ,
columnspan = 4 ,
sticky = " ew "
)
grid_row + = 2
return selections
INPUT_DIR = Path ( OUTPUT_DIR ) . parent / " input "
if not INPUT_DIR . exists ( ) :
messagebox . showerror ( " Erreur " , f " Dossier input introuvable : { INPUT_DIR } " )
return
header_frame = ttk . Frame ( content )
header_frame . pack ( fill = " x " , padx = 10 , pady = 5 )
ttk . Button (
header_frame ,
text = " Help " ,
width = 6 ,
command = open_help
) . pack ( side = " right " )
ttk . Label (
header_frame ,
text = " Génération de fichiers JSON au format normalisé YANG à partir des logs de plusieurs switches " ,
font = ( " Arial " , 8 , " bold " )
) . pack ( side = " left " )
ttk . Label (
content ,
text = " /! \\ Mettre les fichiers/dossiers de configurations dans le dossier `./Parseurs_logs_Switch/src/input/` " ,
font = ( " Arial " , 9 , " italic " ) ,
) . pack ( anchor = " w " , padx = 10 , pady = ( 0 , 10 ) )
ttk . Label (
content ,
text = " Sélectionnez les fichiers de configuration source à traiter : " ,
font = ( " Arial " , 10 )
) . pack ( anchor = " w " , padx = 10 )
files = [ item . name for item in INPUT_DIR . iterdir ( ) if item . is_file ( ) ]
# dirs = [item.name for item in INPUT_DIR.iterdir() if item.is_dir()]
file_selections = create_table (
content ,
" 🗎 Liste des fichiers de configuration source " ,
files ,
mode = " file "
)
# dir_selections = create_table(
# content,
# "🗁 Liste des dossiers de configuration source",
# dirs,
# mode="dir"
# )
ttk . Checkbutton (
content ,
text = " Générer le schéma d ' infrastructure " ,
variable = schema_infra
) . pack ( anchor = " w " , padx = 10 , pady = ( 10 , 0 ) )
schema_infra . set ( True )
ttk . Checkbutton (
content ,
text = " Générer le rapport des liens inter-switches en Excel " ,
variable = rapport_uplink
) . pack ( anchor = " w " , padx = 10 , pady = ( 0 , 0 ) )
rapport_uplink . set ( True )
ttk . Checkbutton (
content ,
text = " Générer le rapport des stack en Excel " ,
variable = rapport_stack
) . pack ( anchor = " w " , padx = 10 , pady = ( 0 , 0 ) )
rapport_stack . set ( True )
ttk . Checkbutton (
content ,
text = " Générer le rapport des interfaces en Excel " ,
variable = rapport_interfaces
) . pack ( anchor = " w " , padx = 10 , pady = ( 0 , 10 ) )
rapport_interfaces . set ( True )
ttk . Label (
content ,
text = " Dossier de sortie : " ,
) . pack ( anchor = " w " , padx = 10 )
ttk . Button (
content ,
text = " Ouvrir le dossier de sortie " ,
command = open_output_folder
) . pack ( anchor = " w " , padx = 10 )
ttk . Button (
content ,
text = " Lancer le traitement " ,
command = run_parser_multi
) . pack ( pady = 15 )
content . mainloop ( )
2026-01-14 14:15:06 +01:00
# Contenu fenêtre Analyse Switch
def open_switch_gui ( root , BASE_DIR ) :
2026-05-20 13:56:08 +02:00
SWITCH_DIR = os . path . join (
BASE_DIR ,
" Parseurs_logs_Switch "
)
SWITCH_MAIN = os . path . join (
SWITCH_DIR ,
" src " ,
" main.py "
)
HELP_FILE_SW = os . path . join ( BASE_DIR , " help_Switch.md " )
OUTPUT_DIR = os . path . join ( SWITCH_DIR , " src " , " output " )
os . makedirs ( OUTPUT_DIR , exist_ok = True )
app = tk . Toplevel ( root )
app . title ( " Analyse Configuration Switch " )
app . geometry ( " 800x550 " )
app . resizable ( True , True )
switch_var = tk . StringVar ( )
input_var = tk . StringVar ( )
output_var = tk . StringVar ( )
rapport_uplink = tk . BooleanVar ( )
schema_infra = tk . BooleanVar ( )
rapport_stack = tk . BooleanVar ( )
rapport_interfaces = tk . BooleanVar ( )
def browse_input ( ) :
sw_type = switch_var . get ( )
if sw_type == " " :
messagebox . showerror ( " Erreur " , " Veuillez d ' abord sélectionner un type de switch. " )
return
path = filedialog . askopenfilename ( title = " Sélectionnez le fichier d ' entrée " , parent = app )
input_var . set ( path )
def update_output_label ( * args ) :
if switch_var . get ( ) == " " :
output_label_var . set ( " Fichier de sortie : " )
return
else :
sw = switch_var . get ( ) . lower ( )
if output_var . get ( ) :
s_json1 = os . path . join ( OUTPUT_DIR , f " { sw } _current_ { output_var . get ( ) } .json " )
s_json2 = os . path . join ( OUTPUT_DIR , f " { sw } _saved_ { output_var . get ( ) } .json " )
s_uplink = os . path . join ( OUTPUT_DIR , f " rapport_uplink_ { sw } _ { output_var . get ( ) } .xlsx " )
s_stack = os . path . join ( OUTPUT_DIR , f " rapport_stack_ { sw } _ { output_var . get ( ) } .xlsx " )
s_interfaces = os . path . join ( OUTPUT_DIR , f " rapport_interfaces_ { sw } _ { output_var . get ( ) } .xlsx " )
s_schema = os . path . join ( OUTPUT_DIR , f " schema_infra_ { sw } _ { output_var . get ( ) } .xlsx " )
else :
dt = datetime . now ( ) . strftime ( " % Y % m %d " )
s_json1 = os . path . join ( OUTPUT_DIR , f " { sw } _current_ { dt } .json " )
s_json2 = os . path . join ( OUTPUT_DIR , f " { sw } _saved_ { dt } .json " )
s_uplink = os . path . join ( OUTPUT_DIR , f " rapport_uplink_ { sw } _ { dt } .xlsx " )
s_stack = os . path . join ( OUTPUT_DIR , f " rapport_stack_ { sw } _ { dt } .xlsx " )
s_interfaces = os . path . join ( OUTPUT_DIR , f " rapport_interfaces_ { sw } _ { dt } .xlsx " )
s_schema = os . path . join ( OUTPUT_DIR , f " schema_infra_ { sw } _ { dt } .xlsx " )
output_label_var . set ( " Fichier de sortie : \n " + s_json1 + " \n " + s_json2 + ( " \n " + s_uplink if rapport_uplink . get ( ) else " " ) + ( " \n " + s_stack if rapport_stack . get ( ) else " " ) + ( " \n " + s_interfaces if rapport_interfaces . get ( ) else " " ) + ( " \n " + s_schema if schema_infra . get ( ) else " " ) )
app . update_idletasks ( )
def open_output_folder ( ) :
if sys . platform == " win32 " :
os . startfile ( OUTPUT_DIR )
elif sys . platform == " darwin " :
subprocess . run ( [ " open " , OUTPUT_DIR ] )
else :
subprocess . run ( [ " xdg-open " , OUTPUT_DIR ] )
def open_help ( ) :
if not os . path . exists ( HELP_FILE_SW ) :
messagebox . showerror ( " Erreur " , " Le fichier d ' aide est introuvable. " )
return
if sys . platform == " win32 " :
os . startfile ( HELP_FILE_SW )
elif sys . platform == " darwin " :
subprocess . run ( [ " open " , HELP_FILE_SW ] )
else :
subprocess . run ( [ " xdg-open " , HELP_FILE_SW ] )
def run_parser ( ) :
if not switch_var . get ( ) :
messagebox . showerror ( " Erreur " , " Veuillez sélectionner un type de switch. " )
return
if not input_var . get ( ) :
messagebox . showerror ( " Erreur " , " Veuillez sélectionner un fichier d ' entrée. " )
return
app . config ( cursor = " watch " )
progress_bar = ttk . Progressbar ( app , mode = " indeterminate " )
progress_bar . pack ( pady = 10 , fill = " x " , padx = 10 )
progress_bar . start ( 10 )
app . update_idletasks ( )
def process ( ) :
cmd = [
sys . executable ,
SWITCH_MAIN ,
switch_var . get ( ) ,
input_var . get ( )
]
if output_var . get ( ) :
cmd . extend ( [ " -o " , output_var . get ( ) ] )
if rapport_uplink . get ( ) :
cmd . append ( " -u " )
if schema_infra . get ( ) :
cmd . append ( " -d " )
if rapport_stack . get ( ) :
cmd . append ( " -s " )
if rapport_interfaces . get ( ) :
cmd . append ( " -i " )
# print("Commande exécutée :", " ".join(cmd))
# print("Dossier courant (cwd) :", SWITCH_DIR)
try :
subprocess . run (
cmd ,
cwd = SWITCH_DIR ,
check = True
)
def on_success ( ) :
progress_bar . stop ( )
progress_bar . destroy ( )
app . config ( cursor = " " )
messagebox . showinfo ( " Succès " , " Traitement terminé avec succès. " )
open_output_folder ( )
app . destroy ( )
app . after ( 0 , on_success )
except subprocess . CalledProcessError as e :
def on_error ( ) :
progress_bar . stop ( )
progress_bar . destroy ( )
app . config ( cursor = " " )
messagebox . showerror (
" Erreur " ,
f " Erreur lors de l ' exécution du traitement. \n \n "
)
app . after ( 0 , on_error )
Thread ( target = process , daemon = True ) . start ( )
header_frame = ttk . Frame ( app )
header_frame . pack ( fill = " x " , padx = 10 , pady = 5 )
ttk . Button (
header_frame ,
text = " Help " ,
width = 6 ,
command = open_help
) . pack ( side = " right " )
ttk . Label (
header_frame ,
text = " Génération d ' un fichier JSON au format normalisé YANG à partir des logs d ' un switch " ,
font = ( " Arial " , 8 , " bold " )
) . pack ( side = " left " )
ttk . Button (
app ,
text = " Plusieurs Switches " ,
command = lambda : open_switch_gui_multi ( app , OUTPUT_DIR , HELP_FILE_SW , SWITCH_DIR , SWITCH_MAIN )
) . pack ( anchor = " w " , padx = 10 )
ttk . Label ( app , text = " Type de switch " ) . pack ( anchor = " w " , padx = 10 , pady = 5 )
ttk . Combobox (
app ,
values = [ " HPE " ] ,
textvariable = switch_var ,
state = " readonly "
) . pack ( fill = " x " , padx = 10 )
input_label_var = tk . StringVar ( )
input_label_var . set ( " Fichier de logs source " )
input_label_frame = ttk . Frame ( app )
input_label_frame . pack ( anchor = " w " , padx = 5 , pady = 5 )
info_label = ttk . Label (
input_label_frame ,
text = " ⓘ " ,
cursor = " hand2 "
)
info_label . pack ( side = " right " )
ttk . Label (
input_label_frame ,
textvariable = input_label_var
) . pack ( side = " left " , padx = ( 5 , 0 ) )
ToolTip (
info_label ,
" /! \\ Mettre le fichier/dossier de configurations \n "
" dans le dossier `/Parseurs_config_Firewall/src/input/` /! \\ "
)
def update_input_label ( * args ) :
switch_type = switch_var . get ( ) . lower ( )
input_label_var . set ( " Fichier de configuration source " )
switch_var . trace_add ( " write " , update_input_label )
input_frame = ttk . Frame ( app )
input_frame . pack ( fill = " x " , padx = 10 )
ttk . Entry ( input_frame , textvariable = input_var ) . pack ( side = " left " , fill = " x " , expand = True )
ttk . Button ( input_frame , text = " Parcourir " , command = browse_input ) . pack ( side = " right " )
ttk . Label ( app , text = " Nom de sortie (optionnel) " ) . pack ( anchor = " w " , padx = 10 , pady = 5 )
ttk . Entry ( app , textvariable = output_var ) . pack ( fill = " x " , padx = 10 )
ttk . Checkbutton (
app ,
text = " Générer le schéma d ' infrastructure " ,
variable = schema_infra
) . pack ( anchor = " w " , padx = 10 , pady = ( 10 , 0 ) )
schema_infra . set ( True )
ttk . Checkbutton (
app ,
text = " Générer le rapport des liens inter-switches en Excel " ,
variable = rapport_uplink
) . pack ( anchor = " w " , padx = 10 , pady = ( 0 , 0 ) )
rapport_uplink . set ( True )
ttk . Checkbutton (
app ,
text = " Générer le rapport des stack en Excel " ,
variable = rapport_stack
) . pack ( anchor = " w " , padx = 10 , pady = ( 0 , 0 ) )
rapport_stack . set ( True )
ttk . Checkbutton (
app ,
text = " Générer le rapport des interfaces en Excel " ,
variable = rapport_interfaces
) . pack ( anchor = " w " , padx = 10 , pady = ( 0 , 10 ) )
rapport_interfaces . set ( True )
output_label_var = tk . StringVar ( )
ttk . Label ( app , textvariable = output_label_var ) . pack ( anchor = " w " , padx = 10 )
switch_var . trace_add ( " write " , update_output_label )
output_var . trace_add ( " write " , update_output_label )
schema_infra . trace_add ( " write " , update_output_label )
rapport_uplink . trace_add ( " write " , update_output_label )
rapport_stack . trace_add ( " write " , update_output_label )
rapport_interfaces . trace_add ( " write " , update_output_label )
update_output_label ( )
ttk . Button (
app ,
text = " Ouvrir le dossier de sortie " ,
command = open_output_folder
) . pack ( anchor = " w " , padx = 10 )
ttk . Button (
app ,
text = " Lancer le traitement " ,
command = run_parser
) . pack ( pady = 15 )
app . mainloop ( )