bin/pvl.hosts-graph
changeset 414 b9aa8c35741f
parent 413 cb7782e5a2fd
child 415 658bc929cf77
equal deleted inserted replaced
413:cb7782e5a2fd 414:b9aa8c35741f
   182     hosts_by_ethernet = { } # ethernet: host
   182     hosts_by_ethernet = { } # ethernet: host
   183     hosts_by_location = { } # (domain, location): host
   183     hosts_by_location = { } # (domain, location): host
   184 
   184 
   185     nodes_port = { } # (local, int(local_port)): remote
   185     nodes_port = { } # (local, int(local_port)): remote
   186     nodes_out = { } # local: {remote}
   186     nodes_out = { } # local: {remote}
       
   187     nodes_in = { } # remote: {local}
   187     links_out = { } # (local, remote): local_port
   188     links_out = { } # (local, remote): local_port
   188     links_in = { } # (remote, local): remote_port
   189     links_in = { } # (remote, local): remote_port
   189     
   190     
   190     # first scan: lldp hosts
   191     # first scan: lldp hosts
   191     for host, host_attrs in snmp.iteritems() :
   192     for host, host_attrs in snmp.iteritems() :
   266 
   267 
   267                     # directional mapping
   268                     # directional mapping
   268                     links_out[(local_node, remote_node)] = local_port
   269                     links_out[(local_node, remote_node)] = local_port
   269                     nodes_port[(local_node, port)] = remote_node
   270                     nodes_port[(local_node, port)] = remote_node
   270                     nodes_out.setdefault(local_node, set()).add(remote_node)
   271                     nodes_out.setdefault(local_node, set()).add(remote_node)
       
   272                     nodes_in.setdefault(remote_node, set()).add(local_node)
   271                     
   273                     
   272                     # bidirectional mappings
   274                     # bidirectional mappings
   273                     remote_port = remote_attrs['port']
   275                     remote_port = remote_attrs['port']
   274 
   276 
   275                     links_in[(remote_node, local_node)] = remote_port
   277                     links_in[(remote_node, local_node)] = remote_port
   347                     log.debug("%s:%s: confirm -> %s", host, port, remote_host)
   349                     log.debug("%s:%s: confirm -> %s", host, port, remote_host)
   348                 
   350                 
   349                 links_out[(local_node, remote_node)] = port
   351                 links_out[(local_node, remote_node)] = port
   350                 nodes_port[(local_node, port)] = remote_node
   352                 nodes_port[(local_node, port)] = remote_node
   351                 nodes_out.setdefault(local_node, set()).add(remote_node)
   353                 nodes_out.setdefault(local_node, set()).add(remote_node)
       
   354                 nodes_in.setdefault(remote_node, set()).add(local_node)
   352 
   355 
   353                 # update directional or missing links
   356                 # update directional or missing links
   354                 remote_port = links_out.get((remote_node, local_node))
   357                 remote_port = links_out.get((remote_node, local_node))
   355                 reverse_port = links_in.get((local_node, remote_node))
   358                 reverse_port = links_in.get((local_node, remote_node))
   356 
   359 
   384                     log.info("%s:%s link -> %s", local_node, local_port, remote_node)
   387                     log.info("%s:%s link -> %s", local_node, local_port, remote_node)
   385 
   388 
   386                     links[(local_node, local_port, None, remote_node)] = None
   389                     links[(local_node, local_port, None, remote_node)] = None
   387 
   390 
   388     if options.graph_bridge :
   391     if options.graph_bridge :
       
   392         # scan hosts with bridges
       
   393         bridge_hosts = set()
       
   394 
       
   395         for host, host_attrs in snmp.iteritems() :
       
   396             if 'bridge' in host_attrs or any('bridge' in vlan_attrs for vlan_attrs in host_attrs.get('vlan', { }).itervalues()) :
       
   397                 bridge_hosts.add(host)
       
   398 
   389         # third graph: bridge
   399         # third graph: bridge
   390         for host, host_attrs in snmp.iteritems() :
   400         for host, host_attrs in snmp.iteritems() :
   391             local_node = host
   401             local_out = nodes_out.get(host)
   392             
   402 
   393             node_out = nodes_out.get(local_node)
   403             if not local_out :
   394 
       
   395             if not node_out :
       
   396                 log.warning("%s: no outgoing links, skipping bridge", host)
   404                 log.warning("%s: no outgoing links, skipping bridge", host)
   397                 continue
   405                 continue
   398 
   406             
   399             bridge = { }
   407             # scan vlan/port bridge ethers
       
   408             bridge = { } # (port, vlan): {ethernet}
   400 
   409 
   401             for port, ethernets in host_attrs.get('bridge', { }).iteritems() :
   410             for port, ethernets in host_attrs.get('bridge', { }).iteritems() :
   402                 bridge[(port, None)] = ethernets
   411                 bridge[(port, None)] = ethernets
   403 
   412 
   404             for vlan, vlan_attrs in host_attrs.get('vlan', { }).iteritems() :
   413             for vlan, vlan_attrs in host_attrs.get('vlan', { }).iteritems() :
   405                 for port, ethernets in vlan_attrs.get('bridge', { }).iteritems()  :
   414                 for port, ethernets in vlan_attrs.get('bridge', { }).iteritems()  :
   406                     bridge[(port, vlan)] = ethernets
   415                     bridge[(port, vlan)] = ethernets
   407 
   416 
   408             for (port, vlan), ethernets in bridge.iteritems() :
   417             for (port, vlan), ethernets in bridge.iteritems() :
       
   418                 local_node = host
   409                 local_port = port
   419                 local_port = port
   410                 
   420                 
   411                 remote_node = nodes_port.get((local_node, local_port))
   421                 remote_node = nodes_port.get((local_node, local_port))
   412                 
   422 
   413                 if remote_node :
   423                 if remote_node :
       
   424                     remote_in = nodes_in.get(remote_node, set())
       
   425                 else :
       
   426                     remote_in = set()
       
   427                 
       
   428                 remote_leaf = (remote_in == set((host, )))
       
   429                 
       
   430                 # TODO: add ether node and link if remote node also has this ether on this link
       
   431                 #       also do this if all remote_in's agree that the ether is on the remote_node
       
   432                 if not remote_node :
       
   433                     log.debug("%s:%s: no remote node", host, port)
       
   434                 
       
   435                 elif remote_leaf and (remote_node not in bridge_hosts) and len(ethernets) > 1 :
       
   436                     log.info("%s:%s: map onto non-bridge leaf remote %s", host, port, remote_node)
       
   437 
       
   438                     # map links out of the assumed remote bridge
       
   439                     local_node = remote_node
       
   440                     local_port = None
       
   441 
       
   442                 else :
   414                     log.debug("%s:%s/%s bridge skip -> %s", host, port, vlan, remote_node)
   443                     log.debug("%s:%s/%s bridge skip -> %s", host, port, vlan, remote_node)
   415                     continue
   444                     continue
   416 
   445 
   417                 for ethernet in ethernets :
   446                 for ethernet in ethernets :
   418                     # remote host
   447                     # remote host
   422                         remote_label = remote_host.location or str(remote_host)
   451                         remote_label = remote_host.location or str(remote_host)
   423 
   452 
   424                         log.debug("%s:%s/%s bridge %s = %s (%s)", host, port, vlan, ethernet, remote_host, remote_label)
   453                         log.debug("%s:%s/%s bridge %s = %s (%s)", host, port, vlan, ethernet, remote_host, remote_label)
   425                     else :
   454                     else :
   426                         remote_node = remote_host = None
   455                         remote_node = remote_host = None
       
   456 
       
   457                         log.debug("%s:%s/%s bridge %s ?", host, port, vlan, ethernet)
   427                     
   458                     
   428                     if not remote_host :
   459                     if not remote_host :
   429                         continue
   460                         continue
       
   461 
       
   462                     elif remote_host == host and local_node != host :
       
   463                         log.debug("%s:%s: skip remote-mapped self", host, port)
   430 
   464 
   431                     if remote_node not in nodes :
   465                     if remote_node not in nodes :
   432                         log.debug("%s:%s: lazy-add remote %s (%s)", host, port, remote_node, remote_label)
   466                         log.debug("%s:%s: lazy-add remote %s (%s)", host, port, remote_node, remote_label)
   433 
   467 
   434                         nodes[remote_node] = remote_label
   468                         nodes[remote_node] = remote_label
   446                     remote_port = links_out.get((remote_node, local_node))
   480                     remote_port = links_out.get((remote_node, local_node))
   447 
   481 
   448                     if remote_port :
   482                     if remote_port :
   449                         reverse = (remote_node, remote_port, None, local_node)
   483                         reverse = (remote_node, remote_port, None, local_node)
   450 
   484 
   451                         log.info("%s:%s <-> %s:%s", local_node, local_port, remote_port, remote_host)
   485                         log.info("%s:%s bridge <-> %s:%s", local_node, local_port, remote_port, remote_host)
   452 
   486 
   453                         # fill in remote_port for bidirectional link
   487                         # fill in remote_port for bidirectional link
   454                         del links[reverse]
   488                         del links[reverse]
   455                         reverse = local_node, local_port, remote_port, remote_node
   489                         reverse = local_node, local_port, remote_port, remote_node
   456                         links[reverse] = link_vlans
   490                         links[reverse] = link_vlans
   457 
   491 
   458                     else :
   492                     else :
   459                         log.info("%s:%s -> %s", local_node, local_port, remote_host)
   493                         log.info("%s:%s bridge -> %s", local_node, local_port, remote_host)
   460 
   494 
   461                         links[forward] = link_vlans
   495                         links[forward] = link_vlans
   462 
   496 
   463 
   497 
   464 
   498