bin/pvl.hosts-lldp
changeset 393 8321a569d5c0
parent 392 e7a55db74072
child 395 9de553b50128
equal deleted inserted replaced
392:e7a55db74072 393:8321a569d5c0
   184         src_label = '"{host.location}"'.format(host=host)
   184         src_label = '"{host.location}"'.format(host=host)
   185 
   185 
   186         if src_name in nodes :
   186         if src_name in nodes :
   187             src = nodes[src_name]
   187             src = nodes[src_name]
   188         else :
   188         else :
   189             src = nodes[src_name] = pydot.Node(src_name, label=src_label)
   189             src = nodes[src_name] = pydot.Node(src_name,
       
   190                     label       = src_label,
       
   191                     fontsize    = 18,
       
   192             )
   190             dot.add_node(src)
   193             dot.add_node(src)
   191         
   194         
   192         # dst
   195         # dst
   193         if remote_host :
   196         if remote_host :
   194             dst_name = str(remote_host)
   197             dst_name = str(remote_host)
   203                 dst_label = '"{remote[chassis]}"'.format(remote=remote)
   206                 dst_label = '"{remote[chassis]}"'.format(remote=remote)
   204         
   207         
   205         if dst_name in nodes :
   208         if dst_name in nodes :
   206             dst = nodes[dst_name]
   209             dst = nodes[dst_name]
   207         else :
   210         else :
   208             dst = nodes[dst_name] = pydot.Node(dst_name, label=dst_label)
   211             dst = nodes[dst_name] = pydot.Node(dst_name,
       
   212                     label       = dst_label,
       
   213                     fontsize    = 18,
       
   214             )
   209             dot.add_node(dst)
   215             dot.add_node(dst)
   210 
   216 
   211         # edges
   217         # edges
   212         headlabel = '"{remote[port]}"'.format(remote=remote)
   218         headlabel = '"{remote[port]}"'.format(remote=remote)
   213         taillabel = '"{local[port]}"'.format(local=local)
   219         taillabel = '"{local[port]}"'.format(local=local)
   214         fillcolor = None
   220         fillcolor = 'black'
   215         color = None
   221         color = 'black'
       
   222         untag = tagged = None
   216 
   223 
   217         # vlans?
   224         # vlans?
   218         if host in vlans and local['port_id'] in vlans[host] :
   225         if vlans and host in vlans and local['port_id'] in vlans[host] :
   219             untag, tagged = vlans[host][local['port_id']]
   226             untag, tagged = vlans[host][local['port_id']]
   220             
   227             
   221             log.debug("%s#%s: %s+%s", host, local['port_id'], untag, tagged)
   228             log.debug("%s#%s: %s+%s", host, local['port_id'], untag, tagged)
   222             
   229             
   223             colors = []
   230             colors = []
   246                 log.warn("%s#%s: chosing new vlan %s color %s", host, local['port_id'], untag, color)
   253                 log.warn("%s#%s: chosing new vlan %s color %s", host, local['port_id'], untag, color)
   247                     
   254                     
   248                 fillcolor = vlan_colors[tag] = color
   255                 fillcolor = vlan_colors[tag] = color
   249             
   256             
   250             # first color overrides fillcolor for heads
   257             # first color overrides fillcolor for heads
   251             if colors and fillcolor :
   258             if colors and untag :
   252                 color = ':'.join([fillcolor] + colors)
   259                 color = ':'.join([fillcolor] + colors)
   253             elif colors :
   260             elif colors :
   254                 color = ':'.join(colors)
   261                 color = ':'.join(colors)
   255             elif fillcolor :
   262             elif fillcolor :
   256                 color = fillcolor
   263                 color = fillcolor
   257             else :
       
   258                 color = 'black'
       
   259 
       
   260             if not fillcolor :
       
   261                 fillcolor = 'black'
       
   262 
   264 
   263         elif vlans :
   265         elif vlans :
   264             # XXX: this happens when LLDP gives us the LACP ports but the VLANS are on the TRK port
   266             # XXX: this happens when LLDP gives us the LACP ports but the VLANS are on the TRK port
   265             log.warn("%s#%s: unknown port for vlans: %s", host, local['port_id'], vlans.get(host))
   267             log.warn("%s#%s: unknown port for vlans: %s", host, local['port_id'], vlans.get(host))
   266 
       
   267             untag = tag = None
       
   268 
       
   269         else :
       
   270             untag = tag = None
       
   271 
   268 
   272         # edge
   269         # edge
   273         if (src_name, local['port'], dst_name, remote['port']) in edges :
   270         if (src_name, local['port'], dst_name, remote['port']) in edges :
   274             log.warning("%s:%s <- %s:%s: duplicate", src_name, local['port'], dst_name, remote['port'])
   271             log.warning("%s:%s <- %s:%s: duplicate", src_name, local['port'], dst_name, remote['port'])
   275         
   272         
   284                 log.warn("%s -> %s: remote port mismatch: %s vs %s", src_name, dst_name, remote['port'], edge.get('taillabel'))
   281                 log.warn("%s -> %s: remote port mismatch: %s vs %s", src_name, dst_name, remote['port'], edge.get('taillabel'))
   285 
   282 
   286             if edge.get('fillcolor') != fillcolor :
   283             if edge.get('fillcolor') != fillcolor :
   287                 log.warn("%s#%s -> %s#%s: remote untag mismatch: %s vs %s", src_name, local['port'], dst_name, remote['port'], fillcolor, edge.get('fillcolor'))
   284                 log.warn("%s#%s -> %s#%s: remote untag mismatch: %s vs %s", src_name, local['port'], dst_name, remote['port'], fillcolor, edge.get('fillcolor'))
   288 
   285 
   289             if edge.get('color') != '"' + (color or 'black') + '"' :
   286             if edge.get('color') != '"' + color + '"' :
   290                 log.warn("%s#%s -> %s#%s: remote tagged mismatch: %s vs %s", src_name, local['port'], dst_name, remote['port'], color, edge.get('color'))
   287                 log.warn("%s#%s -> %s#%s: remote tagged mismatch: %s vs %s", src_name, local['port'], dst_name, remote['port'], color, edge.get('color'))
   291 
   288 
   292             # mark as bidirectional
   289             # mark as bidirectional
   293             edges[(src_name, local['port'], dst_name, remote['port'])] = edge
   290             edges[(src_name, local['port'], dst_name, remote['port'])] = edge
   294             
   291             
   305         else :
   302         else :
   306             edge = edges[(src_name, local['port'], dst_name, remote['port'])] = pydot.Edge(src, dst,
   303             edge = edges[(src_name, local['port'], dst_name, remote['port'])] = pydot.Edge(src, dst,
   307                     dir         = 'forward' if untag else 'none',
   304                     dir         = 'forward' if untag else 'none',
   308                     headlabel   = headlabel,
   305                     headlabel   = headlabel,
   309                     taillabel   = taillabel,
   306                     taillabel   = taillabel,
   310                     color       = '"{color}"'.format(color=color) if color else 'black',
   307                     color       = '"{color}"'.format(color=color),
   311                     fillcolor   = fillcolor or 'black',
   308                     fillcolor   = fillcolor,
   312             )
   309             )
   313 
   310 
   314             dot.add_edge(edge)
   311             dot.add_edge(edge)
   315 
   312 
   316     if options.graph_dot :
   313     if options.graph_dot :
   327     parser.add_option_group(pvl.snmp.snmp.options(parser))
   324     parser.add_option_group(pvl.snmp.snmp.options(parser))
   328 
   325 
   329     parser.add_option('--graph-dot',
   326     parser.add_option('--graph-dot',
   330             help="Output .dot graph data")
   327             help="Output .dot graph data")
   331 
   328 
       
   329     parser.add_option('--no-vlans', action='store_const', dest='vlans', const=False,
       
   330             help="Do not color VLANs")
       
   331 
   332     # input
   332     # input
   333     options, args = parser.parse_args(argv[1:])
   333     options, args = parser.parse_args(argv[1:])
   334     pvl.args.apply(options)
   334     pvl.args.apply(options)
   335 
   335 
   336     hosts = pvl.hosts.apply(options, args)
   336     hosts = pvl.hosts.apply(options, args)
   337     
   337     
   338     # lookup host-port-vlan mappings
   338     # lookup host-port-vlan mappings
   339     vlans = dict(apply_hosts_vlan(options, hosts))
   339     if options.vlans is False :
       
   340         vlans = None
       
   341     else :
       
   342         vlans = dict(apply_hosts_vlan(options, hosts))
   340 
   343 
   341     # discover node/port graph
   344     # discover node/port graph
   342     items = apply_hosts_lldp(options, hosts)
   345     items = apply_hosts_lldp(options, hosts)
   343 
   346 
   344     # print
   347     # print