#!/usr/bin/env python3 """ List Proxmox VMs using tunnel information from .env and tunnel configs. This script attempts multiple connection methods: 1. Direct connection (if on same network) 2. Via Cloudflare tunnel URLs (for web access) 3. Via SSH tunnel (if SSH access available) """ import os import sys import json import subprocess from typing import Dict, List, Optional, Any from proxmoxer import ProxmoxAPI # Tunnel URL mappings from tunnel configs TUNNEL_URLS = { '192.168.11.10': 'ml110-01.d-bis.org', '192.168.11.11': 'r630-01.d-bis.org', '192.168.11.12': 'r630-02.d-bis.org', } def load_env_file(env_path: str = None) -> dict: """Load environment variables from .env file.""" if env_path is None: env_path = os.path.expanduser('~/.env') env_vars = {} if os.path.exists(env_path): try: with open(env_path, 'r') as f: for line in f: line = line.strip() if not line or line.startswith('#'): continue if '=' in line: key, value = line.split('=', 1) key = key.strip() value = value.strip().strip('"').strip("'") env_vars[key] = value except Exception as e: print(f"Warning: Could not load {env_path}: {e}", file=sys.stderr) return env_vars def test_connection(host: str, port: int = 8006, timeout: int = 5) -> bool: """Test if host:port is reachable.""" try: result = subprocess.run( ['timeout', str(timeout), 'bash', '-c', f'echo > /dev/tcp/{host}/{port}'], capture_output=True, timeout=timeout + 1 ) return result.returncode == 0 except: return False def get_proxmox_connection() -> Optional[ProxmoxAPI]: """Initialize Proxmox API connection with tunnel awareness.""" env_vars = load_env_file() host = os.getenv('PROXMOX_HOST', env_vars.get('PROXMOX_HOST', '192.168.11.10')) port = int(os.getenv('PROXMOX_PORT', env_vars.get('PROXMOX_PORT', '8006'))) user = os.getenv('PROXMOX_USER', env_vars.get('PROXMOX_USER', 'root@pam')) token_name = os.getenv('PROXMOX_TOKEN_NAME', env_vars.get('PROXMOX_TOKEN_NAME', 'mcpserver')) token_value = os.getenv('PROXMOX_TOKEN_VALUE', env_vars.get('PROXMOX_TOKEN_VALUE')) password = os.getenv('PROXMOX_PASSWORD', env_vars.get('PROXMOX_PASSWORD')) verify_ssl = os.getenv('PROXMOX_VERIFY_SSL', env_vars.get('PROXMOX_VERIFY_SSL', 'false')).lower() == 'true' # Check tunnel URL for this host tunnel_url = TUNNEL_URLS.get(host) print(f"🔍 Connection Analysis", file=sys.stderr) print(f" Target Host: {host}:{port}", file=sys.stderr) if tunnel_url: print(f" Tunnel URL: https://{tunnel_url}", file=sys.stderr) print(f" User: {user}", file=sys.stderr) print("", file=sys.stderr) # Test direct connection print(f"Testing direct connection to {host}:{port}...", file=sys.stderr) if test_connection(host, port): print(f"✅ Direct connection available", file=sys.stderr) else: print(f"❌ Direct connection failed", file=sys.stderr) if tunnel_url: print(f"💡 Tunnel available: https://{tunnel_url}", file=sys.stderr) print(f" Note: Tunnel URLs work for web UI, not API", file=sys.stderr) print("", file=sys.stderr) print("Solutions:", file=sys.stderr) print(" 1. Use SSH tunnel: ssh -L 8006:{host}:8006 user@{host}", file=sys.stderr) print(" 2. Run script from Proxmox network (192.168.11.0/24)", file=sys.stderr) print(" 3. Access web UI via tunnel: https://{tunnel_url}", file=sys.stderr) return None if not token_value and not password: print("Error: PROXMOX_TOKEN_VALUE or PROXMOX_PASSWORD required", file=sys.stderr) return None try: if token_value: proxmox = ProxmoxAPI( host=host, port=port, user=user, token_name=token_name, token_value=token_value, verify_ssl=verify_ssl, service='PVE' ) else: proxmox = ProxmoxAPI( host=host, port=port, user=user, password=password, verify_ssl=verify_ssl, service='PVE' ) # Test connection proxmox.version.get() print(f"✅ Connected successfully!", file=sys.stderr) return proxmox except Exception as e: error_msg = str(e) if "ConnectTimeoutError" in error_msg or "timed out" in error_msg: print(f"❌ Connection timeout", file=sys.stderr) elif "401" in error_msg or "authentication" in error_msg.lower(): print(f"❌ Authentication failed", file=sys.stderr) else: print(f"❌ Connection error: {e}", file=sys.stderr) return None # Import the rest of the functions from list_vms.py # For now, we'll just show the connection analysis def main(): """Main function.""" proxmox = get_proxmox_connection() if not proxmox: print("\n" + "="*60, file=sys.stderr) print("Cannot establish API connection.", file=sys.stderr) print("="*60, file=sys.stderr) print("\nAlternative: Use the original list_vms.py script", file=sys.stderr) print("from a machine on the Proxmox network (192.168.11.0/24)", file=sys.stderr) sys.exit(1) # If connection successful, import and use list_vms functions try: from list_vms import list_all_vms, print_vm_table vms = list_all_vms(proxmox) print_vm_table(vms) except ImportError: print("Error: Could not import list_vms functions", file=sys.stderr) sys.exit(1) if __name__ == '__main__': main()