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

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

You can view Timeline for single hosts now

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