
"""
Script pentru conectare SSH în cascadă și executarea comenzii racadm pe iDRAC
Optimizat pentru servere Dell iDRAC
"""

import paramiko
import time
import sys
import re

def ssh_idrac_command():
    """
    Conectare directă la iDRAC prin jump server și executare racadm
    """
    jump_server = {
        'hostname': '100.86.145.112',
        'username': 'nsa',
        'password': 'q1w2e3r4',
        'port': 22
    }
    
    idrac_server = {
        'hostname': '192.168.0.69',
        'username': 'root',
        'password': 'q1w2e3Q!W@E#!@#',
        'port': 22
    }
    
    racadm_command = 'racadm serveraction powerup'
    
    jump_ssh = None
    
    try:
        print(f"Conectare la jump server {jump_server['hostname']}...")
        jump_ssh = paramiko.SSHClient()
        jump_ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        jump_ssh.connect(
            hostname=jump_server['hostname'],
            username=jump_server['username'],
            password=jump_server['password'],
            port=jump_server['port'],
            timeout=30
        )
        print("✓ Conectat cu succes la jump server")
        
        # Deschide un shell interactiv
        shell = jump_ssh.invoke_shell(term='vt100', width=120, height=40)
        time.sleep(2)
        
        # Curăță bufferul inițial
        if shell.recv_ready():
            initial_output = shell.recv(4096).decode('utf-8', errors='ignore')
            print("Buffer inițial curățat")
        
        # Execută comanda SSH către iDRAC
        ssh_cmd = f'ssh -o StrictHostKeyChecking=no {idrac_server["username"]}@{idrac_server["hostname"]}\n'
        print(f"Executare: {ssh_cmd.strip()}")
        shell.send(ssh_cmd)
        time.sleep(3)
        
        # Citește răspunsul și caută promptul pentru parolă
        output = ""
        max_attempts = 10
        
        for attempt in range(max_attempts):
            if shell.recv_ready():
                chunk = shell.recv(2048).decode('utf-8', errors='ignore')
                output += chunk
                print(f"Received chunk {attempt + 1}: {repr(chunk)}")
                
                if "password:" in chunk.lower():
                    print("✓ Prompt parolă detectat, trimit parola...")
                    shell.send(f'{idrac_server["password"]}\n')
                    time.sleep(3)
                    break
                elif "/admin1->" in chunk or "admin1->" in chunk:
                    print("✓ Deja conectat la iDRAC!")
                    break
            time.sleep(1)
        
        # Așteaptă să ajungem la promptul iDRAC
        idrac_connected = False
        for attempt in range(10):
            if shell.recv_ready():
                chunk = shell.recv(2048).decode('utf-8', errors='ignore')
                output += chunk
                print(f"Login chunk {attempt + 1}: {repr(chunk)}")
                
                if "/admin1->" in chunk or "admin1->" in chunk:
                    print("✓ Conectat la iDRAC cu succes!")
                    idrac_connected = True
                    break
            time.sleep(1)
        
        if not idrac_connected:
            print("❌ Nu am putut detecta promptul iDRAC")
            print(f"Output complet:\n{output}")
            return False
        
        # Execută comanda racadm
        print(f"Executare comandă: {racadm_command}")
        shell.send(f'{racadm_command}\n')
        time.sleep(5)
        
        # Citește rezultatul comenzii racadm
        racadm_output = ""
        for attempt in range(15):
            if shell.recv_ready():
                chunk = shell.recv(2048).decode('utf-8', errors='ignore')
                racadm_output += chunk
                
                # Verifică dacă comanda s-a terminat (apar din nou promptul)
                if "/admin1->" in chunk or "admin1->" in chunk:
                    break
            time.sleep(0.5)
        
        print(f"\n=== REZULTAT RACADM ===")
        print(racadm_output)
        print("=======================")
        
        # Verifică dacă comanda a avut succes
        success_indicators = [
            "Server power operation successful",
            "RAC1024",  # Success code pentru power up
            "Object value modified successfully"
        ]
        
        error_indicators = [
            "error",
            "failed",
            "invalid",
            "RAC1025"  # Error code
        ]
        
        success = False
        racadm_lower = racadm_output.lower()
        
        for indicator in success_indicators:
            if indicator.lower() in racadm_lower:
                success = True
                print(f"✓ Succes detectat: {indicator}")
                break
        
        for indicator in error_indicators:
            if indicator.lower() in racadm_lower:
                print(f"❌ Eroare detectată: {indicator}")
                success = False
                break
        
        # Ieși din iDRAC
        shell.send('exit\n')
        time.sleep(2)
        
        return success
        
    except Exception as e:
        print(f"❌ Eroare: {e}")
        return False
    finally:
        if jump_ssh:
            jump_ssh.close()
            print("Conexiune închisă")

def ssh_simple_approach():
    """
    Abordare simplă cu expect-like behavior
    """
    jump_server = {
        'hostname': '100.86.145.112',
        'username': 'nsa',
        'password': 'q1w2e3r4'
    }
    
    idrac_server = {
        'hostname': '192.168.0.69',
        'username': 'root',
        'password': 'q1w2e3Q!W@E#!@#'
    }
    
    jump_ssh = None
    
    try:
        print("=== Abordare simplificată ===")
        jump_ssh = paramiko.SSHClient()
        jump_ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        jump_ssh.connect(
            hostname=jump_server['hostname'],
            username=jump_server['username'],
            password=jump_server['password'],
            timeout=30
        )
        print("✓ Conectat la jump server")
        
        # Construiește o comandă SSH cu toate opțiunile
        full_command = (
            f"echo '{idrac_server['password']}' | "
            f"ssh -o StrictHostKeyChecking=no "
            f"-o UserKnownHostsFile=/dev/null "
            f"-o ConnectTimeout=30 "
            f"-o BatchMode=no "
            f"-o PasswordAuthentication=yes "
            f"{idrac_server['username']}@{idrac_server['hostname']} "
            f"'racadm serveraction powerup'"
        )
        
        print("Executare comandă combinată...")
        stdin, stdout, stderr = jump_ssh.exec_command(full_command, timeout=60)
        
        exit_status = stdout.channel.recv_exit_status()
        output = stdout.read().decode('utf-8', errors='ignore')
        error = stderr.read().decode('utf-8', errors='ignore')
        
        print(f"Exit status: {exit_status}")
        print(f"Output:\n{output}")
        if error and "warning" not in error.lower():
            print(f"Error:\n{error}")
        
        return exit_status == 0 and "successful" in output.lower()
        
    except Exception as e:
        print(f"❌ Eroare abordare simplă: {e}")
        return False
    finally:
        if jump_ssh:
            jump_ssh.close()

def main():
    print("=== SSH to iDRAC Script ===")
    print("Conectare: 100.86.145.112 -> 192.168.0.69 (iDRAC)")
    print("Comandă: racadm serveraction powerup")
    print("=" * 50)
    
    # Metodă 1: Shell interactiv optimizat pentru iDRAC
    print("\n--- Metodă 1: Shell interactiv pentru iDRAC ---")
    success = ssh_idrac_command()
    
    if not success:
        print("\n--- Metodă 2: Comandă simplificată ---")
        success = ssh_simple_approach()
    
    if success:
        print("\n✅ SERVERUL A FOST PORNIT CU SUCCES! ✅")
        sys.exit(0)
    else:
        print("\n❌ Nu am putut porni serverul")
        print("\nVerifică:")
        print("- Serverul este oprit și poate fi pornit")
        print("- Credențialele iDRAC sunt corecte")
        print("- Conexiunea la rețea funcționează")
        sys.exit(1)

if __name__ == "__main__":
    main()
