Skip to content

Proxmox

Proxmox set onboot cascade order

This script: - Sets boot VM when node is booted. - Puts periods between each VM is booted.

How to cook it: - Copy the script to Proxmox node (you have to have root access). - Make it executable:

chmod +x proxmox-stagger-boot_03.sh
- Run the script in dry-run mode (report):
sudo bash ./proxmox-stagger-boot_03.sh --dry-run
- If everything is good, apply changes:
sudo bash ./proxmox-stagger-boot_03.sh
- If you want to revert settings:
qm set <VMID> --startup ""

proxmox-stagger-boot_03.sh

Poxmox duplicate MAC addresses

Duplicate VM/CT NIC MAC across all Proxmox clusters. It breaks the network when duplicate MACs are online.

#!/usr/bin/env python3
import re
import requests
from collections import defaultdict

requests.packages.urllib3.disable_warnings()

# --- reuse your existing config ---
proxmoxApiUser = 'user@office.domain.com!user'
proxmoxApiToken1 = '...'
proxmoxApiToken2 = '...'
proxmoxClusterMesh = {
    "pve1": {"clusterAddress": "pve1.in.domain.com", "clusterApiUser": proxmoxApiUser, "clusterApiToken": proxmoxApiToken1},
    "pve2": {"clusterAddress": "pve2.in.domain.com", "clusterApiUser": proxmoxApiUser, "clusterApiToken": proxmoxApiToken2},
}

MAC_RE = re.compile(r'([0-9A-Fa-f]{2}(?::[0-9A-Fa-f]{2}){5})')

def api_get(addr, user, token, path):
    r = requests.get(f"https://{addr}:8006/api2/json{path}",
                     headers={"Authorization": f"PVEAPIToken={user}={token}"},
                     verify=False, timeout=15)
    r.raise_for_status()
    return r.json().get("data", [])

# mac -> list of (cluster, vmname, node, vmid, type)
mac_map = defaultdict(list)

for cluster, cfg in proxmoxClusterMesh.items():
    addr, user, token = cfg["clusterAddress"], cfg["clusterApiUser"], cfg["clusterApiToken"]
    try:
        for res in api_get(addr, user, token, "/cluster/resources?type=vm"):
            node, vmid, vtype = res.get("node"), res.get("vmid"), res.get("type")  # 'qemu' or 'lxc'
            name = res.get("name", f"{vtype}/{vmid}")
            cfgpath = f"/nodes/{node}/{vtype}/{vmid}/config"
            try:
                vmcfg = api_get(addr, user, token, cfgpath)
            except Exception as e:
                print(f"! {cluster} {name} ({vmid}) config error: {e}")
                continue
            # config is a dict; NICs are keys net0, net1, ... (qemu) / net0 (lxc)
            for key, val in (vmcfg.items() if isinstance(vmcfg, dict) else []):
                if key.startswith("net") and isinstance(val, str):
                    m = MAC_RE.search(val)
                    if m:
                        mac_map[m.group(1).lower()].append((cluster, name, node, vmid, vtype))
    except Exception as e:
        print(f"! cluster {cluster} error: {e}")

# --- report duplicates only ---
print("\n=== Duplicate MAC addresses across clusters ===")
found = False
for mac, entries in sorted(mac_map.items()):
    if len(entries) > 1:
        found = True
        print(f"\nMAC {mac}:")
        for cluster, name, node, vmid, vtype in entries:
            print(f"  {cluster:8}  {name:35}  node={node} {vtype}/{vmid}")
if not found:
    print("No duplicate MACs found.")