#!/usr/bin/env ruby # frozen_string_literal: true # ========================================================== # adn/tools/cli/drones/dasuten_download_drive-dasu-sql4.rb # ========================================================== # Dron: Download desde Google Drive a dasu-sql4 # Flujo: Google Drive → F:\BACKUP\sysdasuten_compressed_ADN.bak # Usa: Invoke-WebRequest (sin rclone) # ========================================================== require 'time' require 'json' require 'shellwords' require 'optparse' require 'base64' require 'tempfile' opciones = { test_file: nil, file_id: nil # Google Drive file ID } OptionParser.new do |opts| opts.banner = "Uso: dron lanzar --nota 'Download' --nodo dasu-sql4 -- ruby dasuten_download_drive.rb [opciones]" opts.on("--test-file ARCHIVO", "Archivo específico para test (ej: test_Backup.bak)") { |f| opciones[:test_file] = f } opts.on("--file-id ID", "Google Drive file ID") { |id| opciones[:file_id] = id } end.parse!(ARGV) BACKUP_DIR_WINDOWS = "F:\\BACKUP" BACKUP_NAME_DEFAULT = "sysdasuten_compressed_ADN.bak" TARGET_IP = "192.168.1.11" TARGET_USER = "Administrador" TARGET_PASS = "UTNlarioja00DASU" # Determinar nombre del archivo backup LOCAL_BACKUP = "#{BACKUP_DIR_WINDOWS}\\#{BACKUP_NAME_DEFAULT}" puts "[*] Dron: Download desde Google Drive" puts " Nodo: dasu-sql4" # Determinar archivo a descargar if opciones[:test_file] puts " 🧪 MODO TEST: Descargando archivo específico" # File ID conocido para test_Backup.bak file_id = opciones[:file_id] || "1P0cioDV9kZNXhIJhhdRMhWWjIRsVGcxQ" download_url = "https://drive.google.com/uc?export=download&id=#{file_id}" puts " File ID: #{file_id}" puts " Destino: #{LOCAL_BACKUP}" elsif opciones[:file_id] puts " Download por file ID" download_url = "https://drive.google.com/uc?export=download&id=#{opciones[:file_id]}" puts " File ID: #{opciones[:file_id]}" puts " Destino: #{LOCAL_BACKUP}" else # Intentar leer file_id desde el output del upload UPLOAD_OUTPUT = '/tmp/dron_upload_output.json' if File.exist?(UPLOAD_OUTPUT) upload_data = JSON.parse(File.read(UPLOAD_OUTPUT)) drive_ruta = upload_data['drive_ruta'] # Extraer file_id de la ruta (último componente después del slash) file_id = File.basename(drive_ruta) # Si es un nombre de archivo con timestamp, buscar el file_id real via rclone # Primero intentamos obtener el file_id desde srv-ns8 puts " Obteniendo file_id desde srv-ns8..." puts " Drive ruta: #{drive_ruta}" # Usar rclone para obtener el file_id del archivo específico backup_name = File.basename(drive_ruta) drive_folder = drive_ruta.rpartition('/').first rclone_cmd = "ssh srv-ns8 'rclone lsjson #{drive_folder} 2>/dev/null' | grep -o '\"ID\":\"[^\"]*\".*\"Name\":\"#{backup_name}\"' | head -1 | grep -o '\"ID\":\"[^\"]*\"' | cut -d'\"' -f4" file_id_result = `#{rclone_cmd}`.strip if file_id_result && !file_id_result.empty? file_id = file_id_result puts " File ID obtenido: #{file_id}" else puts " [!] No se pudo obtener file_id, usando nombre de archivo" file_id = File.basename(drive_ruta) end download_url = "https://drive.google.com/uc?export=download&id=#{file_id}" backup_name = file_id # Usar el nombre del archivo desde drive_ruta puts " Download URL: #{download_url}" puts " Backup nombre: #{backup_name}" puts " Destino: #{BACKUP_DIR_WINDOWS}\\#{backup_name}" else puts " [!] Error: Se requiere --test-file o --file-id" puts " Para produccion: obtener file_id con rclone lsjson desde srv-ns8" exit 1 end end # PowerShell script para download # Para archivos grandes, Google Drive muestra página de confirmación de virus. # Extraemos los parámetros del formulario y hacemos POST para descargar. ps_script = <<~'PSCMD' $ErrorActionPreference = "Stop" $BACKUP_DIR = "F:\BACKUP" $DOWNLOAD_URL = "DOWNLOAD_URL_PLACEHOLDER" $BACKUP_NAME = "BACKUP_NAME_PLACEHOLDER" $LOCAL_BACKUP = "$BACKUP_DIR\$BACKUP_NAME" $JSON_PATH = "C:\temp\dron_download_output.json" # Asegurar directorios $null = New-Item -ItemType Directory -Force -Path "C:\temp" $null = New-Item -ItemType Directory -Force -Path $BACKUP_DIR Write-Host "[1/3] Iniciando descarga..." Write-Host " URL: $DOWNLOAD_URL" Write-Host "[2/3] Descargando..." $start = Get-Date try { # Paso 1: Obtener página de confirmación $response = Invoke-WebRequest -Uri $DOWNLOAD_URL -UseBasicParsing -Headers @{ "User-Agent" = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" } # Extraer parámetros del formulario de confirmación $html = $response.Content $fileId = "" $uuid = "" $confirm = "t" if ($html -match 'name="id" value="([^"]+)"') { $fileId = $matches[1] } if ($html -match 'name="uuid" value="([^"]+)"') { $uuid = $matches[1] } if ($html -match 'name="confirm" value="([^"]+)"') { $confirm = $matches[1] } Write-Host " File ID: $fileId" Write-Host " UUID: $uuid" # Paso 2: Construir URL de descarga con confirmación $downloadConfirmUrl = "https://drive.usercontent.google.com/download?id=$fileId&export=download&confirm=$confirm&uuid=$uuid" Write-Host " URL confirmada: $downloadConfirmUrl" # Paso 3: Descargar archivo real $finalResponse = Invoke-WebRequest -Uri $downloadConfirmUrl -UseBasicParsing -Headers @{ "User-Agent" = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" } # Guardar contenido [System.IO.File]::WriteAllBytes($LOCAL_BACKUP, $finalResponse.Content) $dur = (New-TimeSpan -Start $start -End (Get-Date)).TotalSeconds Write-Host "[+] Descarga en $([math]::Round($dur, 2))s" } catch { Write-Host "[!] Error: $_" exit 1 } Write-Host "[3/3] Verificando..." if (Test-Path $LOCAL_BACKUP) { $tam = (Get-Item $LOCAL_BACKUP).Length Write-Host " Tamano: $([math]::Round($tam / 1MB, 2)) MB" if ($tam -eq 0) { Write-Host "[!] Archivo vacío" exit 1 } } else { Write-Host "[!] No existe" exit 1 } $res = @{ paso = "download_complete" backup_local = $LOCAL_BACKUP drive_origen = "Google Drive" nodo = "dasu-sql4" duracion = [math]::Round($dur, 2) timestamp = (Get-Date -Format "o") siguiente_paso = "restaurar_backup" } $res | ConvertTo-Json | Out-File -FilePath $JSON_PATH -Encoding utf8 Write-Host " Output: $($res | ConvertTo-Json -Compress)" PSCMD # Reemplazar placeholders con valores reales ps_script = ps_script.gsub('DOWNLOAD_URL_PLACEHOLDER', download_url) ps_script = ps_script.gsub('BACKUP_NAME_PLACEHOLDER', backup_name) # Codificar script en base64 ps_encoded = Base64.strict_encode64(ps_script) # Script bash que se ejecuta en srv-dasu bash_script = <<~BASHHEREDOC #!/bin/bash export SSHPASS="#{TARGET_PASS}" sshpass -e ssh -o StrictHostKeyChecking=no -p 7022 #{TARGET_USER}@#{TARGET_IP} \ "powershell -Command \\\"Invoke-Expression ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('#{ps_encoded}')))\\\"" BASHHEREDOC # Guardar script bash en archivo temporal bash_file = Tempfile.new(['download', '.sh']) bash_file.write(bash_script) bash_file.chmod(0755) bash_file.close remote_bash_path = "/tmp/dron_download_#{Time.now.to_i}.sh" puts "\n[1/3] Copiando script a srv-dasu..." scp_cmd = "scp -o StrictHostKeyChecking=no #{bash_file.path} srv-dasu:#{remote_bash_path}" unless system(scp_cmd) puts "[!] Error al copiar script" bash_file.unlink exit 1 end puts "\n[2/3] Ejecutando en dasu-sql4 vía srv-dasu..." ssh_cmd = "ssh srv-dasu 'bash #{remote_bash_path}'" output = `#{ssh_cmd}` output = output.encode('UTF-8', invalid: :replace, undef: :replace, replace: '?') if output puts output # Limpieza bash_file.unlink system("ssh srv-dasu 'rm -f #{remote_bash_path}' 2>/dev/null") if $?.success? puts "\n[3/3] Leyendo output JSON..." json_ps = 'Get-Content C:\temp\dron_download_output.json -Raw' json_encoded = Base64.strict_encode64(json_ps) json_script = <<~JSONBASH.strip #!/bin/bash export SSHPASS="#{TARGET_PASS}" sshpass -e ssh -o StrictHostKeyChecking=no -p 7022 #{TARGET_USER}@#{TARGET_IP} \ "powershell -Command \\\"Invoke-Expression ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('#{json_encoded}')))\\\"" JSONBASH json_file = Tempfile.new(['json', '.sh']) json_file.write(json_script) json_file.chmod(0755) json_file.close remote_json_path = "/tmp/dron_json_#{Time.now.to_i}.sh" system("scp -o StrictHostKeyChecking=no #{json_file.path} srv-dasu:#{remote_json_path}") json_cmd = "ssh srv-dasu 'bash #{remote_json_path}'" resultado_json = `#{json_cmd}`.strip resultado_json = resultado_json.encode('UTF-8', invalid: :replace, undef: :replace, replace: '?') if resultado_json json_file.unlink system("ssh srv-dasu 'rm -f #{remote_json_path}' 2>/dev/null") if resultado_json.empty? puts "[!] No se pudo leer output JSON" exit 1 end json_match = resultado_json.match(/\{.*\}/m) resultado_json = json_match ? json_match[0] : resultado_json puts " Output: #{resultado_json}" resultado = JSON.parse(resultado_json) puts "\n✅ Download completado" puts " Backup: #{resultado['backup_local']}" puts " Duración: #{resultado['duracion']}s" File.write('/tmp/dron_download_output.json', resultado_json) puts " JSON guardado en: /tmp/dron_download_output.json" else puts "[!] Error en ejecución (código: #{$?.exitstatus})" exit 1 end