[A04.P006] Integración de Backups DASUTEN en bkps.rb

Implementada integración del pipeline de backups DASUTEN dentro del
sistema unificado de bkps.rb siguiendo el principio "Menos es Más".

Cambios realizados:
- Nuevo procesador: adn/tools/bkps/lib/proc_dasuten.rb
  - Mapea tareas a drones atómicos existentes
  - Ejecuta vía dron lanzar con bitácora automática

- bkps.yml: T8-T15 (tareas) + C7-C8 (comandos)
  - dasuten_export_full/dif (exportar)
  - dasuten_transferir/upload/download (transitar)
  - dasuten_restaurar_full/dif (restaurar)
  - dasuten_verificar (integridad)

- Documentación actualizada:
  - A04.P006_Backups-DASUTEN.md (nuevo plan)
  - A04_dtic-DASUTEN.md (plan agregado)
  - A03_dtic-BKPs.md (comandos DASUTEN)
  - IA.md (lección aprendida)

Comandos disponibles:
  ./adn/tools/run bkps run dasuten_full        # Semanal (~35-40 min)
  ./adn/tools/run bkps run dasuten_diferencial # Diario (~5-10 min)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ricardo Monla
2026-04-14 17:34:17 -03:00
co-authored by Claude Opus 4.6
parent fe3dcec7e9
commit 358cee8e9a
7 changed files with 431 additions and 2 deletions
+8 -2
View File
@@ -17,6 +17,8 @@ require 'time'
require_relative 'lib/config'
require_relative 'lib/proc_proxmox'
require_relative 'lib/proc_xen'
require_relative 'lib/proc_linux'
require_relative 'lib/proc_dasuten'
require_relative 'lib/sync_rclone'
require_relative 'lib/menu'
@@ -29,6 +31,8 @@ module ADN
'proxmox' => -> (log) { BKPs::Procesador::Proxmox.new(log) },
'xva' => -> (log) { BKPs::Procesador::Xen.new(log) },
'rclone' => -> (log) { BKPs::Procesador::Rclone.new(log) },
'linux' => -> (log) { BKPs::Procesador::Linux.new(log) },
'dasuten' => -> (log) { BKPs::Procesador::Dasuten.new(log) },
}.freeze
def initialize(args, logger = nil)
@@ -841,8 +845,10 @@ module ADN
end
# Lanzar dron atómico con reintentos
verbo = tipo == 'rclone' ? '☁️ Sync' : 'Comprimir'
nota = "#{verbo} #{arch[:vm]} (#{tamaño_gb}GB)"
verbo = if tipo == 'rclone' then '☁️ Sync'
elsif tipo == 'linux' then '🐧 Actualizar'
else 'Comprimir' end
nota = "#{verbo} #{arch[:vm]}"
cmd_dron = "#{adn_run} dron lanzar" \
" --nota \"#{nota}\"" \
" --timeout #{timeout}" \
+70
View File
@@ -52,6 +52,63 @@ tareas:
eliminar_origen: false
sobrescribir: false
- id: update_linux_nodes
texto: "🐧 Actualizar nodos Linux (apt update/upgrade)"
tipo: linux
origen: "todos"
destino: "todos"
eliminar_origen: false
sobrescribir: false
# ─── DASUTEN Pipeline ───────────────────────────────────
- id: dasuten_export_full
texto: "📤 Exportar backup COMPLETO DASUTEN (srvv-fenix)"
tipo: dasuten
modo: full
nodo: srvv-fenix
- id: dasuten_export_dif
texto: "📤 Exportar backup DIFERENCIAL DASUTEN (srvv-fenix)"
tipo: dasuten
modo: differential
nodo: srvv-fenix
- id: dasuten_transferir
texto: "🔄 Transferir SMB (fenix → ns8)"
tipo: dasuten
paso: transferir
nodo: srv-ns8
- id: dasuten_upload
texto: "☁️ Upload a Google Drive (ns8)"
tipo: dasuten
paso: upload
nodo: srv-ns8
- id: dasuten_download
texto: "📥 Download desde Google Drive (dasu-sql4)"
tipo: dasuten
paso: download
nodo: dasu-sql4
- id: dasuten_restaurar_full
texto: "💾 Restaurar backup COMPLETO (dasu-sql4)"
tipo: dasuten
modo: restore_full
nodo: dasu-sql4
- id: dasuten_restaurar_dif
texto: "💾 Restaurar backup DIFERENCIAL (dasu-sql4)"
tipo: dasuten
modo: restore_dif
nodo: dasu-sql4
- id: dasuten_verificar
texto: "✅ Verificar integridad BD (dasu-sql4)"
tipo: dasuten
paso: verificar
nodo: dasu-sql4
comandos:
- id: descargar_y_procesar_pmox
texto: "📥⚙️ Descargar y Procesar BKPs de PMOXs"
@@ -74,6 +131,19 @@ comandos:
tareas: [proc_syncXen1, proc_syncPmox, sync_BkpsSERVIDORes_nube, sync_BkpAntiguos_nube, sync_BkpUsers_nube]
post_sanear: true
- id: update_linux
texto: "🐧 Actualizar Nodos Linux"
tareas: [update_linux_nodes]
# ─── Comandos DASUTEN ───────────────────────────────────
- id: dasuten_full
texto: "🔄 Pipeline COMPLETO DASUTEN (semanal)"
tareas: [dasuten_export_full, dasuten_transferir, dasuten_upload, dasuten_download, dasuten_restaurar_full, dasuten_verificar]
- id: dasuten_diferencial
texto: "🔄 Pipeline DIFERENCIAL DASUTEN (diario)"
tareas: [dasuten_export_dif, dasuten_transferir, dasuten_upload, dasuten_download, dasuten_restaurar_dif, dasuten_verificar]
# ─── Retención (3 tiers) ───────────────────────────────────
retencion:
dias_default: 6
+94
View File
@@ -0,0 +1,94 @@
# frozen_string_literal: true
# ==========================================================
# adn/tools/bkps/lib/proc_dasuten.rb
# ==========================================================
# Procesador de Backups DASUTEN
# Integra pipeline de backups en bkps.rb
# ==========================================================
module BKPs
module Procesador
class Dasuten
DRONES_DIR = File.join(
File.dirname(File.dirname(File.expand_path(__FILE__))),
'cli', 'drones'
)
SCRIPTS = {
'dasuten_export_full' => 'dasuten_exportar_srvv-fenix.rb',
'dasuten_export_dif' => 'dasuten_exportar_diferencial_srvv-fenix.rb',
'dasuten_transferir' => 'dasuten_transferir_srvv-fenix-srv-ns8.rb',
'dasuten_upload' => 'dasuten_upload_srv-ns8-drive.rb',
'dasuten_download' => 'dasuten_download_drive-dasu-sql4.rb',
'dasuten_restaurar_full' => 'dasuten_restaurar_dasu-sql4.rb',
'dasuten_restaurar_dif' => 'dasuten_restaurar_diferencial_dasu-sql4.rb',
'dasuten_verificar' => 'dasuten_verificar-integridad_dasu-sql4.rb',
}.freeze
def initialize(logger)
@logger = logger
@dron_runner = File.join(
File.dirname(File.dirname(File.dirname(File.dirname(DRONES_DIR)))),
'tools', 'run'
)
end
def ejecutar(tarea)
script_name = SCRIPTS[tarea[:id]]
unless script_name
@logger.error("Tarea DASUTEN desconocida: #{tarea[:id]}")
return false
end
script_path = File.join(DRONES_DIR, script_name)
unless File.exist?(script_path)
@logger.error("Script no encontrado: #{script_path}")
return false
end
nodo = tarea[:nodo] || detectar_nodo(tarea[:id])
nota = tarea[:texto] || "DASUTEN: #{tarea[:id]}"
# Lanzar dron con bitácora automática
cmd = "#{@dron_runner} dron lanzar --nota #{Shellwords.escape(nota)} --nodo #{Shellwords.escape(nodo)} -- ruby #{script_path}"
@logger.info("Ejecutando dron: #{nota}")
@logger.debug("Comando: #{cmd}")
exito = system(cmd)
codigo = $?.exitstatus
if exito
@logger.info("✅ Dron completado (código: #{codigo})")
true
else
@logger.error("❌ Dron fallido (código: #{codigo})")
false
end
end
# Para modo atómico (no aplica en DASUTEN - todos son pipelines)
def ejecutar_uno(tarea, archivo)
@logger.warn("Modo atómico no soportado para DASUTEN")
ejecutar(tarea)
end
# Listar archivos pendientes (no aplica - pipeline fijo)
def listar(tarea)
[]
end
private
def detectar_nodo(tarea_id)
case tarea_id
when /export/ then 'srvv-fenix'
when /transferir/, /upload/ then 'srv-ns8'
when /download/, /restaurar/, /verificar/ then 'dasu-sql4'
else 'srv-dasu'
end
end
end
end
end