bin/pvl.hosts-lldp
changeset 395 9de553b50128
parent 393 8321a569d5c0
child 398 de275bf6db70
--- a/bin/pvl.hosts-lldp	Tue Mar 18 13:59:22 2014 +0200
+++ b/bin/pvl.hosts-lldp	Tue Mar 18 14:02:26 2014 +0200
@@ -8,7 +8,7 @@
 import pvl.args
 import pvl.hosts
 from pvl.invoke import merge
-from pvl.snmp import snmp, lldp, vlan
+from pvl.snmp import snmp, lldp, vlan, bridge
 
 import logging; log = logging.getLogger('pvl.hosts-lldp')
 import optparse
@@ -79,6 +79,27 @@
 
         yield host, agent
 
+def hosts_bridge (options, hosts) :
+    """
+        Discover Bridge-supporting hosts.
+
+        Yields Host, BridgeAgent
+    """
+
+    for host, host_snmp in hosts_snmp(options, hosts) :
+        agent = bridge.BridgeAgent.apply(options, host.fqdn(), community=host_snmp.get('community'))
+
+        try :
+            agent.ping()
+        except snmp.SNMPError as ex :
+            log.warning("%s: %s", host, ex)
+            continue
+
+        log.info("%s", host)
+
+        yield host, agent
+
+
 def apply_hosts_lldp (options, hosts) :
     """
         Query host LLDP info.
@@ -111,6 +132,8 @@
 def apply_hosts_vlan (options, hosts) :
     """
         Query host VLAN ports.
+
+        Yields host, { port: (untagged, [tagged]) }
     """
 
     _hosts_vlan = list(hosts_vlan(options, hosts))
@@ -141,6 +164,22 @@
             ) for port in set(vlan_untagged) | set(vlan_tagged)
         )
 
+def apply_hosts_bridge (options, hosts) :
+    """
+        Query host bridge tables.
+
+        Yields host, { port: (macs) }
+    """
+
+    for host, agent in hosts_bridge(options, hosts) :
+        ports = collections.defaultdict(list)
+
+        for ether, port in agent.fdb() :
+            if port :
+                ports[port].append(ether)
+        
+        yield host, ports
+
 COLOR_VLANS = {
     1:      'grey',         # pvl-lan
     2:      'blue',         # pvl-lan2
@@ -344,6 +383,9 @@
     # discover node/port graph
     items = apply_hosts_lldp(options, hosts)
 
+    # discover edge nodes
+    leafs = apply_hosts_bridge(options, hosts)
+
     # print
     if options.graph_dot :
         apply_graph(options, items, vlans)
@@ -353,8 +395,10 @@
                 print "{host:30} {host.location:>30} {local[port]:>25} <-> {remote[port]:<25} {remote_host.location:>30} # {remote[chassis]} ({remote_host})".format(host=host, local=local, remote=remote, remote_host=remote_host)
             else :
                 print "{host:30} {host.location:>30} {local[port]:>25} <-- {remote[port]:<25} {empty:30} # {remote[chassis]} ({remote[sys_name]})".format(host=host, local=local, remote=remote, empty='')
-        
-
+       
+        for host, ports in leafs :
+            for port, ethers in ports.iteritems() :
+                print "{host:30} {host.location:>30} {port:25} <== # {ethers}".format(host=host, port=port, ethers=' '.join(ethers))
 
 if __name__ == '__main__':
     pvl.args.main(main)