bin/pvl.hosts-lldp
author Tero Marttila <terom@paivola.fi>
Mon, 17 Mar 2014 20:30:28 +0200
changeset 388 5a034dbd641c
parent 387 75158fd28784
child 391 e2c367b1556f
permissions -rw-r--r--
pvl.hosts-lldp: support multiple edges between nodes
380
78f192fe9e2c pvl.hosts-lldp: snmp-based lldp discovery of connected switches
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     1
#!/usr/bin/env python
78f192fe9e2c pvl.hosts-lldp: snmp-based lldp discovery of connected switches
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     2
78f192fe9e2c pvl.hosts-lldp: snmp-based lldp discovery of connected switches
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     3
"""
78f192fe9e2c pvl.hosts-lldp: snmp-based lldp discovery of connected switches
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     4
    Requirements:
387
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
     5
        pydot
380
78f192fe9e2c pvl.hosts-lldp: snmp-based lldp discovery of connected switches
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     6
"""
78f192fe9e2c pvl.hosts-lldp: snmp-based lldp discovery of connected switches
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     7
78f192fe9e2c pvl.hosts-lldp: snmp-based lldp discovery of connected switches
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     8
import pvl.args
78f192fe9e2c pvl.hosts-lldp: snmp-based lldp discovery of connected switches
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     9
import pvl.hosts
382
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    10
from pvl.invoke import merge
384
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    11
from pvl.snmp import snmp, lldp
380
78f192fe9e2c pvl.hosts-lldp: snmp-based lldp discovery of connected switches
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    12
384
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    13
import logging; log = logging.getLogger('pvl.hosts-lldp')
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    14
import optparse
382
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    15
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    16
def hosts_lldp (options, hosts) :
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    17
    """
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    18
        Discover LLDP-supporting hosts.
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    19
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    20
        Yields Host, LLDPAgent
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    21
    """
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    22
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    23
    for host in hosts :
384
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    24
        host_snmp = host.extensions.get('snmp')
382
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    25
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    26
384
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    27
        if not host_snmp :
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    28
            log.debug("%s: skip non-snmp host", host)
382
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    29
            continue
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    30
384
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    31
        elif host.down :
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    32
            log.debug("%s: skip down host", host)
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    33
            continue
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    34
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    35
        else :
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    36
            log.debug("%s: %s", host, host_snmp)
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    37
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    38
        agent = lldp.LLDPAgent.apply(options, host.fqdn(), community=host_snmp.get('community'))
382
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    39
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    40
        try :
384
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    41
            local = agent.local
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    42
        except snmp.SNMPError as ex :
382
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    43
            log.warning("%s: %s", host, ex)
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    44
            continue
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    45
384
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    46
        log.info("%s: %s", host, local)
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    47
382
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    48
        if local['sys_name'] != host.host :
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    49
            log.warning("%s: SNMP sys_name mismatch: %s", host, local['sys_name'])
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    50
384
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    51
        yield host, agent
382
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    52
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    53
def apply_hosts_lldp (options, hosts) :
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    54
    """
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    55
        Query host LLDP info.
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    56
    """
384
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    57
    
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    58
    _hosts_lldp = list(hosts_lldp(options, hosts))
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    59
    hosts_by_chassis = { }
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    60
    
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    61
    # first pass to discover hosts
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    62
    for host, agent in _hosts_lldp :
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    63
        chassis = agent.local['chassis']
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    64
        log.info("%s: %s", host, chassis)
382
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    65
384
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    66
        hosts_by_chassis[chassis] = host
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    67
    
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    68
    # second pass to discver links
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    69
    for host, agent in _hosts_lldp :
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    70
        for port, remote in agent.remotes() :
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    71
            port = agent.port(port)
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    72
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    73
            remote_chassis = remote['chassis']
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    74
            remote_host = hosts_by_chassis.get(remote_chassis)
382
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    75
            
384
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    76
            log.info("%s: %s: %s (%s)", host, port, remote, remote_host)
382
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
    77
384
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
    78
            yield host, merge(agent.local, port), remote, remote_host
380
78f192fe9e2c pvl.hosts-lldp: snmp-based lldp discovery of connected switches
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    79
387
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
    80
def apply_graph (options, items) :
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
    81
    import pydot
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
    82
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
    83
    dot = pydot.Dot(graph_name='lldp_hosts', graph_type='digraph',
388
5a034dbd641c pvl.hosts-lldp: support multiple edges between nodes
Tero Marttila <terom@paivola.fi>
parents: 387
diff changeset
    84
            # XXX: breaks multi-edges?
5a034dbd641c pvl.hosts-lldp: support multiple edges between nodes
Tero Marttila <terom@paivola.fi>
parents: 387
diff changeset
    85
            #splines     = 'true',
387
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
    86
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
    87
            sep             = '+25,25',
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
    88
            overlap         = 'scalexy',
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
    89
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
    90
            # only applies to loops
388
5a034dbd641c pvl.hosts-lldp: support multiple edges between nodes
Tero Marttila <terom@paivola.fi>
parents: 387
diff changeset
    91
            #nodesep     = 0.5,
387
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
    92
    )
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
    93
    dot.set_edge_defaults(
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
    94
            labeldistance   = 3.0,
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
    95
    )
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
    96
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
    97
    nodes = { }
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
    98
    edges = { }
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
    99
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   100
    for host, local, remote, remote_host in items :
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   101
        # src
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   102
        src_name = str(host)
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   103
        src_label = '"{host.location}"'.format(host=host)
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   104
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   105
        if src_name in nodes :
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   106
            src = nodes[src_name]
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   107
        else :
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   108
            src = nodes[src_name] = pydot.Node(src_name, label=src_label)
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   109
            dot.add_node(src)
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   110
        
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   111
        # dst
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   112
        if remote_host :
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   113
            dst_name = str(remote_host)
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   114
            dst_label = '"{host.location}"'.format(host=remote_host)
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   115
        else :
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   116
            dst_name = remote['chassis'].replace(':', '-')
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   117
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   118
            # XXX: pydot is not smart enough to quote this
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   119
            if remote['sys_name'] :
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   120
                dst_label = '"{remote[chassis]} ({remote[sys_name]})"'.format(remote=remote)
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   121
            else :
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   122
                dst_label = '"{remote[chassis]}"'.format(remote=remote)
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   123
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   124
        
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   125
        if dst_name in nodes :
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   126
            dst = nodes[dst_name]
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   127
        else :
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   128
            dst = nodes[dst_name] = pydot.Node(dst_name, label=dst_label)
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   129
            dot.add_node(dst)
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   130
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   131
        # edge
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   132
        headlabel = '"{remote[port]}"'.format(remote=remote)
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   133
        taillabel = '"{local[port]}"'.format(local=local)
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   134
388
5a034dbd641c pvl.hosts-lldp: support multiple edges between nodes
Tero Marttila <terom@paivola.fi>
parents: 387
diff changeset
   135
        if (src_name, local['port'], dst_name, remote['port']) in edges :
5a034dbd641c pvl.hosts-lldp: support multiple edges between nodes
Tero Marttila <terom@paivola.fi>
parents: 387
diff changeset
   136
            log.warning("%s:%s <- %s:%s: duplicate", src_name, local['port'], dst_name, remote['port'])
387
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   137
        
388
5a034dbd641c pvl.hosts-lldp: support multiple edges between nodes
Tero Marttila <terom@paivola.fi>
parents: 387
diff changeset
   138
        elif (dst_name, remote['port'], src_name, local['port']) in edges :
387
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   139
            log.info("%s <-> %s", src_name, dst_name)
388
5a034dbd641c pvl.hosts-lldp: support multiple edges between nodes
Tero Marttila <terom@paivola.fi>
parents: 387
diff changeset
   140
            edge = edges[(dst_name, remote['port'], src_name, local['port'])]
387
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   141
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   142
            if edge.get('headlabel') != taillabel :
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   143
                log.warn("%s -> %s: local port mismatch: %s vs %s", src_name, dst_name, local['port'], edge.get('headlabel'))
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   144
            
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   145
            if edge.get('taillabel') != headlabel :
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   146
                log.warn("%s -> %s: remote port mismatch: %s vs %s", src_name, dst_name, remote['port'], edge.get('taillabel'))
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   147
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   148
            # mark as bidirectional
388
5a034dbd641c pvl.hosts-lldp: support multiple edges between nodes
Tero Marttila <terom@paivola.fi>
parents: 387
diff changeset
   149
            edges[(src_name, local['port'], dst_name, remote['port'])] = edge
387
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   150
            
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   151
            edge.set('dir', 'both')
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   152
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   153
        else :
388
5a034dbd641c pvl.hosts-lldp: support multiple edges between nodes
Tero Marttila <terom@paivola.fi>
parents: 387
diff changeset
   154
            edge = edges[(src_name, local['port'], dst_name, remote['port'])] = pydot.Edge(src, dst,
387
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   155
                    dir         = 'back',
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   156
                    headlabel   = headlabel,
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   157
                    taillabel   = taillabel,
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   158
            )
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   159
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   160
            dot.add_edge(edge)
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   161
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   162
    if options.graph_dot :
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   163
        dot.write(options.graph_dot)
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   164
380
78f192fe9e2c pvl.hosts-lldp: snmp-based lldp discovery of connected switches
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   165
def main (argv) :
78f192fe9e2c pvl.hosts-lldp: snmp-based lldp discovery of connected switches
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   166
    """
78f192fe9e2c pvl.hosts-lldp: snmp-based lldp discovery of connected switches
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   167
        SNMP polling.
78f192fe9e2c pvl.hosts-lldp: snmp-based lldp discovery of connected switches
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   168
    """
78f192fe9e2c pvl.hosts-lldp: snmp-based lldp discovery of connected switches
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   169
78f192fe9e2c pvl.hosts-lldp: snmp-based lldp discovery of connected switches
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   170
    parser = optparse.OptionParser(main.__doc__)
78f192fe9e2c pvl.hosts-lldp: snmp-based lldp discovery of connected switches
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   171
    parser.add_option_group(pvl.args.parser(parser))
382
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
   172
    parser.add_option_group(pvl.hosts.optparser(parser))
384
caa3dbbdbe83 split upt pvl.hosts-lldp into pvl.snmp.snmp and pvl.snmp.lldp, match remote hosts, better formatting
Tero Marttila <terom@paivola.fi>
parents: 382
diff changeset
   173
    parser.add_option_group(pvl.snmp.snmp.options(parser))
380
78f192fe9e2c pvl.hosts-lldp: snmp-based lldp discovery of connected switches
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   174
387
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   175
    parser.add_option('--graph-dot',
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   176
            help="Output .dot graph data")
380
78f192fe9e2c pvl.hosts-lldp: snmp-based lldp discovery of connected switches
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   177
78f192fe9e2c pvl.hosts-lldp: snmp-based lldp discovery of connected switches
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   178
    options, args = parser.parse_args(argv[1:])
78f192fe9e2c pvl.hosts-lldp: snmp-based lldp discovery of connected switches
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   179
    pvl.args.apply(options)
78f192fe9e2c pvl.hosts-lldp: snmp-based lldp discovery of connected switches
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   180
78f192fe9e2c pvl.hosts-lldp: snmp-based lldp discovery of connected switches
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   181
    # input
382
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
   182
    hosts = pvl.hosts.apply(options, args)
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
   183
    
ba47a64f61f9 pvl.hosts-lldp: refactor lldp collection schema
Tero Marttila <terom@paivola.fi>
parents: 380
diff changeset
   184
    # apply
387
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   185
    items = apply_hosts_lldp(options, hosts)
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   186
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   187
    # print
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   188
    if options.graph_dot :
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   189
        apply_graph(options, items)
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   190
    else :
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   191
        for host, local, remote, remote_host in items :
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   192
            if remote_host :
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   193
                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)
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   194
            else :
75158fd28784 pvl.hosts-lldp: --graph-dot support
Tero Marttila <terom@paivola.fi>
parents: 386
diff changeset
   195
                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='')
380
78f192fe9e2c pvl.hosts-lldp: snmp-based lldp discovery of connected switches
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   196
78f192fe9e2c pvl.hosts-lldp: snmp-based lldp discovery of connected switches
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   197
if __name__ == '__main__':
78f192fe9e2c pvl.hosts-lldp: snmp-based lldp discovery of connected switches
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   198
    pvl.args.main(main)