root/branch/ggpolo/umitInventory/DataGrabber.py @ 1260

Revision 1260, 18.1 kB (checked in by ggpolo, 6 years ago)

minor changes

Line 
1# Copyright (C) 2007 Insecure.Com LLC.
2#
3# Author:  Guilherme Polo <ggpolo@gmail.com>
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18# USA
19
20import datetime
21
22from umitCore.Paths import Path
23
24from umitInventory.Calendar import mdays
25from umitInventory.Calendar import isleap
26#from umitInventory.TLBase import view_kind
27
28from umitDB.InventoryChanges import ChangesRetrieve
29
30umitdb = Path.umitdb_ng
31
32DATA_GRAB_MODES = { "yearly_sum": "changes_in_year",
33                    "monthly_sum": "changes_in_month",
34                    "daily_sum": "changes_in_day",
35                    "hourly_sum": "changes_in_hour",
36                    "category": "changes_by_category"
37                }
38           
39class DataGrabber(ChangesRetrieve):
40    """
41    Grab data from Inventories or a single host for an Inventory, for a time
42    range and format it to be used in Timeline.
43    """
44   
45    def __init__(self, calendar, inventory=None, hostaddr=None):
46        ChangesRetrieve.__init__(self, umitdb)
47
48        self.calendar = calendar
49        self.inventory = inventory
50        self.hostaddr = hostaddr
51       
52       
53    def get_categories(self):
54        """
55        Get all changes categories in database.
56        """
57        categories = { }
58
59        self.use_dict_cursor()
60       
61        # build categories dict
62        for category in self.get_categories_id_name():
63            categories[category['pk']] = (True, category['name'])
64           
65        self.use_standard_cursor()
66
67        return categories
68
69
70    def standard_sum_filter(self):
71        """
72        Standard filter to use when we are grabbing data in Changes Sum kind.
73        """
74        #return {0: (True, view_kind["sum"])}
75        return {0: (True, "Changes Sum")} 
76   
77   
78    def load_changes_for_timerange(self, start, end):
79        """
80        Load changes from database for a timerange.
81        """
82
83       
84    def count_changes_for_timerange(self, start, end):
85        """
86        Return number of changes in a timerange.
87        """
88        count = self.timerange_changes_count(start, end)
89       
90        return count
91
92
93    def changes_by_category(self, *args):
94        """
95        Generic function for changes_anything_by_category
96        """
97        start = [ ] # start points
98        changes = { } # changes in a range
99        categories = self.get_categories()
100
101        # grab data
102        for category in categories.keys():
103            # unused is a filter that we will discard, it is a filter
104            # for Changes Sum, but we will return a filter by category.
105            #unused, cmax, cstart, \
106            unused, cstart, \
107            cevts = self.changes_for_categoryid(category, *args)
108           
109            # add new start point to start list
110            start.extend(cstart)
111
112            # if changes is empty, set initial values to it
113            if not changes:
114                changes = cevts
115                continue
116           
117            # merge lists
118            for key, value in cevts.items():
119
120                cur_list = changes[key]
121                [cur_list[indx].extend(i) for indx, i in enumerate(value)]
122                changes[key] = cur_list
123
124        # decrement by one each key in categories dict, so it follows filter
125        # format used in other places. (0 .. n)
126        c_new = { }
127        for key, values in categories.items():
128            c_new[key - 1] = values
129
130        return c_new, start, changes
131
132         
133    def changes_for_categoryid(self, category, *args):
134        """
135        Generic function for changes_anything_for_categoryid
136        """
137        return self.changes_in_range(category, *args)
138   
139   
140    def changes_in_range(self, category=None, *args):
141        """
142        Generic function for changes_anything
143        """
144        if len(args) == 1: # yearly
145            return self.changes_in_year(args[0], category)
146        elif len(args) == 2: # monthly
147            return self.changes_in_month(args[0], args[1], category)
148        elif len(args) == 3: # daily
149            return self.changes_in_day(args[0], args[1], args[2], category)
150        elif len(args) == 4: # hourly
151            return self.changes_in_hour(args[0], args[1], args[2], args[3], 
152                                        category)
153        else:
154            raise Exception("Invalid number of parameters especified")
155       
156       
157    """
158    Follows changes_in_range especific methods, I plan making them
159    generic too.
160    """
161   
162   
163    def changes_in_year(self, year, category=None):
164        """
165        Gets changes per "week" in an entire year.
166        """   
167        if isleap(year):
168            mdays[2] = 29
169        else:
170            mdays[2] = 28
171       
172        # get last amount of events in past year, or, better:
173        # amount of events that occuried in (year - 1) at December, from
174        # numberOfDaysInDecember / 2 + (numberOfDaysInDecember / 4) till
175        # final of month.
176       
177        if year == self.calendar.year_range[0]:
178            start_value = 0
179           
180        else:
181            half = mdays[12] / 2
182            quarter = half / 2
183            start = datetime.datetime(year - 1, 12, quarter + half)
184            end = datetime.datetime(year, 1, 1)
185       
186            start_value = self.timerange_changes_count_generic(start, end,
187                                                               category,
188                                                               self.inventory,
189                                                               self.hostaddr)
190
191        # get events for year
192        year_events = { }
193       
194        for m in range(12):
195            half = (mdays[m + 1] / 2) + 1
196            quarter = (half / 2)
197           
198            # months with 31 or 30 days:
199            # half = (31/2) + 1 = 16
200            # quarter = 8
201            # will grab 1 -> 8, 8 -> 16, 16 -> 24, 24 -> end month
202            # month with 28 or 29 days:
203            # half = (29/2) + 1 = 15
204            # quarter = 7
205            # will grab 1 -> 7, 7 -> 15, 15 -> 22, 22 -> end month
206           
207            days = (1, quarter, half, half + quarter, 1)
208           
209            mcount = [ ]
210
211            for i in range(len(days) - 1):
212                start = datetime.datetime(year, m + 1, days[i])
213               
214                if i == len(days) - 2:
215                    dyear = year
216                    dmonth = m + 2
217                    if m == 11:
218                        dyear += 1
219                        dmonth = 1
220                       
221                    end = datetime.datetime(dyear, dmonth, days[i + 1])
222                else:
223                    end = datetime.datetime(year, m + 1, days[i + 1])
224               
225                count = self.timerange_changes_count_generic(start, end,
226                                                             category,
227                                                             self.inventory,
228                                                             self.hostaddr)
229
230                mcount.append([count, ])
231           
232            year_events[m] = mcount
233       
234
235        return self.standard_sum_filter(), (start_value, ), year_events
236
237
238    def changes_in_month(self, year, month, category=None):
239        """
240        Get changes in a month.
241        """
242        month_events = { }
243
244        if isleap(year) and month == 2: # month range from 1 to 12
245            mdays[2] = 29
246        else:
247            mdays[2] = 28
248           
249        # get last amount of events in past month, or, better:
250        # amount of events that occuried in (month - 1) at last day, from
251        # 12 PM to 23:59 PM
252        self.calendar.dryrun = True
253        self.calendar.dec_date(1) # 1 indicates it is a month decrement
254        prev_date = self.calendar.temp # what changes were needed to decrement
255        self.calendar.dryrun = False
256   
257        prev_year = year
258        prev_month = month
259       
260        for key, value in prev_date.items():
261            if key == "year":
262                prev_year = value
263            elif key == "month":
264                prev_month = value
265
266        month_range = self.calendar.get_monthrange(prev_year, prev_month)[1]
267        start = datetime.datetime(prev_year, prev_month, month_range, 12)
268        end = datetime.datetime(year, month, 1)
269       
270        start_value = self.timerange_changes_count_generic(start, end,
271                                                           category,
272                                                           self.inventory,
273                                                           self.hostaddr)
274   
275        for day in range(mdays[month]):
276            day_count = [ ]
277
278            # for each day, grab data for 0 AM .. 11:59 AM, 12 PM .. 23:59 PM
279            start = datetime.datetime(year, month, day + 1)
280            end = datetime.datetime(year, month, day + 1, 12)
281
282            count1 = self.timerange_changes_count_generic(start, end,
283                                                          category,
284                                                          self.inventory,
285                                                          self.hostaddr)
286
287            start = datetime.datetime(year, month, day + 1, 12)
288           
289            dyear = year
290            dmonth = month
291            dday = day
292
293            if day == mdays[month] - 1:
294                self.calendar.dryrun = True
295                self.calendar.inc_date(1)
296                next_date = self.calendar.temp
297                self.calendar.dryrun = False
298               
299                dday = 1
300                for key, value in next_date.items():
301                    if key == "year":
302                        dyear = value
303                    elif key == "month":
304                        dmonth = value
305                       
306            else:
307                dday += 2
308           
309            end = datetime.datetime(dyear, dmonth, dday)
310           
311            count2 = self.timerange_changes_count_generic(start, end,
312                                                          category,
313                                                          self.inventory,
314                                                          self.hostaddr)
315
316            day_count.append([count1, ])
317            day_count.append([count2, ])
318            month_events[day] = day_count
319
320
321        return self.standard_sum_filter(), (start_value, ), month_events
322   
323   
324    def changes_in_day(self, year, month, day, category=None):
325        """
326        Get changes in a day.
327        """
328        day_events = { }
329       
330        # get last amount of events in past day, or, better:
331        # amount of events that occuried in (day - 1) at last hour, from
332        # 23:30 to current date 0 hour, 0 minute, 0 second
333        self.calendar.dryrun = True
334        self.calendar.dec_date(2) # 2 indicates it is a day decrement
335        prev_date = self.calendar.temp # what changes were needed to decrement
336        self.calendar.dryrun = False
337       
338        prev_year = year
339        prev_month = month
340        prev_day = day - 1
341
342        for key, value in prev_date.items():
343            if key == "year":
344                prev_year = value
345            elif key == "month":
346                prev_month = value
347            elif key == "day":
348                prev_day = value
349
350        start = datetime.datetime(prev_year, prev_month, prev_day, 23, 30)
351        end = datetime.datetime(year, month, day)
352       
353        start_value = self.timerange_changes_count_generic(start, end,
354                                                           category,
355                                                           self.inventory,
356                                                           self.hostaddr)
357
358        # hour by hour
359        for hour in range(24):
360            hour_count = [ ]
361           
362            # first half hour
363            start = datetime.datetime(year, month, day, hour)
364            end = datetime.datetime(year, month, day, hour, 30)
365           
366            count1 = self.timerange_changes_count_generic(start, end,
367                                                          category,
368                                                          self.inventory,
369                                                          self.hostaddr)
370             
371            # other half
372            start = datetime.datetime(year, month, day, hour, 30)
373           
374            if hour == 23:
375                next_year = year
376                next_month = month
377                next_day = day
378               
379                self.calendar.dryrun = True
380                self.calendar.inc_date(2)
381                next_date = self.calendar.temp
382                self.calendar.dryrun = False
383               
384                for key, value in next_date.items():
385                    if key == "year":
386                        next_year = value
387                    elif key == "month":
388                        next_month = value
389                    elif key == "day":
390                        next_day = value
391                       
392                end = datetime.datetime(next_year, next_month, next_day, 0)
393                   
394            else:
395                end = datetime.datetime(year, month, day, hour + 1)
396           
397            count2 = self.timerange_changes_count_generic(start, end,
398                                                          category,
399                                                          self.inventory,
400                                                          self.hostaddr)
401             
402            hour_count.append([count1, ])
403            hour_count.append([count2, ])
404           
405            day_events[hour] = hour_count
406           
407       
408        return self.standard_sum_filter(), (start_value, ), day_events
409   
410   
411    def changes_in_hour(self, year, month, day, hour, category=None):
412        """
413        Get changes in a especific hour.
414        """
415        hour_events = { }
416       
417        # get last amount of events in past hour, or, better:
418        # amount of events that occuried in (hour - 1) at last minute
419        self.calendar.dryrun = True
420        self.calendar.dec_date(3) # 3 indicates it is an hour decrement
421        prev_date = self.calendar.temp # what changes were needed to decrement
422        self.calendar.dryrun = False
423       
424        prev_year = year
425        prev_month = month
426        prev_day = day
427        prev_hour = hour - 1
428
429        for key, value in prev_date.items():
430            if key == "year":
431                prev_year = value
432            elif key == "month":
433                prev_month = value
434            elif key == "day":
435                prev_day = value
436                prev_hour = 23
437
438        start = datetime.datetime(prev_year, prev_month, prev_day, prev_hour, 
439                                  59)
440        end = datetime.datetime(year, month, day, hour, 0)
441       
442        start_value = self.timerange_changes_count_generic(start, end,
443                                                           category,
444                                                           self.inventory,
445                                                           self.hostaddr)
446
447        # minute by minute
448        for minute in range(60):
449            start = datetime.datetime(year, month, day, hour, minute)
450           
451            if minute == 59:
452                next_year = year
453                next_month = month
454                next_day = day
455                next_hour = hour + 1
456               
457                self.calendar.dryrun = True
458                self.calendar.inc_date(3)
459                next_date = self.calendar.temp
460                self.calendar.dryrun = False
461               
462                for key, value in next_date.items():
463                    if key == "year":
464                        next_year = value
465                    elif key == "month":
466                        next_month = value
467                    elif key == "day":
468                        next_day = value
469                        next_hour = 0
470                       
471                end = datetime.datetime(next_year, next_month, next_day,
472                                        next_hour)
473            else:
474                end = datetime.datetime(year, month, day, hour, minute + 1)
475           
476            count = self.timerange_changes_count_generic(start, end,
477                                                         category,
478                                                         self.inventory,
479                                                         self.hostaddr)
480           
481            hour_events[minute] = [[count, ]]
482           
483       
484        return self.standard_sum_filter(), (start_value, ), hour_events
485   
486
487       
488if __name__ == "__main__":
489    #dg.count_changes_for_timerange(datetime.datetime(2007, 1, 1),
490    #                  datetime.datetime(2007, 1, 31, 23, 59, 59, 999))
491    #lfilter, max_v, start, evts = dg.changes_in_year(2007)
492    #print max_v, start, evts
493   
494    # some methods from ChangesRetrieve
495    #print dg.get_categories_id_name()
496    #print dg.get_categories_name()
497    #print dg.get_category_id_by_name('Fingerprint')
498    #print dg.get_category_name_by_id(1)
499
500    #max_v, start, evts = dg.changes_for_categoryid(2007, 1)
501    #print max_v, start, evts
502
503    from umitInventory.Calendar import startup_calendar_opts
504    from umitInventory.Calendar import CalendarManager
505
506    start = startup_calendar_opts()
507    cal = CalendarManager(**start)
508
509    lfilter, max_v, start, evts = DataGrabber(cal).changes_in_year(2007)
510    print lfilter, max_v, start, evts[6]
511
512    #lfilter, max, start, evts = DataGrabber(cal).changes_by_category(2007, 7)
513    lfilter, max_v, start, evts = DataGrabber(cal).changes_in_month(2007, 7)
514
515    for key, value in evts.items():
516        print key, value
517
Note: See TracBrowser for help on using the browser.