Below is the file 'netinfo.py' from this revision. You can also download the file.
#!/usr/bin/python import ConfigParser import sys import os import pickle import time import sets import traceback from pyPgSQL import libpq from iputils import int_to_length, ip_to_int # netinfo.py # # Parses its configuration file and updates # the information on configured network devices. # # These are then serialised for access by applications # that do something interesting with the data. # # Copyright (C) 2004 Grahame Bowland. # grahame@angrygoats.net def notify(str): sys.stderr.write("%s\n" % (str)) class PluginLibrary: def __init__(self, config): self.config = config orig_path = None self.plugins = {} if self.config.has_option('locations', 'plugin_path'): orig_path = sys.path self.plugin_path = self.config.get('locations', 'plugin_path') sys.path.insert(0, self.plugin_path) if self.config.has_section('plugins'): for option in self.config.options('plugins'): self.do_load_plugin(option) if orig_path: sys.path = orig_path def do_load_plugin(self, plugin_name): mod = __import__('%s' % plugin_name, globals(), locals(), ['']) if not self.plugins.has_key(mod.export['type']): self.plugins[mod.export['type']] = [] self.plugins[mod.export['type']].append(mod) notify("Plugin loaded: " + mod.export['name'] + " version " + mod.export['version'] + " (" + mod.export['type'] + ")") def update(connection, plugins, config): def run_sql(command_list): map(connection.query, command_list) def update_host(hostname): def determine_plugin(): for plugin in plugins: if plugin.suits(hostname, community): return plugin return None def q(s): if s == None: return "NULL" else: return libpq.PgQuoteString(s) def update_start(): notify("[%s] update_start" % (hostname)) yield "BEGIN" yield "DELETE FROM devices WHERE hostname=%s" % (q(hostname)) yield "INSERT INTO devices (hostname,update_started) VALUES (%s,now())" % (q(hostname)) yield "COMMIT" def update_stop(success): notify("[%s] update_start" % (hostname)) yield "BEGIN" yield "UPDATE devices SET update_stopped=now(),update_succeeded=%s WHERE hostname=%s" % (q(str(success)), q(hostname)) yield "COMMIT" def update_arp(): notify("[%s] update_arp" % (hostname)) yield 'BEGIN' yield 'DELETE FROM arp WHERE hostname=%s' % (q(hostname)) for ip_address, mac_address in mod.arp(hostname, community): yield "INSERT INTO arp (hostname,mac_address,ip_address) VALUES (%s,%s,%s)" % (q(hostname), q(mac_address), q(ip_address)) yield 'COMMIT' def update_addresses(): notify("[%s] update_addresses" % (hostname)) yield 'BEGIN' yield 'DELETE FROM addresses WHERE hostname=%s' % (q(hostname)) for ip_address, interface_id in mod.addresses(hostname, community): yield "INSERT INTO addresses (hostname,ip_address,interface_id) VALUES (%s,%s,%s)" % (q(hostname), q(ip_address), q(interface_id)) yield 'COMMIT' def update_vlans(vlans): notify("[%s] update_vlans" % (hostname)) yield "BEGIN" yield "DELETE FROM vlans WHERE hostname=%s" % (q(hostname)) for id, description in mod.vlans(hostname, community): vlans.add(id) yield "INSERT INTO vlans (hostname,vlan_id,description) VALUES (%s,%d,%s)" % (q(hostname), id, q(description)) yield "COMMIT" # these VLANs should be excluded from any ethernet/IP scans (reserved for non-ethernet use) exclude = sets.Set((1002,1003,1004,1005)) vlans -= exclude def update_forwarding(vlans): for vlan in vlans: notify("[%s] update_forwarding: vlan %d" % (hostname, vlan)) yield "BEGIN" yield "DELETE FROM forwarding WHERE hostname=%s and vlan_id=%s" % (q(hostname), vlan) for mac_address, ifindex in mod.forwarding(hostname, community, vlan): yield "INSERT INTO forwarding (hostname,vlan_id,mac_address,interface_id) VALUES (%s,%d,%s,%d)" % (q(hostname), vlan, q(mac_address), ifindex) yield "COMMIT" def update_adjacency(): notify("[%s] update_adjacency" % (hostname)) yield "BEGIN" yield "DELETE FROM adjacency WHERE hostname=%s" % (q(hostname)) for ip_address, name, remote_port in mod.adjacency(hostname, community): yield "INSERT INTO adjacency (hostname, adjacent_hostname, adjacent_interface_description, ip_address) VALUES (%s,%s,%s,%s)" % (q(hostname), q(name), q(remote_port), q(ip_address)) yield "COMMIT" def update_routing(): notify("[%s] update_routing" % (hostname)) yield "BEGIN" yield "DELETE FROM routing WHERE hostname=%s" % (q(hostname)) for type, ifindex, is_null, network, via, metric in mod.routing(hostname, community): yield "INSERT INTO routing (hostname,route_type,interface_id,is_null_route,network,via,metric) VALUES (%s,%s,%s,%s,%s,%s,%s)" % (q(hostname), q(type), q(str(ifindex)), q(str(is_null)), q(network), q(via), q(metric)) yield "COMMIT" def update_interfaces(): notify("[%s] update_interfaces" % (hostname)) yield "BEGIN" yield "DELETE FROM interfaces WHERE hostname=%s" % (q(hostname)) yield "COMMIT" try: run_sql(update_start()) community = config.get('devices', hostname) mod = determine_plugin() if not mod: notify("no suitable plugin found for %" % (hostname)) return notify("[%s] using plugin %s" % (hostname, mod.export['name'])) vlans = sets.Set() run_sql(update_addresses()) run_sql(update_adjacency()) run_sql(update_arp()) run_sql(update_routing()) run_sql(update_vlans(vlans)) run_sql(update_forwarding(vlans)) #run_sql(update_interfaces()) run_sql(update_stop(True)) except: t,v,tr = sys.exc_info() err_data = '\n'.join(traceback.format_exception(t, v, tr)) notify("Exception updating %s:%s\n(sending ABORT)" % (hostname, err_data)) connection.query("ABORT") run_sql(update_stop(False)) for hostname in config.options('devices'): try: update_host(hostname) except: t,v,tr = sys.exc_info() err_data = '\n'.join(traceback.format_exception(t, v, tr)) notify("Exception updating (in loop) %s:%s\n(sending ABORT)" % (hostname, err_data)) if __name__ == '__main__': config = ConfigParser.ConfigParser() config.read("netinfo.cfg") cnx = libpq.PQconnectdb("dbname=netinfo") if config.has_option('locations', 'empty_path'): os.environ['MIBDIR'] = 'empty_path' pl = PluginLibrary(config) update(cnx, pl.plugins['provider'], config)