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
}
}
|