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[a-f0-9:.]+) dev (?P.*) lladdr (?P[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\d+):\s+(?P[^:]*):.+\s+(?:link/ether\s+(?P[a-f0-9:]*)\s+brd|link/none)") # 1: lo: 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: 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 # # # # # Robert_VILO # Robert_VILO # LM5 running on #XM.v5.5.10 # 172.16.10.26 # 169.254.227.212 # # # # br0 # br0 # # # # ... # # }, } 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 } }