14

I have several VMs running on Ubuntu 9.10 via KVM+libvirt. I want to be able to find out the IP address that has been assigned to each host without physically opening a physical "console" to each machine and invoking ifconfig.

Consider:

rascher@localhost:~$ virsh -c qemu:///system list --all
Connecting to uri: qemu:///system
 Id Name                 State
----------------------------------
  1 machine1          running
  2 machine2          running
  - machine3          shut off

My network configuration looks like:

<network>
  <name>default</name>
  <uuid>1be...</uuid>
  <forward mode='route' dev="eth0"/>
  <bridge name='virbr0' stp='on' forwardDelay='0' />
  <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>

So how can I get a listing which says:

machine1 IP address = 192.168.122.16
machine2 IP address = 192.168.122.238
...

I played with arp:

rascher@localhost:~$ arp
Address                  HWtype  HWaddress           Flags Mask            Iface
192.168.122.238          ether   00:16:36:00:61:b0   C                     virbr0
192.168.122.16           ether   00:16:36:52:e8:9c   C                     virbr0
...

But this doesn't map to a virtual machine's ID.

Is there some tool (via the command line, virsh or virt-*) I can ascertain this information? Or do I need to have some fancy script which runs on each individual VM, checks its own IP, and reports it back to the host OS?

8 Answers 8

12

This feature was requested a long time ago. Now libvirt supports it by providing two new commands: domifaddr and net-dhcp-leases

 Usage: domifaddr <domain> [interface] [--full] [--source lease|agent]

 Example outputs:
 virsh # domifaddr f20 --source agent
 Name       MAC address          Protocol     Address
 -------------------------------------------------------------------------------
 lo         00:00:00:00:00:00    ipv4         127.0.0.1/8
 -          -                    ipv6         ::1/128
 eth0       52:54:00:2e:45:ce    ipv4         10.1.33.188/24
 -          -                    ipv6         2001:db8:0:f101::2/64
 -          -                    ipv6         fe80::5054:ff:fe2e:45ce/64
 eth1       52:54:00:b1:70:19    ipv4         192.168.105.201/16
 -          -                    ipv4         192.168.201.195/16
 -          -                    ipv6         2001:db8:ca2:2:1::bd/128
 eth2       52:54:00:36:2a:e5    N/A          N/A
 eth3       52:54:00:20:70:3d    ipv4         192.168.105.240/16
 -          -                    ipv6         fe80::5054:ff:fe20:703d/64

 virsh # domifaddr f20 --full
 Name       MAC address          Protocol     Address
 -------------------------------------------------------------------------------
 vnet0      52:54:00:2e:45:ce    ipv6         2001:db8:0:f101::2/64
 vnet1      52:54:00:b1:70:19    ipv4         192.168.105.201/16
 vnet1      52:54:00:b1:70:19    ipv6         2001:db8:ca2:2:1::bd/128
 vnet3      52:54:00:20:70:3d    ipv4         192.168.105.240/16

 virsh # domifaddr f20 eth0 --source agent --full
 Name       MAC address          Protocol     Address
 -------------------------------------------------------------------------------
 eth0       52:54:00:2e:45:ce    ipv4         10.1.33.188/24
 eth0       52:54:00:2e:45:ce    ipv6         2001:db8:0:f101::2/128
 eth0       52:54:00:2e:45:ce    ipv6         fe80::5054:ff:fe2e:45ce/64

For eth0, ipv6 is managed by libvirt, but ipv4 is not.
For eth1, the second IP is created using ip aliasing.
For eth2, there is no IP configured as of yet.
For eth3, only ipv4 has been configured.
fd00::/8 are private ipv6 ranges. Hence not visible through --source lease

In a different scenario:

 Example Usage: net-dhcp-leases <network> [mac]

 virsh # net-dhcp-leases --network default6
 Expiry Time          MAC address        Protocol  IP address                Hostname        Client ID or DUID
 -------------------------------------------------------------------------------------------------------------------
 2014-06-16 03:40:14  52:54:00:85:90:e2  ipv4      192.168.150.231/24        fedora20-test   01:52:54:00:85:90:e2
 2014-06-16 03:40:17  52:54:00:85:90:e2  ipv6      2001:db8:ca2:2:1::c0/64   fedora20-test   00:04:b1:d8:86:42:e1:6a:aa:cf:d5:86:94:23:6f:94:04:cd
 2014-06-16 03:34:42  52:54:00:e8:73:eb  ipv4      192.168.150.181/24        ubuntu14-vm     -
 2014-06-16 03:34:46  52:54:00:e8:73:eb  ipv6      2001:db8:ca2:2:1::5b/64   -               00:01:00:01:1b:30:c6:aa:52:54:00:e8:73:eb
5

libvirt uses dnsmasq to provide DHCP to the guests, so you could trawl /var/log/daemon.log or dig through the leases file in /var/lib/libvirt to get an IP to hostname mapping.

service start dnsmasq
service enable dnsmasq
2
  • Thank you, for me it was a active dhcpv6-client service that messed up the dhcp-leases for my libvirt vm.
    – barfoos
    Apr 9, 2021 at 8:18
  • I cannot understand why the protocol DHCP in enabled by a service named dns*. Does it rather support cache for the DNS? Oct 30, 2023 at 10:36
2

So, when investigating this, I found that libvirt uses dnsmasq in order to do DHCP and DNS for guest OSes.

And dnsmasq will set the hostname in the hosts's DNS table based on whatever hostname it receives from the guest.

So in accordance with these instructions and a lot of googling, I simply needed to create and add this to /etc/dhclient.conf:

send host-name "machine1"

Now, from my host OS, I can ping machine1.

Does anyone know why I need to add the trailing "." in order for the DNS entry to resolve? How can I change this?

2
  • 1
    Without the trailing dot, your DNS resolver will append it's list of search domains to the hostname when it does a lookup. You could send a FQDN instead, e.g. machine1.example.com and then add example.com to your DNS search order.
    – James
    Jun 23, 2010 at 22:31
  • thanks for this. however the linked notes say to go on the main host machine and edit /etc/resolv.conf and add 192.168.122.1 as the First nameserver (i.e. add the libvirt dnsmasq as an NS), which of course doesnt work on most modern linuxes as there are multiple abstractions nowdays of the networking that rewrite /etc/resolv.conf. havent got mine quite figured out yet.
    – don bright
    Jul 8, 2014 at 10:15
2

I had the same problem so I created the following script:

#!/bin/bash



function showMAC(){
    virsh dumpxml ${1}|grep "mac address"|sed "s/.*'\(.*\)'.*/\1/g"
}

function showIP(){
    for mac in $($0 -m $1); do
        grep $mac /var/log/daemon.log | tail -n 1 | awk '{print $7}'
    done
}

if test -z "${1}"; then
    echo "Usage: ${0} [-i | -m] <domain>"
    echo "  -i   Show IP address (the default)."
    echo "  -m   Show MAC address."
    exit
fi

addr_type="-i"

if test ${1} = "-i" || test ${1} = "-m"; then
    addr_type=${1}
    shift
fi

domain=${1}

test $addr_type = "-i" && showIP $domain || showMAC $domain
2

Lars Kellogg-Stedman has created a set of scripts to automate some of this process. He calls it 'virt-utils'.

He describes it in his blog post here: http://blog.oddbit.com/2013/10/04/automatic-dns-entrie/

He also has a github with some of the scripts he wrote, here:

https://github.com/larsks/virt-utils

You can basically just run this:

git clone https://github.com/larsks/virt-utils 
cd virt-utils 
sudo make install 
virt-hosts

and you will get a listing of each virtual machine by it's "domain name" inside libvirt's virtual-machine-manager. For example, on my machine I have 3 vms running.

don@serebryanya:~/src/virt-utils$ virt-hosts
192.168.122.23  mageia4.x64-net0.default.virt mageia4.x64.default.virt
192.168.122.197 debian7amd64-net0.default.virt debian7amd64.default.virt
192.168.122.15  freebsd10_amd64-net0.default.virt freebsd10_amd64.default.virt

Note, this is not the 'hostname' the VM itself is using, but for a large number of use-cases, it will be 'good enough' and solves the problem of having to 'ifconfig' from within each VM in dhcp land.

Lars' blog posting also shows a way for this to 'auto update' your own /etc/hosts file as libvirt starts and/or stops new VMs. This enables you to do things like ssh myname@fedora20vm or ssh myname@debian6vm without having to find the 192.168.122.x addresses by hand.

I have added a few very minor enhancements, like a script to spit out some ~/.ssh/config options (very very handy for using github on VMs, via Agent Forwarding), here:

https://github.com/donbright/virt-utils (appears to be deleted?)

I'd also like to note that the method of editing dhclient.conf to 'send host-name xxxxx' only works on systems that actually use dhclient.conf in a standard manner. Mageia, for example, has an unusual setup of how it's dhclient works, so the simple instructions wont necessarily work. However, with Lars' method, it works regarldess of the guest OS'es dhcp setup, because he is not relying on the VM to send it's hostname - he is using the 'domain names' within libvirt's machine manager.

1

So how can I get a listing which says:

machine1 IP address = 192.168.122.16

machine2 IP address = 192.168.122.238

at least on fedora you can get that information this way:

cat /var/lib/libvirt/dnsmasq/default.leases

has an output similar to:

1412006226 52:54:00:fe:b3:c0 192.168.122.117 coreos0 01:52:54:00:fe:b3:c0

although that is a bit more than you asked for

0

On Ubuntu dnsmasq is used to provide DNS and DHCP services to the VMs. The dnsmasq processes on the host store their leases in this file:

/var/lib/misc/dnsmasq.leases

This is a normal text file and the lines in it might look similar to this here:

1362729847 52:54:de:ad:be:ef 192.168.122.254 vm-win7 01:52:54:de:ad:be:ef

The fields of interest to you are the third and the fourth column: the third field contains the IPv4 address of the VM and the fourth field either contains an asterisk or the hostname of the VM. This depends on the DHCP reply send by the guest to the dnsmasq service process.

1
  • thanks for this. on my ubuntu machine the file is /var/lib/libvirt/dnsmasq/default.leases with the dhclient.conf file set to do send host-name "myvirtmachine"; as listed above
    – don bright
    Apr 22, 2014 at 2:53
0

You can change the default network definition, map MAC to IP within the xml:

# virsh net-edit default
...
<range start='192.168.122.2' end='192.168.122.254' />
<host mac='52:54:00:6c:3c:02' ip='192.168.122.2' />
<host mac='52:54:00:6c:3c:03' ip='192.168.122.3' />
...
<host mac='52:54:00:6c:3c:fe' ip='192.168.122.254' />

# /etc/init.d/libvirtd restart (restart libvirt service)
# virsh net-destroy default    (remove old settings)
# virsh net-start default      (make changes working)

Once you start a guest, you can list all guest's MAC address via

# virsh list --all --mac

According to the last byte of a MAC address, you can infer the IP address of a guest.

1
  • for what version of virsh should this work? virsh list --all --mac does not work in version 3.0.0
    – reox
    Sep 28, 2018 at 7:35

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .