verx icon indicating copy to clipboard operation
verx copied to clipboard

Getting ip address of guest vm

Open kansi opened this issue 10 years ago • 6 comments

Is there a way to get ip address of booted vm ?

kansi avatar Oct 16 '15 17:10 kansi

It looks like libvirt added a way to get the ip address recently (in January 2015):

https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainInterfaceAddresses

The corresponding function in verx is verx:domain_interface_addresses/2. I haven't tried using it but it should be something like:

verx:domain_interface_addresses(Domain, ?VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE)

If that doesn't work for you or you have an older version of libvirt, other options might be:

  • get the MAC address of the VM and check the arp table

    For example, on linux, you could read through /proc/net/arp

  • read the DHCP leases file (which is what the VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE option seems to be doing)

  • have the guest VM open a connection to the hypervisor at boot or snoop the bridge and match the MAC address (probably similar to what the VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_GUEST option does)

  • login to the console and run shell commands:

https://github.com/msantos/verx/blob/master/bin/set_interface.escript

msantos avatar Oct 16 '15 19:10 msantos

I updated libvirt to the latest release. From the virsh command line I can do,

# net-dhcp-leases default

and it gives me the ip and mac addresses of the clients/domains . But I am not able to do same from verx. I see there's a function called network_get_dhcp_leases/2 but I am not sure how to use it. It would be great if you suggest how to use it.

kansi avatar Oct 17 '15 10:10 kansi

I updated libvirt to the latest release.

Were you able to try verx:domain_interface_addresses/2? I got the parameters wrong. It should be:

% ?VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE = 0
verx:domain_interface_addresses(Ref, [Network, ?VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE, 0])

I see there's a function called network_get_dhcp_leases/2 but I am not sure how to use it. It would be great if you suggest how to use it.

It requires a little reverse engineering.

  • check the source for virsh

    net-dhcp-leases calls virNetworkGetDHCPLeases()

    https://github.com/libvirt/libvirt/blob/0bc5fcffb13e3ea9ab35aeb760d31660f4aea2c8/tools/virsh-network.c#L1381

  • check the libvirt docs for virNetworkGetDHCPLeases()

    https://libvirt.org/html/libvirt-libvirt-network.html#virNetworkGetDHCPLeases

int virNetworkGetDHCPLeases (
   virNetworkPtr network,
   const char * mac,
   virNetworkDHCPLeasePtr ** leases,
   unsigned int flags)
  • check the XDR signature for the RPC call

    https://github.com/libvirt/libvirt/blob/0bc5fcffb13e3ea9ab35aeb760d31660f4aea2c8/src/remote/remote_protocol.x#L3152

    The function signature is:

struct remote_network_get_dhcp_leases_args {
    remote_nonnull_network net;
    remote_string mac;
    int need_results;
    unsigned int flags;
};

The return value is:

struct remote_network_get_dhcp_leases_ret {                                     
    remote_network_dhcp_lease leases<REMOTE_NETWORK_DHCP_LEASES_MAX>;           
    unsigned int ret;                                                           
};

Where a remote_network_get_dhcp_lease is defined as:

struct remote_network_dhcp_lease {                                              
    remote_nonnull_string iface;                                                
    hyper expirytime;                                                           
    int type;                                                                   
    remote_string mac;                                                          
    remote_string iaid;                                                         
    remote_nonnull_string ipaddr;                                               
    unsigned int prefix;                                                        
    remote_string hostname;                                                     
    remote_string clientid;                                                     
};               
  • the generated interface in verx takes 2 arguments: the verx client transport PID and a list of parameters which is a representation of the remote_network_get_dhcp_leases_args struct.

    The parameters are: a network reference, the MAC address, an integer indicating the number of results to return and a flag (which should be set to 0)

    The return value should be a tuple:

{ok, [Leases, non_neg_integer()]} | {error, posix() | libvirt()}

Where Leases is a list:

[Iface :: binary(), Expiry :: integer(), Type :: integer(), MAC :: binary(), Iaid :: binary(), IPaddr :: binary(), Prefix :: non_neg_integer(), Hostname :: binary(), ClientId :: binary()]

And calling it should be something like:

{ok, [Network]} = verx:network_lookup_by_name(Ref, [Name]),
 {ok, [[], Num]} = verx:network_get_dhcp_leases(Ref, [Network, <<"aa:bb:cc:00:11:22">>, 0, 0)
 {ok, [Leases, Num]} = verx:network_get_dhcp_leases(Ref, [Network, <<"aa:bb:cc:00:11:22">>, Num, 0).

I am guessing here, I haven't actually tried running this. If you run into problems, let me know and I'll set up a few tests!

msantos avatar Oct 17 '15 13:10 msantos

This works expect one thing, return value from first function call should be handled as follows,

{ok, [Network]} = verx:network_lookup_by_name(Ref, [Name]),

kansi avatar Oct 17 '15 20:10 kansi

Thanks! I caught that as well and fixed it after I published the comment. The rule is that the 2nd element in both tuples (argument and return) can be thought of as a payload or struct.

Glad to hear it worked for you. If you run into any other issues, let me know!

msantos avatar Oct 17 '15 21:10 msantos

Sure will let you know. Really appreciate your help on this :)

kansi avatar Oct 17 '15 21:10 kansi