summaryrefslogtreecommitdiff
path: root/haircontrol/discovery.py
blob: 680eb4cd3bf4046dce5d1bb46ae453d8672a5345 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import re
import xml.etree.ElementTree
from haircontrol.data import *

class Discovery:
    IPNEIGH = re.compile("(?P<ip>[a-f0-9:.]+) dev (?P<ifname>.*) lladdr (?P<mac>[a-f0-9:]*)")
    IPLINKSHOW = re.compile("(?P<id>\d+):\s+(?P<ifname>[^:]*):.+\s+(?:link/ether\s+(?P<mac>[a-f0-9:]*)\s+brd|link/none)")

    def __init__(self, inspector):
        self.inspector = inspector
        self.net = EtherDomain()

    def discover_hinting_from_lldp(self, e_lldp):
        self.net.add_equipment(e_lldp)
        self.inspector.connect(e_lldp)

        # Learn local interfaces of e_lldp
        fd = self.inspector.command('ip-link')
        for line in fd:
            matches = Discovery.IPLINKSHOW.match(line)
            if matches:
                ifname, mac = [ matches.group(k) for k in ['ifname','mac'] ]
                e_lldp.ifaces[ifname] = Interface(ifname, mac)
        fd.close()

        # Create equipments and ifaces from LLDP neighbour discovery
        fd = self.inspector.command('lldp')
        root = xml.etree.ElementTree.parse(fd).getroot()
        for iface in root.iter('interface'):
            local_ifname = iface.get('name')
            local_mac = e_lldp.ifaces[local_ifname].mac
            chassis = iface.find('chassis')
            remote_name = chassis.find('name').text
            remote_ipmgmt = chassis.find('mgmt-ip').text
            e = Equipment(remote_name, remote_ipmgmt)
            self.net.add_equipment(e)
            for port in iface.findall('port'):
                remote_ifname = port.find('id').text
                e.add_seen_mac(remote_ifname, local_mac)
        fd.close()
        self.inspector.disconnect()

    def discover_from_root(self, e_root):
        self.net.add_equipment(e_root)
        self.inspector.connect(e_root)
        fd = self.inspector.command('ip-neigh')
        for line in fd:
            matches = Discovery.IPNEIGH.match(line)
            if matches:
                ip, ifname, mac = [ matches.group(k) for k in ['ip','ifname','mac'] ]
                self.net.index_mac_ip(mac, ip)
                e_root.add_seen_mac(ifname, mac)
        fd.close()
        self.inspector.disconnect()