summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xsrc/op_mode/lldp_op.py180
1 files changed, 66 insertions, 114 deletions
diff --git a/src/op_mode/lldp_op.py b/src/op_mode/lldp_op.py
index 0df6749aa..06958c605 100755
--- a/src/op_mode/lldp_op.py
+++ b/src/op_mode/lldp_op.py
@@ -16,10 +16,10 @@
import argparse
import jinja2
+import json
from sys import exit
from tabulate import tabulate
-from xml.dom import minidom
from vyos.util import cmd
from vyos.config import Config
@@ -35,106 +35,61 @@ lldp_out = """Capability Codes: R - Router, B - Bridge, W - Wlan r - Repeater, S
Device ID Local Proto Cap Platform Port ID
--------- ----- ----- --- -------- -------
-{% for n in neighbors -%}
-{{ "%-25s" | format(n.chassis) }} {{ "%-9s" | format(n.interface) }} {{ "%-6s" | format(n.proto) }} {{ "%-5s" | format(n.cap) }} {{ "%-20s" | format(n.platform) }} {{ n.port }}
-{% endfor -%}
+{% for neighbor in neighbors %}
+{% for local_if, info in neighbor.items() %}
+{{ "%-25s" | format(info.chassis) }} {{ "%-9s" | format(local_if) }} {{ "%-6s" | format(info.proto) }} {{ "%-5s" | format(info.capabilities) }} {{ "%-20s" | format(info.platform[:18]) }} {{ info.remote_if }}
+{% endfor %}
+{% endfor %}
"""
def get_neighbors():
- return cmd('/usr/sbin/lldpcli -f xml show neighbors')
-
-def extract_neighbor(neighbor):
- """
- Extract LLDP neighbor information from XML document passed as param neighbor
-
- <lldp>
- <interface label="Interface" name="eth0" via="LLDP" rid="3" age="0 day, 00:17:42">
- <chassis label="Chassis">
- <id label="ChassisID" type="mac">00:50:56:9d:a6:11</id>
- <name label="SysName">VyOS</name>
- <descr label="SysDescr">VyOS unknown</descr>
- <mgmt-ip label="MgmtIP">172.18.254.203</mgmt-ip>
- <mgmt-ip label="MgmtIP">fe80::250:56ff:fe9d:a611</mgmt-ip>
- <capability label="Capability" type="Bridge" enabled="off"/>
- <capability label="Capability" type="Router" enabled="on"/>
- <capability label="Capability" type="Wlan" enabled="off"/>
- <capability label="Capability" type="Station" enabled="off"/>
- </chassis>
- <port label="Port">
- <id label="PortID" type="mac">00:50:56:9d:a6:11</id>
- <descr label="PortDescr">eth0</descr>
- <ttl label="TTL">120</ttl>
- <auto-negotiation label="PMD autoneg" supported="no" enabled="no">
- <current label="MAU oper type">10GigBaseCX4 - X copper over 8 pair 100-Ohm balanced cable</current>
- </auto-negotiation>
- </port>
- <vlan label="VLAN" vlan-id="203">eth0.203</vlan>
- <lldp-med label="LLDP-MED">
- <device-type label="Device Type">Network Connectivity Device</device-type>
- <capability label="Capability" type="Capabilities" available="yes"/>
- <capability label="Capability" type="Policy" available="yes"/>
- <capability label="Capability" type="Location" available="yes"/>
- <capability label="Capability" type="MDI/PSE" available="yes"/>
- <capability label="Capability" type="MDI/PD" available="yes"/>
- <capability label="Capability" type="Inventory" available="yes"/>
- <inventory label="Inventory">
- <hardware label="Hardware Revision">None</hardware>
- <software label="Software Revision">4.19.54-amd64-vyos</software>
- <firmware label="Firmware Revision">6.00</firmware>
- <serial label="Serial Number">VMware-42 1d cf 87 ab 7f da 7e-3</serial>
- <manufacturer label="Manufacturer">VMware, Inc.</manufacturer>
- <model label="Model">VMware Virtual Platform</model>
- <asset label="Asset ID">No Asset Tag</asset>
- </inventory>
- </lldp-med>
- </interface>
- </lldp>
- """
-
- device = {
- 'interface' : neighbor.getAttribute('name'),
- 'chassis' : '',
- 'proto' : neighbor.getAttribute('via'),
- 'descr' : '',
- 'cap' : '',
- 'platform' : '',
- 'port' : ''
- }
-
- # first change to <chassis> node and then retrieve <name> and <descr>
- chassis = neighbor.getElementsByTagName('chassis')
- device['chassis'] = chassis[0].getElementsByTagName('name')[0].firstChild.data
- # Cisco IOS comes with a ',' remove character ....
- device['platform'] = chassis[0].getElementsByTagName('descr')[0].firstChild.data[:20].replace(',',' ')
-
- # extract capabilities
- for capability in chassis[0].getElementsByTagName('capability'):
- # we are only interested in enabled capabilities ...
- if capability.getAttribute('enabled') == "on":
- if capability.getAttribute('type') == "Router":
- device['cap'] += 'R'
- elif capability.getAttribute('type') == "Bridge":
- device['cap'] += 'B'
- elif capability.getAttribute('type') == "Wlan":
- device['cap'] += 'W'
- elif capability.getAttribute('type') == "Station":
- device['cap'] += 'S'
- elif capability.getAttribute('type') == "Repeater":
- device['cap'] += 'r'
- elif capability.getAttribute('type') == "Telephone":
- device['cap'] += 'T'
- elif capability.getAttribute('type') == "Docsis":
- device['cap'] += 'D'
- elif capability.getAttribute('type') == "Other":
- device['cap'] += 'O'
-
- # first change to <port> node and then retrieve <descr>
- port = neighbor.getElementsByTagName('port')
- port = port[0].getElementsByTagName('descr')[0].firstChild.data
- device['port'] = port
-
-
- return device
+ return cmd('/usr/sbin/lldpcli -f json show neighbors')
+
+def parse_data(data):
+ output = []
+ for tmp in data:
+ for local_if, values in tmp.items():
+ for chassis, c_value in values.get('chassis', {}).items():
+ capabilities = c_value['capability']
+ if isinstance(capabilities, dict):
+ capabilities = [capabilities]
+
+ cap = ''
+ for capability in capabilities:
+ if capability['enabled']:
+ if capability['type'] == 'Router':
+ cap += 'R'
+ if capability['type'] == 'Bridge':
+ cap += 'B'
+ if capability['type'] == 'Wlan':
+ cap += 'W'
+ if capability['type'] == 'Station':
+ cap += 'S'
+ if capability['type'] == 'Repeater':
+ cap += 'r'
+ if capability['type'] == 'Telephone':
+ cap += 'T'
+ if capability['type'] == 'Docsis':
+ cap += 'D'
+ if capability['type'] == 'Other':
+ cap += 'O'
+
+
+ remote_if = 'Unknown'
+ if 'descr' in values.get('port', {}):
+ remote_if = values.get('port', {}).get('descr')
+ elif 'id' in values.get('port', {}):
+ remote_if = values.get('port', {}).get('id').get('value', 'Unknown')
+
+ output.append({local_if: {'chassis': chassis,
+ 'remote_if': remote_if,
+ 'proto': values.get('via','Unknown'),
+ 'platform': c_value.get('descr', 'Unknown'),
+ 'capabilities': cap}})
+
+
+ output = {'neighbors': output}
+ return output
if __name__ == '__main__':
args = parser.parse_args()
@@ -145,29 +100,26 @@ if __name__ == '__main__':
print('Service LLDP is not configured')
exit(0)
- if args.all:
- neighbors = minidom.parseString(get_neighbors())
- for neighbor in neighbors.getElementsByTagName('interface'):
- tmp['neighbors'].append( extract_neighbor(neighbor) )
-
- elif args.detail:
- out = cmd('/usr/sbin/lldpctl -f plain')
- print(out)
+ if args.detail:
+ print(cmd('/usr/sbin/lldpctl -f plain'))
exit(0)
+ elif args.all or args.interface:
+ tmp = json.loads(get_neighbors())
- elif args.interface:
- neighbors = minidom.parseString(get_neighbors())
- for neighbor in neighbors.getElementsByTagName('interface'):
- # check if neighbor appeared on proper interface
- if neighbor.getAttribute('name') == args.interface:
- tmp['neighbors'].append( extract_neighbor(neighbor) )
+ if args.all:
+ neighbors = tmp['lldp']['interface']
+ elif args.interface:
+ neighbors = []
+ for neighbor in tmp['lldp']['interface']:
+ if args.interface in neighbor:
+ neighbors.append(neighbor)
else:
parser.print_help()
exit(1)
- tmpl = jinja2.Template(lldp_out)
- config_text = tmpl.render(tmp)
+ tmpl = jinja2.Template(lldp_out, trim_blocks=True)
+ config_text = tmpl.render(parse_data(neighbors))
print(config_text)
exit(0)