summaryrefslogtreecommitdiff
path: root/src/op_mode/lldp_op.py
diff options
context:
space:
mode:
authorMarcus Hoff <marcus.hoff@ring2.dk>2020-09-05 09:58:03 +0200
committerMarcus Hoff <marcus.hoff@ring2.dk>2020-09-05 09:58:03 +0200
commit46fb580fa0131f6815bbcfc95631654f6fe999a8 (patch)
tree73ae9fcaa97d5cfab7883bc6fbf3ea036677c2a3 /src/op_mode/lldp_op.py
parent0377b8e40b0d3e424da11194e97659c5066c0a1d (diff)
parentb6b61bc9ecf1328e67a0c15934f8bf3966a6b66d (diff)
downloadvyos-1x-46fb580fa0131f6815bbcfc95631654f6fe999a8.tar.gz
vyos-1x-46fb580fa0131f6815bbcfc95631654f6fe999a8.zip
Merge remote-tracking branch 'upstream/current' into current
Diffstat (limited to 'src/op_mode/lldp_op.py')
-rwxr-xr-xsrc/op_mode/lldp_op.py185
1 files changed, 70 insertions, 115 deletions
diff --git a/src/op_mode/lldp_op.py b/src/op_mode/lldp_op.py
index 5d48e3210..06958c605 100755
--- a/src/op_mode/lldp_op.py
+++ b/src/op_mode/lldp_op.py
@@ -14,19 +14,19 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
import argparse
import jinja2
+import json
-from xml.dom import minidom
from sys import exit
from tabulate import tabulate
-from vyos.util import popen
+from vyos.util import cmd
from vyos.config import Config
parser = argparse.ArgumentParser()
parser.add_argument("-a", "--all", action="store_true", help="Show LLDP neighbors on all interfaces")
+parser.add_argument("-d", "--detail", action="store_true", help="Show detailes LLDP neighbor information on all interfaces")
parser.add_argument("-i", "--interface", action="store", help="Show LLDP neighbors on specific interface")
# Please be careful if you edit the template.
@@ -35,108 +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():
- command = '/usr/sbin/lldpcli -f xml show neighbors'
- out,_ = popen(command)
- return out
-
-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
+def get_neighbors():
+ 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()
@@ -147,24 +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) )
+ 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)