Getting ip address of guest vm
Is there a way to get ip address of booted vm ?
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
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.
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-leasescalls 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_argsstruct.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!
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]),
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!
Sure will let you know. Really appreciate your help on this :)