# Plan: Backups y Refresco de Base de Datos DASUTEN > **Ámbito:** A04 — dtic-DASUTEN **Código:** A04.P006 **Fecha:** 14 de abril de 2026 **Autor:** Sistema ADN **Versión:** 1.0 **Estado:** 🚧 EN EJECUCIÓN (Pipeline diferencial implementado, pendiente integración bkps) **Dependencia:** A04.P005 (DASUTEN sin DC), A03.P002 (Automatización Backups) ## 📊 Progreso | Fase | Estado | Avance | |------|--------|--------| | **Fase 1: Backup de VMs** | ✅ Completado | 100% | | **Fase 2: Pipeline Google Drive** | ✅ Completado | 100% | | **Fase 3: Pipeline Diferencial** | ✅ Completado | 100% | | **Fase 4: Integración BKPs** | ✅ Completado | 100% | ## 🎯 Objetivo Establecer un sistema de backups y refrescos de la base de datos DASUTEN que permita: 1. **Resguardar VMs** del ámbito mediante vzdump (Proxmox) 2. **Refrescar la BD** desde el servidor original (`srvv-fenix`) hacia `dasu-sql4` 3. **Automatizar el pipeline** mediante drones atómicos integrados en `bkps.rb` 4. **Soportar modos completo y diferencial** según frecuencia requerida ## 🌐 Arquitectura del Pipeline ### Flujo Completo (Semanal/Mensual) ``` srvv-fenix (SQL Server) ↓ BACKUP DATABASE TO DISK = 'X:\' WITH COMPRESSION X:\sysdasuten_FULL_YYYYMMDD_HHMMSS.bak (~1.3 GB) ↓ Copy local (share → /var/tmp) srv-ns8 (/var/tmp/) ↓ rclone upload Google Drive (drive_bkps-dasu) ↓ HTTP Download (Invoke-WebRequest) dasu-sql4 (F:\BACKUP\) ↓ RESTORE DATABASE WITH REPLACE sysdasuten ONLINE ``` **Duración estimada:** ~35-40 minutos total ### Flujo Diferencial (Diario) ``` srvv-fenix (SQL Server) ↓ BACKUP DATABASE TO DISK = 'X:\' WITH DIFFERENTIAL X:\sysdasuten_DIF_YYYYMMDD_HHMMSS.bak (~0.4-10 MB) ↓ Copy local (share → /var/tmp) srv-ns8 (/var/tmp/) ↓ rclone upload Google Drive (drive_bkps-dasu) ↓ HTTP Download (Invoke-WebRequest) dasu-sql4 (F:\BACKUP\) ↓ RESTORE DATABASE WITH DIFFERENTIAL sysdasuten ONLINE ``` **Duración estimada:** ~5-10 minutos total ### Nota de Arquitectura **Un solo destino:** Los backups se generan directamente en `X:\` (share de srv-ns8), eliminando pasos intermedios innecesarios. - **Antes:** `E:\BK_SQL\sysdasuten\` → `X:\` → `/var/tmp/` (3 ubicaciones) - **Ahora:** `X:\` → `/var/tmp/` (2 ubicaciones, 1 copia) Esto simplifica el flujo y reduce puntos de falla. ## 📋 Tareas Configuradas (bkps.yml) ### Tareas Individuales | ID | Descripción | Tipo | Nodo | |----|-------------|------|------| | `dasuten_export_full` | 📤 Exportar backup COMPLETO DASUTEN | dasuten | srvv-fenix | | `dasuten_export_dif` | 📤 Exportar backup DIFERENCIAL DASUTEN | dasuten | srvv-fenix | | `dasuten_transferir` | 🔄 Transferir SMB (fenix → ns8) | dasuten | srv-ns8 | | `dasuten_upload` | ☁️ Upload a Google Drive | dasuten | srv-ns8 | | `dasuten_download` | 📥 Download desde Google Drive | dasuten | dasu-sql4 | | `dasuten_restaurar_full` | 💾 Restaurar backup COMPLETO | dasuten | dasu-sql4 | | `dasuten_restaurar_dif` | 💾 Restaurar backup DIFERENCIAL | dasuten | dasu-sql4 | | `dasuten_verificar` | ✅ Verificar integridad BD | dasuten | dasu-sql4 | ### Comandos Compuestos | ID | Descripción | Tareas | Frecuencia | |----|-------------|--------|------------| | `dasuten_full` | 🔄 Pipeline COMPLETO DASUTEN | export_full → transferir → upload → download → restaurar_full → verificar | Semanal | | `dasuten_diferencial` | 🔄 Pipeline DIFERENCIAL DASUTEN | export_dif → transferir → upload → download → restaurar_dif → verificar | Diario (lun-vie) | ## 🛸 Drones Atómicos Implementados | Dron | Script | Nodo | Función | Output JSON | |------|--------|------|---------|-------------| | `exportar` | `dasuten_exportar_srvv-fenix.rb` | srvv-fenix | BACKUP DIRECTO A X: COMPRESSION | `backup_ruta_unix`, `backup_tipo` | | `exportar_dif` | `dasuten_exportar_diferencial_srvv-fenix.rb` | srvv-fenix | BACKUP DIRECTO A X: DIFFERENTIAL | `backup_ruta_unix`, `backup_tipo` | | `transferir` | `dasuten_transferir_srvv-fenix-srv-ns8.rb` | srv-ns8 | Copy share → /var/tmp | `backup_local`, `backup_origen` | | `upload` | `dasuten_upload_srv-ns8-drive.rb` | srv-ns8 | rclone copy | `drive_ruta`, `drive_url` | | `download` | `dasuten_download_drive-dasu-sql4.rb` | dasu-sql4 | Invoke-WebRequest | `backup_local`, `duracion` | | `restaurar` | `dasuten_restaurar_dasu-sql4.rb` | dasu-sql4 | RESTORE DATABASE | `estado_integridad` | | `restaurar_dif` | `dasuten_restaurar_diferencial_dasu-sql4.rb` | dasu-sql4 | RESTORE DATABASE DIFFERENTIAL | `estado_integridad` | | `verificar` | `dasuten_verificar-integridad_dasu-sql4.rb` | dasu-sql4 | DBCC CHECKDB | `estado_integridad` | ### Orquestadores | Script | Función | Uso | |--------|---------|-----| | `orquestador_pipeline.rb` | Pipeline completo | `ruby orquestador_pipeline.rb` | | `orquestador_pipeline_diferencial.rb` | Pipeline diferencial | `ruby orquestador_pipeline_diferencial.rb --paso upload` | ## 🔧 Integración con BKPs (IMPLEMENTADO) ### Procesador: `adn/tools/bkps/lib/proc_dasuten.rb` El procesador `Dasuten` fue integrado en `bkps.rb` como un nuevo tipo de tarea: ```ruby 'dasuten' => -> (log) { BKPs::Procesador::Dasuten.new(log) } ``` **Funcionamiento:** 1. Cada tarea DASUTEN se mapea a un script de dron atómico 2. El dron se lanza vía `./adn/tools/run dron lanzar` 3. La bitácora se registra automáticamente con el nodo y ámbito correspondiente 4. El output de cada dron se guarda en `/tmp/dron_*_output.json` para el siguiente paso ### Comandos disponibles (vía bkps.rb) ```bash # Pipeline completo (semanal - ~35-40 min) ./adn/tools/run bkps run dasuten_full # Pipeline diferencial (diario - ~5-10 min) ./adn/tools/run bkps run dasuten_diferencial # Tareas individuales ./adn/tools/run bkps run dasuten_export_full # Solo exportar completo ./adn/tools/run bkps run dasuten_export_dif # Solo exportar diferencial ./adn/tools/run bkps run dasuten_transferir # Solo transferir SMB ./adn/tools/run bkps run dasuten_upload # Solo upload Drive ./adn/tools/run bkps run dasuten_download # Solo download Drive ./adn/tools/run bkps run dasuten_restaurar_full # Solo restore completo ./adn/tools/run bkps run dasuten_restaurar_dif # Solo restore diferencial ./adn/tools/run bkps run dasuten_verificar # Solo verificar integridad # Con dry-run (simulación) ./adn/tools/run bkps run dasuten_full --dry-run # Con modo batch (sin interacción, para cron) ./adn/tools/run bkps run dasuten_diferencial --batch ``` ### Frecuencias recomendadas | Comando | Frecuencia | Horario | Duración | |---------|------------|---------|----------| | `dasuten_full` | Semanal (lunes 08:00) | Inicio jornada | ~35-40 min | | `dasuten_diferencial` | Diario (lun-vie 08:00) | Inicio jornada | ~5-10 min | ## 📅 Frecuencia de Backups | Tipo | Frecuencia | Retención | Horario | |------|------------|-----------|---------| | **VMs (vzdump)** | Semanal (domingo 03:00) | 4 semanas | Madrugada | | **BD Completo** | Semanal (lunes 08:00) | 4 semanas | Inicio jornada | | **BD Diferencial** | Diario (lun-vie 08:00) | 5 días | Inicio jornada | ## 📊 Resultados Históricos | Fecha | Tipo | Duración | Tamaño | Estado | |-------|------|----------|--------|--------| | 2026-04-14 15:54 | Completo | 44.8s | 1.33 GB | ✅ | | 2026-04-14 16:03 | Diferencial | 2.44s | 0.39 MB | ✅ | | 2026-04-14 16:35 | Upload Drive | 23.79s | 0.39 MB | ✅ | ## ⚠️ Consideraciones Técnicas ### Google Drive Download - **Virus confirmation page:** Archivos >100MB requieren confirmación. Se maneja extrayendo parámetros `id`, `uuid`, `confirm` del HTML. - **URL confirmada:** `https://drive.usercontent.google.com/download?id=...&confirm=...&uuid=...` ### dasu-sql4 Sleep Mode - La VM entra en suspensión cuando no se usa. - **Solución:** Acceso vía relay SSH desde `srv-dasu` con `sshpass` + ProxyCommand. ### Base64 Encoding - Scripts PowerShell se codifican en base64 para transporte sobre SSH. - Evita problemas de escaping UTF-8 en Windows Core. ### Comunicación entre Drones - Cada dron escribe output en `/tmp/dron_*_output.json` - El siguiente dron lee el JSON del anterior para obtener contexto - Formato: `{"paso": "...", "backup_local": "...", "duracion": N, ...}` ### Módulo Común: `dasu_executor.rb` Para evitar código repetido, los drones que se comunican con `dasu-sql4` o `srvv-fenix` usan el módulo `DasuExecutor`: ```ruby require_relative 'lib/dasu_executor' # Ejecutar PowerShell en dasu-sql4 vía srv-dasu DasuExecutor.execute_ps_on_dasu(ps_script, output_path: 'C:\temp\output.json') # Leer JSON desde dasu-sql4 resultado = DasuExecutor.read_json_from_dasu('C:\temp\output.json') # Verificar archivo en fenix (share X:) file_info = DasuExecutor.get_file_info_on_fenix(client, 'X:\backup.bak') ``` **Funciones disponibles:** | Función | Propósito | |---------|-----------| | `execute_ps_on_dasu(ps_script, output_path:)` | Ejecuta PowerShell en dasu-sql4 vía SSH | | `read_json_from_dasu(output_path)` | Lee y parsea JSON desde dasu-sql4 | | `execute_ps_on_fenix(client, ps_script)` | Ejecuta PowerShell en fenix vía xp_cmdshell | | `file_exists_on_fenix?(client, path)` | Verifica si existe archivo en fenix | | `get_file_info_on_fenix(client, path)` | Obtiene tamaño y existencia de archivo | **Beneficio:** El patrón SSH/PowerShell se define en **un solo lugar**. Si cambia, se actualiza solo el módulo. ## 🔗 Referencias - **Ámbito A03:** [A03_dtic-BKPs.md](../dtic-BKPs/A03_dtic-BKPs.md) - **Ámbito A04:** [A04_dtic-DASUTEN.md](A04_dtic-DASUTEN.md) - **Pipeline Diferencial:** [A04.P005_DASUTEN-sin-DC.md](A04.P005_DASUTEN-sin-DC.md#fase-8b-refresco-final-de-bd) - **Drones:** `adn/tools/cli/drones/` - **Bitácoras:** `./adn/tools/run db evento:listar --ambito dtic-DASUTEN` ## 📝 Lecciones Aprendidas | Fecha | Lección | Impacto | |-------|---------|---------| | 2026-04-14 | SMB password con `$` requiere escape (`\\$`) | Transferencia fallida sin escape | | 2026-04-14 | Upload dron debe leer `backup_local` desde transfer output | Timeout por archivo incorrecto | | 2026-04-14 | Download dron requiere `--file-id` o leer desde upload output | Error por falta de parámetro | | 2026-04-14 | Pipeline diferencial: 0.39 MB vs 1.3 GB completo | 90% más rápido para refrescos diarios | | 2026-04-14 | Un solo destino (X:) vs 3 directorios | Menos puntos de falla, más simple | | 2026-04-14 | Módulo común DasuExecutor: 6 drones, 1 solo patrón | -52% código, mantenibilidad |