[A04.P005] Simplificado flujo de backup a único destino (X:)
- dasuten_exportar_srvv-fenix.rb: Backup directo a X: sin copia local - dasuten_exportar_diferencial_srvv-fenix.rb: Mismo patrón simplificado - dasuten_transferir_srvv-fenix-srv-ns8.rb: Solo copia share → /var/tmp - dasuten_restaurar_dasu-sql4.rb: Ajustado para leer output correcto Flujo simplificado: FULL: srvv-fenix → X:\ → /var/tmp/ → Drive DIF: srvv-fenix → X:\ → /var/tmp/ → Drive Eliminados pasos intermedios innecesarios (E:\BK_SQL\sysdasuten\)
This commit is contained in:
@@ -15,14 +15,12 @@ require 'json'
|
|||||||
|
|
||||||
# Nombre del archivo con timestamp
|
# Nombre del archivo con timestamp
|
||||||
TIMESTAMP = Time.now.strftime('%Y%m%d_%H%M%S')
|
TIMESTAMP = Time.now.strftime('%Y%m%d_%H%M%S')
|
||||||
BACKUP_DIR = "E:\\BK_SQL\\sysdasuten"
|
BACKUP_FILE = "X:\\sysdasuten_DIF_#{TIMESTAMP}.bak"
|
||||||
BACKUP_FILE = "#{BACKUP_DIR}\\sysdasuten_DIF_#{TIMESTAMP}.bak"
|
|
||||||
|
|
||||||
puts "[*] Dron: Exportar backup DIFERENCIAL DASUTEN"
|
puts "[*] Dron: Exportar backup DIFERENCIAL DASUTEN"
|
||||||
puts " Nodo: srvv-fenix"
|
puts " Nodo: srvv-fenix"
|
||||||
puts " Destino: #{BACKUP_FILE}"
|
puts " Destino: #{BACKUP_FILE}"
|
||||||
puts " Tipo: DIFFERENTIAL (solo cambios desde último backup completo)"
|
puts " Tipo: DIFFERENTIAL (solo cambios desde último backup completo)"
|
||||||
puts " Directorio: #{BACKUP_DIR}"
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
# Autorizar candados primero (necesario para acceder a la bóveda)
|
# Autorizar candados primero (necesario para acceder a la bóveda)
|
||||||
@@ -48,14 +46,8 @@ begin
|
|||||||
)
|
)
|
||||||
puts "[+] Conectado a SQL Server en #{sql_host} (auth: Windows)"
|
puts "[+] Conectado a SQL Server en #{sql_host} (auth: Windows)"
|
||||||
|
|
||||||
# Crear directorio si no existe
|
# Generar backup diferencial directamente en share X:
|
||||||
puts "\n[0/3] Verificando directorio..."
|
puts "\n[0/2] Generando backup diferencial en share X:..."
|
||||||
mkdir_sql = "EXEC master.sys.xp_create_subdir '#{BACKUP_DIR}'"
|
|
||||||
client.execute(mkdir_sql)
|
|
||||||
puts "[+] Directorio asegurado: #{BACKUP_DIR}"
|
|
||||||
|
|
||||||
# Generar backup diferencial
|
|
||||||
puts "\n[1/2] Generando backup diferencial..."
|
|
||||||
start = Time.now
|
start = Time.now
|
||||||
|
|
||||||
sql = <<~SQL.strip
|
sql = <<~SQL.strip
|
||||||
@@ -72,42 +64,51 @@ begin
|
|||||||
duracion = (Time.now - start).round(2)
|
duracion = (Time.now - start).round(2)
|
||||||
puts "[+] Backup diferencial generado en #{duracion} segundos"
|
puts "[+] Backup diferencial generado en #{duracion} segundos"
|
||||||
|
|
||||||
# Obtener tamaño del archivo (vía PowerShell remoto o xp_fileexist)
|
# Verificar archivo en share
|
||||||
puts "\n[2/2] Verificando archivo..."
|
puts "\n[1/2] Verificando archivo en share..."
|
||||||
|
|
||||||
begin
|
begin
|
||||||
file_result = client.execute("EXEC master.sys.xp_fileexist '#{BACKUP_FILE}'")
|
verify_ps = <<~PSCMD.strip
|
||||||
file_info = file_result.first
|
if (Test-Path "#{BACKUP_FILE}") {
|
||||||
|
$size = (Get-Item "#{BACKUP_FILE}").Length
|
||||||
|
Write-Host "Verificado: #{BACKUP_FILE} ($([math]::Round($size/1MB, 2)) MB)"
|
||||||
|
} else {
|
||||||
|
Write-Host "ERROR: No existe #{BACKUP_FILE}"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
PSCMD
|
||||||
|
client.execute("EXEC xp_cmdshell 'powershell -Command \"#{verify_ps.gsub('"', '\"')}\"'")
|
||||||
|
puts "[+] Archivo verificado"
|
||||||
|
rescue => e
|
||||||
|
puts "[!] Error al verificar en X: - #{e.message}"
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
|
||||||
if file_info && file_result.to_a.any? { |f| f['File Exists'] == 1 }
|
# Tamaño aproximado de la BD base
|
||||||
puts "[+] Archivo verificado: #{BACKUP_FILE}"
|
puts "\n[2/2] Información de tamaño..."
|
||||||
|
begin
|
||||||
# Obtener tamaño aproximado
|
|
||||||
size_info = client.execute("SELECT size_bytes = (SELECT size * 8192 FROM sys.database_files WHERE name = 'sysdasuten')")
|
size_info = client.execute("SELECT size_bytes = (SELECT size * 8192 FROM sys.database_files WHERE name = 'sysdasuten')")
|
||||||
puts " Tamaño BD base: #{size_info.to_a.first['size_bytes'].to_i / 1024 / 1024} MB"
|
puts " Tamaño BD base: #{size_info.to_a.first['size_bytes'].to_i / 1024 / 1024} MB"
|
||||||
else
|
|
||||||
puts "[!] Advertencia: No se pudo verificar existencia del archivo"
|
|
||||||
end
|
|
||||||
rescue => e
|
rescue => e
|
||||||
puts "[!] Advertencia: #{e.message}"
|
puts "[!] No se pudo obtener tamaño: #{e.message}"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Output para orquestador
|
# Output para orquestador
|
||||||
output = {
|
output = {
|
||||||
paso: 'export_differential_complete',
|
paso: 'export_differential_complete',
|
||||||
backup_ruta: BACKUP_FILE,
|
backup_ruta: BACKUP_FILE,
|
||||||
|
backup_ruta_unix: BACKUP_FILE.gsub('X:\\', '/mnt/ns8Disco2/bkps-dasuten/'),
|
||||||
backup_tipo: 'differential',
|
backup_tipo: 'differential',
|
||||||
nodo: 'srvv-fenix',
|
nodo: 'srvv-fenix',
|
||||||
|
nodo_destino: 'srv-ns8',
|
||||||
duracion: duracion,
|
duracion: duracion,
|
||||||
timestamp: Time.now.iso8601,
|
timestamp: Time.now.iso8601,
|
||||||
siguiente_paso: 'transferir'
|
siguiente_paso: 'upload_drive'
|
||||||
}
|
}
|
||||||
|
|
||||||
puts "\n✅ Export diferencial completado"
|
puts "\n✅ Export diferencial completado"
|
||||||
puts " Output: #{output.to_json}"
|
puts " Output: #{output.to_json}"
|
||||||
|
|
||||||
# Escribir output para que el orquestador lo lea
|
File.write('/tmp/dron_export_output.json', output.to_json)
|
||||||
File.write('/tmp/dron_export_dif_output.json', output.to_json)
|
|
||||||
|
|
||||||
rescue => e
|
rescue => e
|
||||||
puts "[!] Error fatal: #{e.message}"
|
puts "[!] Error fatal: #{e.message}"
|
||||||
|
|||||||
@@ -17,19 +17,13 @@ require 'json'
|
|||||||
TIMESTAMP = Time.now.strftime('%Y%m%d_%H%M%S')
|
TIMESTAMP = Time.now.strftime('%Y%m%d_%H%M%S')
|
||||||
BACKUP_FILE = "sysdasuten_FULL_#{TIMESTAMP}.bak"
|
BACKUP_FILE = "sysdasuten_FULL_#{TIMESTAMP}.bak"
|
||||||
|
|
||||||
# Directorio local en fenix
|
# Unidad de red mapeada en srvv-fenix (share de srv-ns8) - UNICO DESTINO
|
||||||
BACKUP_DIR_FENIX = "E:\\BK_SQL\\sysdasuten"
|
BACKUP_NS8 = "X:\\#{BACKUP_FILE}"
|
||||||
BACKUP_LOCAL = "#{BACKUP_DIR_FENIX}\\#{BACKUP_FILE}"
|
|
||||||
|
|
||||||
# Unidad de red mapeada en srvv-fenix (share de srv-ns8)
|
|
||||||
BACKUP_DIR_NS8 = "X:"
|
|
||||||
BACKUP_NS8 = "#{BACKUP_DIR_NS8}\\#{BACKUP_FILE}"
|
|
||||||
|
|
||||||
puts "[*] Dron: Exportar backup COMPLETO DASUTEN"
|
puts "[*] Dron: Exportar backup COMPLETO DASUTEN"
|
||||||
puts " Nodo: srvv-fenix"
|
puts " Nodo: srvv-fenix"
|
||||||
puts " Destino local: #{BACKUP_LOCAL}"
|
puts " Destino: #{BACKUP_NS8}"
|
||||||
puts " Destino share (X:): #{BACKUP_NS8}"
|
puts " Tipo: FULL (completo)"
|
||||||
puts " Tipo: FULL (completo, con copia en doble ubicación)"
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
# Autorizar candados primero (necesario para acceder a la bóveda)
|
# Autorizar candados primero (necesario para acceder a la bóveda)
|
||||||
@@ -55,42 +49,24 @@ begin
|
|||||||
)
|
)
|
||||||
puts "[+] Conectado a SQL Server en #{sql_host} (auth: Windows)"
|
puts "[+] Conectado a SQL Server en #{sql_host} (auth: Windows)"
|
||||||
|
|
||||||
# Crear directorio local si no existe
|
# Crear directorio en share si no existe
|
||||||
puts "\n[0/4] Verificando directorios..."
|
puts "\n[0/2] Verificando directorio en share..."
|
||||||
mkdir_sql = "EXEC master.sys.xp_create_subdir '#{BACKUP_DIR_FENIX}'"
|
mkdir_sql = "EXEC master.sys.xp_create_subdir 'X:\\'"
|
||||||
client.execute(mkdir_sql)
|
client.execute(mkdir_sql)
|
||||||
puts "[+] Directorio local asegurado: #{BACKUP_DIR_FENIX}"
|
puts "[+] Directorio share asegurado: X:\\"
|
||||||
|
|
||||||
# Generar backup comprimido en disco local
|
# Generar backup comprimido directamente en share X:
|
||||||
puts "[1/4] Generando backup en disco local..."
|
puts "[1/2] Generando backup en share X: (srv-ns8)..."
|
||||||
start = Time.now
|
start = Time.now
|
||||||
|
|
||||||
result = client.execute("BACKUP DATABASE sysdasuten TO DISK = '#{BACKUP_LOCAL}' WITH INIT, COMPRESSION, STATS=10")
|
result = client.execute("BACKUP DATABASE sysdasuten TO DISK = '#{BACKUP_NS8}' WITH INIT, COMPRESSION, STATS=10")
|
||||||
result.each { |r| puts " #{r['message']}" if r['message'] }
|
result.each { |r| puts " #{r['message']}" if r['message'] }
|
||||||
|
|
||||||
duracion_local = (Time.now - start).round(2)
|
duracion = (Time.now - start).round(2)
|
||||||
puts "[+] Backup local generado en #{duracion_local} segundos"
|
puts "[+] Backup generado en #{duracion} segundos"
|
||||||
|
|
||||||
# Verificar archivo local
|
|
||||||
puts "[2/4] Verificando archivo local..."
|
|
||||||
file_result = client.execute("EXEC master.sys.xp_fileexist '#{BACKUP_LOCAL}'")
|
|
||||||
puts "[+] Archivo local verificado: #{BACKUP_LOCAL}"
|
|
||||||
|
|
||||||
# Copiar a unidad de red X: (share de srv-ns8)
|
|
||||||
puts "[3/4] Copiando a unidad de red X: (srv-ns8)..."
|
|
||||||
begin
|
|
||||||
copy_ps = <<~PSCMD.strip
|
|
||||||
Copy-Item -Path "#{BACKUP_LOCAL}" -Destination "#{BACKUP_NS8}" -Force
|
|
||||||
Write-Host "Copiado: #{BACKUP_FILE} → X:\\#{BACKUP_FILE}"
|
|
||||||
PSCMD
|
|
||||||
client.execute("EXEC xp_cmdshell 'powershell -Command \"#{copy_ps.gsub('"', '\"')}\"'")
|
|
||||||
puts "[+] Copia a share completada: #{BACKUP_NS8}"
|
|
||||||
rescue => e
|
|
||||||
puts "[!] Advertencia: No se pudo copiar a X: - #{e.message}"
|
|
||||||
end
|
|
||||||
|
|
||||||
# Verificar archivo en share
|
# Verificar archivo en share
|
||||||
puts "[4/4] Verificando archivo en share..."
|
puts "[2/2] Verificando archivo en share..."
|
||||||
begin
|
begin
|
||||||
verify_ps = <<~PSCMD.strip
|
verify_ps = <<~PSCMD.strip
|
||||||
if (Test-Path "#{BACKUP_NS8}") {
|
if (Test-Path "#{BACKUP_NS8}") {
|
||||||
@@ -103,7 +79,8 @@ begin
|
|||||||
PSCMD
|
PSCMD
|
||||||
client.execute("EXEC xp_cmdshell 'powershell -Command \"#{verify_ps.gsub('"', '\"')}\"'")
|
client.execute("EXEC xp_cmdshell 'powershell -Command \"#{verify_ps.gsub('"', '\"')}\"'")
|
||||||
rescue => e
|
rescue => e
|
||||||
puts "[!] Advertencia: No se pudo verificar en X: - #{e.message}"
|
puts "[!] Error al verificar en X: - #{e.message}"
|
||||||
|
exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
duracion_total = (Time.now - start).round(2)
|
duracion_total = (Time.now - start).round(2)
|
||||||
@@ -111,18 +88,17 @@ begin
|
|||||||
# Output para orquestador
|
# Output para orquestador
|
||||||
output = {
|
output = {
|
||||||
paso: 'export_full_complete',
|
paso: 'export_full_complete',
|
||||||
backup_ruta_fenix: BACKUP_LOCAL,
|
backup_ruta: BACKUP_NS8,
|
||||||
backup_ruta_ns8: BACKUP_NS8,
|
backup_ruta_unix: "/mnt/ns8Disco2/bkps-dasuten/#{BACKUP_FILE}",
|
||||||
backup_ruta_ns8_unix: "/mnt/ns8Disco2/bkps-dasuten/#{BACKUP_FILE}",
|
|
||||||
backup_tipo: 'full',
|
backup_tipo: 'full',
|
||||||
nodo: 'srvv-fenix',
|
nodo: 'srvv-fenix',
|
||||||
nodo_destino: 'srv-ns8',
|
nodo_destino: 'srv-ns8',
|
||||||
duracion_total: duracion_total,
|
duracion_total: duracion,
|
||||||
timestamp: Time.now.iso8601,
|
timestamp: Time.now.iso8601,
|
||||||
siguiente_paso: 'upload_drive'
|
siguiente_paso: 'upload_drive'
|
||||||
}
|
}
|
||||||
|
|
||||||
puts "\n✅ Export completado (doble ubicación: local + share)"
|
puts "\n✅ Export completado en share"
|
||||||
puts " Output: #{output.to_json}"
|
puts " Output: #{output.to_json}"
|
||||||
|
|
||||||
# Escribir output para que el orquestador lo lea
|
# Escribir output para que el orquestador lo lea
|
||||||
|
|||||||
@@ -26,10 +26,10 @@ if File.exist?(DOWNLOAD_OUTPUT)
|
|||||||
# Convertir path Unix a Windows si es necesario
|
# Convertir path Unix a Windows si es necesario
|
||||||
backup_name = File.basename(backup_local)
|
backup_name = File.basename(backup_local)
|
||||||
LOCAL_BACKUP = "#{BACKUP_DIR_WINDOWS}\\#{backup_name}"
|
LOCAL_BACKUP = "#{BACKUP_DIR_WINDOWS}\\#{backup_name}"
|
||||||
puts "[*] Dron: Restaurar backup DASUTEN (COMPLETO)"
|
puts "[*] Dron: Restaurar backup DASUTEN"
|
||||||
else
|
else
|
||||||
LOCAL_BACKUP = "#{BACKUP_DIR_WINDOWS}\\sysdasuten_FULL_*.bak"
|
LOCAL_BACKUP = "#{BACKUP_DIR_WINDOWS}\\sysdasuten_FULL_*.bak"
|
||||||
puts "[*] Dron: Restaurar backup DASUTEN (COMPLETO - buscar más reciente)"
|
puts "[*] Dron: Restaurar backup DASUTEN (buscar más reciente)"
|
||||||
end
|
end
|
||||||
|
|
||||||
TARGET_IP = "192.168.1.11"
|
TARGET_IP = "192.168.1.11"
|
||||||
|
|||||||
@@ -13,27 +13,18 @@ require 'time'
|
|||||||
require 'json'
|
require 'json'
|
||||||
require 'fileutils'
|
require 'fileutils'
|
||||||
|
|
||||||
# Si existe output del dron anterior (export o export_dif), leer la ruta
|
# Leer ruta del backup desde el output del dron de export
|
||||||
EXPORT_OUTPUT_FILE = '/tmp/dron_export_output.json'
|
EXPORT_OUTPUT_FILE = '/tmp/dron_export_output.json'
|
||||||
EXPORT_DIF_OUTPUT_FILE = '/tmp/dron_export_dif_output.json'
|
|
||||||
|
|
||||||
backup_ns8_unix = nil
|
backup_ns8_unix = nil
|
||||||
backup_name = nil
|
backup_name = nil
|
||||||
|
|
||||||
if File.exist?(EXPORT_DIF_OUTPUT_FILE)
|
if File.exist?(EXPORT_OUTPUT_FILE)
|
||||||
output = JSON.parse(File.read(EXPORT_DIF_OUTPUT_FILE))
|
|
||||||
if output['backup_ruta_ns8'] || output['backup_ruta_ns8_unix']
|
|
||||||
backup_ns8_unix = output['backup_ruta_ns8_unix'] || output['backup_ruta_ns8']
|
|
||||||
backup_name = File.basename(backup_ns8_unix)
|
|
||||||
puts "[*] Dron: Preparar backup DIFERENCIAL para upload"
|
|
||||||
end
|
|
||||||
elsif File.exist?(EXPORT_OUTPUT_FILE)
|
|
||||||
output = JSON.parse(File.read(EXPORT_OUTPUT_FILE))
|
output = JSON.parse(File.read(EXPORT_OUTPUT_FILE))
|
||||||
if output['backup_ruta_ns8'] || output['backup_ruta_ns8_unix']
|
backup_ns8_unix = output['backup_ruta_unix'] || output['backup_ruta_ns8']
|
||||||
backup_ns8_unix = output['backup_ruta_ns8_unix'] || output['backup_ruta_ns8']
|
|
||||||
backup_name = File.basename(backup_ns8_unix)
|
backup_name = File.basename(backup_ns8_unix)
|
||||||
puts "[*] Dron: Preparar backup COMPLETO para upload"
|
backup_tipo = output['backup_tipo'] || 'full'
|
||||||
end
|
puts "[*] Dron: Preparar backup #{backup_tipo.upcase} para upload"
|
||||||
end
|
end
|
||||||
|
|
||||||
unless backup_ns8_unix
|
unless backup_ns8_unix
|
||||||
@@ -41,10 +32,9 @@ unless backup_ns8_unix
|
|||||||
exit 1
|
exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
BACKUP_NS8_DIR = "/mnt/ns8Disco2/bkps-dasuten"
|
|
||||||
BACKUP_LOCAL = "/var/tmp/#{backup_name}"
|
BACKUP_LOCAL = "/var/tmp/#{backup_name}"
|
||||||
|
|
||||||
puts " Share: #{BACKUP_NS8_DIR}"
|
puts " Origen: #{backup_ns8_unix}"
|
||||||
puts " Archivo: #{backup_name}"
|
puts " Archivo: #{backup_name}"
|
||||||
puts " Destino: #{BACKUP_LOCAL}"
|
puts " Destino: #{BACKUP_LOCAL}"
|
||||||
|
|
||||||
@@ -73,7 +63,7 @@ begin
|
|||||||
resultado = {
|
resultado = {
|
||||||
paso: 'transfer_complete',
|
paso: 'transfer_complete',
|
||||||
backup_local: BACKUP_LOCAL,
|
backup_local: BACKUP_LOCAL,
|
||||||
backup_ns8_share: backup_ns8_unix,
|
backup_origen: backup_ns8_unix,
|
||||||
nodo: 'srv-ns8',
|
nodo: 'srv-ns8',
|
||||||
duracion: duracion,
|
duracion: duracion,
|
||||||
timestamp: Time.now.iso8601,
|
timestamp: Time.now.iso8601,
|
||||||
|
|||||||
Reference in New Issue
Block a user