160 lines
5.9 KiB
Python
160 lines
5.9 KiB
Python
|
|
#!/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()
|