msantos / verx

Erlang implementation of the libvirtd remote protocol
59 stars 11 forks source link

Getting ip address of guest vm #9

Open kansi opened 9 years ago

kansi commented 9 years ago

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

msantos commented 9 years ago

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:

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

kansi commented 9 years ago

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.

msantos commented 9 years ago

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.

int virNetworkGetDHCPLeases (
   virNetworkPtr network,
   const char * mac,
   virNetworkDHCPLeasePtr ** leases,
   unsigned int flags)
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;                                                     
};               
{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!

kansi commented 9 years ago

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]),
msantos commented 9 years ago

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!

kansi commented 9 years ago

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