diff -r afe9cc8032ec -r 9ac5dae42adb bin/pvl.hosts-graph --- a/bin/pvl.hosts-graph Mon Mar 31 16:36:45 2014 +0300 +++ b/bin/pvl.hosts-graph Mon Mar 31 17:14:51 2014 +0300 @@ -182,6 +182,8 @@ hosts_by_ethernet = { } # ethernet: host hosts_by_location = { } # (domain, location): host + nodes_port = { } # (local, int(local_port)): remote + nodes_out = { } # local: {remote} links_out = { } # (local, remote): local_port links_in = { } # (remote, local): remote_port @@ -258,6 +260,8 @@ # directional mapping links_out[(local_node, remote_node)] = local_port + nodes_port[(local_node, port)] = remote_node + nodes_out.setdefault(local_node, set()).add(remote_node) # bidirectional mappings remote_port = remote_attrs['port'] @@ -287,63 +291,6 @@ links[reverse] = (remote_untag, remote_tagged, local_untag) - # second graph: bridge - if not options.graph_bridge : - bridge = { } - elif 'bridge' in host_attrs : - bridge = host_attrs['bridge'] - else : - bridge = { } - - for port, ethernets in bridge.iteritems() : - local_node = host - local_port = port - - for ethernet in ethernets : - if ethernet in hosts_by_ethernet : - remote_node = remote_host = hosts_by_ethernet[ethernet] - - remote_label = remote_host.location or str(remote_host) - - log.info("%s:%s bridge %s = %s (%s)", host, port, ethernet, remote_host, remote_label) - else : - remote_node = remote_host = None - - if not remote_host : - continue - - if remote_node not in nodes : - log.debug("%s:%s: lazy-add remote %s (%s)", host, port, remote_node, remote_label) - - nodes[remote_node] = remote_label - - # unknown vlans - link_vlans = None - - # directional link - links_out[(local_node, remote_node)] = local_port - - # bidirectional link - forward = (local_node, local_port, None, remote_node) - - # scan for reverse - remote_port = links_out.get((remote_node, local_node)) - - if remote_port : - reverse = (remote_node, remote_port, None, local_node) - - log.info("%s:%s <-> %s:%s", local_node, local_port, remote_port, remote_host) - - # fill in remote_port for bidirectional link - del links[reverse] - reverse = local_node, local_port, remote_port, remote_node - links[reverse] = link_vlans - - else : - log.info("%s:%s -> %s", local_node, local_port, remote_host) - - links[forward] = link_vlans - # second graph: manual ports for host in hosts : local_node = host @@ -354,7 +301,12 @@ # XXX: copypasta nodes[local_node] = host.location or str(host) - for port, remote in host_links.iteritems() : + for link_port, remote in host_links.iteritems() : + if link_port.isdigit() : + port = int(link_port) + else : + port = str(link_port) + # map remote -> remote_host if '@' in remote : remote_location, remote_domain = remote.split('@', 1) @@ -389,12 +341,15 @@ log.debug("%s:%s: confirm -> %s", host, port, remote_host) links_out[(local_node, remote_node)] = port + nodes_port[(local_node, port)] = remote_node + nodes_out.setdefault(local_node, set()).add(remote_node) # update directional or missing links remote_port = links_out.get((remote_node, local_node)) reverse_port = links_in.get((local_node, remote_node)) if reverse_port and reverse_port != port : + # XXX: this can be caused by str vs int >_> log.warn("%s:%s: reverse port mismatch %s <- %s", host, port, reverse_port, remote_node) @@ -424,6 +379,82 @@ links[(local_node, local_port, None, remote_node)] = None + if options.graph_bridge : + # third graph: bridge + for host, host_attrs in snmp.iteritems() : + local_node = host + + node_out = nodes_out.get(local_node) + + if not node_out : + log.warning("%s: no outgoing links, skipping bridge", host) + continue + + bridge = { } + + for port, ethernets in host_attrs.get('bridge', { }).iteritems() : + bridge[(port, None)] = ethernets + + for vlan, vlan_attrs in host_attrs.get('vlan', { }).iteritems() : + for port, ethernets in vlan_attrs.get('bridge', { }).iteritems() : + bridge[(port, vlan)] = ethernets + + for (port, vlan), ethernets in bridge.iteritems() : + local_port = port + + remote_node = nodes_port.get((local_node, local_port)) + + if remote_node : + log.debug("%s:%s/%s bridge skip -> %s", host, port, vlan, remote_node) + continue + + for ethernet in ethernets : + # remote host + if ethernet in hosts_by_ethernet : + remote_node = remote_host = hosts_by_ethernet[ethernet] + + remote_label = remote_host.location or str(remote_host) + + log.debug("%s:%s/%s bridge %s = %s (%s)", host, port, vlan, ethernet, remote_host, remote_label) + else : + remote_node = remote_host = None + + if not remote_host : + continue + + if remote_node not in nodes : + log.debug("%s:%s: lazy-add remote %s (%s)", host, port, remote_node, remote_label) + + nodes[remote_node] = remote_label + + # unknown vlans + link_vlans = None + + # directional link + links_out[(local_node, remote_node)] = local_port + + # bidirectional link + forward = (local_node, local_port, None, remote_node) + + # scan for reverse + remote_port = links_out.get((remote_node, local_node)) + + if remote_port : + reverse = (remote_node, remote_port, None, local_node) + + log.info("%s:%s <-> %s:%s", local_node, local_port, remote_port, remote_host) + + # fill in remote_port for bidirectional link + del links[reverse] + reverse = local_node, local_port, remote_port, remote_node + links[reverse] = link_vlans + + else : + log.info("%s:%s -> %s", local_node, local_port, remote_host) + + links[forward] = link_vlans + + return nodes, links