186 lines
6.9 KiB
Ruby
186 lines
6.9 KiB
Ruby
#!/usr/bin/env ruby
|
|
# frozen_string_literal: true
|
|
|
|
# Transferencia y restauración de DASUTEN backup comprimido a dasu-sql4
|
|
# Ruta: srvv-fenix (SMB) → NS8 (local) → srv-dasu (SCP) → dasu-sql4 (HTTP → RESTORE)
|
|
#
|
|
# Ejecutar: ruby adn/tools/scripts/dasuten_restore_sql4.rb
|
|
# O como dron: ./adn/tools/run dron lanzar --nota "Migrar DB DASUTEN a dasu-sql4" --timeout 3600 -- ruby adn/tools/scripts/dasuten_restore_sql4.rb
|
|
|
|
require 'fileutils'
|
|
|
|
TOOLS_DIR = File.expand_path("..", __dir__)
|
|
CANDADOS = File.join(TOOLS_DIR, "candados", "candados.rb")
|
|
WZOMBI = File.join(TOOLS_DIR, "w-zombi", "bin", "w-zombi")
|
|
TELE_LOG = File.join(TOOLS_DIR, "w-zombi", "data", "telemetria.log")
|
|
|
|
BAK_FILE = "sysdasuten_compressed_ADN.bak"
|
|
SMB_SHARE = "//10.0.10.200/BK_SQL"
|
|
SMB_KEY = "utnlarioja.intranet:monlaricardo"
|
|
LOCAL_TMP = "/var/tmp/#{BAK_FILE}"
|
|
DASU_TMP = "/tmp/#{BAK_FILE}"
|
|
SQL4_DEST = "F:\\BACKUP\\#{BAK_FILE}"
|
|
|
|
def paso(n, desc)
|
|
puts "\n#{"="*60}"
|
|
puts " PASO #{n}: #{desc}"
|
|
puts "#{"="*60}"
|
|
end
|
|
|
|
def run!(desc, cmd)
|
|
puts "▶ #{desc}"
|
|
puts " CMD: #{cmd}"
|
|
result = system(cmd)
|
|
unless result
|
|
puts "❌ FALLO: #{desc}"
|
|
exit 1
|
|
end
|
|
puts "✅ OK"
|
|
end
|
|
|
|
def candados_run(key, cmd)
|
|
system("ruby", CANDADOS, "run", key, cmd)
|
|
end
|
|
|
|
def wzombi_cmd(cmd)
|
|
system("ruby", WZOMBI, "cmd", cmd)
|
|
end
|
|
|
|
def wait_wzombi_result(timeout: 600, interval: 15)
|
|
# Obtener el último ID antes del comando
|
|
sleep 5
|
|
lines = File.readlines(TELE_LOG, encoding: "utf-8:utf-8")
|
|
last_exec = lines.reverse.find { |l| l.include?("EJECUTANDO") }
|
|
return nil unless last_exec
|
|
|
|
id = last_exec.match(/\[ID:(\d+)\]/)[1]
|
|
puts " ⏳ Esperando resultado ID:#{id}..."
|
|
|
|
elapsed = 0
|
|
loop do
|
|
sleep interval
|
|
elapsed += interval
|
|
|
|
current_lines = File.readlines(TELE_LOG, encoding: "utf-8:utf-8")
|
|
result = current_lines.reverse.find { |l| l.include?("[ID:#{id}]") && (l.include?("RESULTADO") || l.include?("ERROR")) }
|
|
|
|
if result
|
|
if result.include?("ERROR")
|
|
puts " ❌ Error: #{result.strip}"
|
|
return nil
|
|
end
|
|
puts " ✅ Resultado recibido (ID:#{id})"
|
|
return result
|
|
end
|
|
|
|
if elapsed >= timeout
|
|
puts " ⏰ Timeout (#{timeout}s)"
|
|
return nil
|
|
end
|
|
|
|
puts " ⏳ #{elapsed}s/#{timeout}s..."
|
|
end
|
|
end
|
|
|
|
# ============================================================
|
|
paso(1, "Descargar backup comprimido desde srvv-fenix vía SMB")
|
|
# ============================================================
|
|
# Crear script wrapper para evitar problemas de escape con candados run
|
|
smb_script = "/tmp/smb_download.sh"
|
|
File.write(smb_script, <<~SH)
|
|
#!/bin/bash
|
|
smbclient #{SMB_SHARE} -U "monlaricardo%$PASS" -W UTNlarioja -c "lcd /var/tmp; get #{BAK_FILE}"
|
|
SH
|
|
File.chmod(0755, smb_script)
|
|
run!("SMB download #{BAK_FILE}", "ruby #{CANDADOS} run #{SMB_KEY} #{smb_script}")
|
|
|
|
# Verificar tamaño
|
|
size = File.size(LOCAL_TMP) rescue 0
|
|
puts " 📦 Archivo descargado: #{(size / 1024.0 / 1024.0).round(1)} MB"
|
|
if size < 1_000_000
|
|
puts "❌ Archivo demasiado pequeño, posible error de descarga"
|
|
exit 1
|
|
end
|
|
|
|
# ============================================================
|
|
paso(2, "Transferir backup a srv-dasu vía SCP")
|
|
# ============================================================
|
|
scp_script = "/tmp/scp_to_dasu.sh"
|
|
File.write(scp_script, <<~SH)
|
|
#!/bin/bash
|
|
sshpass -p "$PASS" scp -o StrictHostKeyChecking=no #{LOCAL_TMP} root@srv-dasu:#{DASU_TMP}
|
|
SH
|
|
File.chmod(0755, scp_script)
|
|
run!("SCP a srv-dasu", "ruby #{CANDADOS} run srv-dasu:root #{scp_script}")
|
|
|
|
# ============================================================
|
|
paso(3, "Servir archivo desde srv-dasu por HTTP")
|
|
# ============================================================
|
|
http_script = "/tmp/http_srv_dasu.sh"
|
|
File.write(http_script, <<~SH)
|
|
#!/bin/bash
|
|
sshpass -p "$PASS" ssh -o StrictHostKeyChecking=no root@srv-dasu 'pkill -f "http.server 9090" 2>/dev/null; cd /tmp && nohup python3 -m http.server 9090 > /dev/null 2>&1 &'
|
|
SH
|
|
File.chmod(0755, http_script)
|
|
run!("HTTP server en srv-dasu:9090", "ruby #{CANDADOS} run srv-dasu:root #{http_script}")
|
|
sleep 3
|
|
|
|
# ============================================================
|
|
paso(4, "Descargar backup en dasu-sql4 vía W-Zombi")
|
|
# ============================================================
|
|
puts "▶ Enviando comando de descarga a dasu-sql4..."
|
|
wzombi_cmd("iwr http://192.168.1.13:9090/#{BAK_FILE} -OutFile #{SQL4_DEST}")
|
|
result = wait_wzombi_result(timeout: 600, interval: 20)
|
|
unless result
|
|
puts "❌ No se pudo descargar el archivo en dasu-sql4"
|
|
exit 1
|
|
end
|
|
|
|
# Verificar que llegó
|
|
wzombi_cmd("(Get-Item '#{SQL4_DEST}').Length")
|
|
size_result = wait_wzombi_result(timeout: 60, interval: 10)
|
|
puts " 📦 Tamaño en destino: #{size_result&.strip}"
|
|
|
|
# ============================================================
|
|
paso(5, "Restaurar base de datos DASUTEN en dasu-sql4")
|
|
# ============================================================
|
|
# Primero obtener los nombres lógicos del backup
|
|
puts "▶ Listando archivos lógicos del backup..."
|
|
sqlcmd_path = 'C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\170\Tools\Binn\SQLCMD.EXE'
|
|
wzombi_cmd("& '#{sqlcmd_path}' -S localhost -U sa -P UTNlarioja00DASU -Q \"RESTORE FILELISTONLY FROM DISK=N'#{SQL4_DEST}'\" -h -1 -W")
|
|
filelist = wait_wzombi_result(timeout: 120, interval: 15)
|
|
puts " 📋 FileList: #{filelist&.strip}"
|
|
|
|
# Restaurar con rutas en disco F:
|
|
puts "\n▶ Ejecutando RESTORE DATABASE..."
|
|
restore_sql = "RESTORE DATABASE [sysdasuten] FROM DISK=N'#{SQL4_DEST}' WITH REPLACE, MOVE N'sysdasuten_Data' TO N'F:\\DATA\\sysdasuten.mdf', MOVE N'sysdasuten_Log' TO N'F:\\LOG\\sysdasuten_log.ldf'"
|
|
wzombi_cmd("& '#{sqlcmd_path}' -S localhost -U sa -P UTNlarioja00DASU -Q \"#{restore_sql}\" -t 600")
|
|
restore_result = wait_wzombi_result(timeout: 900, interval: 30)
|
|
|
|
if restore_result && !restore_result.include?("ERROR")
|
|
puts "✅ BASE DE DATOS RESTAURADA EXITOSAMENTE"
|
|
else
|
|
puts "⚠️ Verificar resultado del restore manualmente"
|
|
end
|
|
|
|
# ============================================================
|
|
paso(6, "Verificación final")
|
|
# ============================================================
|
|
wzombi_cmd("& '#{sqlcmd_path}' -S localhost -U sa -P UTNlarioja00DASU -Q \"SELECT name, state_desc, size*8/1024 AS size_mb FROM sys.master_files WHERE database_id = DB_ID('sysdasuten')\" -h -1 -W")
|
|
verify = wait_wzombi_result(timeout: 60, interval: 10)
|
|
puts " 📊 Estado de archivos: #{verify&.strip}"
|
|
|
|
# ============================================================
|
|
paso(7, "Limpieza de temporales")
|
|
# ============================================================
|
|
File.delete(LOCAL_TMP) if File.exist?(LOCAL_TMP)
|
|
puts " 🗑️ Eliminado #{LOCAL_TMP}"
|
|
|
|
# Limpiar en srv-dasu
|
|
system("ruby #{CANDADOS} run srv-dasu:root \"sshpass -p '$PASS' ssh -o StrictHostKeyChecking=no root@srv-dasu 'rm -f #{DASU_TMP}; pkill -f http.server.9090'\"")
|
|
puts " 🗑️ Limpieza en srv-dasu"
|
|
|
|
puts "\n#{"="*60}"
|
|
puts " 🎯 MIGRACIÓN DASUTEN A dasu-sql4 COMPLETADA"
|
|
puts "#{"="*60}"
|