- Frontend v4 accessible sur réseau local (192.168.1.40) - Ports ouverts: 3002 (frontend), 5001 (backend), 5004 (dashboard) - Ollama GPU fonctionnel - Self-healing interactif - Dashboard confiance Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
272 lines
11 KiB
Python
272 lines
11 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Gestionnaire de lancement unifié pour RPA Vision V3
|
|
Unifie l'environnement vers la production systemd avec synchronisation des données
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import json
|
|
import shutil
|
|
import subprocess
|
|
from pathlib import Path
|
|
from datetime import datetime
|
|
from typing import Dict, List, Optional
|
|
|
|
class UnifiedLaunchManager:
|
|
"""Gestionnaire unifié pour le lancement de RPA Vision V3"""
|
|
|
|
def __init__(self):
|
|
self.local_root = Path.cwd()
|
|
self.prod_root = Path("/opt/rpa_vision_v3")
|
|
self.services = [
|
|
"rpa-vision-v3-api.service",
|
|
"rpa-vision-v3-dashboard.service",
|
|
"rpa-vision-v3-worker.service"
|
|
]
|
|
|
|
def print_status(self, message: str, status: str = "INFO"):
|
|
"""Affiche un message avec couleur"""
|
|
colors = {
|
|
"INFO": "\033[0;34m", # Bleu
|
|
"SUCCESS": "\033[0;32m", # Vert
|
|
"WARNING": "\033[1;33m", # Jaune
|
|
"ERROR": "\033[0;31m", # Rouge
|
|
"RESET": "\033[0m" # Reset
|
|
}
|
|
print(f"{colors.get(status, '')}{message}{colors['RESET']}")
|
|
|
|
def check_systemd_services(self) -> Dict[str, bool]:
|
|
"""Vérifie l'état des services systemd"""
|
|
status = {}
|
|
for service in self.services:
|
|
try:
|
|
result = subprocess.run(
|
|
["sudo", "systemctl", "is-active", service],
|
|
capture_output=True, text=True
|
|
)
|
|
status[service] = result.returncode == 0
|
|
except Exception:
|
|
status[service] = False
|
|
return status
|
|
|
|
def stop_systemd_services(self):
|
|
"""Arrête tous les services systemd"""
|
|
self.print_status("🛑 Arrêt des services systemd...", "WARNING")
|
|
for service in self.services:
|
|
try:
|
|
subprocess.run(["sudo", "systemctl", "stop", service], check=True)
|
|
self.print_status(f"✓ Service {service} arrêté", "SUCCESS")
|
|
except subprocess.CalledProcessError:
|
|
self.print_status(f"⚠ Impossible d'arrêter {service}", "WARNING")
|
|
|
|
def start_systemd_services(self):
|
|
"""Démarre tous les services systemd"""
|
|
self.print_status("🚀 Démarrage des services systemd...", "INFO")
|
|
for service in self.services:
|
|
try:
|
|
subprocess.run(["sudo", "systemctl", "start", service], check=True)
|
|
self.print_status(f"✓ Service {service} démarré", "SUCCESS")
|
|
except subprocess.CalledProcessError:
|
|
self.print_status(f"❌ Échec du démarrage de {service}", "ERROR")
|
|
|
|
def sync_data_to_production(self):
|
|
"""Synchronise les données locales vers la production"""
|
|
self.print_status("📂 Synchronisation des données vers la production...", "INFO")
|
|
|
|
local_data = self.local_root / "data"
|
|
prod_data = self.prod_root / "data"
|
|
|
|
if not local_data.exists():
|
|
self.print_status("⚠ Aucune donnée locale à synchroniser", "WARNING")
|
|
return
|
|
|
|
# Créer une sauvegarde des données de production
|
|
if prod_data.exists():
|
|
backup_path = self.prod_root / f"data_backup_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
|
|
self.print_status(f"💾 Sauvegarde des données prod vers {backup_path}", "INFO")
|
|
try:
|
|
subprocess.run(["sudo", "cp", "-r", str(prod_data), str(backup_path)], check=True)
|
|
except subprocess.CalledProcessError:
|
|
self.print_status("❌ Échec de la sauvegarde", "ERROR")
|
|
return
|
|
|
|
# Synchroniser les données
|
|
try:
|
|
# Copier les sessions
|
|
local_sessions = local_data / "training" / "sessions"
|
|
prod_sessions = prod_data / "training" / "sessions"
|
|
|
|
if local_sessions.exists():
|
|
subprocess.run(["sudo", "mkdir", "-p", str(prod_sessions.parent)], check=True)
|
|
subprocess.run(["sudo", "cp", "-r", str(local_sessions), str(prod_sessions.parent)], check=True)
|
|
subprocess.run(["sudo", "chown", "-R", "rpa:rpa", str(prod_data)], check=True)
|
|
self.print_status("✓ Sessions synchronisées", "SUCCESS")
|
|
|
|
# Copier les workflows
|
|
local_workflows = local_data / "workflows"
|
|
prod_workflows = prod_data / "workflows"
|
|
|
|
if local_workflows.exists():
|
|
subprocess.run(["sudo", "cp", "-r", str(local_workflows), str(prod_workflows.parent)], check=True)
|
|
subprocess.run(["sudo", "chown", "-R", "rpa:rpa", str(prod_workflows)], check=True)
|
|
self.print_status("✓ Workflows synchronisés", "SUCCESS")
|
|
|
|
except subprocess.CalledProcessError as e:
|
|
self.print_status(f"❌ Erreur de synchronisation: {e}", "ERROR")
|
|
|
|
def sync_data_from_production(self):
|
|
"""Synchronise les données de production vers local (pour développement)"""
|
|
self.print_status("📂 Synchronisation des données depuis la production...", "INFO")
|
|
|
|
local_data = self.local_root / "data"
|
|
prod_data = self.prod_root / "data"
|
|
|
|
if not prod_data.exists():
|
|
self.print_status("⚠ Aucune donnée de production à synchroniser", "WARNING")
|
|
return
|
|
|
|
try:
|
|
# Créer le répertoire local si nécessaire
|
|
local_data.mkdir(exist_ok=True)
|
|
|
|
# Copier les sessions
|
|
prod_sessions = prod_data / "training" / "sessions"
|
|
local_sessions = local_data / "training" / "sessions"
|
|
|
|
if prod_sessions.exists():
|
|
local_sessions.parent.mkdir(parents=True, exist_ok=True)
|
|
subprocess.run(["sudo", "cp", "-r", str(prod_sessions), str(local_sessions.parent)], check=True)
|
|
subprocess.run(["sudo", "chown", "-R", f"{os.getenv('USER')}:{os.getenv('USER')}", str(local_sessions)], check=True)
|
|
self.print_status("✓ Sessions copiées depuis la production", "SUCCESS")
|
|
|
|
# Copier les workflows
|
|
prod_workflows = prod_data / "workflows"
|
|
local_workflows = local_data / "workflows"
|
|
|
|
if prod_workflows.exists():
|
|
subprocess.run(["sudo", "cp", "-r", str(prod_workflows), str(local_workflows.parent)], check=True)
|
|
subprocess.run(["sudo", "chown", "-R", f"{os.getenv('USER')}:{os.getenv('USER')}", str(local_workflows)], check=True)
|
|
self.print_status("✓ Workflows copiés depuis la production", "SUCCESS")
|
|
|
|
except subprocess.CalledProcessError as e:
|
|
self.print_status(f"❌ Erreur de synchronisation: {e}", "ERROR")
|
|
|
|
def show_service_status(self):
|
|
"""Affiche l'état des services"""
|
|
self.print_status("📊 État des services RPA Vision V3", "INFO")
|
|
print()
|
|
|
|
status = self.check_systemd_services()
|
|
for service, is_active in status.items():
|
|
status_text = "🟢 ACTIF" if is_active else "🔴 ARRÊTÉ"
|
|
self.print_status(f" {service}: {status_text}")
|
|
|
|
print()
|
|
self.print_status("🌐 URLs d'accès:", "INFO")
|
|
self.print_status(" API Server: http://localhost:8000")
|
|
self.print_status(" Dashboard: http://localhost:5001")
|
|
print()
|
|
|
|
def show_data_info(self):
|
|
"""Affiche les informations sur les données"""
|
|
self.print_status("📂 Informations sur les données", "INFO")
|
|
print()
|
|
|
|
# Données locales
|
|
local_sessions = self.local_root / "data" / "training" / "sessions"
|
|
if local_sessions.exists():
|
|
local_count = len(list(local_sessions.iterdir()))
|
|
self.print_status(f" Données locales: {local_count} sessions dans {local_sessions}")
|
|
else:
|
|
self.print_status(" Données locales: Aucune")
|
|
|
|
# Données de production
|
|
prod_sessions = self.prod_root / "data" / "training" / "sessions"
|
|
if prod_sessions.exists():
|
|
try:
|
|
result = subprocess.run(["sudo", "ls", str(prod_sessions)], capture_output=True, text=True)
|
|
prod_count = len(result.stdout.strip().split('\n')) if result.stdout.strip() else 0
|
|
self.print_status(f" Données production: {prod_count} sessions dans {prod_sessions}")
|
|
except:
|
|
self.print_status(" Données production: Erreur d'accès")
|
|
else:
|
|
self.print_status(" Données production: Aucune")
|
|
print()
|
|
|
|
def unified_start(self):
|
|
"""Démarrage unifié en mode production"""
|
|
self.print_status("🎼 RPA Vision V3 - Démarrage Unifié (Production)", "INFO")
|
|
print()
|
|
|
|
# 1. Synchroniser les données vers la production
|
|
self.sync_data_to_production()
|
|
print()
|
|
|
|
# 2. Démarrer les services systemd
|
|
self.start_systemd_services()
|
|
print()
|
|
|
|
# 3. Attendre que les services démarrent
|
|
self.print_status("⏳ Attente du démarrage des services...", "INFO")
|
|
import time
|
|
time.sleep(5)
|
|
|
|
# 4. Afficher le statut final
|
|
self.show_service_status()
|
|
|
|
def unified_stop(self):
|
|
"""Arrêt unifié"""
|
|
self.print_status("🛑 RPA Vision V3 - Arrêt Unifié", "WARNING")
|
|
print()
|
|
|
|
# Arrêter les services systemd
|
|
self.stop_systemd_services()
|
|
print()
|
|
|
|
# Synchroniser les données vers local pour développement
|
|
self.sync_data_from_production()
|
|
print()
|
|
|
|
self.print_status("✓ Arrêt complet terminé", "SUCCESS")
|
|
|
|
def unified_restart(self):
|
|
"""Redémarrage unifié"""
|
|
self.print_status("🔄 RPA Vision V3 - Redémarrage Unifié", "INFO")
|
|
print()
|
|
|
|
self.unified_stop()
|
|
print()
|
|
self.unified_start()
|
|
|
|
|
|
def main():
|
|
"""Point d'entrée principal"""
|
|
manager = UnifiedLaunchManager()
|
|
|
|
if len(sys.argv) < 2:
|
|
print("Usage: python unified_launch_manager.py [start|stop|restart|status|sync-to-prod|sync-from-prod]")
|
|
sys.exit(1)
|
|
|
|
command = sys.argv[1]
|
|
|
|
if command == "start":
|
|
manager.unified_start()
|
|
elif command == "stop":
|
|
manager.unified_stop()
|
|
elif command == "restart":
|
|
manager.unified_restart()
|
|
elif command == "status":
|
|
manager.show_service_status()
|
|
manager.show_data_info()
|
|
elif command == "sync-to-prod":
|
|
manager.sync_data_to_production()
|
|
elif command == "sync-from-prod":
|
|
manager.sync_data_from_production()
|
|
else:
|
|
print(f"Commande inconnue: {command}")
|
|
sys.exit(1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main() |