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
138 lines
4.9 KiB
Ruby
Executable File
138 lines
4.9 KiB
Ruby
Executable File
#!/usr/bin/env ruby
|
|
# frozen_string_literal: true
|
|
|
|
# ==========================================================
|
|
# adn/tools/cli/dasuten_orquestador.rb — Orquestador Fase 8b
|
|
# ==========================================================
|
|
# Flujo completo: srvv-fenix → Google Drive → dasu-sql4
|
|
# Uso: ruby adn/tools/cli/dasuten_orquestador.rb [upload|download|restore]
|
|
# ==========================================================
|
|
|
|
require 'optparse'
|
|
require_relative 'dron/dispatcher'
|
|
|
|
PROJECT_ROOT = File.expand_path('../..', __dir__)
|
|
CLI_DIR = File.join(PROJECT_ROOT, 'adn', 'tools', 'cli')
|
|
ADN_RUN = File.join(PROJECT_ROOT, 'adn', 'tools', 'run')
|
|
|
|
opciones = {
|
|
paso: 'all',
|
|
dry_run: false,
|
|
nodo: nil
|
|
}
|
|
|
|
OptionParser.new do |opts|
|
|
opts.banner = "Uso: #{ADN_RUN} dasuten_orquestador [opciones]"
|
|
opts.on("--paso PASO", %w[upload download restore all], "Ejecutar solo este paso (upload|download|restore|all)") { |p| opciones[:paso] = p }
|
|
opts.on("--nodo NOMBRE", "Nodo para bitácora del dron") { |n| opciones[:nodo] = n }
|
|
opts.on("--dry-run", "Simulación sin ejecutar") { opciones[:dry_run] = true }
|
|
end.parse!(ARGV)
|
|
|
|
puts "\n#{'='*60}"
|
|
puts "🛸 ORQUESTADOR DASUTEN — Fase 8b (Refresco BD vía Google Drive)"
|
|
puts '='*60
|
|
puts " Paso seleccionado: #{opciones[:paso]}"
|
|
puts " Dry-run: #{opciones[:dry_run]}"
|
|
puts " Nodo: #{opciones[:nodo] || 'auto-detect'}"
|
|
puts '='*60
|
|
|
|
def lanzar_dron(cmd, nota, nodo: nil)
|
|
puts "\n🛸 Lanzando dron: #{nota}"
|
|
puts " Comando: #{cmd}"
|
|
|
|
args = ["lanzar", "--nota", nota]
|
|
args << "--nodo" << nodo if nodo
|
|
args << "--" << cmd
|
|
|
|
# Ejecutar dron directamente
|
|
require_relative 'dron/ejecutor'
|
|
resultado = Dron::Ejecutor.lanzar(
|
|
cmd: cmd,
|
|
nota: nota,
|
|
nodo: nodo,
|
|
timeout: 1800 # 30 minutos max
|
|
)
|
|
|
|
resultado
|
|
end
|
|
|
|
caso = opciones[:paso]
|
|
|
|
# ──────────────────────────────────────────────────────────────
|
|
# PASO 1: UPLOAD desde srvv-fenix a Google Drive
|
|
# ──────────────────────────────────────────────────────────────
|
|
if caso == 'all' || caso == 'upload'
|
|
puts "\n" + "─"*60
|
|
puts "📤 PASO 1: Upload desde srvv-fenix → Google Drive"
|
|
puts "─"*60
|
|
|
|
cmd_upload = "ruby #{CLI_DIR}/dasuten_backup_upload.rb"
|
|
|
|
if opciones[:dry_run]
|
|
puts "[DRY-RUN] Ejecutaría: #{cmd_upload}"
|
|
else
|
|
resultado = lanzar_dron(cmd_upload, "📤 Upload backup DASUTEN a Drive", nodo: 'srvv-fenix')
|
|
if resultado[:exit_code] != 0
|
|
puts "\n❌ Upload fallido. Deteniendo orquestación."
|
|
exit 1
|
|
end
|
|
end
|
|
end
|
|
|
|
# ──────────────────────────────────────────────────────────────
|
|
# PASO 2: DOWNLOAD desde Google Drive a dasu-sql4
|
|
# ──────────────────────────────────────────────────────────────
|
|
if caso == 'all' || caso == 'download'
|
|
puts "\n" + "─"*60
|
|
puts "📥 PASO 2: Download desde Google Drive → dasu-sql4"
|
|
puts "─"*60
|
|
|
|
cmd_download = "ruby #{CLI_DIR}/dasuten_backup_download.rb"
|
|
|
|
if opciones[:dry_run]
|
|
puts "[DRY-RUN] Ejecutaría: #{cmd_download}"
|
|
else
|
|
resultado = lanzar_dron(cmd_download, "📥 Download backup DASUTEN desde Drive", nodo: 'dasu-sql4')
|
|
if resultado[:exit_code] != 0
|
|
puts "\n❌ Download fallido. Deteniendo orquestación."
|
|
exit 1
|
|
end
|
|
end
|
|
end
|
|
|
|
# ──────────────────────────────────────────────────────────────
|
|
# PASO 3: RESTORE en dasu-sql4
|
|
# ──────────────────────────────────────────────────────────────
|
|
if caso == 'all' || caso == 'restore'
|
|
puts "\n" + "─"*60
|
|
puts "💾 PASO 3: Restore + DBCC CHECKDB en dasu-sql4"
|
|
puts "─"*60
|
|
|
|
cmd_restore = <<~SQL.gsub("\n", ' ').strip
|
|
powershell -Command "
|
|
$query = @'
|
|
RESTORE DATABASE sysdasuten FROM DISK = 'F:\\BACKUP\\sysdasuten_compressed_ADN.bak'
|
|
WITH REPLACE,
|
|
MOVE 'sysdasuten' TO 'F:\\DATA\\sysdasuten.mdf',
|
|
MOVE 'sysdasuten_log' TO 'F:\\LOG\\sysdasuten_log.ldf';
|
|
DBCC CHECKDB('sysdasuten');
|
|
'@
|
|
sqlcmd -S localhost -Q $query
|
|
"
|
|
SQL
|
|
|
|
if opciones[:dry_run]
|
|
puts "[DRY-RUN] Ejecutaría: #{cmd_restore}"
|
|
else
|
|
resultado = lanzar_dron(cmd_restore, "💾 Restore + CHECKDB DASUTEN", nodo: 'dasu-sql4')
|
|
if resultado[:exit_code] != 0
|
|
puts "\n❌ Restore fallido. Verificar logs."
|
|
exit 1
|
|
end
|
|
end
|
|
end
|
|
|
|
puts "\n" + "═"*60
|
|
puts "✅ Orquestación completada exitosamente!"
|
|
puts "═"*60
|