~ubuntu-branches/ubuntu/dapper/flow-tools/dapper

« back to all changes in this revision

Viewing changes to bin/flow-rpt2rrd

  • Committer: Bazaar Package Importer
  • Author(s): Radu Spineanu
  • Date: 2005-06-02 20:12:57 UTC
  • mfrom: (1.1.1 upstream) (2.1.1 sarge)
  • Revision ID: james.westby@ubuntu.com-20050602201257-jv0qdk3hjhpdf04b
Tags: 1:0.68-2
Fixed a bashism in init script (closes: #311568)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/local/bin/python
 
2
 
 
3
import getopt
 
4
import os
 
5
import rrdtool
 
6
import sys
 
7
import string
 
8
 
 
9
#
 
10
# flow-rpt2rrd - convert flow-report output to rrd format
 
11
#
 
12
 
 
13
# TODO
 
14
#  work with time-series flow-report output
 
15
#  relax 5 minute sample requirement.
 
16
 
 
17
#
 
18
# load key file
 
19
#
 
20
def load_keyfile(fname):
 
21
  keys = []
 
22
  f = open(fname, "r")
 
23
  line = f.readline().strip()
 
24
  while line:
 
25
    if line[0:1] == '#':
 
26
      line = f.readline()
 
27
      continue
 
28
    keys.append(line)
 
29
    line = f.readline().strip()
 
30
  f.close()
 
31
  return string.join(keys, ',')
 
32
 
 
33
#
 
34
# Class: ftsym
 
35
#   load a symbol table from a file in value symbol format, provide
 
36
#   access methods findbyname and findbyval
 
37
#
 
38
class ftsym:
 
39
 
 
40
#
 
41
# load symbols
 
42
#
 
43
  def __init__(self,field):
 
44
    self.sv = {}
 
45
    self.vs = {}
 
46
    __symbol_lookup = { 'ip-source-port' : 'tcp-port.sym',
 
47
                      'ip-destination-port' : 'tcp-port.sym',
 
48
                      'ip-protocol' : 'ip-prot.sym',
 
49
                      'source-as' : 'asn.sym',
 
50
                      'destination-as' : 'asn.sym',
 
51
                      'source-tag' : 'tag.sym',
 
52
                      'destination-tag' : 'tag.sym',
 
53
                      'ip-address-type' : 'ip-type.sym',
 
54
                    }
 
55
    fname = "/usr/local/netflow/var/sym/%s" % __symbol_lookup[field]
 
56
    f = open(fname, "r")
 
57
    line = f.readline().strip()
 
58
    while line:
 
59
      (v,s) = line.split();
 
60
      self.vs[v] = s
 
61
      self.sv[s] = v
 
62
      line = f.readline().strip()
 
63
    f.close()
 
64
 
 
65
#
 
66
# access by name, return value.  If the name does not exist return the name.
 
67
#
 
68
  def findbyname(self, name):
 
69
    return self.sv.get(name,name)
 
70
 
 
71
#
 
72
# access by value, return name.  If the value does not exist return the value.
 
73
#
 
74
  def findbyval(self, val):
 
75
    return self.vs.get(val,val)
 
76
 
 
77
 
 
78
#
 
79
# Class: ftrpt2rrd
 
80
#
 
81
#   Read in output of flow-report, make suitable for rrd
 
82
#
 
83
#   pickfields - pick flows,octets,packets for inclusion into new rrd
 
84
#   pickkeys - pick keys for inclusion into new rrds.
 
85
#   mapsym() - replace key values with symbols
 
86
#   setrrd() - set rrd params
 
87
#   convert(stream) - convert to rrd format
 
88
#
 
89
class ftrpt2rrd:
 
90
#
 
91
#
 
92
#
 
93
  def __init__(self):
 
94
    # not in data area
 
95
    self.debug = 0
 
96
    self.verbose = 0
 
97
    self.in_data = 0
 
98
    self.use_key_names = {}
 
99
    self.use_key_names_special = {}
 
100
    self.use_key_names_total = 0
 
101
    self.use_fields = {'flows' : 1, 'octets' : 1, 'packets' : 1}
 
102
    self.mapsym = 0
 
103
    self.rrd_5min = 0
 
104
    self.rrd_30min = 0
 
105
    self.rrd_2hr = 0
 
106
    self.rrd_1day = 0
 
107
    self.rrd_path = '.'
 
108
    self.rrd_postfix = ''
 
109
    self.field_names = {}
 
110
    self.field_names2 = {}
 
111
    self.field_total = 0
 
112
    self.field_keys = {}
 
113
    self.field_vals = {}
 
114
    self.start_time = 0
 
115
    self.sym = {}
 
116
    self.records_processed = 0
 
117
 
 
118
  def set_use_fields(self,f):
 
119
    self.use_fields = {}
 
120
    for i in string.split(f, ','):
 
121
      self.use_fields[i] = 1
 
122
    
 
123
  def set_use_key_names(self,f):
 
124
    self.use_key_names = {}
 
125
    self.use_key_names_special = {}
 
126
    for i in string.split(f, ','):
 
127
      if i[:6] == 'total_':
 
128
        self.use_key_names_special[i] = 1
 
129
      else:
 
130
        self.use_key_names[i] = 1
 
131
        self.use_key_names_total += 1
 
132
 
 
133
  def set_mapsym(self):
 
134
    self.mapsym = 1
 
135
 
 
136
  def set_debug(self, debug):
 
137
    self.debug = debug
 
138
 
 
139
  def set_verbose(self, verbose):
 
140
    self.verbose = verbose
 
141
 
 
142
  def setrrd(self, storage, path, postfix):
 
143
    (self.rrd_5min, self.rrd_30min, self.rrd_2hr, self.rrd_1day) = \
 
144
      string.split(storage,':')
 
145
    self.rrd_path = path
 
146
    self.rrd_postfix = postfix
 
147
 
 
148
  def update_rrd(self, key, vals, use_fields_index):
 
149
 
 
150
    # / in the key maps to - for files
 
151
    key = key.replace('/','-')
 
152
 
 
153
    # open an rrd, it it doesn't exist create it.
 
154
    rrdFile = "%s/%s%s.rrd" % (self.rrd_path, key, self.rrd_postfix)
 
155
 
 
156
    # exists?
 
157
    if not os.access(rrdFile, os.F_OK):
 
158
 
 
159
      print "Creating RRD", rrdFile
 
160
 
 
161
      rrdParams = []
 
162
      t = str(int(self.start_time) - 300)
 
163
      rrdParams.append('--start')
 
164
      rrdParams.append(t)
 
165
      for i in use_fields_index.keys():
 
166
        rrdParams.append("DS:%s:ABSOLUTE:600:U:U" % use_fields_index[i])
 
167
      if (self.rrd_5min):
 
168
        rrdParams.append('RRA:AVERAGE:0.5:1:%s' % self.rrd_5min)
 
169
        rrdParams.append('RRA:MAX:0.5:1:%s' % self.rrd_5min)
 
170
      if (self.rrd_30min):
 
171
        rrdParams.append('RRA:AVERAGE:0.5:6:%s' % self.rrd_30min)
 
172
        rrdParams.append('RRA:MAX:0.5:6:%s' % self.rrd_30min)
 
173
      if (self.rrd_2hr):
 
174
        rrdParams.append('RRA:AVERAGE:0.5:24:%s' % self.rrd_2hr)
 
175
        rrdParams.append('RRA:MAX:0.5:24:%s' % self.rrd_2hr)
 
176
      if (self.rrd_1day):
 
177
        rrdParams.append('RRA:AVERAGE:0.5:288:%s' % self.rrd_1day)
 
178
        rrdParams.append('RRA:MAX:0.5:288:%s' % self.rrd_1day)
 
179
 
 
180
      rrdtool.create(rrdFile, *rrdParams)
 
181
      if self.debug:
 
182
        print >>sys.stderr, string.join(rrdParams,' ')
 
183
 
 
184
    # foreach value
 
185
 
 
186
    update = self.start_time
 
187
    for i in use_fields_index.keys():
 
188
      update = "%s:%s" % (update,vals[i])
 
189
    if self.debug:
 
190
      print >>sys.stderr, "update", update
 
191
 
 
192
    if (self.verbose):
 
193
      print "Updating RRD", rrdFile
 
194
 
 
195
    rrdtool.update(rrdFile,update)
 
196
    
 
197
#
 
198
#
 
199
#
 
200
  def convert(self, f):
 
201
 
 
202
    # first line
 
203
    line = f.readline().strip()
 
204
  
 
205
    while line:
 
206
  
 
207
      # report data starts after recn comment
 
208
      if (not self.in_data) :
 
209
 
 
210
        if line[:13] == '# first-flow:':
 
211
          self.start_time = (string.split(line[14:]))[0]
 
212
 
 
213
        # handle the totals record differently
 
214
        if line[:53] == '# rec1: records,ignores,flows,octets,packets,duration':
 
215
          tmp = string.split(line[8:], ',')
 
216
          line = f.readline().strip()
 
217
          tmp_use_fields_index = {}
 
218
          tmp_splt = string.split(line, ',')
 
219
          x = 0
 
220
          ds = 0
 
221
          for i in tmp:
 
222
            if self.use_key_names_special.get("total_%s" % i,0):
 
223
              tmp_use_fields_index[x] = i
 
224
              ds = ds + 1
 
225
            x = x + 1
 
226
          if ds:
 
227
            self.update_rrd('totals', tmp_splt, tmp_use_fields_index)
 
228
          del tmp_splt, tmp_use_fields_index, i, x, ds
 
229
          continue
 
230
    
 
231
        if line[:6] == '# recn':
 
232
          self.in_data = 1
 
233
    
 
234
          # foreach element in field names
 
235
          for i in string.split(line[8:],','):
 
236
    
 
237
            # remove key designators
 
238
            if i[-1:] == '*':
 
239
              i = i[:-1]
 
240
              self.field_keys[self.field_total] = 1
 
241
            else:
 
242
              self.field_vals[self.field_total] = 1
 
243
 
 
244
            # store the field names
 
245
            self.field_names[self.field_total] = i
 
246
            self.field_names2[i] = self.field_total
 
247
 
 
248
            self.field_total += 1
 
249
 
 
250
          # start time must be set by now
 
251
          if (self.start_time == 0):
 
252
            raise ValueError, "Start time not found, make sure flow-report is including the header"
 
253
 
 
254
          # load symbol tables
 
255
          if self.mapsym == 1:
 
256
            for i in self.field_keys.keys():
 
257
              self.sym[i] = ftsym(self.field_names[i])
 
258
 
 
259
          # convert use_fields to use_fields_index for easier access
 
260
          self.use_fields_index = {}
 
261
          for i in self.use_fields.keys():
 
262
            if self.use_fields[i] and self.field_names2.get(i,'x') != 'x':
 
263
              self.use_fields_index[self.field_names2[i]] = i
 
264
 
 
265
      else :
 
266
    
 
267
        # if in the data area and not a comment, store it
 
268
        if self.in_data and line [:1] != '#':
 
269
    
 
270
          splt = string.split(line, ',')
 
271
 
 
272
          # combine the key fields to form one key
 
273
          k = ''
 
274
          for i in self.field_keys.keys():
 
275
            # try a symbol table lookup
 
276
            if self.mapsym == 1:
 
277
              t = self.sym[i].findbyval(splt[i])
 
278
            else:
 
279
              t = splt[i]
 
280
            k = "%s-%s" % (k, t)
 
281
 
 
282
          # done if all entries in key_names list have been stored.
 
283
          if self.use_key_names_total:
 
284
            if self.records_processed == self.use_key_names_total:
 
285
              break
 
286
 
 
287
          # if set, only allow specified keys
 
288
          if self.use_key_names.get(k[1:],0) == 0:
 
289
            line = f.readline().strip()
 
290
            continue
 
291
 
 
292
          # mark this key as processed
 
293
          self.use_key_names[k[1:]] |= 2
 
294
 
 
295
          self.records_processed += 1
 
296
 
 
297
          self.update_rrd(k[1:], splt, self.use_fields_index)
 
298
 
 
299
      # next line
 
300
      line = f.readline().strip()
 
301
 
 
302
    # keys which were not available in the report also need to be
 
303
    # updated with 0 values.
 
304
    for i in xrange(len(splt)):
 
305
      splt[i] = 0
 
306
    for x in self.use_key_names.keys():
 
307
      if not (self.use_key_names[x] & 2):
 
308
        self.update_rrd(x, splt, self.use_fields_index)
 
309
 
 
310
#
 
311
# main
 
312
#
 
313
   
 
314
(opts,rags) = getopt.getopt(sys.argv[1:], "dhk:K:f:np:P:r:v")
 
315
 
 
316
# mrtg defaults
 
317
opt_rrd_storage = "600:600:600:732"
 
318
opt_keys = ''
 
319
opt_fields = 'flows,octets,packets'
 
320
opt_names = 0
 
321
opt_rrd_path = './'
 
322
opt_keyfile = ''
 
323
opt_debug = 0
 
324
opt_rrd_postfix = ''
 
325
opt_verbose = 0
 
326
 
 
327
for o,v in opts:
 
328
 
 
329
  if o == '-d':
 
330
    opt_debug = 1
 
331
  elif o == '-k':
 
332
    opt_keys = v
 
333
  elif o == '-K':
 
334
    opt_keys = load_keyfile(v)
 
335
  elif o == '-f':
 
336
    opt_fields = v
 
337
  elif o == '-n':
 
338
    opt_names = 1
 
339
  elif o == '-p':
 
340
     opt_rrd_path = v
 
341
  elif o == '-P':
 
342
     opt_rrd_postfix = v
 
343
  elif o == '-r':
 
344
    opt_rrd_storage = v
 
345
  elif o == '-v':
 
346
    opt_verbose = 1
 
347
  elif o == '-h':
 
348
    print "Usage: flow-rpt2rrd [-nv] [-k keys] [-K keyfile] [-f fields]"
 
349
    print "                    [-p rrd_path] [-P fname_postfix]"
 
350
    print "                    [-r rrd_storage 5_min:30_min:2_hr:1_day ]"
 
351
    sys.exit(0)
 
352
 
 
353
if opt_keys == '':
 
354
  print >>sys.stderr, "Keys must be defined with -k or -K."
 
355
  sys.exit(1)
 
356
 
 
357
ftrrd = ftrpt2rrd()
 
358
if (opt_names == 1):
 
359
  ftrrd.set_mapsym()
 
360
ftrrd.setrrd(opt_rrd_storage, opt_rrd_path, opt_rrd_postfix)
 
361
ftrrd.set_use_key_names(opt_keys)
 
362
ftrrd.set_use_fields(opt_fields)
 
363
ftrrd.set_debug(opt_debug)
 
364
ftrrd.set_verbose(opt_verbose)
 
365
ftrrd.convert(sys.stdin)
 
366