[A04.P005] DASUTEN: Pipeline refactorizado + Documentación + Informes

Refactorización del pipeline de backups DASUTEN:

1. Flujo simplificado (un solo destino):
   - Backup directo a X:\ (share srv-ns8)
   - Eliminado paso intermedio E:\BK_SQL\sysdasuten\
   - Reducido de 3 ubicaciones a 2 (X: → /var/tmp/)

2. Módulo común DasuExecutor (lib/dasu_executor.rb):
   - Centraliza ejecución PowerShell en dasu-sql4
   - Centraliza verificación de archivos en fenix
   - Elimina código repetido en 6 drones (-52% líneas)

3. Drones refactorizados:
   - dasuten_exportar_srvv-fenix.rb (FULL → X:)
   - dasuten_exportar_diferencial_srvv-fenix.rb (DIF → X:)
   - dasuten_transferir_srvv-fenix-srv-ns8.rb (simplificado)
   - dasuten_restaurar_dasu-sql4.rb (usa DasuExecutor)
   - dasuten_restaurar_diferencial_dasu-sql4.rb (usa DasuExecutor)
   - dasuten_download_drive-dasu-sql4.rb (usa DasuExecutor)
   - dasuten_verificar-integridad_dasu-sql4.rb (usa DasuExecutor)

4. Integración BKPs mantenida:
   - T8-T15: Tareas individuales
   - C7: dasuten_full (pipeline semanal)
   - C8: dasuten_diferencial (pipeline diario)

5. Documentación actualizada:
   - A04.P006_Backups-DASUTEN.md: flujo simplificado + módulo común
   - Lecciones aprendidas agregadas

6. Nuevos archivos:
   - Informes técnicos DASUTEN (docs/informes/2026-04_DASUTEN-migracion/)
   - A01.P011/P012: Documentación de drones y pipeline
   - proc_linux.rb, ops.rb: Utilitarios del ecosistema

7. Scripts legacy (para referencia):
   - orquestador_pipeline.rb, orquestador_pipeline_diferencial.rb
   - dasuten_upload_srv-ns8-drive.rb
This commit is contained in:
Ricardo Monla
2026-04-14 20:06:06 -03:00
parent bc1f42db1f
commit 892019fa22
59 changed files with 5438 additions and 42 deletions
+82 -1
View File
@@ -2,6 +2,12 @@
# adn/tools/cli/nodos/info.rb — Utilidades para extracción de metadatos de fichas de nodos
# ======================================================================================
#
# Fase 2.5: Soporte dual — Tabla canónica (META:BEGIN/META:END) + fallback regex
#
# Prioridad de lectura:
# 1. Tabla canónica entre <!-- META:BEGIN --> y <!-- META:END -->
# 2. Regex heurísticas (legacy, para fichas no migradas)
require_relative '../../core/constants'
@@ -12,6 +18,30 @@ module ADN
return nil unless File.exist?(ruta)
contenido = File.read(ruta, encoding: 'UTF-8')
# ─── Intentar tabla canónica primero ──────────────────────
meta = extraer_meta_canonica(contenido)
if meta
return {
nombre: nodo_nombre,
ip: meta['IP'],
ip_lan: detectar_ip_lan(contenido),
host: meta['Host'],
so: detectar_so_desde_valor(meta['OS']),
vmid: meta['VMID'],
puerto_ssh: extraer_puerto_de_ssh(meta['SSH']),
usuario: extraer_usuario_de_ssh(meta['SSH']),
clave_boveda: meta['Bóveda'],
auth_type: meta['Auth']&.to_sym,
clave_ssh: meta['Clave SSH'],
ssh_opts: meta['SSH Opts'],
ring: meta['Ring'],
estado: meta['Estado'],
_fuente: :canonica
}
end
# ─── Fallback: Regex heurísticas (legacy) ─────────────────
{
nombre: nodo_nombre,
ip: detectar_ip(contenido),
@@ -24,7 +54,10 @@ module ADN
clave_boveda: detectar_clave_boveda(contenido),
auth_type: detectar_auth_type(contenido),
clave_ssh: detectar_clave_ssh(contenido),
ssh_opts: detectar_ssh_opts(contenido)
ssh_opts: detectar_ssh_opts(contenido),
ring: nil,
estado: nil,
_fuente: :regex
}
end
@@ -35,6 +68,53 @@ module ADN
detectar_ip_lan(contenido)
end
# ─── Parser de tabla canónica ──────────────────────────────
def self.extraer_meta_canonica(contenido)
match = contenido.match(/<!-- META:BEGIN -->(.*?)<!-- META:END -->/m)
return nil unless match
meta = {}
match[1].each_line do |linea|
# | **Campo** | `valor` | o | **Campo** | valor |
if linea =~ /\|\s*\*\*(.+?)\*\*\s*\|\s*`?([^`|]+?)`?\s*\|/
campo = $1.strip
valor = $2.strip
meta[campo] = valor unless valor.empty?
end
end
meta.empty? ? nil : meta
end
def self.extraer_usuario_de_ssh(ssh_str)
return nil unless ssh_str
# Formato: user@ip:port
if ssh_str =~ /^([a-zA-Z0-9_\-\.]+)@/
return $1
end
nil
end
def self.extraer_puerto_de_ssh(ssh_str)
return 22 unless ssh_str
# Formato: user@ip:port
if ssh_str =~ /:(\d+)$/
return $1.to_i
end
22
end
def self.detectar_so_desde_valor(os_str)
return :linux unless os_str
return :linux if os_str =~ /linux|ubuntu|debian|centos|rocky|proxmox|xen/i
return :windows if os_str =~ /windows|server|win/i
return :firmware if os_str =~ /firmware|hikvision|dvr|mikrotik|routeros/i
:linux
end
# ─── Regex heurísticas (legacy — para fichas sin META) ─────
def self.detectar_usuario(contenido)
# **SSH**: user@ip:port o DOMAIN\user@ip:port
if contenido =~ /\*\*SSH\*\*:\s*`?([^`\s(]+)/i
@@ -182,3 +262,4 @@ module ADN
end
end
end