276 lines
10 KiB
Python
276 lines
10 KiB
Python
"""
|
|
AutoBackups - Aplicación Principal
|
|
Sistema automatizado de backup para proyectos Simatic S7
|
|
"""
|
|
|
|
import sys
|
|
import os
|
|
import logging
|
|
from pathlib import Path
|
|
from datetime import datetime
|
|
|
|
# Agregar el directorio src al path para imports
|
|
current_dir = Path(__file__).parent
|
|
src_dir = current_dir
|
|
sys.path.insert(0, str(src_dir))
|
|
|
|
# Imports de módulos propios
|
|
from models.config_model import Config
|
|
from models.project_model import ProjectManager
|
|
from utils.file_utils import DiskSpaceChecker
|
|
from services.basic_backup_service import BasicBackupService
|
|
|
|
|
|
class AutoBackupsApp:
|
|
"""Aplicación principal de AutoBackups"""
|
|
|
|
def __init__(self):
|
|
self.config = None
|
|
self.project_manager = None
|
|
self.discovery_service = None
|
|
self.disk_checker = None
|
|
self.logger = None
|
|
|
|
# Inicializar aplicación
|
|
self._setup_logging()
|
|
self._load_configuration()
|
|
self._initialize_services()
|
|
|
|
def _setup_logging(self):
|
|
"""Configurar sistema de logging"""
|
|
try:
|
|
# Crear directorio de logs si no existe
|
|
logs_dir = Path(__file__).parent / ".logs"
|
|
logs_dir.mkdir(exist_ok=True)
|
|
|
|
# Nombre del archivo de log con timestamp
|
|
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
|
|
log_filename = logs_dir / f"autobackups_{timestamp}.log"
|
|
|
|
# Configurar logging
|
|
logging.basicConfig(
|
|
level=logging.INFO,
|
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
|
handlers=[
|
|
logging.FileHandler(log_filename, encoding='utf-8'),
|
|
logging.StreamHandler(sys.stdout)
|
|
]
|
|
)
|
|
|
|
self.logger = logging.getLogger(__name__)
|
|
self.logger.info(f"AutoBackups iniciado - Log: {log_filename}")
|
|
|
|
except Exception as e:
|
|
print(f"Error configurando logging: {e}")
|
|
sys.exit(1)
|
|
|
|
def _load_configuration(self):
|
|
"""Cargar configuración del sistema"""
|
|
try:
|
|
self.logger.info("Cargando configuración...")
|
|
self.config = Config()
|
|
self.logger.info("Configuración cargada exitosamente")
|
|
|
|
# Mostrar información básica de configuración
|
|
self.logger.info(f"Directorios de observación: {len(self.config.observation_directories)}")
|
|
self.logger.info(f"Destino de backups: {self.config.backup_destination}")
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Error cargando configuración: {e}")
|
|
sys.exit(1)
|
|
|
|
def _initialize_services(self):
|
|
"""Inicializar servicios principales"""
|
|
try:
|
|
self.logger.info("Inicializando servicios...")
|
|
|
|
# Project Manager
|
|
self.project_manager = ProjectManager()
|
|
self.logger.info("Project Manager inicializado")
|
|
|
|
# Disk Space Checker
|
|
self.disk_checker = DiskSpaceChecker()
|
|
self.logger.info("Disk Space Checker inicializado")
|
|
|
|
# Basic Backup Service (Fase 1)
|
|
self.backup_service = BasicBackupService(self.config)
|
|
self.logger.info("Basic Backup Service inicializado")
|
|
|
|
# Project Discovery Service (temporalmente comentado)
|
|
# self.discovery_service = ProjectDiscoveryService(self.config, self.project_manager)
|
|
# self.logger.info("Project Discovery Service inicializado")
|
|
|
|
self.logger.info("Todos los servicios inicializados correctamente")
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Error inicializando servicios: {e}")
|
|
sys.exit(1)
|
|
|
|
def check_system_requirements(self) -> bool:
|
|
"""Verificar requerimientos del sistema"""
|
|
try:
|
|
self.logger.info("Verificando requerimientos del sistema...")
|
|
|
|
# Verificar espacio en disco
|
|
backup_destination = self.config.backup_destination
|
|
min_space_mb = self.config.get_min_free_space_mb()
|
|
|
|
free_space_mb = self.disk_checker.get_free_space_mb(backup_destination)
|
|
|
|
if free_space_mb < min_space_mb:
|
|
self.logger.error(
|
|
f"Espacio insuficiente en destino de backup. "
|
|
f"Disponible: {free_space_mb:.1f}MB, "
|
|
f"Requerido: {min_space_mb}MB"
|
|
)
|
|
return False
|
|
|
|
self.logger.info(f"Espacio en disco OK: {free_space_mb:.1f}MB disponibles")
|
|
|
|
# Verificar Everything API (opcional en Fase 1)
|
|
if hasattr(self, 'backup_service'):
|
|
if self.backup_service.check_system_requirements():
|
|
self.logger.info("Requerimientos del sistema verificados")
|
|
else:
|
|
self.logger.warning("Algunos requerimientos fallaron")
|
|
else:
|
|
self.logger.warning("Backup service no disponible")
|
|
|
|
# Verificar directorios de observación
|
|
missing_dirs = []
|
|
for obs_dir in self.config.observation_directories:
|
|
if not Path(obs_dir["path"]).exists():
|
|
missing_dirs.append(obs_dir["path"])
|
|
|
|
if missing_dirs:
|
|
self.logger.warning(f"Directorios de observación no encontrados: {missing_dirs}")
|
|
|
|
self.logger.info("Verificación de requerimientos completada")
|
|
return True
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Error verificando requerimientos del sistema: {e}")
|
|
return False
|
|
|
|
def discover_projects(self) -> int:
|
|
"""Descubrir proyectos en directorios de observación"""
|
|
try:
|
|
self.logger.info("Iniciando descubrimiento de proyectos...")
|
|
|
|
# Usar el servicio básico de backup
|
|
if hasattr(self, 'backup_service'):
|
|
projects = self.backup_service.discover_projects_basic()
|
|
else:
|
|
projects = []
|
|
|
|
# Agregar proyectos al manager
|
|
for project_info in projects:
|
|
self.project_manager.add_or_update_project(project_info)
|
|
|
|
msg = f"Descubrimiento completado: {len(projects)} proyectos"
|
|
self.logger.info(msg)
|
|
|
|
return len(projects)
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Error en descubrimiento de proyectos: {e}")
|
|
return 0
|
|
|
|
def show_system_status(self):
|
|
"""Mostrar estado actual del sistema"""
|
|
try:
|
|
self.logger.info("=== ESTADO DEL SISTEMA ===")
|
|
|
|
# Información de configuración
|
|
self.logger.info(f"Directorios de observación configurados: {len(self.config.observation_directories)}")
|
|
self.logger.info(f"Destino de backups: {self.config.backup_destination}")
|
|
|
|
# Información de proyectos
|
|
all_projects = self.project_manager.get_all_projects()
|
|
enabled_projects = self.project_manager.get_enabled_projects()
|
|
|
|
self.logger.info(f"Total de proyectos: {len(all_projects)}")
|
|
self.logger.info(f"Proyectos habilitados: {len(enabled_projects)}")
|
|
|
|
# Información de espacio en disco
|
|
backup_dest = self.config.backup_destination
|
|
total_mb, used_mb, free_mb = self.disk_checker.get_disk_usage_info(backup_dest)
|
|
|
|
self.logger.info(f"Espacio en disco (destino backup):")
|
|
self.logger.info(f" Total: {total_mb:.1f}MB")
|
|
self.logger.info(f" Usado: {used_mb:.1f}MB")
|
|
self.logger.info(f" Libre: {free_mb:.1f}MB")
|
|
|
|
# Información de Everything API
|
|
if self.discovery_service.everything_searcher:
|
|
self.logger.info("Everything API: Disponible")
|
|
else:
|
|
self.logger.info("Everything API: No disponible")
|
|
|
|
self.logger.info("=== FIN ESTADO DEL SISTEMA ===")
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Error mostrando estado del sistema: {e}")
|
|
|
|
def run_initial_setup(self):
|
|
"""Ejecutar configuración inicial de la aplicación"""
|
|
try:
|
|
self.logger.info("=== CONFIGURACIÓN INICIAL DE AUTOBACKUPS ===")
|
|
|
|
# Verificar requerimientos del sistema
|
|
if not self.check_system_requirements():
|
|
self.logger.error("Los requerimientos del sistema no se cumplen")
|
|
return False
|
|
|
|
# Descubrir proyectos
|
|
projects_found = self.discover_projects()
|
|
|
|
if projects_found == 0:
|
|
self.logger.warning("No se encontraron proyectos para backup")
|
|
|
|
# Mostrar estado del sistema
|
|
self.show_system_status()
|
|
|
|
self.logger.info("=== CONFIGURACIÓN INICIAL COMPLETADA ===")
|
|
return True
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Error en configuración inicial: {e}")
|
|
return False
|
|
|
|
|
|
def main():
|
|
"""Función principal"""
|
|
try:
|
|
print("AutoBackups - Sistema de Backup Automatizado")
|
|
print("=" * 50)
|
|
|
|
# Crear y configurar aplicación
|
|
app = AutoBackupsApp()
|
|
|
|
# Ejecutar configuración inicial
|
|
if app.run_initial_setup():
|
|
app.logger.info("AutoBackups configurado correctamente")
|
|
|
|
# TODO: En las siguientes fases:
|
|
# - Iniciar scheduler de backups
|
|
# - Iniciar interfaz web Flask
|
|
# - Configurar tareas en background
|
|
|
|
print("\nConfiguración inicial completada.")
|
|
print("Revisa el archivo de log para más detalles.")
|
|
|
|
else:
|
|
print("Error en la configuración inicial. Revisa los logs.")
|
|
sys.exit(1)
|
|
|
|
except KeyboardInterrupt:
|
|
print("\nAplicación interrumpida por el usuario")
|
|
except Exception as e:
|
|
print(f"Error inesperado: {e}")
|
|
sys.exit(1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|