-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdevops_exercise6.py
More file actions
266 lines (223 loc) · 11.7 KB
/
devops_exercise6.py
File metadata and controls
266 lines (223 loc) · 11.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
"""
EXERCICE 6 — Bascule vers une région secondaire (Regional Failover)
Contexte :
- Une région d'hébergement présente des signes de dégradation
Question : L'agent doit décider s'il faut basculer vers une autre région.
Éléments observables :
- Latence régionale
- Taux d'erreur
- Résultats des contrôles de santé
- État de la région secondaire
- Synchronisation des données
"""
from 03_domains.devops.agents.regional_failover_agent import RegionalFailoverAgent
from 03_domains.devops.agents.export import export_devops_decision
from 01_core_engine.reasoning.export import export_to_json_file
from 01_core_engine.graph.types import ReasoningStatus
from datetime import datetime
def format_time():
"""Retourne l'heure actuelle formatée."""
return datetime.now().strftime("%H:%M")
def exercise6_regional_failover_decision():
"""Exercice 6 : Bascule vers une région secondaire."""
print("=" * 70)
print("EXERCICE 6 — BASCULE VERS UNE REGION SECONDAIRE (REGIONAL FAILOVER)")
print("=" * 70)
print("\nContexte :")
print(" - Une region d'hebergement presente des signes de degradation")
print("\nQuestion :")
print(" L'agent doit decider s'il faut basculer vers une autre region.")
print("\nElements observables :")
print(" - Latence regionale")
print(" - Taux d'erreur")
print(" - Resultats des controles de sante")
print(" - Etat de la region secondaire")
print(" - Synchronisation des donnees")
# Historique des décisions
decisions_history = []
# ============================================================
# SCÉNARIO 1 : État initial (signaux incertains)
# ============================================================
print("\n" + "=" * 70)
print("SCENARIO 1 : ETAT INITIAL (SIGNAUX INCERTAINS)")
print("=" * 70)
agent = RegionalFailoverAgent(threshold=0.7)
# Afficher l'état initial
print("\nEtat des signaux de bascule :")
node_a = agent.graph.get_node("A")
node_b = agent.graph.get_node("B")
node_c = agent.graph.get_node("C")
node_d = agent.graph.get_node("D")
node_e = agent.graph.get_node("E")
node_g = agent.graph.get_node("G")
for node in [node_a, node_b, node_c, node_d, node_e, node_g]:
if node:
status_icon = "[OK]" if node.status == ReasoningStatus.PROVEN else "[?]"
print(f" {status_icon} {node.id}: {node.content} ({node.status.value})")
# Évaluer la décision initiale
result1 = agent.decide_failover()
label1 = f"{format_time()} - Initial state"
decisions_history.append({"label": label1, "result": result1})
print(f"\nDecision initiale :")
print(f" - Statut : {result1.get('status', 'unknown')}")
print(f" - Decision : {result1.get('decision', 'No decision')}")
print(f" - Failover type : {result1.get('devops_context', {}).get('failover_type', 'unknown')}")
print(f" - Niveau de risque : {result1.get('devops_context', {}).get('risk_level', 'unknown')}")
print(f" - Recommandation : {result1.get('devops_context', {}).get('recommendation', '')}")
print(f" - Justification : {result1.get('justification', '')[:100]}...")
# ============================================================
# SCÉNARIO 2 : Latence élevée (signal isolé)
# ============================================================
print("\n" + "=" * 70)
print("SCENARIO 2 : LATENCE ELEVEE (SIGNAL ISOLE)")
print("=" * 70)
node_a = agent.graph.get_node("A")
if node_a:
node_a.update_status(ReasoningStatus.PROVEN, "Regional latency confirmed high")
result2 = agent.decide_failover()
label2 = f"{format_time()} - High latency"
decisions_history.append({"label": label2, "result": result2})
print("\nApres confirmation latence elevee :")
print(f" - Statut : {result2.get('status', 'unknown')}")
print(f" - Decision : {result2.get('decision', 'No decision')}")
print(f" - Failover type : {result2.get('devops_context', {}).get('failover_type', 'unknown')}")
print(f" - Recommandation : {result2.get('devops_context', {}).get('recommendation', '')}")
print(f" - Justification : {result2.get('justification', '')[:100]}...")
# ============================================================
# SCÉNARIO 3 : Latence + Taux d'erreur (convergence)
# ============================================================
print("\n" + "=" * 70)
print("SCENARIO 3 : LATENCE + TAUX D'ERREUR (CONVERGENCE)")
print("=" * 70)
node_a = agent.graph.get_node("A")
node_b = agent.graph.get_node("B")
if node_a:
node_a.update_status(ReasoningStatus.PROVEN, "Regional latency confirmed high")
if node_b:
node_b.update_status(ReasoningStatus.PROVEN, "Error rate confirmed high")
result3 = agent.decide_failover()
label3 = f"{format_time()} - High latency + Error rate"
decisions_history.append({"label": label3, "result": result3})
print("\nApres confirmation Latence + Taux d'erreur :")
print(f" - Statut : {result3.get('status', 'unknown')}")
print(f" - Decision : {result3.get('decision', 'No decision')}")
print(f" - Failover type : {result3.get('devops_context', {}).get('failover_type', 'unknown')}")
print(f" - Recommandation : {result3.get('devops_context', {}).get('recommendation', '')}")
# ============================================================
# SCÉNARIO 4 : Région secondaire saine (pivot fort)
# ============================================================
print("\n" + "=" * 70)
print("SCENARIO 4 : REGION SECONDAIRE SAINE (PIVOT FORT)")
print("=" * 70)
# Nouvel agent pour ce scénario
agent2 = RegionalFailoverAgent(threshold=0.7)
node_a = agent2.graph.get_node("A")
node_d = agent2.graph.get_node("D")
if node_a:
node_a.update_status(ReasoningStatus.PROVEN, "Regional latency confirmed high")
if node_d:
node_d.update_status(ReasoningStatus.PROVEN, "Secondary region confirmed healthy")
result4 = agent2.decide_failover()
label4 = f"{format_time()} - High latency + Secondary healthy"
decisions_history.append({"label": label4, "result": result4})
print("\nAvec region secondaire saine :")
print(f" - Statut : {result4.get('status', 'unknown')}")
print(f" - Decision : {result4.get('decision', 'No decision')}")
print(f" - Failover type : {result4.get('devops_context', {}).get('failover_type', 'unknown')}")
print(f" - Recommandation : {result4.get('devops_context', {}).get('recommendation', '')}")
print(f" - Justification : {result4.get('justification', '')[:100]}...")
# ============================================================
# SCÉNARIO 5 : Synchronisation des données (bascule sûre)
# ============================================================
print("\n" + "=" * 70)
print("SCENARIO 5 : SYNCHRONISATION DES DONNEES (BASCULE SURE)")
print("=" * 70)
agent3 = RegionalFailoverAgent(threshold=0.7)
node_a = agent3.graph.get_node("A")
node_b = agent3.graph.get_node("B")
node_d = agent3.graph.get_node("D")
node_e = agent3.graph.get_node("E")
if node_a:
node_a.update_status(ReasoningStatus.PROVEN, "Regional latency confirmed high")
if node_b:
node_b.update_status(ReasoningStatus.PROVEN, "Error rate confirmed high")
if node_d:
node_d.update_status(ReasoningStatus.PROVEN, "Secondary region confirmed healthy")
if node_e:
node_e.update_status(ReasoningStatus.PROVEN, "Data synchronization confirmed")
result5 = agent3.decide_failover()
label5 = f"{format_time()} - All signals + Data synced"
decisions_history.append({"label": label5, "result": result5})
print("\nAvec synchronisation des donnees :")
print(f" - Statut : {result5.get('status', 'unknown')}")
print(f" - Decision : {result5.get('decision', 'No decision')}")
print(f" - Failover type : {result5.get('devops_context', {}).get('failover_type', 'unknown')}")
print(f" - Recommandation : {result5.get('devops_context', {}).get('recommendation', '')}")
# ============================================================
# SCÉNARIO 6 : Convergence forte sans synchronisation (bascule risquée)
# ============================================================
print("\n" + "=" * 70)
print("SCENARIO 6 : CONVERGENCE FORTE SANS SYNCHRONISATION (BASCULE RISQUEE)")
print("=" * 70)
agent4 = RegionalFailoverAgent(threshold=0.7)
node_a = agent4.graph.get_node("A")
node_b = agent4.graph.get_node("B")
node_c = agent4.graph.get_node("C")
node_d = agent4.graph.get_node("D")
if node_a:
node_a.update_status(ReasoningStatus.PROVEN, "Regional latency confirmed high")
if node_b:
node_b.update_status(ReasoningStatus.PROVEN, "Error rate confirmed high")
if node_c:
node_c.update_status(ReasoningStatus.PROVEN, "Health checks confirmed failed")
if node_d:
node_d.update_status(ReasoningStatus.PROVEN, "Secondary region confirmed healthy")
# E reste UNCERTAIN (données non synchronisées)
result6 = agent4.decide_failover()
label6 = f"{format_time()} - All signals but data not synced"
decisions_history.append({"label": label6, "result": result6})
print("\nAvec convergence forte mais donnees non synchronisees :")
print(f" - Statut : {result6.get('status', 'unknown')}")
print(f" - Decision : {result6.get('decision', 'No decision')}")
print(f" - Failover type : {result6.get('devops_context', {}).get('failover_type', 'unknown')}")
print(f" - Recommandation : {result6.get('devops_context', {}).get('recommendation', '')}")
# ============================================================
# EXPORT POUR VISUALISATION
# ============================================================
print("\n" + "=" * 70)
print("EXPORT POUR VISUALISATION")
print("=" * 70)
try:
from pathlib import Path
# Utiliser le dernier résultat pour l'export principal
export_data = export_devops_decision(agent4.graph, result6, history=decisions_history)
json_path = Path("03_domains/devops/visualizations/devops_exercise6_data.json")
json_path.parent.mkdir(parents=True, exist_ok=True)
export_to_json_file(export_data, str(json_path))
if json_path.exists():
file_size = json_path.stat().st_size
print(f"\n[OK] Donnees exportees vers {json_path}")
print(f" Taille: {file_size} octets")
print(f" Historique: {len(decisions_history)} decisions")
else:
print(f"\n[ERREUR] Le fichier {json_path} n'a pas ete cree")
except Exception as e:
print(f"\n[ERREUR] Impossible d'exporter les donnees: {e}")
import traceback
traceback.print_exc()
# ============================================================
# RÉSUMÉ DES APPRENTISSAGES
# ============================================================
print("\n" + "=" * 70)
print("RESUME DES APPRENTISSAGES")
print("=" * 70)
print("\nL'agent de bascule regionale :")
print(" [OK] Refuse la bascule sur un seul signal isole (evite bascules prematurees)")
print(" [OK] Exige que la region secondaire soit saine (pivot fort)")
print(" [OK] Gere la synchronisation des donnees (bascule sure vs risquee)")
print(" [OK] Passe en decision PARTIAL en cas d'instabilite globale")
print(" [OK] Accepte la bascule uniquement lorsque les signaux convergent")
print(" [OK] Convergence forte (2+ signaux) + region secondaire saine = bascule acceptee")
print("\n" + "=" * 70)
if __name__ == "__main__":
exercise6_regional_failover_decision()