104 file = open(file) |
104 file = open(file) |
105 else : |
105 else : |
106 file = sys.stdin |
106 file = sys.stdin |
107 |
107 |
108 root = { } |
108 root = { } |
109 |
109 |
110 for host_name, attr, value in _load_snmp_data(options, file) : |
110 hosts_by_namedomain = dict( |
111 host = hosts.get(host_name) |
111 ( |
|
112 '{host}@{domain}'.format(host=host, domain=host.domain), host |
|
113 ) for host in hosts |
|
114 ) |
|
115 |
|
116 for host_domain, attr, value in _load_snmp_data(options, file) : |
|
117 host = hosts_by_namedomain.get(host_domain) |
112 |
118 |
113 if value : |
119 if value : |
114 log.debug("[%s] %s: %s", host, ' '.join(str(a) for a in attr), value) |
120 log.debug("[%s] %s: %s", host, ' '.join(str(a) for a in attr), value) |
115 else : |
121 else : |
116 log.debug("[%s] %s", host, ' '.join(str(a) for a in attr),) |
122 log.debug("[%s] %s", host, ' '.join(str(a) for a in attr),) |
170 """ |
176 """ |
171 |
177 |
172 nodes = { } # host: label |
178 nodes = { } # host: label |
173 links = { } |
179 links = { } |
174 |
180 |
175 hosts_by_lldp = { } |
181 hosts_by_lldp = { } # chassis: host |
|
182 hosts_by_ethernet = { } # ethernet: host |
176 |
183 |
177 # first scan: lldp hosts |
184 # first scan: lldp hosts |
178 for host, host_attrs in snmp.iteritems() : |
185 for host, host_attrs in snmp.iteritems() : |
179 lldp = host_attrs.get('lldp') |
186 lldp = host_attrs.get('lldp') |
180 |
187 |
181 if lldp : |
188 if lldp : |
182 lldp_local = lldp['local'] |
189 lldp_local = lldp['local'] |
183 local = lldp_local['chassis'] |
190 local = lldp_local['chassis'] |
184 |
191 |
185 nodes[host] = host.location |
192 nodes[host] = host.location or str(host) |
186 hosts_by_lldp[local] = host |
193 hosts_by_lldp[local] = host |
187 |
194 |
|
195 # second scan: nodes by ethernet |
|
196 for host in hosts : |
|
197 for ethernet in host.ethernet.itervalues() : |
|
198 hosts_by_ethernet[ethernet] = host |
|
199 |
188 # second scan: lldp remotes |
200 # second scan: lldp remotes |
189 for host, host_attrs in snmp.iteritems() : |
201 for host, host_attrs in snmp.iteritems() : |
190 lldp = host_attrs.get('lldp') |
202 lldp = host_attrs.get('lldp') |
191 |
203 |
192 if not lldp : |
204 if not lldp : |
202 |
214 |
203 for port, port_attrs in lldp.get('port', { }).iteritems() : |
215 for port, port_attrs in lldp.get('port', { }).iteritems() : |
204 local_port = port_attrs['local']['port'] |
216 local_port = port_attrs['local']['port'] |
205 |
217 |
206 for remote, remote_attrs in port_attrs['remote'].iteritems() : |
218 for remote, remote_attrs in port_attrs['remote'].iteritems() : |
|
219 # determine remote node |
|
220 remote_label = remote_attrs['sys_name'] |
|
221 |
207 if remote in hosts_by_lldp : |
222 if remote in hosts_by_lldp : |
208 remote_node = hosts_by_lldp[remote] |
223 remote_node = remote_host = hosts_by_lldp[remote] |
|
224 |
|
225 elif remote in hosts_by_ethernet : |
|
226 remote_node = remote_host = hosts_by_ethernet[remote] |
|
227 |
|
228 if remote_host.location : |
|
229 remote_label = remote_host.location |
|
230 |
|
231 log.info("%s:%s: guessing lldp host %s -> %s (%s)", host, port, remote, remote_host, remote_label) |
|
232 |
209 else : |
233 else : |
210 remote_node = remote |
234 remote_node = remote |
211 |
235 remote_host = None |
212 # non-snmp lldp host |
236 |
213 nodes[remote_node] = remote_attrs['sys_name'] |
237 log.warning("%s:%s: unknown remote %s (%s)", host, port, remote, remote_label) |
214 |
238 |
215 remote_port = remote_attrs['port'] |
239 # ensure remote node |
|
240 if remote_node not in nodes : |
|
241 log.info("%s:%s: lazy-add remote %s (%s)", host, port, remote_node, remote_label) |
|
242 |
|
243 nodes[remote_node] = remote_label |
216 |
244 |
217 # local vlans |
245 # local vlans |
218 if vlans : |
246 if vlans : |
219 port_vlans = vlans.get(port) |
247 port_vlans = vlans.get(port) |
220 else : |
248 else : |
222 |
250 |
223 if port_vlans : |
251 if port_vlans : |
224 local_untag, local_tagged = port_vlans |
252 local_untag, local_tagged = port_vlans |
225 |
253 |
226 # bidirectional mappings |
254 # bidirectional mappings |
|
255 remote_port = remote_attrs['port'] |
|
256 |
227 forward = (local_node, local_port, remote_port, remote_node) |
257 forward = (local_node, local_port, remote_port, remote_node) |
228 reverse = (remote_node, remote_port, local_port, local_node) |
258 reverse = (remote_node, remote_port, local_port, local_node) |
229 |
259 |
230 if reverse not in links : |
260 if reverse not in links : |
231 links[forward] = (local_untag, local_tagged, None) |
261 links[forward] = (local_untag, local_tagged, None) |
397 |
427 |
398 # input |
428 # input |
399 options, args = parser.parse_args(argv[1:]) |
429 options, args = parser.parse_args(argv[1:]) |
400 pvl.args.apply(options) |
430 pvl.args.apply(options) |
401 |
431 |
402 # load hosts for correlation |
432 # load hosts |
403 hosts = dict((str(host), host) for host in pvl.hosts.apply(options, args)) |
433 hosts = list(pvl.hosts.apply(options, args)) |
404 |
434 |
405 # load raw snmp data |
435 # load raw snmp data |
406 snmp = load_snmp_data(options, options.snmp_data, hosts) |
436 snmp = load_snmp_data(options, options.snmp_data, hosts) |
407 |
437 |
408 # process data into graph |
438 # process data into graph |