[PATCH] List IPs of VM Ifaces

Signed-off-by: Christy Perez <christy@linux.vnet.ibm.com> --- docs/API.md | 1 + src/kimchi/mockmodel.py | 9 +++++++++ src/kimchi/model/vmifaces.py | 28 ++++++++++++++++++++++++++++ tests/test_rest.py | 6 ++++++ 4 files changed, 44 insertions(+) diff --git a/docs/API.md b/docs/API.md index e022c9e..10e80ac 100644 --- a/docs/API.md +++ b/docs/API.md @@ -299,6 +299,7 @@ A interface represents available network interface on VM. * bridge *(optional)*: the name of resource bridge, only be available when the interface type is bridge. * mac: Media Access Control Address of the VM interface. + * ips: A list of IP addresses associated with this MAC. * model *(optional)*: model of emulated network interface card. It will be one of these models: ne2k_pci, i82551, i82557b, i82559er, rtl8139, e1000, pcnet and virtio. * network *(optional)*: the name of resource network, only be available when the diff --git a/src/kimchi/mockmodel.py b/src/kimchi/mockmodel.py index aaf1af2..3f74b80 100644 --- a/src/kimchi/mockmodel.py +++ b/src/kimchi/mockmodel.py @@ -24,6 +24,7 @@ import random import time import kimchi.model.cpuinfo +import kimchi.model.vmifaces from lxml import objectify from lxml.builder import E @@ -76,6 +77,7 @@ class MockModel(Model): kimchi.model.cpuinfo.get_topo_capabilities = \ MockModel.get_topo_capabilities + kimchi.model.vmifaces.getDHCPLeases = MockModel.getDHCPLeases libvirt.virConnect.defineXML = MockModel.domainDefineXML libvirt.virDomain.XMLDesc = MockModel.domainXMLDesc libvirt.virDomain.undefine = MockModel.undefineDomain @@ -235,6 +237,13 @@ class MockModel(Model): pool = vol.storagePoolLookupByVolume() pool.createXML(new_xml) + @staticmethod + def getDHCPLeases(net, mac): + return [{'iface': 'virbr1', 'ipaddr': '192.168.0.167', + 'hostname': 'kimchi', 'expirytime': 1433285036L, + 'prefix': 24, 'clientid': '01:%s' % mac, + 'mac': mac, 'iaid': None, 'type': 0}] + def _probe_image(self, path): return ('unknown', 'unknown') diff --git a/src/kimchi/model/vmifaces.py b/src/kimchi/model/vmifaces.py index 93a769b..630e4dc 100644 --- a/src/kimchi/model/vmifaces.py +++ b/src/kimchi/model/vmifaces.py @@ -29,6 +29,14 @@ from kimchi.model.vms import DOM_STATE_MAP, VMModel from kimchi.xmlutils.interface import get_iface_xml +def getDHCPLeases(net, mac): + try: + leases = net.DHCPLeases(mac) + return leases + except libvirt.libvirtError: + return [] + + class VMIfacesModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] @@ -132,9 +140,29 @@ class VMIfaceModel(object): info['network'] = iface.source.get('network') if info['type'] == 'bridge': info['bridge'] = iface.source.get('bridge') + info['ips'] = self._get_ips(info['mac'], info['network']) return info + def _get_ips(self, mac, network): + ips = [] + conn = self.conn.get() + # An iface may have multiple IPs + # An IP could have been assigned without libvirt. + # First check the ARP cache. + with open('/proc/net/arp') as f: + ips = [line.split()[0] for line in f.xreadlines() if mac in line] + # Some ifaces may be inactive, so if the ARP cache didn't have them, + # and they happen to be assigned via DHCP, we can check there too. + net = conn.networkLookupByName(network) + leases = getDHCPLeases(net, mac) + for lease in leases: + ip = lease.get('ipaddr') + if ip not in ips: + ips.append(ip) + + return ips + def delete(self, vm, mac): dom = VMModel.get_vm(vm, self.conn) iface = self._get_vmiface(vm, mac) diff --git a/tests/test_rest.py b/tests/test_rest.py index 7fe6831..2145d00 100644 --- a/tests/test_rest.py +++ b/tests/test_rest.py @@ -707,6 +707,7 @@ class RestTests(unittest.TestCase): self.assertEquals(17, len(res['mac'])) self.assertEquals(get_template_default('old', 'nic_model'), res['model']) + self.assertTrue('ips' in res) # try to attach an interface without specifying 'model' req = json.dumps({'type': 'network'}) @@ -737,6 +738,11 @@ class RestTests(unittest.TestCase): newMacAddr).read()) self.assertEquals(newMacAddr, iface['mac']) + # Check for an IP address + iface = json.loads(self.request('/vms/test-vm/ifaces/%s' % + newMacAddr).read()) + self.assertTrue(len(iface['ips']) > 0) + # detach network interface from vm resp = self.request('/vms/test-vm/ifaces/%s' % iface['mac'], '{}', 'DELETE') -- 2.1.0

Reviewed-by: Crístian Deives <cristiandeives@gmail.com> However, I'm worried with the DHCP lease code. AFAIU, it only works if the guest system has a predictable IP mechanism (i.e. static IP or a DHCP server which always assigns the same IP address to the same MAC). I tried "GET /vms/<vm>/ifaces/<iface>/ips" on a shutoff VM and I got the IP address the VM had when it was running. That's most probably the same address it will use on next boot, but we can't be sure of that, that depends on the guest network configuration and/or the external DHCP server. I guess even the ARP code might not be always correct, so I guess both approaches has their faults. This patch fetches the most likely IP address the guest VM has, which should be correct on most of the times, so I think this is good enough for the end user. I just don't feel it's 100% trustworthy - but maybe 99% :-) On 03-06-2015 12:06, Christy Perez wrote:
Signed-off-by: Christy Perez <christy@linux.vnet.ibm.com> --- docs/API.md | 1 + src/kimchi/mockmodel.py | 9 +++++++++ src/kimchi/model/vmifaces.py | 28 ++++++++++++++++++++++++++++ tests/test_rest.py | 6 ++++++ 4 files changed, 44 insertions(+)

I could add a check for the VM being off, and always return an empty list in that case. On 06/09/2015 08:21 AM, Crístian Deives wrote:
Reviewed-by: Crístian Deives <cristiandeives@gmail.com>
However, I'm worried with the DHCP lease code. AFAIU, it only works if the guest system has a predictable IP mechanism (i.e. static IP or a DHCP server which always assigns the same IP address to the same MAC). I tried "GET /vms/<vm>/ifaces/<iface>/ips" on a shutoff VM and I got the IP address the VM had when it was running. That's most probably the same address it will use on next boot, but we can't be sure of that, that depends on the guest network configuration and/or the external DHCP server. I guess even the ARP code might not be always correct, so I guess both approaches has their faults. This patch fetches the most likely IP address the guest VM has, which should be correct on most of the times, so I think this is good enough for the end user. I just don't feel it's 100% trustworthy - but maybe 99% :-)
On 03-06-2015 12:06, Christy Perez wrote:
Signed-off-by: Christy Perez <christy@linux.vnet.ibm.com> --- docs/API.md | 1 + src/kimchi/mockmodel.py | 9 +++++++++ src/kimchi/model/vmifaces.py | 28 ++++++++++++++++++++++++++++ tests/test_rest.py | 6 ++++++ 4 files changed, 44 insertions(+)

On 09/06/2015 10:47, Christy Perez wrote:
I could add a check for the VM being off, and always return an empty list in that case.
Sounds good.
On 06/09/2015 08:21 AM, Crístian Deives wrote:
Reviewed-by: Crístian Deives <cristiandeives@gmail.com>
However, I'm worried with the DHCP lease code. AFAIU, it only works if the guest system has a predictable IP mechanism (i.e. static IP or a DHCP server which always assigns the same IP address to the same MAC). I tried "GET /vms/<vm>/ifaces/<iface>/ips" on a shutoff VM and I got the IP address the VM had when it was running. That's most probably the same address it will use on next boot, but we can't be sure of that, that depends on the guest network configuration and/or the external DHCP server. I guess even the ARP code might not be always correct, so I guess both approaches has their faults. This patch fetches the most likely IP address the guest VM has, which should be correct on most of the times, so I think this is good enough for the end user. I just don't feel it's 100% trustworthy - but maybe 99% :-)
On 03-06-2015 12:06, Christy Perez wrote:
Signed-off-by: Christy Perez <christy@linux.vnet.ibm.com> --- docs/API.md | 1 + src/kimchi/mockmodel.py | 9 +++++++++ src/kimchi/model/vmifaces.py | 28 ++++++++++++++++++++++++++++ tests/test_rest.py | 6 ++++++ 4 files changed, 44 insertions(+)
Kimchi-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel
participants (3)
-
Aline Manera
-
Christy Perez
-
Crístian Deives