#!/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 X:\ (share srv-ns8) # Salida: export_complete con ruta del backup # ========================================================== require 'tiny_tds' require 'time' require 'json' require 'base64' require_relative 'lib/dasu_executor' # Nombre del archivo con timestamp TIMESTAMP = Time.now.strftime('%Y%m%d_%H%M%S') BACKUP_FILE = "sysdasuten_FULL_#{TIMESTAMP}.bak" BACKUP_NS8 = "X:\\#{BACKUP_FILE}" puts "[*] Dron: Exportar backup COMPLETO DASUTEN" puts " Nodo: srvv-fenix" puts " Destino: #{BACKUP_NS8}" puts " Tipo: FULL (completo)" begin # Autorizar candados primero system("ruby adn/tools/candados/candados.rb authorize >/dev/null 2>&1") # Obtener credencial de candados 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' smb_user = 'rmonla' smb_server = 'srv-ns8' smb_share = 'bkps-dasuten' smb_path = "\\\\#{smb_server}\\#{smb_share}" if sql_pass.empty? puts "[!] Error: No se pudo obtener credencial de candados" 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)" # Mapear share SMB con credenciales usando net use puts "\n[0/3] Mapeando share SMB #{smb_path}..." sql_pass_escaped = sql_pass.gsub("'", "''") ps_map = "net use X: #{smb_path} #{sql_pass_escaped} /user:#{smb_user} /persistent:no" map_result = client.execute("EXEC xp_cmdshell '#{ps_map}'") map_output = [] map_result.each { |r| map_output << r['output'] if r['output'] && !r['output'].strip.empty? } puts " #{map_output.join("\n ")}" puts "[+] Share mapeado en X: -> #{smb_path}" # Crear directorio en share si no existe puts "\n[1/3] Verificando directorio en share..." client.execute("EXEC master.sys.xp_create_subdir 'X:\\'").each { |r| } puts "[+] Directorio share asegurado: X:\\" # Generar backup comprimido directamente en share X: puts "[2/3] Generando backup en share X: (srv-ns8)..." start = Time.now result = client.execute("BACKUP DATABASE sysdasuten TO DISK = '#{BACKUP_NS8}' WITH INIT, COMPRESSION, STATS=10") result.each { |r| puts " #{r['message']}" if r['message'] } duracion = (Time.now - start).round(2) puts "[+] Backup generado en #{duracion} segundos" # Verificar archivo en share directamente en srv-ns8 vía SSH puts "[3/3] Verificando archivo en share..." backup_unix = BACKUP_NS8.gsub('X:\\', '/mnt/ns8Disco2/bkps-dasuten/') ls_result = `ssh rmonla@10.0.10.8 "ls -l '#{backup_unix}' 2>&1"`.strip if $?.success? && ls_result.include?(File.basename(backup_unix)) # Extraer tamaño del output de ls -l file_size = ls_result.split[4].to_i puts "[+] Archivo verificado: #{backup_unix} (#{file_size.to_i / 1024 / 1024} MB)" else puts "[!] Error: No existe el archivo en #{backup_unix}" puts " SSH output: #{ls_result}" exit 1 end duracion_total = (Time.now - start).round(2) # Output para orquestador output = { paso: 'export_full_complete', backup_ruta: BACKUP_NS8, backup_ruta_unix: "/mnt/ns8Disco2/bkps-dasuten/#{BACKUP_FILE}", backup_tipo: 'full', nodo: 'srvv-fenix', nodo_destino: 'srv-ns8', duracion_total: duracion, timestamp: Time.now.iso8601, siguiente_paso: 'upload_drive' } puts "\n✅ Export completado en share" puts " Output: #{output.to_json}" File.write('/tmp/dron_export_output.json', output.to_json) rescue => e puts "[!] Error fatal: #{e.message}" exit 1 end