bin/pvl.hosts-lldp
changeset 395 9de553b50128
parent 393 8321a569d5c0
child 398 de275bf6db70
equal deleted inserted replaced
394:7077379fb5a0 395:9de553b50128
     6 """
     6 """
     7 
     7 
     8 import pvl.args
     8 import pvl.args
     9 import pvl.hosts
     9 import pvl.hosts
    10 from pvl.invoke import merge
    10 from pvl.invoke import merge
    11 from pvl.snmp import snmp, lldp, vlan
    11 from pvl.snmp import snmp, lldp, vlan, bridge
    12 
    12 
    13 import logging; log = logging.getLogger('pvl.hosts-lldp')
    13 import logging; log = logging.getLogger('pvl.hosts-lldp')
    14 import optparse
    14 import optparse
    15 
    15 
    16 def hosts_snmp (options, hosts) :
    16 def hosts_snmp (options, hosts) :
    76             continue
    76             continue
    77 
    77 
    78         log.info("%s: %s", host, count)
    78         log.info("%s: %s", host, count)
    79 
    79 
    80         yield host, agent
    80         yield host, agent
       
    81 
       
    82 def hosts_bridge (options, hosts) :
       
    83     """
       
    84         Discover Bridge-supporting hosts.
       
    85 
       
    86         Yields Host, BridgeAgent
       
    87     """
       
    88 
       
    89     for host, host_snmp in hosts_snmp(options, hosts) :
       
    90         agent = bridge.BridgeAgent.apply(options, host.fqdn(), community=host_snmp.get('community'))
       
    91 
       
    92         try :
       
    93             agent.ping()
       
    94         except snmp.SNMPError as ex :
       
    95             log.warning("%s: %s", host, ex)
       
    96             continue
       
    97 
       
    98         log.info("%s", host)
       
    99 
       
   100         yield host, agent
       
   101 
    81 
   102 
    82 def apply_hosts_lldp (options, hosts) :
   103 def apply_hosts_lldp (options, hosts) :
    83     """
   104     """
    84         Query host LLDP info.
   105         Query host LLDP info.
    85     """
   106     """
   109 import collections
   130 import collections
   110 
   131 
   111 def apply_hosts_vlan (options, hosts) :
   132 def apply_hosts_vlan (options, hosts) :
   112     """
   133     """
   113         Query host VLAN ports.
   134         Query host VLAN ports.
       
   135 
       
   136         Yields host, { port: (untagged, [tagged]) }
   114     """
   137     """
   115 
   138 
   116     _hosts_vlan = list(hosts_vlan(options, hosts))
   139     _hosts_vlan = list(hosts_vlan(options, hosts))
   117 
   140 
   118     for host, agent in _hosts_vlan :
   141     for host, agent in _hosts_vlan :
   138         yield host, dict(
   161         yield host, dict(
   139             (
   162             (
   140                     port, (vlan_untagged.get(port), tuple(vlan_tagged[port]))
   163                     port, (vlan_untagged.get(port), tuple(vlan_tagged[port]))
   141             ) for port in set(vlan_untagged) | set(vlan_tagged)
   164             ) for port in set(vlan_untagged) | set(vlan_tagged)
   142         )
   165         )
       
   166 
       
   167 def apply_hosts_bridge (options, hosts) :
       
   168     """
       
   169         Query host bridge tables.
       
   170 
       
   171         Yields host, { port: (macs) }
       
   172     """
       
   173 
       
   174     for host, agent in hosts_bridge(options, hosts) :
       
   175         ports = collections.defaultdict(list)
       
   176 
       
   177         for ether, port in agent.fdb() :
       
   178             if port :
       
   179                 ports[port].append(ether)
       
   180         
       
   181         yield host, ports
   143 
   182 
   144 COLOR_VLANS = {
   183 COLOR_VLANS = {
   145     1:      'grey',         # pvl-lan
   184     1:      'grey',         # pvl-lan
   146     2:      'blue',         # pvl-lan2
   185     2:      'blue',         # pvl-lan2
   147     3:      'red',          # pvl-san
   186     3:      'red',          # pvl-san
   342         vlans = dict(apply_hosts_vlan(options, hosts))
   381         vlans = dict(apply_hosts_vlan(options, hosts))
   343 
   382 
   344     # discover node/port graph
   383     # discover node/port graph
   345     items = apply_hosts_lldp(options, hosts)
   384     items = apply_hosts_lldp(options, hosts)
   346 
   385 
       
   386     # discover edge nodes
       
   387     leafs = apply_hosts_bridge(options, hosts)
       
   388 
   347     # print
   389     # print
   348     if options.graph_dot :
   390     if options.graph_dot :
   349         apply_graph(options, items, vlans)
   391         apply_graph(options, items, vlans)
   350     else :
   392     else :
   351         for host, local, remote, remote_host in items :
   393         for host, local, remote, remote_host in items :
   352             if remote_host :
   394             if remote_host :
   353                 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)
   395                 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)
   354             else :
   396             else :
   355                 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='')
   397                 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='')
   356         
   398        
   357 
   399         for host, ports in leafs :
       
   400             for port, ethers in ports.iteritems() :
       
   401                 print "{host:30} {host.location:>30} {port:25} <== # {ethers}".format(host=host, port=port, ethers=' '.join(ethers))
   358 
   402 
   359 if __name__ == '__main__':
   403 if __name__ == '__main__':
   360     pvl.args.main(main)
   404     pvl.args.main(main)