Bug 1179729

Summary: [RFE] libvirt should be able to report guest ip addresses on virtual networks
Product: Red Hat Enterprise Linux 7 Reporter: Federico Simoncelli <fsimonce>
Component: libvirtAssignee: Michal Privoznik <mprivozn>
Status: CLOSED ERRATA QA Contact: Virtualization Bugs <virt-bugs>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 7.2CC: djasa, dyuan, fweimer, honzhang, laine, lmiksik, mprivozn, mzhan, rbalakri, rjones, shyu
Target Milestone: rcKeywords: FutureFeature, Upstream
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: libvirt-1.2.14-1.el7 Doc Type: Enhancement
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2015-11-19 06:07:14 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On: 559366    
Bug Blocks:    

Description Federico Simoncelli 2015-01-07 12:29:41 UTC
Description of problem:
Libvirt should implement an API to report the IP addresses of the guest on its virtual networks.

Multiple strategies to find the ip address could be implemented:

- read the entries from /proc/net/arp (find vm mac address and ip)
- send an inarp/rarp packet to request what's the ip from the mac address
- read the entries in the dnsmasq lease file (if enabled and we trust that the guest is not using a static ip)
- monitor the traffic and cache the ip
- ask to qemu-ga

I think we can't protect against a malicious guests but I think we should consider that accidental misconfigurations can happen (using a static ip vs using the libvirt dhcp, etc.).

Comment 2 Michal Privoznik 2015-01-07 13:36:51 UTC
Federico, libvirt already has a set of APIs to query guest's IP addresses. For instance 'virsh net-dhcp-leases' which boils down to virNetworkGetDHCPLeases(). This will give you the list of IP addresses assigned by dnsmasq.

Truth to be told, not every method you mention is implemented yet. But, hey, we're trying. For instance, there's this patchset:

https://www.redhat.com/archives/libvir-list/2014-December/msg00866.html

But there's an workaround for qemu-ga. You can already issue an arbitrary qemu-ga command. Although you will need to parse the json reply yourself. Anyway, the approaches that are not implemented yet, will require new API which is not feasible in 7.1, thus moving to 7.2.

And for the arp table, Rich Jones has a script for that already:

http://rwmj.wordpress.com/2010/10/26/tip-find-the-ip-address-of-a-virtual-machine/

Comment 3 Federico Simoncelli 2015-01-07 15:17:28 UTC
(In reply to Michal Privoznik from comment #2)
> Federico, libvirt already has a set of APIs to query guest's IP addresses.
> For instance 'virsh net-dhcp-leases' which boils down to
> virNetworkGetDHCPLeases(). This will give you the list of IP addresses
> assigned by dnsmasq.
> 
> Truth to be told, not every method you mention is implemented yet. But, hey,
> we're trying. For instance, there's this patchset:
> 
> https://www.redhat.com/archives/libvir-list/2014-December/msg00866.html

This bz was filed to indeed track the inclusion of that patchset in 7.2.

> But there's an workaround for qemu-ga. You can already issue an arbitrary
> qemu-ga command. Although you will need to parse the json reply yourself.
> Anyway, the approaches that are not implemented yet, will require new API
> which is not feasible in 7.1, thus moving to 7.2.

Even though qemu-ga is a very good method to get the ip address it's not reliable enough for all the use cases. In fact probably the most important one is to access for the first time a VM to install qemu-ga (which may not be included in the base image).

> And for the arp table, Rich Jones has a script for that already:
> 
> http://rwmj.wordpress.com/2010/10/26/tip-find-the-ip-address-of-a-virtual-
> machine/

I already saw that one and I provided a python library/cli that is using the same method:

https://github.com/simon3z/virt-address

I am looking forward to see that method being included as one of the implemented ones for virDomainInterfaceAddresses.

Comment 4 Michal Privoznik 2015-04-27 05:32:39 UTC
I proudly announce that the patches are pushed upstream for a while now:

commit 2f36e6944e6eb56a00e19fcd85ec8513461597c9
Author:     Nehal J Wani <nehaljw.kkd1>
AuthorDate: Mon Jan 26 00:08:49 2015 +0530
Commit:     Daniel P. Berrange <berrange>
CommitDate: Tue Mar 17 15:15:39 2015 +0000

    domifaddr: Add virsh support
    
    tools/virsh-domain-monitor.c
       * Introduce new command : domifaddr
         Usage: domifaddr <domain> [interface] [--full] [--source lease|agent]
    
         Example outputs:
         virsh # domifaddr f20
         Name       MAC address          Protocol     Address
         -------------------------------------------------------------------------------
         lo         00:00:00:00:00:00    ipv4         127.0.0.1/8
         -          -                    ipv6         ::1/128
         vnet0      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
         vnet1      52:54:00:b1:70:19    ipv4         192.168.105.201/16
         -          -                    ipv4         192.168.201.195/16
         -          -                    ipv6         fe80::5054:ff:feb1:7019/64
         vnet2      52:54:00:36:2a:e5    N/A          N/A
         vnet3      52:54:00:20:70:3d    ipv4         192.168.105.240/16
         -          -                    ipv6         fe80::5054:ff:fe20:703d/64
    
         virsh # domifaddr f20 eth1 --source lease
         Name       MAC address          Protocol     Address
         -------------------------------------------------------------------------------
         vnet1      52:54:00:b1:70:19    ipv4         192.168.105.201/16
         -          -                    ipv4         192.168.201.195/16
         -          -                    ipv6         fe80::5054:ff:feb1:7019/64
    
         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/64
         eth0       52:54:00:2e:45:ce    ipv6         fe80::5054:ff:fe2e:45ce/64
    
    tools/virsh.pod
       * Document new command
    
    Signed-off-by: Nehal J Wani <nehaljw.kkd1>

commit 0977b8aa071de550e1a013d35e2c72615e65d520
Author:     Nehal J Wani <nehaljw.kkd1>
AuthorDate: Mon Jan 26 00:08:48 2015 +0530
Commit:     Daniel P. Berrange <berrange>
CommitDate: Tue Mar 17 15:15:38 2015 +0000

    domifaddr: Implement the API for qemu
    
    By querying the qemu guest agent with the QMP command
    "guest-network-get-interfaces" and converting the received JSON
    output to structured objects.
    
    Although "ifconfig" is deprecated, IP aliases created by "ifconfig"
    are supported by this API. The legacy syntax of an IP alias is:
    "<ifname>:<alias-name>". Since we want all aliases to be clubbed
    under parent interface, simply stripping ":<alias-name>" suffices.
    Note that IP aliases formed by "ip" aren't visible to "ifconfig",
    and aliases created by "ip" do not have any specific name. But
    we are lucky, as qemu guest agent detects aliases created by both.
    
    src/qemu/qemu_agent.h:
      * Define qemuAgentGetInterfaces
    
    src/qemu/qemu_agent.c:
      * Implement qemuAgentGetInterface
    
    src/qemu/qemu_driver.c:
      * New function qemuGetDHCPInterfaces
      * New function qemuDomainInterfaceAddresses
    
    src/remote_protocol-sructs:
      * Define new structs
    
    tests/qemuagenttest.c:
      * Add new test: testQemuAgentGetInterfaces
        Test cases for IP aliases, 0 or multiple ipv4/ipv6 address(es)
    
    Signed-off-by: Nehal J Wani <nehaljw.kkd1>

commit 71546d1798fc6ae4a55acf1b63f33d37ec71ba3e
Author:     Nehal J Wani <nehaljw.kkd1>
AuthorDate: Mon Jan 26 00:08:47 2015 +0530
Commit:     Daniel P. Berrange <berrange>
CommitDate: Tue Mar 17 15:15:38 2015 +0000

    domifaddr: Implement the remote protocol
    
    daemon/remote.c
       * Define remoteSerializeDomainInterface, remoteDispatchDomainInterfaceAddresses
    
    src/remote/remote_driver.c
       * Define remoteDomainInterfaceAddresses
    
    src/remote/remote_protocol.x
       * New RPC procedure: REMOTE_PROC_DOMAIN_INTERFACE_ADDRESSES
       * Define structs remote_domain_ip_addr, remote_domain_interface,
         remote_domain_interfaces_addresse_args, remote_domain_interface_addresses_ret
       * Introduce upper bounds (to handle DoS attacks):
         REMOTE_DOMAIN_INTERFACE_MAX = 2048
         REMOTE_DOMAIN_IP_ADDR_MAX = 2048
         Restrictions on the maximum number of aliases per interface were
         removed after kernel v2.0, and theoretically, at present, there
         are no upper limits on number of interfaces per virtual machine
         and on the number of IP addresses per interface.
    
    src/remote_protocol-structs
       * New structs added
    
    Signed-off-by: Nehal J Wani <nehaljw.kkd1>

commit 5b5242a7cba7a851c748e1c8645e5a564ad867b0
Author:     Nehal J Wani <nehaljw.kkd1>
AuthorDate: Mon Jan 26 00:08:46 2015 +0530
Commit:     Daniel P. Berrange <berrange>
CommitDate: Tue Mar 17 15:15:38 2015 +0000

    domifaddr: Implement the public APIs
    
    Define helper function virDomainInterfaceFree, which allows
    the upper layer application to free the domain interface object
    conveniently.
    
    The API is going to provide multiple methods by flags, e.g.
      * Query guest agent
      * Parse DHCP lease file
    
    include/libvirt/libvirt-domain.h
      * Define virDomainInterfaceAddresses, virDomainInterfaceFree
      * Define structs virDomainInterface, virDomainIPAddress
    
    src/driver-hypervisor.h:
      * Define domainInterfaceAddresses
    
    src/libvirt-domain.c:
      * Implement virDomainInterfaceAddresses
      * Implement virDomainInterfaceFree
    
    src/libvirt_public.syms:
      * Export the new symbols
    
    Signed-off-by: Nehal J Wani <nehaljw.kkd1>

$ git describe --contains  2f36e6944e6eb56a00e19fcd85ec8513461597c9
v1.2.14-rc1~118

Comment 6 Michal Privoznik 2015-05-07 07:49:16 UTC
*** Bug 1195281 has been marked as a duplicate of this bug. ***

Comment 7 hongming 2015-06-03 09:41:31 UTC
Verify it as follows

# rpm -q libvirt
libvirt-1.2.15-2.el7.x86_64

# virsh start test3
Domain test3 started

# virsh domuuid test3
7347d748-f7ce-448f-8d49-3d29c9bcac30

# virsh domid test3
8

# virsh domifaddr 7347d748-f7ce-448f-8d49-3d29c9bcac30
 Name       MAC address          Protocol     Address
-------------------------------------------------------------------------------
 vnet3      52:54:00:27:0b:8f    ipv4         192.168.122.89/24
 vnet4      52:54:00:fe:80:17    ipv4         192.168.122.20/24

# virsh domifaddr 8
 Name       MAC address          Protocol     Address
-------------------------------------------------------------------------------
 vnet3      52:54:00:27:0b:8f    ipv4         192.168.122.89/24
 vnet4      52:54:00:fe:80:17    ipv4         192.168.122.20/24

# virsh domifaddr test3
 Name       MAC address          Protocol     Address
-------------------------------------------------------------------------------
 vnet3      52:54:00:27:0b:8f    ipv4         192.168.122.89/24
 vnet4      52:54:00:fe:80:17    ipv4         192.168.122.20/24


# virsh domifaddr test3 vnet3
 Name       MAC address          Protocol     Address
-------------------------------------------------------------------------------
 vnet3      52:54:00:27:0b:8f    ipv4         192.168.122.89/24

# virsh domifaddr test3 vnet4
 Name       MAC address          Protocol     Address
-------------------------------------------------------------------------------
 vnet4      52:54:00:fe:80:17    ipv4         192.168.122.20/24


# virsh domifaddr test3 --source lease
 Name       MAC address          Protocol     Address
-------------------------------------------------------------------------------
 vnet3      52:54:00:27:0b:8f    ipv4         192.168.122.89/24
 vnet4      52:54:00:fe:80:17    ipv4         192.168.122.20/24

# virsh domifaddr test3 --source agent
 Name       MAC address          Protocol     Address
-------------------------------------------------------------------------------
 lo         00:00:00:00:00:00    ipv4         127.0.0.1/8
 -          -                    ipv6         ::1/128
 eth439     52:54:00:27:0b:8f    ipv4         192.168.122.89/24
 -          -                    ipv6         fe80::5054:ff:fe27:b8f/64
 eth440     52:54:00:fe:80:17    ipv4         192.168.122.20/24
 -          -                    ipv6         fe80::5054:ff:fefe:8017/64
 virbr0     52:54:00:86:5f:43    ipv4         192.168.122.1/24
 virbr0-nic 52:54:00:86:5f:43    ipv6         fe80::5054:ff:fe86:5f43/64


Login guest to check the address . The result is consistent with result returned by libvirt.

Comment 8 hongming 2015-06-03 10:33:28 UTC
# virsh domifaddr test3 --source agent
 Name       MAC address          Protocol     Address
-------------------------------------------------------------------------------
 lo         00:00:00:00:00:00    ipv4         127.0.0.1/8
 -          -                    ipv6         ::1/128
 eth439     52:54:00:27:0b:8f    ipv4         192.168.122.10/24
 -          -                    ipv6         fe80::5054:ff:fe27:b8f/64
 -          -                    ipv4         192.168.122.11/24
 -          -                    ipv4         192.168.122.12/24
 -          -                    ipv4         192.168.122.13/24
 eth440     52:54:00:fe:80:17    ipv4         192.168.122.20/24
 -          -                    ipv6         fe80::5054:ff:fefe:8017/64
 virbr0     52:54:00:86:5f:43    ipv4         192.168.122.1/24
 virbr0-nic 52:54:00:86:5f:43    ipv6         fe80::5054:ff:fe86:5f43/64

# virsh domifaddr test3 --source agent --full
 Name       MAC address          Protocol     Address
-------------------------------------------------------------------------------
 lo         00:00:00:00:00:00    ipv4         127.0.0.1/8
 lo         00:00:00:00:00:00    ipv6         ::1/128
 eth439     52:54:00:27:0b:8f    ipv4         192.168.122.10/24
 eth439     52:54:00:27:0b:8f    ipv6         fe80::5054:ff:fe27:b8f/64
 eth439     52:54:00:27:0b:8f    ipv4         192.168.122.11/24
 eth439     52:54:00:27:0b:8f    ipv4         192.168.122.12/24
 eth439     52:54:00:27:0b:8f    ipv4         192.168.122.13/24
 eth440     52:54:00:fe:80:17    ipv4         192.168.122.20/24
 eth440     52:54:00:fe:80:17    ipv6         fe80::5054:ff:fefe:8017/64
 virbr0     52:54:00:86:5f:43    ipv4         192.168.122.1/24
 virbr0-nic 52:54:00:86:5f:43    ipv6         fe80::5054:ff:fe86:5f43/64

In guest , the eth439 has multiple addresses or alias as follows. 
eth439:0 eth439:1 eth439:2 eth439:3  

But the result returned by libvirt only display it as eth439 . Do you think it is a bug ?

Comment 9 Michal Privoznik 2015-06-03 16:30:41 UTC
(In reply to hongming from comment #8)
> # virsh domifaddr test3 --source agent
>  Name       MAC address          Protocol     Address
> -----------------------------------------------------------------------------
> --
>  lo         00:00:00:00:00:00    ipv4         127.0.0.1/8
>  -          -                    ipv6         ::1/128
>  eth439     52:54:00:27:0b:8f    ipv4         192.168.122.10/24
>  -          -                    ipv6         fe80::5054:ff:fe27:b8f/64
>  -          -                    ipv4         192.168.122.11/24
>  -          -                    ipv4         192.168.122.12/24
>  -          -                    ipv4         192.168.122.13/24
>  eth440     52:54:00:fe:80:17    ipv4         192.168.122.20/24
>  -          -                    ipv6         fe80::5054:ff:fefe:8017/64
>  virbr0     52:54:00:86:5f:43    ipv4         192.168.122.1/24
>  virbr0-nic 52:54:00:86:5f:43    ipv6         fe80::5054:ff:fe86:5f43/64
> 
> # virsh domifaddr test3 --source agent --full
>  Name       MAC address          Protocol     Address
> -----------------------------------------------------------------------------
> --
>  lo         00:00:00:00:00:00    ipv4         127.0.0.1/8
>  lo         00:00:00:00:00:00    ipv6         ::1/128
>  eth439     52:54:00:27:0b:8f    ipv4         192.168.122.10/24
>  eth439     52:54:00:27:0b:8f    ipv6         fe80::5054:ff:fe27:b8f/64
>  eth439     52:54:00:27:0b:8f    ipv4         192.168.122.11/24
>  eth439     52:54:00:27:0b:8f    ipv4         192.168.122.12/24
>  eth439     52:54:00:27:0b:8f    ipv4         192.168.122.13/24
>  eth440     52:54:00:fe:80:17    ipv4         192.168.122.20/24
>  eth440     52:54:00:fe:80:17    ipv6         fe80::5054:ff:fefe:8017/64
>  virbr0     52:54:00:86:5f:43    ipv4         192.168.122.1/24
>  virbr0-nic 52:54:00:86:5f:43    ipv6         fe80::5054:ff:fe86:5f43/64
> 
> In guest , the eth439 has multiple addresses or alias as follows. 
> eth439:0 eth439:1 eth439:2 eth439:3  
> 
> But the result returned by libvirt only display it as eth439 . Do you think
> it is a bug ?

Well, that's how qemu-ga reports the adresses. Since it's using getifaddrs() to iterate over guest interfaces, it's not likely to be a bug. I think we are okay here.

Comment 10 Laine Stump 2015-06-03 19:06:09 UTC
Yes, it's definitely not a libvirt bug (since libvirt's job is just to relay what it's told by qemu-ga), and whether or not it's a qemu-ga bug is up to interpretation.

The "alias interfaces" like eth439:1 are not real interfaces according to the kernel (for example, they have no ifindex) and are deprecated (the proper method of assigning multiple IP addresses to a single interface is to add more addresses to the interface, not to define an alias), so my opinion is that this is just an artifact the guest using a deprecated config style, so it shouldn't be counted as a bug in any package.

Comment 11 hongming 2015-06-04 07:53:56 UTC
Add test scenario for flag combination. The result is expected.

# virsh domifaddr test3 --source agent --full
 Name       MAC address          Protocol     Address
-------------------------------------------------------------------------------
 lo         00:00:00:00:00:00    ipv4         127.0.0.1/8
 lo         00:00:00:00:00:00    ipv6         ::1/128
 eth439     52:54:00:27:0b:8f    ipv4         192.168.122.10/24
 eth439     52:54:00:27:0b:8f    ipv6         fe80::5054:ff:fe27:b8f/64
 eth439     52:54:00:27:0b:8f    ipv4         192.168.122.11/24
 eth439     52:54:00:27:0b:8f    ipv4         192.168.122.12/24
 eth439     52:54:00:27:0b:8f    ipv4         192.168.122.13/24
 eth440     52:54:00:fe:80:17    ipv4         192.168.122.20/24
 eth440     52:54:00:fe:80:17    ipv6         fe80::5054:ff:fefe:8017/64

# cat /var/lib/libvirt/dnsmasq/virbr0.status
[
    {
        "ip-address": "192.168.122.49",
        "mac-address": "52:54:00:cc:6d:e8",
        "expiry-time": 1433399040
    },
    {
        "ip-address": "192.168.122.20",
        "mac-address": "52:54:00:fe:80:17",
        "expiry-time": 1433399768
    }
]


# virsh domifaddr test3 --source agent --interface eth439
 Name       MAC address          Protocol     Address
-------------------------------------------------------------------------------
 eth439     52:54:00:27:0b:8f    ipv4         192.168.122.10/24
 -          -                    ipv6         fe80::5054:ff:fe27:b8f/64
 -          -                    ipv4         192.168.122.11/24
 -          -                    ipv4         192.168.122.12/24
 -          -                    ipv4         192.168.122.13/24


# virsh domifaddr test3 --source agent --interface eth439 --full
 Name       MAC address          Protocol     Address
-------------------------------------------------------------------------------
 eth439     52:54:00:27:0b:8f    ipv4         192.168.122.10/24
 eth439     52:54:00:27:0b:8f    ipv6         fe80::5054:ff:fe27:b8f/64
 eth439     52:54:00:27:0b:8f    ipv4         192.168.122.11/24
 eth439     52:54:00:27:0b:8f    ipv4         192.168.122.12/24
 eth439     52:54:00:27:0b:8f    ipv4         192.168.122.13/24


# virsh domifaddr test3 --source lease --interface vnet4
 Name       MAC address          Protocol     Address
-------------------------------------------------------------------------------
 vnet4      52:54:00:fe:80:17    ipv4         192.168.122.20/24

Comment 12 hongming 2015-06-04 08:04:38 UTC
Add some negative test scenario. The result is expected. And according the result of comment 7 , comment 10 and comment 11. Move its status to VERIFIED. 

# virsh list --all
 Id    Name                           State
----------------------------------------------------
 9     test3                          running
 -     maximum                        shut off
 -     r7                             shut off
 -     r7a                            shut off
 -     r7b                            shut off

# virsh domifaddr r7
error: Failed to query for interfaces addresses
error: Requested operation is not valid: domain is not running

# virsh domifaddr aa
error: failed to get domain 'aa'
error: Domain not found: no domain with matching name 'aa'

# virsh domifaddr test3 --fully
error: command 'domifaddr' doesn't support option --fully

In guest , stop the qemu-ga service 

In host , run the following cmd
# virsh domifaddr test3 --source agent
error: Failed to query for interfaces addresses
error: Guest agent is not responding: QEMU guest agent is not connected

In guest, start the qemu-ga service 

In host , run the following cmd
# virsh domifaddr test3 --source agent --full
 Name       MAC address          Protocol     Address
-------------------------------------------------------------------------------
 lo         00:00:00:00:00:00    ipv4         127.0.0.1/8
 lo         00:00:00:00:00:00    ipv6         ::1/128
 eth439     52:54:00:27:0b:8f    ipv4         192.168.122.10/24
 eth439     52:54:00:27:0b:8f    ipv6         fe80::5054:ff:fe27:b8f/64
 eth439     52:54:00:27:0b:8f    ipv4         192.168.122.11/24
 eth439     52:54:00:27:0b:8f    ipv4         192.168.122.12/24
 eth439     52:54:00:27:0b:8f    ipv4         192.168.122.13/24
 eth440     52:54:00:fe:80:17    ipv4         192.168.122.20/24
 eth440     52:54:00:fe:80:17    ipv6         fe80::5054:ff:fefe:8017/64

Comment 14 errata-xmlrpc 2015-11-19 06:07:14 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory, and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://rhn.redhat.com/errata/RHBA-2015-2202.html