180 |
180 |
181 hosts_by_lldp = { } # chassis: host |
181 hosts_by_lldp = { } # chassis: host |
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 nodes_in = { } # remote: {local} |
188 links_out = { } # (local, remote): local_port |
188 links_out = { } # (local, remote): local_port |
189 links_in = { } # (remote, local): remote_port |
189 links_in = { } # (remote, local): remote_port |
190 |
190 |
265 if port_vlans : |
265 if port_vlans : |
266 local_untag, local_tagged = port_vlans |
266 local_untag, local_tagged = port_vlans |
267 |
267 |
268 # directional mapping |
268 # directional mapping |
269 links_out[(local_node, remote_node)] = local_port |
269 links_out[(local_node, remote_node)] = local_port |
270 nodes_port[(local_node, port)] = remote_node |
270 nodes_port.setdefault((local_node, port), set()).add(remote_node) |
271 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) |
272 nodes_in.setdefault(remote_node, set()).add(local_node) |
273 |
273 |
274 # bidirectional mappings |
274 # bidirectional mappings |
275 remote_port = remote_attrs['port'] |
275 remote_port = remote_attrs['port'] |
347 |
347 |
348 else : |
348 else : |
349 log.debug("%s:%s: confirm -> %s", host, port, remote_host) |
349 log.debug("%s:%s: confirm -> %s", host, port, remote_host) |
350 |
350 |
351 links_out[(local_node, remote_node)] = port |
351 links_out[(local_node, remote_node)] = port |
352 nodes_port[(local_node, port)] = remote_node |
352 nodes_port.setdefault((local_node, port), set()).add(remote_node) |
353 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) |
354 nodes_in.setdefault(remote_node, set()).add(local_node) |
355 |
355 |
356 # update directional or missing links |
356 # update directional or missing links |
357 remote_port = links_out.get((remote_node, local_node)) |
357 remote_port = links_out.get((remote_node, local_node)) |
386 # mapping was completely missing |
386 # mapping was completely missing |
387 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) |
388 |
388 |
389 links[(local_node, local_port, None, remote_node)] = None |
389 links[(local_node, local_port, None, remote_node)] = None |
390 |
390 |
|
391 |
|
392 # verify non-p2p links |
|
393 for (node, port), remotes in nodes_port.iteritems() : |
|
394 if len(remotes) > 1 : |
|
395 log.warning("%s:%s: multiple remotes: %s", node, port, ' '.join(str(host) for host in remotes)) |
|
396 |
391 if options.graph_bridge : |
397 if options.graph_bridge : |
392 # scan hosts with bridges |
398 # scan hosts with bridges |
393 bridge_hosts = set() |
399 bridge_hosts = set() |
|
400 bridge_ports = { } |
394 |
401 |
395 for host, host_attrs in snmp.iteritems() : |
402 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()) : |
403 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) |
404 bridge_hosts.add(host) |
398 |
405 |
416 |
423 |
417 for (port, vlan), ethernets in bridge.iteritems() : |
424 for (port, vlan), ethernets in bridge.iteritems() : |
418 local_node = host |
425 local_node = host |
419 local_port = port |
426 local_port = port |
420 |
427 |
421 remote_node = nodes_port.get((local_node, local_port)) |
428 remote_nodes = nodes_port.get((local_node, local_port)) |
|
429 |
|
430 if not remote_nodes : |
|
431 remote_node = None |
|
432 elif len(remote_nodes) == 1 : |
|
433 remote_node, = remote_nodes |
|
434 else : |
|
435 log.warning("%s:%s: ignore port with multiple remotes: %s", host, port, ' '.join(str(host) for host in remotes)) |
|
436 continue |
422 |
437 |
423 if remote_node : |
438 if remote_node : |
424 remote_in = nodes_in.get(remote_node, set()) |
439 remote_in = nodes_in.get(remote_node, set()) |
425 else : |
440 else : |
426 remote_in = set() |
441 remote_in = set() |
472 # unknown vlans |
487 # unknown vlans |
473 link_vlans = None |
488 link_vlans = None |
474 |
489 |
475 # directional link |
490 # directional link |
476 links_out[(local_node, remote_node)] = local_port |
491 links_out[(local_node, remote_node)] = local_port |
|
492 |
|
493 if local_port : |
|
494 bridge_ports.setdefault((local_node, local_port), set()).add(remote_node) |
477 |
495 |
478 # bidirectional link |
496 # bidirectional link |
479 forward = (local_node, local_port, None, remote_node) |
497 forward = (local_node, local_port, None, remote_node) |
480 |
498 |
481 # scan for reverse |
499 # scan for reverse |
493 |
511 |
494 else : |
512 else : |
495 log.info("%s:%s bridge -> %s", local_node, local_port, remote_host) |
513 log.info("%s:%s bridge -> %s", local_node, local_port, remote_host) |
496 |
514 |
497 links[forward] = link_vlans |
515 links[forward] = link_vlans |
498 |
516 |
499 |
517 # verify unmanaged bridges |
|
518 for (node, port), remotes in bridge_ports.iteritems() : |
|
519 if len(remotes) > 1 : |
|
520 log.warning("%s:%s: multiple bridge remotes: %s", node, port, ' '.join(str(host) for host in remotes)) |
500 |
521 |
501 return nodes, links |
522 return nodes, links |
502 |
523 |
503 class GraphVlans (object) : |
524 class GraphVlans (object) : |
504 """ |
525 """ |