Ansible Proxmox Inventory and DHCP VMs
Fix for community.general.proxmox (now community.proxmox.proxmox) dynamic inventory not setting ansible_host for QEMU VMs with DHCP networking. Without this, you need -e ansible_host=192.168.1.x every time you target the VM.
The Problem
The Proxmox inventory plugin has want_proxmox_nodes_ansible_host for nodes, but nothing equivalent for QEMU guests. For VMs using cloud-init with ip=dhcp, the plugin sets proxmox_ipconfig0 to:
{"ip": "dhcp"}
Not an actual address. The documented compose example from the plugin docs:
compose:
ansible_host: proxmox_ipconfig0.ip | default(proxmox_net0.ip) | ipaddr('address')
doesn’t help — "dhcp" isn’t an IP, and proxmox_net0 only contains the MAC address and bridge config, not an IP.
The Solution
If the QEMU guest agent is running (agent: 1 in the VM config), the inventory plugin populates proxmox_agent_interfaces with live network data from inside the VM. This includes actual DHCP-assigned addresses.
The tricky part: the agent data uses hyphenated keys (ip-addresses, mac-address) which Jinja2 interprets as subtraction. You can’t use map(attribute='ip-addresses') — it parses as attribute='ip' - addresses. Use .get('ip-addresses', []) instead.
compose:
ansible_host: >-
((proxmox_agent_interfaces | default([])
| selectattr('name', 'equalto', 'eth0') | list | first | default({}))
.get('ip-addresses', [])
| ansible.utils.ipv4 | first | default(''))
| ansible.utils.ipaddr('address')
| default(ansible_host | default(inventory_hostname, true), true)
What this does:
- Finds the
eth0interface inproxmox_agent_interfaces - Extracts its
ip-addresseslist (working around the hyphenated key) - Filters to IPv4 only with
ansible.utils.ipv4 - Strips the CIDR suffix (
192.168.1.83/24→192.168.1.83) - Falls back to existing
ansible_hostorinventory_hostnamefor hosts without agent data
The default(..., true) at the end is important — without the second argument, Jinja2’s default only triggers on undefined variables, not on None or False. The ipaddr filter returns False for invalid input, and want_proxmox_nodes_ansible_host can set ansible_host to None.
Requirements
- QEMU guest agent installed and running in the VM
agent: 1in the VM config (so Proxmox queries the agent)want_facts: truein the inventory plugin configansible.utilscollection (included with the fullansiblepackage)netaddrPython library (pulled in as a dependency ofansible.utils)
Verification
ansible-inventory -i inventory/pve.proxmox.yaml --list 2>/dev/null \
| python3 -c "
import json, sys
data = json.load(sys.stdin)
for host, vars in data['_meta']['hostvars'].items():
print(f\"{host}: {vars.get('ansible_host', 'NOT SET')}\")"
homeassistant: homeassistant
pve: pve
tank: tank
ubuntu-cloud: 192.168.1.83