Hay entornos donde no se usa root en absoluto, así que ni `sudo -n` ni una cuenta root son opciones. Este modo actualiza una instalación existente dejando su unit de systemd intacto, que es lo único que una actualización necesita de verdad: reemplazar el binario y reiniciar el proceso. Se apoya en dos hechos, uno de ellos contrario a lo que decía el propio repo: - `install` NO sufre ETXTBSY. A diferencia de `cp` —que abre con O_TRUNC—, desvincula el destino antes de crearlo, y por eso `make install` funciona sobre binarios en ejecución. Comprobado: `cp` sobre un ELF corriendo da "Text file busy" y `install` no. La consecuencia es la que importa: reemplazar el binario exige escritura en el DIRECTORIO, no en el archivo. El comentario de install.sh, BUILD.md y el CHANGELOG afirmaban lo contrario y mandaban al operador a diagnosticar un archivo en uso cuando lo que tenía era un EACCES. - El unit corre como el usuario que instaló (cadena SUDO_USER) y trae Restart=always, así que esa cuenta puede señalizar el proceso y systemd lo relevanta con el binario nuevo. No hace falta systemctl ni tocar /etc. Robustez, que es donde estaba el trabajo real: - **Reversible.** Respalda el binario antes de reemplazarlo y, si el nuevo no arranca, lo restaura y confirma que el proceso volvió. Sin esto, una actualización fallida deja el servidor sin agente. Si tampoco puede revertir, conserva el respaldo y lo dice en vez de fingir éxito. - **No interrumpe restauraciones.** El agente no atiende SIGTERM: matarlo a media restauración deja ese respaldo vetado para siempre (has_blocking_job_by_hash) y puede dejar la base en SINGLE_USER. Se comprueba Temp/ dos veces —antes de copiar y otra vez justo antes de señalizar, para cerrar la ventana— y sale con 75 (EX_TEMPFAIL), que el panel traduce a "reintenta luego" y no a un fallo. - **Diagnostica por qué no volvió**: distingue un unit sin Restart=always de un StartLimitBurst agotado, con el comando de recuperación. - Omite el bootstrap de 20 s: es redundante en una actualización (ensure_runtime_layout corre en cada arranque) y una segunda instancia junto a la viva purgaría el Temp de la que está trabajando. Un bug que solo aparecía fuera del camino feliz: con `set -euo pipefail`, un `$(pgrep ... | head -1)` sin resultados hace fallar la sustitución y `set -e` mataba el script en silencio — justo en el caso "el proceso no volvió", que es el que había que manejar. Por eso el rollback no se ejecutaba nunca.
166 lines
7.0 KiB
Markdown
166 lines
7.0 KiB
Markdown
# Changelog
|
|
|
|
## [1.1.0] - 2026-07-29
|
|
|
|
### Distribución e instalación automatizada vía Gitea + PANEL
|
|
|
|
#### Publicación de versiones
|
|
- Artefactos con versión en el nombre: `CloudRestoreAS-<version>-{linux,win}-<arch>.{tar.gz,zip}`,
|
|
más `SHA256SUMS` y `release.json` (manifiesto con sha256, tamaño y deps embebidas).
|
|
- `packaging/scripts/publish-release.sh`: publica en los paquetes genéricos de Gitea
|
|
(`ADUANASOFT/generic/cloudrestoreas/<version>`) y **verifica el sha256 contra la propia
|
|
API de Gitea** antes de dar la publicación por buena. Soporta `--dry-run`, `--force` y
|
|
`--notify-panel`.
|
|
- `build-all.sh --publish` encadena build → empaquetado → publicación. Se niega a publicar
|
|
si falta una plataforma: los paquetes genéricos son inmutables y corregirlo quemaría el
|
|
número de versión.
|
|
|
|
#### Contrato con el PANEL
|
|
- `POST /api/restore/instance-config` ahora reporta también `platform` y `arch`, para que
|
|
el PANEL sepa qué artefacto le corresponde a cada servidor.
|
|
- `processed_folder` ya se envía en ese mismo reporte (antes se calculaba, no se mandaba).
|
|
|
|
#### Instaladores
|
|
- **Nuevo `install.ps1`**: instalador de despliegue Windows, autocontenido. Registra una
|
|
tarea programada ONSTART como SYSTEM para el 24/7 headless — sin NSSM ni descargas en el
|
|
servidor destino. Detiene la instancia en ejecución antes de reemplazar el `.exe`.
|
|
- El antiguo `install.ps1` (preparación del entorno de desarrollo: Python, venv, pip) se
|
|
movió a `scripts/dev-setup.ps1`. **Se estaba empaquetando por error** en el zip del
|
|
ejecutable autocontenido, que no necesita nada de eso.
|
|
- `install.sh` e `install.ps1` aceptan `--panel-env-file` / `-PanelEnvFile`: fusionan las
|
|
claves `CLOUDRESTORE_PANEL_*` en `config/.env` (replace-or-append, idempotente, con lista
|
|
blanca) y borran el archivo. El token viaja por archivo 0600, nunca por argumentos, para
|
|
que no quede visible en `ps` ni en el historial del destino.
|
|
- `install.sh` detiene el servicio antes de reemplazar el binario y lo vuelve a levantar si
|
|
estaba activo. (La razón que se dio aquí —que un ELF en ejecución da `ETXTBSY`— era incorrecta:
|
|
eso le pasa a `cp`, no a `install`, que desvincula el destino antes de crearlo. Ver BUILD.md.)
|
|
|
|
#### Versionado
|
|
- `app/__init__.py` es la fuente única de la versión; el diálogo *Acerca de* ya no la trae
|
|
hardcodeada.
|
|
- Flag `--version` en el binario, y sello `config/.version` que escribe el bootstrap (el
|
|
instalador remoto lo lee por SFTP, porque el `.exe` se compila con `console=False`).
|
|
- El `.exe` ya lleva metadatos de versión de Windows (`VSVersionInfo`).
|
|
|
|
#### Correcciones
|
|
- `config/7zip` y `config/odbc` se re-despliegan cuando el build trae otras versiones
|
|
embebidas, comparando un sello con el sha256 de `bundled-versions.json`. Antes solo se
|
|
copiaban si la carpeta estaba vacía, así que una actualización con driver ODBC nuevo
|
|
conservaba el viejo indefinidamente.
|
|
|
|
## [1.0.0] - 2026-01-25
|
|
|
|
### Lanzamiento Inicial
|
|
|
|
#### Características Principales
|
|
- ✅ Interfaz gráfica completa con PySide6/Qt
|
|
- ✅ Motor de procesamiento concurrente con workers configurables
|
|
- ✅ Vigilancia automática de carpeta de entrada
|
|
- ✅ Soporte para archivos ZIP multipart (.zip.001, .zip.002, etc.)
|
|
- ✅ Extracción automática con 7-Zip
|
|
- ✅ Restauración automática de bases de datos SQL Server
|
|
- ✅ Sistema de mapeo de nodos (archivo → base de datos)
|
|
- ✅ Minimización a bandeja del sistema (system tray)
|
|
- ✅ Base de datos SQLite para métricas y auditoría
|
|
- ✅ Logging rotativo con múltiples niveles
|
|
- ✅ Cifrado de contraseñas con DPAPI
|
|
- ✅ Soporte Windows Auth y SQL Auth
|
|
- ✅ Modo Dry Run para pruebas
|
|
- ✅ Detección de estabilidad de archivos
|
|
- ✅ Soporte para marcador .ready
|
|
- ✅ Timeouts configurables
|
|
- ✅ Tolerancia a fallos y manejo de errores
|
|
|
|
#### Tabs de la Interfaz
|
|
- Dashboard: Estadísticas en tiempo real
|
|
- Jobs: Gestión y visualización de jobs con detalles
|
|
- Nodos: CRUD de mapeos nodo → base de datos
|
|
- Configuración: Configuración completa de la aplicación
|
|
- Logs: Visualización de eventos y logs
|
|
|
|
#### Base de Datos
|
|
- Tabla `jobs`: Registro completo de jobs
|
|
- Tabla `job_steps`: Pasos detallados de cada job
|
|
- Tabla `nodes`: Mapeos de nodos
|
|
- Tabla `events`: Log de eventos
|
|
- Tabla `config`: Configuración persistente
|
|
|
|
#### Documentación
|
|
- README.md: Documentación completa
|
|
- QUICKSTART.md: Guía rápida de inicio
|
|
- ADVANCED.md: Configuración avanzada
|
|
- SCRIPTS.md: Ejemplos de scripts de automatización
|
|
|
|
#### Scripts Incluidos
|
|
- `runner.py`: Punto de entrada principal
|
|
- `install.ps1`: Script de instalación automática
|
|
- `build.ps1`: Script para generar ejecutable con PyInstaller
|
|
- `test_installation.py`: Script de verificación de instalación
|
|
|
|
#### Requisitos del Sistema
|
|
- Windows 10/11 o Windows Server 2019/2022+
|
|
- Python 3.11+
|
|
- 7-Zip
|
|
- ODBC Driver 17 for SQL Server
|
|
- SQL Server 2016+ (destino de restauraciones)
|
|
|
|
#### Dependencias
|
|
- PySide6 >= 6.6.0
|
|
- pyodbc >= 5.0.0
|
|
- pywin32 >= 306
|
|
|
|
### Características Futuras Planificadas
|
|
|
|
#### v1.1.0 (Próximo Release)
|
|
- [ ] Reintentos automáticos configurables desde UI
|
|
- [ ] Notificaciones por email
|
|
- [ ] Verificación de espacio en disco antes de procesar
|
|
- [ ] Soporte para múltiples instancias SQL Server
|
|
- [ ] Importación/Exportación de nodos desde CSV
|
|
- [ ] Dashboard mejorado con gráficos
|
|
- [ ] Filtros avanzados en tabla de jobs
|
|
|
|
#### v1.2.0 (Futuro)
|
|
- [ ] API REST para integración externa
|
|
- [ ] Webhooks para notificaciones
|
|
- [ ] Programación de restauraciones (scheduling)
|
|
- [ ] Soporte para otros formatos de compresión (RAR, TAR)
|
|
- [ ] Modo cluster (múltiples instancias coordinadas)
|
|
- [ ] Soporte para Azure SQL Database
|
|
- [ ] Backup/Restore de configuración desde UI
|
|
|
|
#### v2.0.0 (Largo Plazo)
|
|
- [ ] Soporte multiplataforma (Linux)
|
|
- [ ] Interfaz web opcional
|
|
- [ ] Modo servicio de Windows
|
|
- [ ] Soporte para PostgreSQL y MySQL
|
|
- [ ] Machine learning para predicción de tiempos
|
|
- [ ] Dashboard en tiempo real con WebSockets
|
|
|
|
### Problemas Conocidos
|
|
|
|
#### Limitaciones Actuales
|
|
- Solo soporta una configuración SQL Server (no múltiples instancias)
|
|
- Reintentos automáticos no expuestos en UI (requiere edición manual)
|
|
- No hay verificación automática de espacio en disco
|
|
- System tray no muestra notificaciones toast
|
|
- No hay soporte nativo para archivos RAR
|
|
|
|
#### Workarounds Documentados
|
|
- Múltiples instancias SQL: Ver ADVANCED.md sección 7
|
|
- Notificaciones: Ver SCRIPTS.md para monitoreo externo
|
|
- Limpieza automática: Ver SCRIPTS.md para scripts de limpieza
|
|
|
|
### Notas de Seguridad
|
|
- Las contraseñas se cifran con DPAPI (vinculadas a usuario/máquina)
|
|
- Los logs pueden contener información sensible (rutas, nombres de DB)
|
|
- Se recomienda ejecutar con cuenta de servicio dedicada
|
|
- Asegurar permisos apropiados en carpetas de trabajo
|
|
|
|
### Agradecimientos
|
|
Desarrollado por el equipo de Aduanasoft para automatización de restauraciones de bases de datos SQL Server.
|
|
|
|
---
|
|
|
|
**Nota de Versión**: Esta es la versión inicial de CloudRestoreAS. Se agradecen comentarios y sugerencias para futuras versiones.
|