The most straightforward method is examining the DHCP lease file maintained by libvirt's dnsmasq instance. On Ubuntu systems, this is typically located at:
sudo cat /var/lib/libvirt/dnsmasq/virbr0.status
This JSON-formatted output will show all active leases with MAC addresses and assigned IPs. For older systems, you might need to check:
sudo cat /var/lib/libvirt/dnsmasq/default.leases
To create a complete mapping from VM names to IP addresses, you'll need to combine the lease information with VM configuration data:
for vm in $(virsh list --name --all); do
vm_mac=$(virsh dumpxml $vm | grep 'mac address' | awk -F\' '{print $2}')
vm_ip=$(grep -B1 "$vm_mac" /var/lib/libvirt/dnsmasq/virbr0.status | grep ip-address | cut -d\" -f4)
echo "$vm: $vm_ip"
done
For newer libvirt versions (1.2.6+), a built-in command provides this functionality:
virsh net-dhcp-leases default
Sample output:
Expiry Time MAC address Protocol IP address Hostname Client ID or DUID ------------------------------------------------------------------------------------------------------ 2023-07-15 14:23:45 52:54:00:12:34:56 ipv4 192.168.122.45 machine1 -
For environments where DHCP lease files aren't accessible, you can parse the ARP cache after correlating MAC addresses:
arp -n -i virbr0 | grep -v incomplete | while read ip _ _ mac _; do
vm=$(virsh list --name --all | while read name; do
[[ $(virsh dumpxml $name | grep -q $mac) ]] && echo $name && break
done)
[ -n "$vm" ] && echo "$vm: $ip"
done
Ensure your network is properly configured for DHCP. The XML should resemble:
<network>
<name>default</name>
<bridge name='virbr0'/>
<forward mode='nat'/>
<ip address='192.168.122.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.122.2' end='192.168.122.254'/>
</dhcp>
</ip>
</network>
If you're not seeing expected results:
- Verify the network is active:
virsh net-list --all
- Check dnsmasq is running:
ps aux | grep dnsmasq
- Restart the network:
virsh net-destroy default && virsh net-start default
When working with KVM/libvirt virtual networks, DHCP lease information is stored in a specific location. For the default network configuration shown in your XML, leases are recorded in:
/var/lib/libvirt/dnsmasq/virbr0.status
This JSON-formatted file contains the complete mapping between MAC addresses and assigned IPs, along with lease timestamps.
The most reliable way to list active DHCP leases is through libvirt's network commands:
virsh net-dhcp-leases default
Sample output for your case would look like:
Expiry Time MAC address Protocol IP address Hostname Client ID or DUID
-----------------------------------------------------------------------------------------
2024-03-15 12:34:56 00:16:36:52:e8:9c ipv4 192.168.122.16 machine1 -
2024-03-15 12:35:12 00:16:36:00:61:b0 ipv4 192.168.122.238 machine2 -
For older libvirt versions without net-dhcp-leases
support, parse the JSON file directly:
sudo cat /var/lib/libvirt/dnsmasq/virbr0.status | jq -r '.[] | "\(.hostname) IP address = \(.ip-address)"'
This produces your desired output format:
machine1 IP address = 192.168.122.16
machine2 IP address = 192.168.122.238
When you need to cross-reference ARP data with libvirt domain information:
for mac in $(virsh dumpxml machine1 | xmllint --xpath "string(/domain/devices/interface/mac/@address)" -); do
grep "$mac" /proc/net/arp
done
Here's a complete Bash solution that combines all approaches:
#!/bin/bash
NETWORK="default"
OUTPUT_FORMAT="%-20s %-15s %-17s\\n"
printf "$OUTPUT_FORMAT" "VM Name" "IP Address" "MAC Address"
printf "===================================================\\n"
for domain in $(virsh list --name --all); do
MAC=$(virsh dumpxml "$domain" | xmllint --xpath "string(/domain/devices/interface/mac/@address)" - 2>/dev/null)
if [ -n "$MAC" ]; then
IP=$(virsh net-dhcp-leases "$NETWORK" | awk -v mac="$MAC" '$2 == mac {print $5}')
printf "$OUTPUT_FORMAT" "$domain" "${IP:-N/A}" "$MAC"
fi
done
- Use
virsh net-dhcp-leases
as the primary method (libvirt 1.2.6+) - For legacy systems, parse
virbr0.status
with JSON tools - Combine with
virsh domifaddr
for additional interface data - Consider setting static DHCP mappings in your network XML for critical VMs