summaryrefslogtreecommitdiff
path: root/haircontrol/inspectors.py
blob: 33bf360c985a0be56a943c8f854ab8eb08513182 (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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import re
import xml.etree.ElementTree

class Inspector():
    cmds = {}

    def __init__(self):
        #XXX in a mockup class ?
        self.testDataPath = '../test-data/input'
        self.e = None

    def connect(self, e):
        self.e = e

    def disconnect(self):
        self.e = None

    def command(self, cmdname):
        cmddef = self.cmds.get(cmdname)
        if not cmddef:
            return None
        fd = self._exec(cmdname, cmddef['cmd'])
        result = []
        re = cmddef.get('re')
        func = cmddef.get('func')
        if re:
            for line in fd:
                matches = re.match(line)
                if matches:
                    result.append(matches.groups())
        elif func:
            result = func(self, fd)
        fd.close()
        return result

    def _exec(self, cmdname, cmd):
        #XXX in a mockup class ?
        mockfile = self.testDataPath + '/' + self.e.name + '-' + cmdname + '.out'
        return open(mockfile)



class LinuxInspector(Inspector):

    def parse_lldpctl_xml(self, fd):
        result = []
        root = xml.etree.ElementTree.parse(fd).getroot()
        for iface in root.iter('interface'):
            local_ifname = iface.get('name')
            local_mac = self.e.ifaces[local_ifname].mac
            chassis = iface.find('chassis')
            remote_name = chassis.find('name').text
            remote_ipmgmt = chassis.find('mgmt-ip').text
            ports = []
            for port in iface.findall('port'):
                remote_ifname = port.find('id').text
                ports.append(remote_ifname)
            result.append( (local_ifname, local_mac, remote_name, remote_ipmgmt, ports) )
        return result

    cmds = {
            'ip-neigh': {
                'cmd': 'ip neigh',
                're': re.compile("(?P<ip>[a-f0-9:.]+) dev (?P<ifname>.*) lladdr (?P<mac>[a-f0-9:]*)")
                # fe80::8300 dev eth1 lladdr 10:fe:ed:f1:e1:f3 router STALE
                # 172.16.20.210 dev eth1 lladdr c0:4a:00:fe:1f:87 REACHABLE
            },
            'ip-link': {
                'cmd': 'ip -o link',
                'kind': 'text',
                're': re.compile("(?P<id>\d+):\s+(?P<ifname>[^:]*):.+\s+(?:link/ether\s+(?P<mac>[a-f0-9:]*)\s+brd|link/none)")
                # 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default \    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
                # 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000\    link/ether 8c:89:a5:c7:be:88 brd ff:ff:ff:ff:ff:ff
                },
            'lldpctl': {
                'cmd': 'lldpctl -f xml',
                'func': parse_lldpctl_xml
                #<?xml version="1.0" encoding="UTF-8"?>
                #<lldp label="LLDP neighbors">
                # <interface label="Interface" name="eth0" via="CDPv1" rid="2" age="0 day, 21:41:18">
                #  <chassis label="Chassis">
                #   <id label="ChassisID" type="local">Robert_VILO</id>
                #   <name label="SysName">Robert_VILO</name>
                #   <descr label="SysDescr">LM5 running on
                #XM.v5.5.10</descr>
                #   <mgmt-ip label="MgmtIP">172.16.10.26</mgmt-ip>
                #   <mgmt-ip label="MgmtIP">169.254.227.212</mgmt-ip>
                #   <capability label="Capability" type="Bridge" enabled="on"/>
                #  </chassis>
                #  <port label="Port">
                #   <id label="PortID" type="ifname">br0</id>
                #   <descr label="PortDescr">br0</descr>
                #  </port>
                # </interface>
                # <interface label="Interface" name="eth0" via="CDPv1" rid="4" age="0 day, 21:41:18">
                # ...
                # </interface>
                #</lldp>
            },
    }



class UbntInspector(Inspector):

    def parse_status_json(self, fd):
        return 'parse_status_json'

    def parse_brmacs_json(self, fd):
        return 'parse_brmacs_json'

    cmds = {
            'status.cgi': {
                'cmd':'..',
                'kind': 'cgi-json',
                'func': parse_status_json
                },
            'brmacs.cgi': {
                'cmd':'..',
                'kind': 'cgi-json',
                'func': parse_brmacs_json
                }
    }