Files
dtic-DIIAA/adn/tools/cli/drones/dasuten_exportar_srvv-fenix.rb
T
Ricardo MonlaandClaude Opus 4.6 900457a778 [A04.P006] Exportar backup en doble ubicación (fenix + share ns8)
Cambios realizados:

1. dasuten_exportar_srvv-fenix.rb:
   - Genera backup en disco local: E:\BK_SQL\sysdasuten\
   - Copia automáticamente a unidad de red X: (share srv-ns8)
   - Usa PowerShell para copiar al share mapeado
   - Verifica ambos destinos

2. dasuten_transferir_srvv-fenix-srv-ns8.rb:
   - Simplificado: ya no descarga desde fenix vía SMB
   - El backup ya está en /mnt/ns8Disco2/bkps-dasuten/
   - Copia local: share → /var/tmp/ (para rclone upload)

Flujo actualizado:
  1. SQL Server → E:\BK_SQL\sysdasuten\archivo.bak (local fenix)
  2. PowerShell → X:\archivo.bak (share srv-ns8)
  3. Transfer dron → /var/tmp/archivo.bak (para rclone)
  4. Upload dron → Google Drive

Requisito en srvv-fenix:
  net use X: \\10.0.10.8\bkps-dasuten /user:rmonla <password>

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-14 19:44:13 -03:00

135 lines
4.5 KiB
Ruby
Executable File

#!/usr/bin/env ruby
# frozen_string_literal: true
# ==========================================================
# adn/tools/cli/drones/dasuten_exportar_srvv-fenix.rb
# ==========================================================
# Dron: Exportar backup en srvv-fenix
# Flujo: srvv-fenix → Backup comprimido en E:\BK_SQL\
# Salida: Marca evento como 'export_complete' con ruta del backup
# ==========================================================
require 'tiny_tds'
require 'time'
require 'json'
# Nombre del archivo con timestamp
TIMESTAMP = Time.now.strftime('%Y%m%d_%H%M%S')
BACKUP_FILE = "sysdasuten_FULL_#{TIMESTAMP}.bak"
# Directorio local en fenix
BACKUP_DIR_FENIX = "E:\\BK_SQL\\sysdasuten"
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 " Nodo: srvv-fenix"
puts " Destino local: #{BACKUP_LOCAL}"
puts " Destino share (X:): #{BACKUP_NS8}"
puts " Tipo: FULL (completo, con copia en doble ubicación)"
begin
# Autorizar candados primero (necesario para acceder a la bóveda)
system("ruby adn/tools/candados/candados.rb authorize >/dev/null 2>&1")
# Obtener credencial de candados (patrón usado en otros drones)
pass_cmd = "ruby adn/tools/candados/candados.rb get utnlarioja.intranet:monlaricardo 2>/dev/null"
sql_pass = `#{pass_cmd}`.strip
sql_user = 'UTNlarioja\\monlaricardo'
sql_host = '10.0.10.200'
if sql_pass.empty?
puts "[!] Error: No se pudo obtener credencial de candados (utnlarioja.intranet:monlaricardo)"
exit 1
end
client = TinyTds::Client.new(
username: sql_user,
password: sql_pass,
host: sql_host,
timeout: 600
)
puts "[+] Conectado a SQL Server en #{sql_host} (auth: Windows)"
# Crear directorio local si no existe
puts "\n[0/4] Verificando directorios..."
mkdir_sql = "EXEC master.sys.xp_create_subdir '#{BACKUP_DIR_FENIX}'"
client.execute(mkdir_sql)
puts "[+] Directorio local asegurado: #{BACKUP_DIR_FENIX}"
# Generar backup comprimido en disco local
puts "[1/4] Generando backup en disco local..."
start = Time.now
result = client.execute("BACKUP DATABASE sysdasuten TO DISK = '#{BACKUP_LOCAL}' WITH INIT, COMPRESSION, STATS=10")
result.each { |r| puts " #{r['message']}" if r['message'] }
duracion_local = (Time.now - start).round(2)
puts "[+] Backup local generado en #{duracion_local} 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
puts "[4/4] Verificando archivo en share..."
begin
verify_ps = <<~PSCMD.strip
if (Test-Path "#{BACKUP_NS8}") {
$size = (Get-Item "#{BACKUP_NS8}").Length
Write-Host "Verificado: #{BACKUP_NS8} ($([math]::Round($size/1MB, 2)) MB)"
} else {
Write-Host "ERROR: No existe #{BACKUP_NS8}"
exit 1
}
PSCMD
client.execute("EXEC xp_cmdshell 'powershell -Command \"#{verify_ps.gsub('"', '\"')}\"'")
rescue => e
puts "[!] Advertencia: No se pudo verificar en X: - #{e.message}"
end
duracion_total = (Time.now - start).round(2)
# Output para orquestador
output = {
paso: 'export_full_complete',
backup_ruta_fenix: BACKUP_LOCAL,
backup_ruta_ns8: BACKUP_NS8,
backup_ruta_ns8_unix: "/mnt/ns8Disco2/bkps-dasuten/#{BACKUP_FILE}",
backup_tipo: 'full',
nodo: 'srvv-fenix',
nodo_destino: 'srv-ns8',
duracion_total: duracion_total,
timestamp: Time.now.iso8601,
siguiente_paso: 'upload_drive'
}
puts "\n✅ Export completado (doble ubicación: local + share)"
puts " Output: #{output.to_json}"
# Escribir output para que el orquestador lo lea
File.write('/tmp/dron_export_output.json', output.to_json)
rescue => e
puts "[!] Error fatal: #{e.message}"
exit 1
end