source: genesis/tools/get-link-traffic.py@ 12356

Last change on this file since 12356 was 10041, checked in by rick, 13 years ago

Do not chdir as it confuses storing files without an prefix in the WC.

  • Property svn:executable set to *
File size: 4.3 KB
RevLine 
[9987]1#!/usr/bin/env python
2#
3# XXX: Parsing snmpwalk is soo wrong todo, use a proper python library.
4#
[10035]5#
[9987]6# Rick van der Zwet <info@rickvanderzwet.nl>
7#
[10040]8import gformat
[9987]9import glob
10import logging
11import subprocess
12import sys
13import yaml
[9988]14from multiprocessing import Process, Manager, Pool, Queue, freeze_support
15
[9987]16logging.basicConfig(level=logging.DEBUG)
17logger = logging.getLogger()
18
[9988]19
20
[9987]21DATASTORE='store.yaml'
22
23class ConnectError(Exception):
24 pass
25
[9988]26def get_snmp_stats(logger, ip,target):
[9987]27 p = subprocess.Popen("snmpwalk -t 1 -r 1 -Oq -c public -v2c %s %s" % (ip, target),
28 shell=True,
29 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
30 (stdout, stderr) = p.communicate()
31 if p.returncode != 0:
32 logger.error(stderr.strip())
33 raise ConnectError
34 r = {}
35 for line in stdout.strip().split('\n'):
36 index = line.split()[0][len(target)+1:]
37 value = line.split()[1]
38 r[index] = value
39 return r
40
[9988]41def get_snmp_value(logger, ip, target):
[9987]42 p = subprocess.Popen("snmpget -t 1 -r 1 -Ovt -c public -v2c %s %s" % (ip, target),
43 shell=True,
44 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
45 (stdout, stderr) = p.communicate()
46 if p.returncode != 0:
47 logger.error(stderr.strip())
48 raise ConnectError
49 return stdout.strip()
50
[9988]51def find_right_snmp_ip(logger, data):
52 for k,v in data.iteritems():
53 if k.startswith('iface_'):
54 ip = v['ip'].split('/')[0]
55 logger.info("Trying ip %s", ip)
56 try:
57 uptime = get_snmp_value(logger, ip, 'DISMAN-EVENT-MIB::sysUpTimeInstance')
58 return ip
59 except ConnectError:
60 pass
61 return None
62
[9987]63try:
64 ff = sys.argv[1]
65except IndexError:
66 ff = ''
67
[10040]68def process_file(logger, m_snmp, m_traffic, m_uptime, host, rescan):
69 data = gformat.get_yaml(host)
[9988]70 nodename = data['nodename']
71
[10035]72 if m_snmp.has_key(nodename):
73 ip = m_snmp[nodename]
[9988]74 if not ip and rescan:
75 logger.info("Re-scanning for new valid IP")
76 ip = find_right_snmp_ip(logger, data)
[10035]77 m_snmp[nodename] = ip
[9987]78 else:
[9988]79 try:
80 uptime = get_snmp_value(logger, ip, 'DISMAN-EVENT-MIB::sysUpTimeInstance')
81 except ConnectError:
82 logger.info("Re-scanning for new valid IP")
83 ip = find_right_snmp_ip(logger, data)
[10035]84 m_snmp[nodename] = ip
[9988]85 else:
86 logger.info("Running discovery for %s", nodename)
87 ip = find_right_snmp_ip(logger, data)
[10035]88 m_snmp[nodename] = ip
[9987]89
[9988]90 if ip == None:
91 logger.error("No valid ip found for node %s", nodename)
92 return
[10035]93
[9988]94 logger.info("Processing %s via %s", nodename, ip)
95 target = 'IF-MIB::ifDescr'
[10035]96
[9988]97 try:
98 iface = get_snmp_stats(logger, ip, 'IF-MIB::ifDescr')
99 ifout = get_snmp_stats(logger, ip, 'IF-MIB::ifOutOctets')
100 ifin = get_snmp_stats(logger, ip, 'IF-MIB::ifInOctets')
101
102 uptime = get_snmp_value(logger, ip, 'DISMAN-EVENT-MIB::sysUpTimeInstance')
[10035]103 m_uptime[nodename] = int(uptime)
104
[9988]105 traffic = {}
106 for i,f in iface.iteritems():
107 traffic[f] = (int(ifin[i]), int(ifout[i]))
[10035]108 m_traffic[nodename] = traffic
[9988]109 except ConnectError:
110 logger.error("Unable to get all data")
111 pass
[9987]112
[10035]113def worker(i, input, m_snmp, m_traffic, m_uptime):
[9988]114 logger = logging.getLogger('Worker%s' % i)
115 logger.info("Worker")
[10040]116 for (host, rescan) in iter(input.get, 'STOP'):
117 process_file(logger, m_snmp, m_traffic, m_uptime, host, rescan)
[9988]118 logger.info("END")
[9987]119
[9988]120if __name__ == '__main__':
121 freeze_support()
122 task_queue = Queue()
123 manager = Manager()
[9987]124
[9988]125 try:
126 store = yaml.load(open(DATASTORE,'r'))
127 except IOError:
128 store = { 'snmp' : {}, 'traffic' : {}, 'uptime' : {}}
129 pass
[10035]130 # XXX: Manager.dict has bug of handling dicts inside dicts, using awefull quick
131 # XXX: http://bugs.python.org/issue6766
132 m_snmp = manager.dict(store['snmp'])
133 m_traffic = manager.dict(store['traffic'])
134 m_uptime = manager.dict(store['uptime'])
[9987]135
[9988]136 NUMBER_OF_PROCESSES = 10
137 RESCAN = True
138 plist = {}
139 for i in range(NUMBER_OF_PROCESSES):
[10035]140 plist[i] = Process(target=worker, args=(i, task_queue,m_snmp,m_traffic,m_uptime))
[9988]141 plist[i].start()
142
[10040]143 for host in sorted(gformat.get_hostlist()):
144 if ff and not ff in host:
145 continue
146 task_queue.put((host, RESCAN))
[10035]147
[9988]148 for i in range(NUMBER_OF_PROCESSES):
149 task_queue.put('STOP')
150
151 for i in range(NUMBER_OF_PROCESSES):
152 plist[i].join()
153
[10035]154 store = {'snmp' : dict(m_snmp), 'traffic' : dict(m_traffic), 'uptime' : dict(m_uptime)}
[9988]155 yaml.dump(store,open(DATASTORE,'w'))
[10041]156 logger.info("Stored data at %s" % DATASTORE)
[9988]157
158
159
Note: See TracBrowser for help on using the repository browser.