239 lines
7.6 KiB
Python
239 lines
7.6 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
"""
|
||
|
|
Get all NPMplus proxy host mappings with VMID, Service, IP, Port, and FQDN
|
||
|
|
"""
|
||
|
|
|
||
|
|
import os
|
||
|
|
import sys
|
||
|
|
import json
|
||
|
|
import subprocess
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
# IP to VMID mapping
|
||
|
|
IP_TO_VMID = {
|
||
|
|
"192.168.11.26": "105",
|
||
|
|
"192.168.11.27": "130",
|
||
|
|
"192.168.11.30": "103",
|
||
|
|
"192.168.11.31": "104",
|
||
|
|
"192.168.11.32": "100",
|
||
|
|
"192.168.11.33": "101",
|
||
|
|
"192.168.11.35": "6200",
|
||
|
|
"192.168.11.36": "7811",
|
||
|
|
"192.168.11.37": "7810",
|
||
|
|
"192.168.11.50": "7800",
|
||
|
|
"192.168.11.51": "7801",
|
||
|
|
"192.168.11.52": "7802",
|
||
|
|
"192.168.11.53": "7803",
|
||
|
|
"192.168.11.57": "6201",
|
||
|
|
"192.168.11.64": "6400",
|
||
|
|
"192.168.11.65": "6000",
|
||
|
|
"192.168.11.100": "1000",
|
||
|
|
"192.168.11.101": "1001",
|
||
|
|
"192.168.11.102": "1002",
|
||
|
|
"192.168.11.103": "1003",
|
||
|
|
"192.168.11.104": "1004",
|
||
|
|
"192.168.11.105": "10100",
|
||
|
|
"192.168.11.106": "10101",
|
||
|
|
"192.168.11.110": "106",
|
||
|
|
"192.168.11.111": "107",
|
||
|
|
"192.168.11.112": "108",
|
||
|
|
"192.168.11.120": "10120",
|
||
|
|
"192.168.11.130": "10130",
|
||
|
|
"192.168.11.140": "5000",
|
||
|
|
"192.168.11.150": "1500",
|
||
|
|
"192.168.11.151": "1501",
|
||
|
|
"192.168.11.152": "1502",
|
||
|
|
"192.168.11.153": "1503",
|
||
|
|
"192.168.11.154": "1504",
|
||
|
|
"192.168.11.155": "10150",
|
||
|
|
"192.168.11.156": "10151",
|
||
|
|
"192.168.11.166": "10233",
|
||
|
|
"192.168.11.167": "10234",
|
||
|
|
"192.168.11.211": "2101",
|
||
|
|
"192.168.11.221": "2201",
|
||
|
|
"192.168.11.232": "2301",
|
||
|
|
"192.168.11.233": "2303",
|
||
|
|
"192.168.11.234": "2304",
|
||
|
|
"192.168.11.235": "2305",
|
||
|
|
"192.168.11.236": "2306",
|
||
|
|
"192.168.11.237": "2307",
|
||
|
|
"192.168.11.238": "2308",
|
||
|
|
"192.168.11.240": "2400",
|
||
|
|
"192.168.11.241": "2401",
|
||
|
|
"192.168.11.242": "2402",
|
||
|
|
"192.168.11.243": "2403",
|
||
|
|
}
|
||
|
|
|
||
|
|
# IP to hostname mapping (from documentation)
|
||
|
|
IP_TO_HOSTNAME = {
|
||
|
|
"192.168.11.26": "nginxproxymanager",
|
||
|
|
"192.168.11.27": "monitoring-1",
|
||
|
|
"192.168.11.30": "omada",
|
||
|
|
"192.168.11.31": "gitea",
|
||
|
|
"192.168.11.32": "proxmox-mail-gateway",
|
||
|
|
"192.168.11.33": "proxmox-datacenter-manager",
|
||
|
|
"192.168.11.35": "firefly-1",
|
||
|
|
"192.168.11.36": "mim-api-1",
|
||
|
|
"192.168.11.37": "mim-web-1",
|
||
|
|
"192.168.11.50": "sankofa-api-1",
|
||
|
|
"192.168.11.51": "sankofa-portal-1",
|
||
|
|
"192.168.11.52": "sankofa-keycloak-1",
|
||
|
|
"192.168.11.53": "sankofa-postgres-1",
|
||
|
|
"192.168.11.57": "firefly-ali-1",
|
||
|
|
"192.168.11.64": "indy-1",
|
||
|
|
"192.168.11.65": "fabric-1",
|
||
|
|
"192.168.11.100": "besu-validator-1",
|
||
|
|
"192.168.11.101": "besu-validator-2",
|
||
|
|
"192.168.11.102": "besu-validator-3",
|
||
|
|
"192.168.11.103": "besu-validator-4",
|
||
|
|
"192.168.11.104": "besu-validator-5",
|
||
|
|
"192.168.11.105": "dbis-postgres-primary",
|
||
|
|
"192.168.11.106": "dbis-postgres-replica-1",
|
||
|
|
"192.168.11.110": "redis-rpc-translator",
|
||
|
|
"192.168.11.111": "web3signer-rpc-translator",
|
||
|
|
"192.168.11.112": "vault-rpc-translator",
|
||
|
|
"192.168.11.120": "dbis-redis",
|
||
|
|
"192.168.11.130": "dbis-frontend",
|
||
|
|
"192.168.11.140": "blockscout-1",
|
||
|
|
"192.168.11.150": "besu-sentry-1",
|
||
|
|
"192.168.11.151": "besu-sentry-2",
|
||
|
|
"192.168.11.152": "besu-sentry-3",
|
||
|
|
"192.168.11.153": "besu-sentry-4",
|
||
|
|
"192.168.11.154": "besu-sentry-ali",
|
||
|
|
"192.168.11.155": "dbis-api-primary",
|
||
|
|
"192.168.11.156": "dbis-api-secondary",
|
||
|
|
"192.168.11.166": "npmplus",
|
||
|
|
"192.168.11.167": "npmplus-secondary",
|
||
|
|
"192.168.11.211": "besu-rpc-core-1",
|
||
|
|
"192.168.11.221": "besu-rpc-public-1",
|
||
|
|
"192.168.11.232": "besu-rpc-private-1",
|
||
|
|
"192.168.11.233": "besu-rpc-ali-0x8a",
|
||
|
|
"192.168.11.234": "besu-rpc-ali-0x1",
|
||
|
|
"192.168.11.235": "besu-rpc-luis-0x8a",
|
||
|
|
"192.168.11.236": "besu-rpc-luis-0x1",
|
||
|
|
"192.168.11.237": "besu-rpc-putu-0x8a",
|
||
|
|
"192.168.11.238": "besu-rpc-putu-0x1",
|
||
|
|
"192.168.11.240": "thirdweb-rpc-1",
|
||
|
|
"192.168.11.241": "besu-rpc-thirdweb-0x8a-1",
|
||
|
|
"192.168.11.242": "besu-rpc-thirdweb-0x8a-2",
|
||
|
|
"192.168.11.243": "besu-rpc-thirdweb-0x8a-3",
|
||
|
|
}
|
||
|
|
|
||
|
|
def get_hostname_from_proxmox(ip, vmid):
|
||
|
|
"""Try to get hostname from Proxmox"""
|
||
|
|
try:
|
||
|
|
result = subprocess.run(
|
||
|
|
["ssh", "-o", "StrictHostKeyChecking=no", "-o", "ConnectTimeout=2",
|
||
|
|
"root@192.168.11.11", f"pct config {vmid} 2>/dev/null | grep '^hostname:' | awk '{{print $2}}'"],
|
||
|
|
capture_output=True,
|
||
|
|
text=True,
|
||
|
|
timeout=3
|
||
|
|
)
|
||
|
|
if result.returncode == 0 and result.stdout.strip():
|
||
|
|
return result.stdout.strip()
|
||
|
|
except:
|
||
|
|
pass
|
||
|
|
return IP_TO_HOSTNAME.get(ip, f"VMID-{vmid}")
|
||
|
|
|
||
|
|
def main():
|
||
|
|
project_root = Path(__file__).parent.parent
|
||
|
|
|
||
|
|
# Load .env
|
||
|
|
env_file = project_root / ".env"
|
||
|
|
npm_email = None
|
||
|
|
npm_password = None
|
||
|
|
|
||
|
|
if env_file.exists():
|
||
|
|
with open(env_file) as f:
|
||
|
|
for line in f:
|
||
|
|
if line.startswith("NPM_EMAIL="):
|
||
|
|
npm_email = line.split("=", 1)[1].strip().strip('"').strip("'")
|
||
|
|
elif line.startswith("NPM_PASSWORD="):
|
||
|
|
npm_password = line.split("=", 1)[1].strip().strip('"').strip("'")
|
||
|
|
|
||
|
|
if not npm_email or not npm_password:
|
||
|
|
print("Error: NPM_EMAIL and NPM_PASSWORD must be set in .env", file=sys.stderr)
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
npm_url = "https://192.168.11.166:81"
|
||
|
|
|
||
|
|
# Authenticate
|
||
|
|
import urllib.request
|
||
|
|
import urllib.parse
|
||
|
|
|
||
|
|
auth_data = json.dumps({
|
||
|
|
"identity": npm_email,
|
||
|
|
"secret": npm_password
|
||
|
|
}).encode()
|
||
|
|
|
||
|
|
try:
|
||
|
|
req = urllib.request.Request(
|
||
|
|
f"{npm_url}/api/tokens",
|
||
|
|
data=auth_data,
|
||
|
|
headers={"Content-Type": "application/json"}
|
||
|
|
)
|
||
|
|
with urllib.request.urlopen(req, context=None) as response:
|
||
|
|
token_response = json.loads(response.read().decode())
|
||
|
|
token = token_response.get("token")
|
||
|
|
except Exception as e:
|
||
|
|
print(f"Error authenticating: {e}", file=sys.stderr)
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
if not token:
|
||
|
|
print("Error: Authentication failed", file=sys.stderr)
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
# Get proxy hosts
|
||
|
|
try:
|
||
|
|
req = urllib.request.Request(
|
||
|
|
f"{npm_url}/api/nginx/proxy-hosts",
|
||
|
|
headers={"Authorization": f"Bearer {token}"}
|
||
|
|
)
|
||
|
|
with urllib.request.urlopen(req, context=None) as response:
|
||
|
|
proxy_hosts = json.loads(response.read().decode())
|
||
|
|
except Exception as e:
|
||
|
|
print(f"Error fetching proxy hosts: {e}", file=sys.stderr)
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
# Format output
|
||
|
|
rows = []
|
||
|
|
for host in proxy_hosts:
|
||
|
|
host_id = host.get("id")
|
||
|
|
domain_names = host.get("domain_names", [])
|
||
|
|
forward_host = host.get("forward_host", "")
|
||
|
|
forward_port = host.get("forward_port", "")
|
||
|
|
forward_scheme = host.get("forward_scheme", "http")
|
||
|
|
|
||
|
|
if not domain_names:
|
||
|
|
continue
|
||
|
|
|
||
|
|
fqdn = domain_names[0] if isinstance(domain_names, list) else str(domain_names)
|
||
|
|
vmid = IP_TO_VMID.get(forward_host, "N/A")
|
||
|
|
|
||
|
|
if vmid != "N/A":
|
||
|
|
service = get_hostname_from_proxmox(forward_host, vmid)
|
||
|
|
else:
|
||
|
|
service = f"External/{forward_host}"
|
||
|
|
|
||
|
|
rows.append({
|
||
|
|
"vmid": vmid,
|
||
|
|
"service": service,
|
||
|
|
"ip": forward_host,
|
||
|
|
"port": forward_port,
|
||
|
|
"fqdn": fqdn,
|
||
|
|
"scheme": forward_scheme
|
||
|
|
})
|
||
|
|
|
||
|
|
# Sort by VMID
|
||
|
|
rows.sort(key=lambda x: (int(x["vmid"]) if x["vmid"].isdigit() else 999999, x["fqdn"]))
|
||
|
|
|
||
|
|
# Print table
|
||
|
|
print(f"{'VMID':<8} {'Service/Hostname':<40} {'IP Address':<18} {'Port':<6} {'FQDN':<60}")
|
||
|
|
print(f"{'-'*8} {'-'*40} {'-'*18} {'-'*6} {'-'*60}")
|
||
|
|
|
||
|
|
for row in rows:
|
||
|
|
print(f"{row['vmid']:<8} {row['service']:<40} {row['ip']:<18} {row['port']:<6} {row['fqdn']:<60}")
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
main()
|