138 lines
4.7 KiB
Python
138 lines
4.7 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
"""
|
||
|
|
Scan all containers across all Proxmox hosts
|
||
|
|
Outputs: VMID, name, host, IP config, current IP, status
|
||
|
|
"""
|
||
|
|
|
||
|
|
import subprocess
|
||
|
|
import sys
|
||
|
|
from datetime import datetime
|
||
|
|
import re
|
||
|
|
|
||
|
|
HOSTS = [
|
||
|
|
("192.168.11.10", "ml110"),
|
||
|
|
("192.168.11.11", "r630-01"),
|
||
|
|
("192.168.11.12", "r630-02"),
|
||
|
|
]
|
||
|
|
|
||
|
|
def ssh_command(host, command):
|
||
|
|
"""Execute SSH command and return output"""
|
||
|
|
try:
|
||
|
|
result = subprocess.run(
|
||
|
|
["ssh", "-o", "ConnectTimeout=10", f"root@{host}", command],
|
||
|
|
capture_output=True,
|
||
|
|
text=True,
|
||
|
|
timeout=30
|
||
|
|
)
|
||
|
|
return result.stdout.strip() if result.returncode == 0 else ""
|
||
|
|
except Exception as e:
|
||
|
|
print(f" Error executing command on {host}: {e}", file=sys.stderr)
|
||
|
|
return ""
|
||
|
|
|
||
|
|
def get_container_info(host, vmid):
|
||
|
|
"""Get all info for a container in one call"""
|
||
|
|
script = f"""
|
||
|
|
name=$(pct config {vmid} 2>/dev/null | grep '^name:' | cut -d: -f2 | tr -d ' ' || echo 'unnamed')
|
||
|
|
hostname_vm=$(pct config {vmid} 2>/dev/null | grep '^hostname:' | cut -d: -f2 | tr -d ' ' || echo 'N/A')
|
||
|
|
status=$(pct status {vmid} 2>/dev/null | grep 'status:' | awk '{{print $2}}' || echo 'unknown')
|
||
|
|
net_config=$(pct config {vmid} 2>/dev/null | grep '^net0:' || echo '')
|
||
|
|
ip_config='N/A'
|
||
|
|
current_ip='N/A'
|
||
|
|
if echo "$net_config" | grep -q 'ip='; then
|
||
|
|
ip_config=$(echo "$net_config" | grep -oE 'ip=[^,]+' | cut -d= -f2)
|
||
|
|
if [ "$ip_config" = 'dhcp' ] || [ "$ip_config" = 'auto' ]; then
|
||
|
|
if [ "$status" = 'running' ]; then
|
||
|
|
current_ip=$(pct exec {vmid} -- hostname -I 2>/dev/null | awk '{{print $1}}' || echo 'N/A')
|
||
|
|
fi
|
||
|
|
else
|
||
|
|
current_ip=$(echo "$ip_config" | cut -d'/' -f1)
|
||
|
|
fi
|
||
|
|
fi
|
||
|
|
echo "$name|$hostname_vm|$status|$ip_config|$current_ip"
|
||
|
|
"""
|
||
|
|
output = ssh_command(host, script)
|
||
|
|
if output:
|
||
|
|
parts = output.split('|')
|
||
|
|
if len(parts) == 5:
|
||
|
|
return {
|
||
|
|
'name': parts[0],
|
||
|
|
'hostname': parts[1],
|
||
|
|
'status': parts[2],
|
||
|
|
'ip_config': parts[3],
|
||
|
|
'current_ip': parts[4]
|
||
|
|
}
|
||
|
|
return None
|
||
|
|
|
||
|
|
def main():
|
||
|
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||
|
|
output_file = f"/home/intlc/projects/proxmox/CONTAINER_INVENTORY_{timestamp}.md"
|
||
|
|
csv_file = f"/home/intlc/projects/proxmox/container_inventory_{timestamp}.csv"
|
||
|
|
|
||
|
|
print("=== Scanning All Containers Across All Hosts ===\n")
|
||
|
|
|
||
|
|
# Create output files
|
||
|
|
with open(output_file, 'w') as f:
|
||
|
|
f.write(f"""# Container Inventory - Complete Scan
|
||
|
|
|
||
|
|
**Generated**: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
|
||
|
|
**Purpose**: Complete inventory of all containers across all Proxmox hosts
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## All Containers
|
||
|
|
|
||
|
|
| VMID | Name | Host | Status | IP Config | Current IP | Hostname |
|
||
|
|
|------|------|------|--------|----------|------------|----------|
|
||
|
|
""")
|
||
|
|
|
||
|
|
with open(csv_file, 'w') as f:
|
||
|
|
f.write("VMID,Name,Host,Status,IP_Config,Current_IP,Hostname\n")
|
||
|
|
|
||
|
|
dhcp_count = 0
|
||
|
|
static_count = 0
|
||
|
|
total_count = 0
|
||
|
|
|
||
|
|
for host_ip, hostname in HOSTS:
|
||
|
|
print(f"Scanning {hostname} ({host_ip})...")
|
||
|
|
|
||
|
|
# Get all VMIDs
|
||
|
|
vmids_output = ssh_command(host_ip, "pct list 2>/dev/null | tail -n +2 | awk '{print $1}'")
|
||
|
|
if not vmids_output:
|
||
|
|
print(f" No containers found on {hostname}")
|
||
|
|
continue
|
||
|
|
|
||
|
|
vmids = [vmid.strip() for vmid in vmids_output.split('\n') if vmid.strip()]
|
||
|
|
|
||
|
|
for vmid in vmids:
|
||
|
|
info = get_container_info(host_ip, vmid)
|
||
|
|
if not info:
|
||
|
|
continue
|
||
|
|
|
||
|
|
total_count += 1
|
||
|
|
|
||
|
|
# Count by type
|
||
|
|
if info['ip_config'] in ['dhcp', 'auto']:
|
||
|
|
dhcp_count += 1
|
||
|
|
elif info['ip_config'] != 'N/A' and info['ip_config']:
|
||
|
|
static_count += 1
|
||
|
|
|
||
|
|
# Write to files
|
||
|
|
with open(output_file, 'a') as f:
|
||
|
|
f.write(f"| {vmid} | {info['name']} | {hostname} | {info['status']} | {info['ip_config']} | {info['current_ip']} | {info['hostname']} |\n")
|
||
|
|
|
||
|
|
with open(csv_file, 'a') as f:
|
||
|
|
f.write(f"{vmid},\"{info['name']}\",{hostname},{info['status']},{info['ip_config']},{info['current_ip']},{info['hostname']}\n")
|
||
|
|
|
||
|
|
print(f"\n=== Scan Complete ===")
|
||
|
|
print(f"Total containers scanned: {total_count}")
|
||
|
|
print(f"Output files:")
|
||
|
|
print(f" - {output_file}")
|
||
|
|
print(f" - {csv_file}")
|
||
|
|
print(f"\n=== Summary by IP Configuration ===")
|
||
|
|
print(f"DHCP containers: {dhcp_count}")
|
||
|
|
print(f"Static IP containers: {static_count}")
|
||
|
|
print(f"Total containers: {total_count}")
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
main()
|