Actualizar a 1.1.4 fallaba con "no escribio config\.version tras la actualizacion" aunque el binario nuevo estuviera instalado y corriendo desde la ruta correcta. La causa era el ORDEN dentro de ensure_runtime_layout(): el sello iba al final, detras del re-despliegue de las deps embebidas (7-Zip y ODBC). Al cambiar de version esas deps se re-copian ENTERAS, asi que el sello quedaba por detras de esa copia y del desempaquetado del onefile de ~254 MB con el antivirus escaneando cada archivo. El PANEL se rendia esperandolo y daba por fallida una actualizacion que iba bien. - El sello se escribe lo primero, en cuanto existen las carpetas. Es tambien mas honesto sobre lo que significa —"que binario esta corriendo"—, que es cierto desde que el proceso arranca. El sello de DEPS sigue yendo al final, donde su comentario explica por que: si la copia falla a medias, el proximo arranque reintenta en vez de quedar marcado como al dia. - La version va en la PRIMERA linea del log de arranque. Permite comprobar que binario corre de verdad mirando solo config/logs, sin depender del sello ni del reporte al panel: verificar una actualizacion deja de obligar a creerse lo que diga otro sistema. La prueba nueva observa el estado del sello EN EL MOMENTO en que empieza la copia de deps, no al final, que es la unica forma de fijar el orden. Comprobado que muerde: devolviendo el sello al final falla con `assert None == '1.1.5'`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CloudRestoreAS
Aplicación de Escritorio para Restauración Automática de Bases de Datos SQL Server
CloudRestoreAS es una aplicación Windows de escritorio desarrollada en Python 3.11+ con interfaz gráfica PySide6/Qt que funciona como daemon de usuario para automatizar la restauración de bases de datos SQL Server a partir de respaldos ZIP (incluyendo ZIP multipart).
🎯 Características Principales
- Vigilancia Automática: Monitorea carpetas por nuevos archivos ZIP con detección de estabilidad
- ZIP Multipart: Soporte completo para archivos .zip.001, .zip.002, etc.
- Extracción con 7-Zip: Integración nativa con 7-Zip para descompresión
- Restauración SQL Server: Conexión directa vía pyodbc con soporte Windows Auth y SQL Auth
- Motor Concurrente: Workers configurables para extracción y restauración
- Mapeo de Nodos: Sistema flexible de mapeo nombre_archivo -> base_datos
- Interfaz Gráfica Completa: Dashboard, gestión de jobs, configuración, logs
- System Tray: Minimización a bandeja del sistema para operación 24/7
- Métricas Persistentes: Base de datos SQLite con auditoría completa
- Logging Rotativo: Logs automáticos con rotación por tamaño
- Tolerancia a Fallos: Reintentos, timeouts, y manejo de errores robusto
- Modo Dry Run: Prueba el pipeline sin ejecutar RESTORE real
📋 Requisitos
Sistema Operativo
- Windows 10/11
- Windows Server 2019/2022 o superior
- Linux x86-64 (servidor o escritorio). En servidor headless (sin pantalla) corre
automáticamente en modo Qt
offscreen. El binario Linux es autocontenido: no requiere instalar Python, 7-Zip, driver ODBC ni librerías Qt en el destino.
Software Requerido
-
Python 3.11+
- Descargar desde: https://www.python.org/downloads/
- Asegurarse de agregar Python al PATH durante la instalación
-
7-Zip
- Descargar desde: https://www.7-zip.org/
- Instalar en ubicación estándar (C:\Program Files\7-Zip)
- La aplicación puede auto-detectar la instalación
-
ODBC Driver 17 for SQL Server (o superior)
- Descargar desde: https://docs.microsoft.com/en-us/sql/connect/odbc/download-odbc-driver-for-sql-server
- Requerido para la conexión con SQL Server
-
SQL Server (destino de restauraciones)
- SQL Server 2016 o superior recomendado
- Permisos necesarios:
CREATE DATABASEALTER DATABASERESTORE DATABASE- Acceso de lectura/escritura en carpetas de datos
🚀 Instalación
Opción 1: Ejecución desde Código Fuente
-
Clonar o descargar el proyecto
cd C:\Aduanasoft\CloudRestoreAs -
Crear entorno virtual (recomendado)
python -m venv venv .\venv\Scripts\Activate.ps1 -
Instalar dependencias
pip install -r requirements.txt -
Ejecutar la aplicación
python runner.py
Opción 2: Ejecutable portable (recomendado para producción)
Todo de una vez (desde WSL) — genera Windows + Linux + los paquetes de release:
./build-all.sh # ambos + dist/release/*.tar.gz y *.zip
./build-all.sh --linux-only # solo Linux (Docker)
./build-all.sh --windows-only # solo Windows (PowerShell + build.ps1)
./build-all.sh --clean # rebuild desde cero
Requiere Docker (para Linux) y, para Windows, powershell.exe accesible desde WSL con Python 3.11+ instalado en Windows.
Solo Windows — generar: .\build.ps1 → dist\CloudRestoreAS.exe
Solo Linux — generar: ./build.sh (o packaging/scripts/docker-build-linux.sh para el entorno controlado) → dist/CloudRestoreAS
📦 Referencia completa de compilación, empaquetado, instalación (
install.sh/systemd), flags del binario y verificación: BUILD.md.
El build de Linux embebe dentro del binario, además de la app: las libs de sistema de Qt (cluster xcb/X11 + EGL), el driver ODBC 18 con sus dependencias (unixODBC, Kerberos/GSSAPI, OpenSSL) y el 7-Zip (
7zz). Por eso el destino no necesitaapt installde nada. (El build se hace en un entorno con esas libs; verpackaging/scripts/download-bundled-deps.shydocker-build-linux.sh.)
Desplegar en cada equipo (sin Python, sin instalador, sin dependencias de sistema):
- Copiar solo el ejecutable a una carpeta.
- Ejecutarlo (doble clic o
./CloudRestoreAS). - Se crean automáticamente:
config/,Entrada/,Procesados/,Fallados/,Temp/. - Editar
config/.env(URL, token e instancia del panel). - Reiniciar la aplicación.
Despliegue en servidor Linux (headless / SQL Server sobre Linux):
sudo ./install.sh --service # servicio systemd 24/7 (offscreen, motor auto-inicio)
# o manual:
QT_QPA_PLATFORM=offscreen ./CloudRestoreAS --start-engine --headless
install.sh no instala ni descarga nada del sistema: solo coloca el binario, hace
el bootstrap de config/ y registra el arranque (systemd headless o autostart de
escritorio con --desktop). El data_folder del destino viene del PANEL; con SQL
Server sobre Linux serán rutas POSIX (p. ej. /var/opt/mssql/data) y el RESTORE
las adapta automáticamente.
Ver packaging/LEEME.txt para instrucciones resumidas.
⚙️ Configuración Inicial
1. Primera Ejecución
Al ejecutar la aplicación por primera vez:
-
Ve al tab Configuración
-
Configura las siguientes carpetas:
- Carpeta de Entrada: Donde se monitoreará por nuevos archivos ZIP
- Carpeta Procesados: Donde se moverán los ZIP exitosos
- Carpeta Fallados: Donde se moverán los ZIP que fallen
- Carpeta Extracción: Temporal para extraer archivos (se limpia automáticamente)
- Carpeta Data SQL: Donde SQL Server almacena los archivos .mdf/.ldf
-
Configura 7-Zip:
- Haz clic en "🔍 Detectar" para auto-detectar
- O selecciona manualmente
7z.exe
-
Configura SQL Server:
- Nombre del servidor (ej:
localhost,.\SQLEXPRESS, o IP) - Tipo de autenticación:
- Windows Auth: Recomendado (usa credenciales de Windows)
- SQL Auth: Requiere usuario y contraseña SQL Server
- Prueba la conexión con "🔌 Probar Conexión"
- Nombre del servidor (ej:
-
Guarda la configuración (💾 Guardar Configuración)
2. Configurar Nodos
Los nodos son el mapeo entre nombre de archivo ZIP y base de datos destino.
- Ve al tab Nodos
- Haz clic en ➕ Nuevo Nodo
- Configura:
- Nombre del Nodo: Nombre exacto del archivo ZIP CON EXTENSIÓN (ej:
BACKUP_SISTEMA.ZIP)- Se compara en MAYÚSCULAS y case-insensitive
- Base de Datos: Nombre de la base de datos destino en SQL Server (ej:
Sistema_DB) - Activo: Marca si el nodo está activo
- Notas: Información opcional
- Nombre del Nodo: Nombre exacto del archivo ZIP CON EXTENSIÓN (ej:
Ejemplo de configuración de nodo:
Nombre del Nodo: BACKUP_VENTAS.ZIP
Base de Datos: Ventas_Prod
Activo: ✓
Notas: Base de datos de ventas - restauración diaria
3. Configuración Avanzada
Concurrencia:
- Workers de Extracción: Número de extracciones simultáneas (default: 1)
- Workers de Restore: Número de restauraciones simultáneas (default: 1)
- ⚠️ Recomendado mantener en 1 para no saturar SQL Server
Estabilidad de Archivos:
- Verificar Estabilidad: Activa/desactiva verificación antes de procesar
- Intervalo de Verificación: Tiempo entre checks (default: 5s)
- Duración Estable: Tiempo que el archivo debe estar sin cambios (default: 10s)
- Usar Marcador .ready: Si se activa, requiere archivo
.readyjunto al ZIP
Timeouts:
- Extracción: Timeout máximo para 7-Zip (default: 30 min)
- Restauración: Timeout máximo para RESTORE (default: 60 min)
Características:
- Modo Dry Run: Simula todo sin ejecutar RESTORE real (para pruebas)
- Escaneo Automático: Auto-escanea la carpeta de entrada
- Intervalo de Escaneo: Frecuencia de escaneo (default: 30s)
🎮 Uso
Iniciar el Motor
- Menú Motor → ▶️ Iniciar
- O presiona el botón de inicio en el Dashboard
- La aplicación comenzará a monitorear la carpeta de entrada
Procesamiento Automático
- Copia un archivo ZIP a la Carpeta de Entrada
- La aplicación detectará el archivo cuando esté estable
- Procesamiento automático:
- ✅ Verificar estabilidad del archivo
- ✅ Identificar nodo y base de datos destino
- ✅ Extraer .bak del ZIP (soporta multipart)
- ✅ Obtener estructura lógica del backup (FILELISTONLY)
- ✅ Restaurar base de datos con REPLACE
- ✅ Limpiar archivos temporales
- ✅ Mover ZIP a carpeta Procesados (con subcarpeta por fecha)
Procesamiento Manual
- Menú Motor → 🔍 Escanear Ahora
- Fuerza un escaneo inmediato de la carpeta de entrada
Monitoreo
Dashboard:
- Contadores en tiempo real (Total, En Cola, Ejecutando, Completados, Fallados)
- Tiempos promedio de ejecución
- Estado del motor (Corriendo/Pausado/Detenido)
- Últimos 10 jobs
Jobs:
- Lista completa de todos los jobs procesados
- Filtros por estado, nombre, fecha
- Vista detallada de cada job:
- Información general
- Pasos ejecutados con tiempos
- Errores y mensajes
Logs:
- Visualización de eventos del sistema
- Filtros por nivel (DEBUG, INFO, WARNING, ERROR, CRITICAL)
- Acceso rápido a carpeta de logs en disco
Pausar/Continuar
- Menú Motor → ⏸️ Pausar: Detiene el escaneo pero permite terminar jobs en curso
- Menú Motor → ▶️ Continuar: Reanuda el monitoreo
Minimizar a Tray
- Cerrar la ventana la minimiza a la bandeja del sistema
- Doble clic en el icono del tray para mostrar/ocultar
- Clic derecho en el icono para acceder al menú:
- Mostrar/Ocultar
- Pausar/Continuar
- Salir
📊 Archivos Multipart
La aplicación soporta automáticamente archivos ZIP multipart:
BACKUP_SISTEMA.ZIP.001
BACKUP_SISTEMA.ZIP.002
BACKUP_SISTEMA.ZIP.003
Comportamiento:
- Solo coloca el archivo
.001en la carpeta de entrada - Los demás archivos (
.002,.003, etc.) deben estar en la misma carpeta - 7-Zip detectará automáticamente todas las partes
- Todos los archivos se moverán juntos a Procesados/Fallados
🔐 Seguridad
Contraseñas SQL
Las contraseñas de SQL Server se cifran usando DPAPI (Data Protection API) de Windows:
- El cifrado está vinculado al usuario y máquina actuales
- Las contraseñas no son portables entre usuarios/máquinas
- Si cambias de usuario, debes reconfigurar las credenciales
Permisos Requeridos
En SQL Server:
-- Crear login (si usa SQL Auth)
CREATE LOGIN [CloudRestoreUser] WITH PASSWORD = 'P@ssw0rd';
-- Otorgar permisos
GRANT CREATE DATABASE TO [CloudRestoreUser];
ALTER SERVER ROLE [dbcreator] ADD MEMBER [CloudRestoreUser];
En Windows:
- Permiso de lectura/escritura en carpetas configuradas
- Permiso de ejecución de 7-Zip
🗂️ Estructura de Base de Datos
La aplicación usa SQLite local (data/app.db) con las siguientes tablas:
jobs
Registro de todos los jobs procesados.
job_steps
Pasos individuales de cada job con tiempos y códigos de salida.
nodes
Mapeos de nodo a base de datos.
events
Log de eventos del sistema.
config
Configuración persistente de la aplicación.
🐛 Solución de Problemas
El motor no inicia
Síntomas: Al hacer clic en Iniciar, el motor se detiene inmediatamente.
Solución:
- Verifica que todas las carpetas estén configuradas y existan
- Verifica que 7-Zip esté instalado y la ruta sea correcta
- Revisa los logs para errores específicos
No se detectan archivos ZIP
Síntomas: Copias un ZIP a la carpeta de entrada pero no se procesa.
Solución:
- Asegúrate de que el motor esté corriendo (no pausado)
- Verifica que el archivo sea
.zipo.zip.001 - Espera el tiempo de estabilidad configurado (default 10s)
- Prueba con Escanear Ahora
- Revisa si hay errores de permisos en la carpeta
Error "NODE_NOT_MAPPED"
Síntomas: El job falla con "No existe mapeo activo para nodo..."
Solución:
- Ve al tab Nodos
- Verifica que existe un nodo con el nombre EXACTO del archivo (con extensión)
- Ejemplo: Si el archivo es
backup.zip, el nodo debe serBACKUP.ZIP - Verifica que el nodo esté marcado como Activo
Error de conexión SQL Server
Síntomas: "Error conectando a SQL Server..."
Solución:
- Verifica que SQL Server esté corriendo
- Prueba la conexión en el tab Configuración (🔌 Probar Conexión)
- Si usas SQL Auth, verifica usuario y contraseña
- Si usas Windows Auth, verifica que el usuario de Windows tenga permisos
- Verifica que ODBC Driver 17 esté instalado:
Get-OdbcDriver | Where-Object {$_.Name -like "*SQL Server*"}
Extracción falla con código de salida 2
Síntomas: El step "extract" falla con exit_code=2
Solución:
- Verifica que el archivo ZIP no esté corrupto
- Para multipart, asegúrate de que TODAS las partes estén presentes
- Verifica que haya espacio suficiente en disco para la extracción
- Revisa los logs de 7-Zip en el step para más detalles
RESTORE falla
Síntomas: El step "restore" falla
Solución:
- Verifica que el usuario tenga permisos
CREATE DATABASEyALTER DATABASE - Verifica que la carpeta Data SQL exista y tenga permisos de escritura
- Si la base de datos ya existe, el RESTORE la sobrescribirá (REPLACE)
- Revisa el error específico en el detalle del job
- Activa Modo Dry Run para ver el SQL generado sin ejecutarlo
📁 Estructura del Proyecto
CloudRestoreAs/
├── app/
│ ├── db/ # Capa de acceso a datos
│ │ ├── database.py # Gestor de SQLite
│ │ ├── job_repository.py
│ │ ├── node_repository.py
│ │ └── ...
│ ├── engine/ # Motor de procesamiento
│ │ ├── engine.py # Motor principal
│ │ ├── file_watcher.py # Vigilancia de archivos
│ │ └── restore_worker.py
│ ├── extract/ # Extracción con 7-Zip
│ │ └── seven_zip.py
│ ├── sql/ # Operaciones SQL Server
│ │ └── sql_manager.py
│ ├── ui/ # Interfaz gráfica
│ │ ├── main_window.py
│ │ ├── dashboard_tab.py
│ │ ├── jobs_tab.py
│ │ ├── nodes_tab.py
│ │ ├── config_tab.py
│ │ └── logs_tab.py
│ ├── utils/ # Utilidades
│ │ ├── logger.py
│ │ └── crypto.py
│ └── constants.py
├── data/ # Base de datos SQLite
│ └── app.db
├── logs/ # Archivos de log
│ └── app.log
├── runner.py # Punto de entrada
├── requirements.txt # Dependencias
├── build.ps1 # Script de build
└── README.md # Este archivo
🔧 Desarrollo
Ejecutar en Modo Debug
python runner.py
Los logs se escriben en:
- Consola (stdout)
- Archivo
logs/app.log(con rotación automática)
Ejecutar Tests
(Opcional: agregar tests con pytest)
pip install pytest
pytest tests/
📝 Notas Importantes
-
Backups Antes de Restaurar: Aunque la aplicación usa
REPLACE, asegúrate de tener backups de las bases de datos existentes. -
Carpeta Data SQL: La carpeta configurada debe ser accesible por SQL Server. Generalmente es:
- SQL Server 2019:
C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\DATA - SQL Server 2022:
C:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\DATA
- SQL Server 2019:
-
Nombres de Nodos: Los nombres de nodos son case-insensitive pero deben incluir la extensión completa.
-
Operación 24/7: La aplicación está diseñada para correr continuamente. Minimízala a tray y déjala corriendo.
-
Logs Rotativos: Los logs se rotan automáticamente cada 10MB. Se mantienen 10 archivos de respaldo.
❓ FAQ
P: ¿Puedo procesar múltiples archivos simultáneamente?
R: Sí, configura más workers en Configuración → Concurrencia. Sin embargo, recomendamos mantener restore_workers=1 para no saturar SQL Server.
P: ¿Qué pasa si la aplicación se cierra mientras procesa un job?
R: Al reiniciar, los jobs en estado "extracting/restoring" se marcan como "failed_restart". Puedes configurar políticas de reintento (actualmente el código base lo soporta pero no está en la UI).
P: ¿Puedo usar esto para SQL Server en otra máquina?
R: Sí, especifica el nombre o IP del servidor remoto en Configuración → SQL Server. Asegúrate de que:
- El puerto SQL Server esté abierto (default 1433)
- Las credenciales tengan permisos remotos
- La carpeta Data SQL sea accesible remotamente (o usa UNC paths)
P: ¿Soporta bases de datos con múltiples archivos de datos?
R: Sí, la aplicación usa RESTORE FILELISTONLY para detectar todos los archivos lógicos (MDF, LDF, y archivos adicionales). Solo mantiene el archivo principal de datos (.mdf) y de log (.ldf).
P: ¿Puedo ejecutar esto como Windows Service?
R: Sí, con install.ps1 -Service: registra una tarea programada ONSTART que corre como SYSTEM, sin sesión iniciada y sin UI. No se usa NSSM ni ningún envoltorio descargado — el servidor destino no instala ni baja nada, y una tarea programada ya viene en el SO. Requiere PowerShell como Administrador. Ver BUILD.md §6.
📄 Licencia
© 2026 Aduanasoft. Todos los derechos reservados.
🆘 Soporte
Para soporte o reportar problemas:
- Revisa primero la sección Solución de Problemas
- Revisa los logs en el tab Logs o en la carpeta
logs/ - Contacta al equipo de desarrollo
CloudRestoreAS v1.0.0 - Restauración Automática de Bases de Datos SQL Server