1
2
3
4
5
6
7
8
9
10
11
12
13
14 __doc__ = """EventManagerBase
15 Data connector to backend of the event management system.
16 """
17
18 import time
19 import types
20 import random
21 random.seed()
22 import logging
23 log = logging.getLogger("zen.Events")
24
25 from AccessControl import ClassSecurityInfo
26 from AccessControl import getSecurityManager
27 from Globals import DTMLFile
28 from Acquisition import aq_base
29 import DateTime
30 from Products.ZenModel.ZenossSecurity import *
31
32 from Products.ZenUtils.ObjectCache import ObjectCache
33
34
35 from ZEvent import ZEvent
36 from EventDetail import EventDetail
37 from BetterEventDetail import BetterEventDetail
38 from EventCommand import EventCommand
39 from Products.ZenEvents.Exceptions import *
40
41 from Products.ZenModel.ZenModelRM import ZenModelRM
42 from Products.ZenModel.ZenossSecurity import *
43 from Products.ZenRelations.RelSchema import *
44 from Products.ZenUtils import Time
45 from Products.ZenUtils.FakeRequest import FakeRequest
46 from Products.ZenEvents.ZenEventClasses import Status_Ping, Status_Wmi_Conn
47 from Products.ZenWidgets import messaging
48
49 from ZenEventClasses import Unknown
50
51 from DbAccessBase import DbAccessBase
52
53 from Products.ZenUtils.Utils import unused
54
55 __pychecker__="maxargs=16"
56
58 """
59 Prepares data from L{Products.ZenEvents.EventManagerBase.getEventSummary}
60 for rendering in the eventrainbow template macro.
61
62 Each cell of the old-style event rainbow needs a CSS class specified in
63 order to render its color, fill and border style. evtprep determines the
64 proper class and returns it, along with a string representation of the
65 number of live and acknowledged events.
66
67 >>> from Products.ZenEvents.EventManagerBase import evtprep
68 >>> evtprep(['zenevents_5_noack noack', 2, 2])
69 {'cssclass': 'zenevents_5_noack noack empty thin', 'data': '2/2'}
70 >>> evtprep(['zenevents_5_noack noack', 1, 2])
71 {'cssclass': 'zenevents_5_noack noack', 'data': '1/2'}
72
73 @param evts: A tuple of the form (Severity string, Number Acknowledged int,
74 Number Live int)
75 @type evts: tuple
76 @return: A dictionary of the form {'cssclass': Class string, 'data': Event
77 count representation string}
78
79 """
80 evtsdata = "%d/%d" % (evts[1],evts[2])
81 if evts[1]==evts[2] or evts[2]==0:
82 return {'cssclass':evts[0] + " empty thin",
83 'data':evtsdata}
84 else:
85 return {'cssclass':evts[0], 'data':evtsdata}
86
87
89 """
90 Data connector to backend of the event management system.
91 """
92
93
94
95
96 eventStateConversions = (
97 ('New', 0),
98 ('Acknowledged',1),
99 ('Suppressed', 2),
100
101 )
102
103 eventActions = ('status', 'history', 'drop')
104
105 severityConversions = (
106 ('Critical', 5),
107 ('Error', 4),
108 ('Warning', 3),
109 ('Info', 2),
110 ('Debug', 1),
111 ('Clear', 0),
112 )
113 severities = dict([(b, a) for a, b in severityConversions])
114
115 priorityConversions = (
116 ('None', -1),
117 ('Emergency', 0),
118 ('Alert', 1),
119 ('Critical', 2),
120 ('Error', 3),
121 ('Warning', 4),
122 ('Notice', 6),
123 ('Info', 8),
124 ('Debug', 10),
125 )
126 priorities = dict([(b, a) for a, b in priorityConversions])
127
128 statusTable = "status"
129 detailTable = "detail"
130 logTable = "log"
131 lastTimeField = "lastTime"
132 firstTimeField = "firstTime"
133 deviceField = "device"
134 componentField = "component"
135 eventClassField = "eventClass"
136 severityField = "severity"
137 stateField = "eventState"
138 countField = "count"
139 prodStateField = "prodState"
140 DeviceGroupField = "DeviceGroups"
141 SystemField = "Systems"
142
143 DeviceWhere = "\"device = '%s'\" % me.getDmdKey()"
144 DeviceResultFields = ("component", "eventClass", "summary", "firstTime",
145 "lastTime", "count" )
146 ComponentWhere = ("\"(device = '%s' and component = '%s')\""
147 " % (me.device().getDmdKey(), me.name())")
148 ComponentResultFields = ("eventClass", "summary", "firstTime",
149 "lastTime", "count" )
150 IpAddressWhere = "\"ipAddress='%s'\" % (me.getId())"
151 EventClassWhere = "\"eventClass like '%s%%'\" % me.getDmdKey()"
152 EventClassInstWhere = """\"eventClass = '%s' and eventClassKey = '%s'\" % (\
153 me.getEventClass(), me.eventClassKey)"""
154 DeviceClassWhere = "\"DeviceClass like '%s%%'\" % me.getDmdKey()"
155 LocationWhere = "\"Location like '%s%%'\" % me.getDmdKey()"
156 SystemWhere = "\"Systems like '%%|%s%%'\" % me.getDmdKey()"
157 DeviceGroupWhere = "\"DeviceGroups like '%%|%s%%'\" % me.getDmdKey()"
158
159 defaultResultFields = ("device", "component", "eventClass", "summary",
160 "firstTime", "lastTime", "count" )
161
162 defaultFields = ('eventState', 'severity', 'evid')
163
164 defaultEventId = ('device', 'component', 'eventClass',
165 'eventKey', 'severity')
166
167 requiredEventFields = ('device', 'summary', 'severity')
168
169 refreshConversionsForm = DTMLFile('dtml/refreshNcoProduct', globals())
170
171 defaultAvailabilityDays = 7
172 defaultPriority = 3
173 eventAgingHours = 4
174 eventAgingSeverity = 4
175 historyMaxAgeDays = 0
176
177 _properties = (
178 {'id':'backend', 'type':'string','mode':'r', },
179 {'id':'username', 'type':'string', 'mode':'w'},
180 {'id':'password', 'type':'string', 'mode':'w'},
181 {'id':'host', 'type':'string', 'mode':'w'},
182 {'id':'database', 'type':'string', 'mode':'w'},
183 {'id':'port', 'type':'int', 'mode':'w'},
184 {'id':'defaultWhere', 'type':'text', 'mode':'w'},
185 {'id':'defaultOrderby', 'type':'text', 'mode':'w'},
186 {'id':'defaultResultFields', 'type':'lines', 'mode':'w'},
187 {'id':'statusTable', 'type':'string', 'mode':'w'},
188 {'id':'detailTable', 'type':'string', 'mode':'w'},
189 {'id':'logTable', 'type':'string', 'mode':'w'},
190 {'id':'lastTimeField', 'type':'string', 'mode':'w'},
191 {'id':'firstTimeField', 'type':'string', 'mode':'w'},
192 {'id':'deviceField', 'type':'string', 'mode':'w'},
193 {'id':'componentField', 'type':'string', 'mode':'w'},
194 {'id':'severityField', 'type':'string', 'mode':'w'},
195 {'id':'countField', 'type':'string', 'mode':'w'},
196 {'id':'DeviceGroupField', 'type':'string', 'mode':'w'},
197 {'id':'SystemField', 'type':'string', 'mode':'w'},
198 {'id':'DeviceWhere', 'type':'string', 'mode':'w'},
199 {'id':'DeviceResultFields', 'type':'lines', 'mode':'w'},
200 {'id':'ComponentResultFields', 'type':'lines', 'mode':'w'},
201 {'id':'EventClassWhere', 'type':'string', 'mode':'w'},
202 {'id':'EventClassInstWhere', 'type':'string', 'mode':'w'},
203 {'id':'DeviceClassWhere', 'type':'string', 'mode':'w'},
204 {'id':'LocationWhere', 'type':'string', 'mode':'w'},
205 {'id':'SystemWhere', 'type':'string', 'mode':'w'},
206 {'id':'DeviceGroupWhere', 'type':'string', 'mode':'w'},
207 {'id':'requiredEventFields', 'type':'lines', 'mode':'w'},
208 {'id':'defaultEventId', 'type':'lines', 'mode':'w'},
209 {'id':'defaultFields', 'type':'lines', 'mode':'w'},
210 {'id':'timeout', 'type':'int', 'mode':'w'},
211 {'id':'clearthresh', 'type':'int', 'mode':'w'},
212 {'id':'defaultAvailabilityDays', 'type':'int', 'mode':'w'},
213 {'id':'defaultPriority', 'type':'int', 'mode':'w'},
214 {'id':'eventAgingHours', 'type':'int', 'mode':'w'},
215 {'id':'eventAgingSeverity', 'type':'int', 'mode':'w'},
216 {'id':'historyMaxAgeDays', 'type':'int', 'mode':'w'},
217 )
218
219 _relations = (
220 ("commands", ToManyCont(ToOne, "Products.ZenEvents.EventCommand", "eventManager")),
221 )
222
223 factory_type_information = (
224 {
225 'immediate_view' : 'editEventManager',
226 'actions' :
227 (
228 { 'id' : 'edit'
229 , 'name' : 'Edit'
230 , 'action' : 'editEventManager'
231 , 'permissions' : ( "Manage DMD", )
232 },
233 { 'id' : 'edit'
234 , 'name' : 'Fields'
235 , 'action' : 'editEventManagerFields'
236 , 'permissions' : ( "Manage DMD", )
237 },
238 { 'id' : 'history_edit'
239 , 'name' : 'History Fields'
240 , 'action' : 'editEventManagerHistoryFields'
241 , 'permissions' : ( "Manage DMD", )
242 },
243 { 'id' : 'commands'
244 , 'name' : 'Commands'
245 , 'action' : 'listEventCommands'
246 , 'permissions' : ( "Manage DMD", )
247 },
248 { 'id' : 'changes'
249 , 'name' : 'Modifications'
250 , 'action' : 'viewHistory'
251 , 'permissions' : (ZEN_VIEW_MODIFICATIONS,)
252 },
253 )
254 },
255 )
256
257 security = ClassSecurityInfo()
258
259
260 - def __init__(self, id, title='', hostname='localhost', username='root',
261 password='', database='events', port=3306,
262 defaultWhere='',defaultOrderby='',defaultResultFields=[]):
263 """
264 Sets up event database access and initializes the cache.
265
266 @param id: A unique id
267 @type id: string
268 @param title: A title
269 @type title: string
270 @param hostname: The hostname of the events database server
271 @type hostname: string
272 @param username: The name of a user with permissions to access the
273 events database
274 @type username: string
275 @param password: The password of the user
276 @type password: string
277 @param database: The name of the events database
278 @type database: string
279 @param port: The port on which the database server is listening
280 @type port: int
281 @param defaultWhere: The default where clause to use when building
282 queries
283 @type defaultWhere: string
284 @param defaultOrderby: The default order by clause to use when building
285 queries
286 @type defaultOrderby: string
287 @param defaultResultFields: DEPRECATED. Currently unused.
288 @type defaultResultFields: list
289
290 """
291 unused(defaultOrderby, defaultResultFields)
292 self.id = id
293 self.title = title
294 self.username=username
295 self.password=password
296 self.database=database
297 self.host=hostname
298 self.port=port
299 DbAccessBase.__init__(self)
300
301 self.defaultWhere = defaultWhere
302 self.defaultOrderby="%s desc, %s desc" % (
303 self.severityField, self.lastTimeField)
304
305 self._schema = {}
306 self._fieldlist = []
307 self._colors = ()
308 self._ackedcolors = ()
309 ObjectCache.__init__(self)
310 self.initCache()
311
312
313
314
315
316
318 """
319 A wrapper for L{lookupManagedEntityResultFields} accepting an object
320 with an C{event_key} attribute.
321
322 >>> class dummy(object):
323 ... event_key = 'Device'
324 ...
325 >>> d = dummy()
326 >>> f = dmd.ZenEventManager.getEventResultFields(d)
327 >>> f==dmd.ZenEventManager.DeviceResultFields
328 True
329 >>> d.event_key = 'Robot'
330 >>> f = dmd.ZenEventManager.getEventResultFields(d)
331 >>> f==dmd.ZenEventManager.defaultResultFields
332 True
333
334 @param context: An object with an C{event_key} attribute.
335 @type context: L{ManagedEntity}
336 @return: A sequence of strings representing columns in the database.
337 @rtype: tuple
338 """
339 return self.lookupManagedEntityResultFields(getattr(context,
340 'event_key', 'Default'))
341
362
363
364 - def getEventBatchME(self, me, selectstatus=None, resultFields=[],
365 where="", orderby="", severity=None, state=2,
366 startdate=None, enddate=None, offset=0, rows=0,
367 getTotalCount=False, filter="", goodevids=[],
368 badevids=[], **kwargs):
369 """
370 Returns a batch of events based on criteria from checked rows on the
371 event console.
372
373 The event console can show thousands of events, and we want to support a
374 "Select All" feature; enter this method. It builds a query based on the
375 select status from the console ("All", "None", "Acknowledged",
376 "Unacknowledged") and any checkboxes that have been modified manually.
377
378 @param me: The managed entity for which to query events.
379 @type me: L{ManagedEntity}
380 @param resultFields: The columns to return from the database.
381 @type resultFields: list
382 @param where: The base where clause to modify.
383 @type where: string
384 @param orderby: The "ORDER BY" string governing sort order.
385 @type orderby: string
386 @param severity: The minimum severity for which to query.
387 @type severity: int
388 @param state: The minimum state for which to query.
389 @type state: int
390 @param startdate: The early date limit
391 @type startdate: string, DateTime
392 @param enddate: The late date limit
393 @type enddate: string, DateTime
394 @param offset: The row at which to begin returning
395 @type offset: int
396 @param rows: DEPRECATED The number of rows to return (ignored).
397 @type rows: int
398 @param getTotalCount: Whether or not to return a count of the total
399 number of rows
400 @type getTotalCount: bool
401 @param filter: A glob by which to filter events
402 @type filter: string
403 @param goodevids: Ids of events that specifically should be included
404 @type goodevids: list
405 @param badevids: Ids of events that specifically should not be included
406 @type badevids: list
407 @return: Ids of matching events
408 @rtype: list
409 @todo: Remove unused parameters from the method definition
410 """
411 unused(getTotalCount, rows)
412 newwhere = self.lookupManagedEntityWhere(me)
413 if where: newwhere = self._wand(newwhere, '%s%s', where, '')
414 where = newwhere
415 badevidsstr, goodevidsstr = '',''
416 if not isinstance(goodevids, (list, tuple)): goodevids = [goodevids]
417 if not isinstance(badevids, (list, tuple)): badevids = [badevids]
418 if badevids: badevidsstr = " and evid not in ('%s')" %(
419 "','".join(badevids))
420 if goodevids: goodevidsstr = " and evid in ('%s')" %(
421 "','".join(goodevids))
422 if selectstatus=='all':
423 where += badevidsstr
424 elif selectstatus=='none':
425 where += goodevidsstr or ' and 0'
426 elif selectstatus=='acked':
427 oper = bool(goodevidsstr) and ' or' or ' and'
428 where += goodevidsstr + oper + " (eventstate=1 %s) " % badevidsstr
429 elif selectstatus=='unacked':
430 oper = bool(goodevidsstr) and ' or' or 'and'
431 where += goodevidsstr + oper + " (eventstate=0 %s) " % badevidsstr
432 try:
433 resultFields = kwargs['resultFields']; del kwargs['resultFields']
434 except KeyError:
435 resultFields = self.lookupManagedEntityResultFields(me.event_key)
436 events = self.getEventList(
437 filter=filter,
438 offset=offset,
439 getTotalCount=False,
440 startdate=startdate,
441 enddate=enddate, severity=severity,
442 state=state, orderby=orderby,
443 resultFields=resultFields,
444 where=where,**kwargs)
445 return [ev.evid for ev in events]
446
447
449 """This is a hook do not delete me!"""
450 return where
451
452
453 - def getEventList(self, resultFields=None, where="", orderby="",
454 severity=None, state=2, startdate=None, enddate=None, offset=0,
455 rows=0, getTotalCount=False, filter="", **kwargs):
456 """
457 Fetch a list of events from the database matching certain criteria.
458
459 @param resultFields: The columns to return from the database.
460 @type resultFields: list
461 @param where: The base where clause to modify.
462 @type where: string
463 @param orderby: The "ORDER BY" string governing sort order.
464 @type orderby: string
465 @param severity: The minimum severity for which to query.
466 @type severity: int
467 @param state: The minimum state for which to query.
468 @type state: int
469 @param startdate: The early date limit
470 @type startdate: string, DateTime
471 @param enddate: The late date limit
472 @type enddate: string, DateTime
473 @param offset: The row at which to begin returning
474 @type offset: int
475 @param rows: The number of rows to return.
476 @type rows: int
477 @param getTotalCount: Whether or not to return a count of the total
478 number of rows
479 @type getTotalCount: bool
480 @param filter: A glob by which to filter events
481 @type filter: string
482 @return: Matching events as L{ZEvent}s.
483 @rtype: list
484 @todo: Remove unused parameters from the method definition
485 """
486 unused(kwargs)
487 try:
488 where = self.restrictedUserFilter(where)
489 if not resultFields:
490 resultFields = self.defaultResultFields
491 resultFields = list(resultFields)
492 resultFields.extend(self.defaultFields)
493 calcfoundrows = ''
494 if getTotalCount:
495 calcfoundrows = 'SQL_CALC_FOUND_ROWS'
496 select = ["select ", calcfoundrows, ','.join(resultFields),
497 "from %s where" % self.statusTable ]
498 if not where:
499 where = self.defaultWhere
500 where = self._wand(where, "%s >= %s", self.severityField, severity)
501 where = self._wand(where, "%s <= %s", self.stateField, state)
502 if filter:
503 where += ' and (%s) ' % (' or '.join(['%s LIKE "%%%s%%"' % (
504 x, filter) for x in resultFields]))
505 if startdate:
506 startdate, enddate = self._setupDateRange(startdate, enddate)
507 where += " and %s >= '%s' and %s <= '%s'" % (
508 self.lastTimeField, startdate,
509 self.firstTimeField, enddate)
510 select.append(where)
511 if not orderby:
512 orderby = self.defaultOrderby
513 if orderby:
514 select.append("order by")
515 select.append(orderby)
516 if rows:
517 select.append("limit %s, %s" % (offset, rows))
518 select.append(';')
519 select = " ".join(select)
520 if getTotalCount:
521 try: retdata, totalCount = self.checkCache(select)
522 except TypeError:
523 retdata, totalCount = self.checkCache(select), 100
524 else: retdata = self.checkCache(select)
525 if not False:
526 conn = self.connect()
527 try:
528 curs = conn.cursor()
529 curs.execute(select)
530 retdata = []
531
532
533 if self.checkRemotePerm(ZEN_VIEW, self.dmd.Events):
534 eventPermission = True
535 else:
536 eventPermission = False
537 for row in curs.fetchall():
538 row = map(self.convert, resultFields, row)
539 evt = ZEvent(self, resultFields, row, eventPermission)
540 retdata.append(evt)
541 if getTotalCount:
542 curs.execute("SELECT FOUND_ROWS()")
543 totalCount = curs.fetchone()[0]
544 finally: self.close(conn)
545 if getTotalCount: self.addToCache(select, (retdata, totalCount))
546 else: self.addToCache(select, retdata)
547 self.cleanCache()
548 if getTotalCount:
549 return retdata, totalCount
550 else: return retdata
551 except:
552 log.exception("Failure querying events")
553 raise
554
555
557 """
558 Return the CSS class, number of acknowledged events, and number of
559 unacknowledged events, per severity, for a C{ManagedEntity}.
560
561 @param me: The object of the inquiry.
562 @type me: L{ManagedEntity}
563 @param severity: The minimum severity for which to retrieve events
564 @type severity: int
565 @param state: The minimum state for which to retrieve events
566 @type state: int
567 @param prodState: The minimum production state for which to retrieve
568 events
569 @type prodState: int
570 @return: List of lists of the form [class, acked count, unacked count].
571 @rtype: list
572 """
573 try:
574 where = self.lookupManagedEntityWhere(me)
575 return self.getEventSummary(where, severity, state, prodState)
576 except:
577 log.exception("event summary for %s failed" % me.getDmdKey())
578 raise
579
580
582 """
583 Return a list of tuples with number of events and the color of the
584 severity that the number represents.
585
586 This method should not be called directly, but overridden by subclasses.
587
588 @param where: The base where clause to modify.
589 @type where: string
590 @param severity: The minimum severity for which to retrieve events
591 @type severity: int
592 @param state: The minimum state for which to retrieve events
593 @type state: int
594 @param prodState: The minimum production state for which to retrieve
595 events
596 @type prodState: int
597 @return: List of lists of the form [class, acked count, unacked count].
598 @rtype: list
599 """
600 raise NotImplementedError
601
602
603 - def getEventDetailFromStatusOrHistory(self, evid=None, dedupid=None,
604 better=False):
605 try:
606 event = self.dmd.ZenEventManager.getEventDetail(
607 evid, dedupid, better)
608 except ZenEventNotFound:
609 event = self.dmd.ZenEventHistory.getEventDetail(evid, dedupid,
610 better)
611 return event
612
614 """
615 Return an EventDetail object for a particular event.
616
617 @param evid: Event ID
618 @type evid: string
619 @param dedupid: string used to determine duplicates
620 @type dedupid: string
621 @param better: provide even more detail than normal?
622 @type better: boolean
623 @return: fields from the event
624 @rtype: EventDetail object
625 """
626 idfield = evid and "evid" or "dedupid"
627 if not evid: evid = dedupid
628 cachekey = '%s%s' % (idfield, evid)
629 event = self.checkCache(cachekey)
630 if event: return event
631 fields = self.getFieldList()
632 selectevent = "select "
633 selectevent += ", ".join(fields)
634 selectevent += " from %s where" % self.statusTable
635 selectevent += " %s = '%s'" % (idfield, evid)
636 conn = self.connect()
637 try:
638 curs = conn.cursor()
639 curs.execute(selectevent)
640 evrow = curs.fetchone()
641 if not evrow:
642 raise ZenEventNotFound( "Event id '%s' not found" % evid)
643 evdata = map(self.convert, fields, evrow)
644 if better:
645 event = BetterEventDetail(self, fields, evdata)
646 else:
647 event = EventDetail(self, fields, evdata)
648
649 selectdetail = "select name, value from %s where" % self.detailTable
650 selectdetail += " evid = '%s'" % event.evid
651
652 curs.execute(selectdetail)
653 event._details = curs.fetchall()
654
655 selectlogs = "select userName, ctime, text"
656 selectlogs += " from %s where" % self.logTable
657 selectlogs += " evid = '%s' order by ctime desc" % event.evid
658
659 curs.execute(selectlogs)
660 jrows = curs.fetchall()
661 logs = []
662 for row in jrows:
663 user = self.cleanstring(row[0])
664 date = self.dateString(row[1])
665 text = row[2]
666 logs.append((user, date, text))
667 event._logs = logs
668 finally: self.close(conn)
669
670 self.addToCache(cachekey, event)
671 self.cleanCache()
672 return event
673
674
675 - def getStatusME(self, me, statusclass=None, **kwargs):
689
690
692 """Return status based on a where clause defined for the me event_type.
693 No fancy caching done this might be a little slow if there are a lot
694 of events. Where clause is evaled
695 """
696 where = self.lookupManagedEntityWhere(me)
697 select = "select count(*) from %s where %s" % (self.statusTable, where)
698 statusCount = self.checkCache(select)
699 if not statusCount:
700 conn = self.connect()
701 try:
702 curs = conn.cursor()
703
704 curs.execute(select)
705 statusCount = curs.fetchone()[0]
706 finally: self.close(conn)
707
708 self.addToCache(select,statusCount)
709 return statusCount
710
711
712 - def getOrganizerStatus(self, org, statusclass=None, severity=None,
713 state=0, where=""):
714 """see IEventStatus
715 """
716 orgfield = self.lookupManagedEntityField(org.event_key)
717 select = "select %s from %s where " % (orgfield, self.statusTable)
718 where = self._wand(where, "%s = '%s'", self.eventClassField,statusclass)
719 where = self._wand(where, "%s >= %s", self.severityField, severity)
720 where = self._wand(where, "%s <= %s", self.stateField, state)
721 select += where
722
723 statusCache = self.checkCache(select)
724 if not statusCache:
725 conn = self.connect()
726 try:
727 curs = conn.cursor()
728 curs.execute(select)
729 statusCache=[]
730 orgdict={}
731 for row in curs.fetchall():
732 orgfield = self.cleanstring(row[0])
733 if not orgfield: continue
734 if orgfield.startswith("|"): orgfield = orgfield[1:]
735 for orgname in orgfield.split("|"):
736 orgdict.setdefault(orgname, 0)
737 orgdict[orgname] += 1
738 statusCache = orgdict.items()
739 self.addToCache(select,statusCache)
740 finally: self.close(conn)
741 countevts = 0
742 for key, value in statusCache:
743 if key.startswith(org.getOrganizerName()):
744 countevts += value
745 return countevts
746
747
750 """Return list of tuples (org, count) for all organizers with events.
751 """
752 orgfield = self.lookupManagedEntityField(event_key)
753 select = "select %s, count from %s where " % (orgfield,self.statusTable)
754 where = self._wand(where, "%s >= %s", self.severityField, severity)
755 where = self._wand(where, "%s <= %s", self.stateField, state)
756 where = self._wand(where,"%s like '%s'",self.eventClassField,"/Status%")
757 select += where
758 statusCache = self.checkCache(select)
759 if not statusCache:
760 conn = self.connect()
761 try:
762 curs = conn.cursor()
763 curs.execute(select)
764 statusCache=[]
765 orgdict={}
766 for row in curs.fetchall():
767 orgfield = self.cleanstring(row[0])
768 if not orgfield: continue
769 if orgfield.startswith("|"): orgfield = orgfield[1:]
770 for orgname in orgfield.split("|"):
771 if not orgname: continue
772 count, total = orgdict.setdefault(orgname, (0,0))
773 count+=1
774 total+=row[1]
775 orgdict[orgname] = (count,total)
776 statusCache = [ [n, c[0], int(c[1])] for n, c in orgdict.items() ]
777 statusCache.sort(lambda x,y: cmp(x[1],y[1]))
778 statusCache.reverse()
779 if limit:
780 statusCache = statusCache[:limit]
781 self.addToCache(select,statusCache)
782 finally: self.close(conn)
783 return statusCache
784
785
793
794
801
802
808
809
811 """Return list of tuples (device, count, total) of events for
812 all devices with events.
813 """
814 where = self._wand(where, "%s >= %s", self.severityField, severity)
815 where = self._wand(where, "%s <= %s", self.stateField, state)
816 select = """select distinct device, count(device) as evcount,
817 sum(count) from status where %s group by device
818 having evcount > %s""" % (where, mincount)
819 statusCache = self.checkCache(select)
820 if not statusCache:
821 try:
822 conn = self.connect()
823 try:
824 curs = conn.cursor()
825 curs.execute(select)
826 statusCache = [ [d,int(c),int(s)] for d,c,s in curs.fetchall() ]
827
828 statusCache.sort(lambda x,y: cmp(x[1],y[1]))
829 statusCache.reverse()
830 if limit:
831 statusCache = statusCache[:limit]
832 finally: self.close(conn)
833 except:
834 log.exception(select)
835 raise
836 return statusCache
837
838
839 - def getDeviceStatus(self, device, statclass=None, countField=None,
840 severity=3, state=None, where=""):
841 """see IEventStatus
842 """
843 if countField == None: countField = self.countField
844 select = "select %s, %s from %s where " % (
845 self.deviceField, self.countField, self.statusTable)
846 where = self._wand(where, "%s = '%s'", self.eventClassField, statclass)
847 where = self._wand(where, "%s >= %s", self.severityField, severity)
848 where = self._wand(where, "%s <= %s", self.stateField, state)
849 select += where
850
851 statusCache = self.checkCache(select)
852 if not statusCache:
853 try:
854 conn = self.connect()
855 try:
856 curs = conn.cursor()
857 curs.execute(select)
858 statusCache = {}
859 for dev, count in curs.fetchall():
860 dev = self.cleanstring(dev)
861 statusCache[dev] = count
862 self.addToCache(select,statusCache)
863 finally: self.close(conn)
864 except:
865 log.exception("status failed for device %s", device)
866 return -1
867 return statusCache.get(device, 0)
868
869
872
873
876
877
879 import Availability
880 for name in "device", "component", "eventClass", "systems":
881 if hasattr(state, name):
882 kw.setdefault(name, getattr(state, name))
883 try:
884 kw.setdefault('severity',
885 dict(self.severityConversions)[state.severity])
886 except (ValueError, KeyError):
887 pass
888 for name in "startDate", "endDate":
889 if hasattr(state, name):
890 kw.setdefault(name, Time.ParseUSDate(getattr(state, name)))
891 kw.setdefault('startDate',
892 time.time() - 60*60*24*self.defaultAvailabilityDays)
893 return Availability.query(self.dmd, **kw)
894
895
896 - def getHeartbeat(self, failures=True, simple=False, limit=0, db=None):
897 """Return all heartbeat issues list of tuples (device, component, secs)
898 """
899 sel = """select device, component, lastTime from heartbeat """
900 if failures:
901 sel += "where DATE_ADD(lastTime, INTERVAL timeout SECOND) <= NOW();"
902
903 statusCache = self.checkCache(sel)
904 cleanup = lambda : None
905 if not statusCache:
906 statusCache = []
907 conn = self.connect()
908 try:
909 curs = conn.cursor()
910 curs.execute(sel)
911 res = list(curs.fetchall())
912 res.sort(lambda x,y: cmp(x[2],y[2]))
913 devclass = self.getDmdRoot("Devices")
914 for devname, comp, dtime in res:
915 dtime = "%d" % int(time.time()-dtime.timeTime())
916 dev = devclass.findDevice(devname)
917 if dev and not simple:
918 alink = "<a href='%s'>%s</a>" % (
919 dev.getPrimaryUrlPath(), dev.id)
920 else: alink = devname
921 statusCache.append([alink, comp, dtime, devname])
922 if limit:
923 statusCache = statusCache[:limit]
924 cleanup()
925 finally: self.close(conn)
926 return statusCache
927
928
930 beats = self.getHeartbeat(failures, simple, limit, db)
931 return [{'alink':b[0], 'comp':b[1], 'dtime':b[2], 'devId':b[3]}
932 for b in beats]
933
934
935 - def getAllComponentStatus(self,
936 statclass,
937 countField=None,
938 severity=3,
939 state=1,
940 where=""):
941 "Fetch the counts on all components matching statClass"
942 if countField == None: countField = self.countField
943 select = "select %s, %s, %s from %s where "\
944 % (self.deviceField, self.componentField, countField,
945 self.statusTable)
946 where = self._wand(where, "%s = '%s'", self.eventClassField, statclass)
947 where = self._wand(where, "%s >= %s", self.severityField, severity)
948 where = self._wand(where, "%s <= %s", self.stateField, state)
949 select += where
950 conn = self.connect()
951 try:
952 curs = conn.cursor()
953 curs.execute(select)
954 result = {}
955 for dev, comp, count in curs.fetchall():
956 dev = self.cleanstring(dev)
957 comp = self.cleanstring(comp)
958 result[dev,comp] = count
959 return result
960 finally:
961 self.close(conn)
962
963
980
981
982 - def getComponentStatus(self, device, component, statclass=None,
983 countField=None, severity=3, state=1, where=""):
984 """see IEventStatus
985 """
986 if countField == None: countField = self.countField
987 select = "select %s, %s, %s from %s where "\
988 % (self.deviceField, self.componentField, countField,
989 self.statusTable)
990 where = self._wand(where, "%s = '%s'", self.eventClassField, statclass)
991 where = self._wand(where, "%s >= %s", self.severityField, severity)
992 where = self._wand(where, "%s <= %s", self.stateField, state)
993 select += where
994 statusCache = self.checkCache(select)
995 if not statusCache:
996 conn = self.connect()
997 try:
998 curs = conn.cursor()
999 curs.execute(select)
1000 statusCache ={}
1001 for dev, comp, count in curs.fetchall():
1002 dev = self.cleanstring(dev)
1003 comp = self.cleanstring(comp)
1004 statusCache[dev+comp] = count
1005 self.addToCache(select,statusCache)
1006 finally: self.close(conn)
1007 return statusCache.get(device+component, 0)
1008
1010 """
1011 Given a list of dicts with keys 'device', 'component', make a query to
1012 get an overall severity and device status for the group.
1013 """
1014 severity, state = 3, 1
1015 components = list(components)
1016
1017 def doQuery(query):
1018 conn = self.connect()
1019 data = None
1020 try:
1021 curs = conn.cursor()
1022 curs.execute(query)
1023 data = curs.fetchall()
1024 finally: self.close(conn)
1025 return data
1026
1027 select = "select MAX(%s) from %s where " % (self.severityField,
1028 self.statusTable)
1029 where = self._wand("", "%s >= %s", self.severityField, severity)
1030 where = self._wand(where, "%s <= %s", self.stateField, state)
1031 def componentWhere(device, component):
1032 return "device = '%s' and component= '%s'" % (device, component)
1033 cwheres = ' and ' + ' or '.join(['(%s)'% componentWhere(**comp)
1034 for comp in components])
1035 sevquery = select + where + cwheres
1036
1037 select = "select MAX(%s) from %s where " % (self.countField,
1038 self.statusTable)
1039 where = self._wand("", "%s >= %s", self.severityField, severity)
1040 where = self._wand(where, "%s <= %s", self.stateField, state)
1041 where = self._wand(where, "%s = '%s'", self.eventClassField,
1042 '/Status/Ping')
1043 devwhere = lambda d:"device = '%s'" % d
1044 dwheres = ' and ' + '(%s)' % (' or '.join(
1045 map(devwhere, [x['device'] for x in components])))
1046 statquery = select + where + dwheres
1047
1048 maxseverity = doQuery(sevquery)[0][0]
1049 maxstatus = doQuery(statquery)[0][0]
1050 return maxseverity, maxstatus
1051
1061
1062
1064 """Return a list of userids that correspond to the events in where.
1065 select distinct ownerid from status where
1066 device="win2k.confmon.loc" and eventState > 2
1067 """
1068 select ="select distinct ownerid from status where "
1069 where = self._wand(where, "%s >= %s", self.severityField, severity)
1070 where = self._wand(where, "%s <= %s", self.stateField, state)
1071 select += where
1072
1073 statusCache = self.checkCache(select)
1074 if statusCache: return statusCache
1075 conn = self.connect()
1076 try:
1077 curs = conn.cursor()
1078 curs.execute(select)
1079 statusCache = [ uid[0] for uid in curs.fetchall() if uid[0] ]
1080 self.addToCache(select,statusCache)
1081 finally: self.close(conn)
1082 return statusCache
1083
1084
1086 """
1087 Lookup and build where clause for managed entity.
1088
1089 @param me: managed entity
1090 @type me: object
1091 @return: where clause
1092 @rtype: string
1093 """
1094 key = me.event_key + "Where"
1095 wheretmpl = getattr(aq_base(self), key, False)
1096 if not wheretmpl:
1097 raise ValueError("No 'where' clause found for event_key %s" % me.event_key)
1098 return eval(wheretmpl,{'me':me})
1099
1100
1102 """
1103 Lookup database field for managed entity default
1104 using event_key.
1105
1106 @param event_key: event
1107 @type event_key: string
1108 @return: field for the managed entity
1109 @rtype: object
1110 """
1111 key = event_key + "Field"
1112 return getattr(aq_base(self), key, event_key)
1113
1114
1116 """
1117 Gets the column names that should be requested in an event query for
1118 this entity type.
1119
1120 Returns a set of result fields predefined for this entity type. If
1121 none have been defined, returns the default result fields.
1122
1123 >>> f = dmd.ZenEventManager.lookupManagedEntityResultFields('Device')
1124 >>> f==dmd.ZenEventManager.DeviceResultFields
1125 True
1126 >>> f = dmd.ZenEventManager.lookupManagedEntityResultFields('Robot')
1127 >>> f==dmd.ZenEventManager.defaultResultFields
1128 True
1129
1130 @param event_key: The event key of a managed entity.
1131 @type event_key: string
1132 @return: A tuple of strings representing columns in the database.
1133 """
1134 key = event_key + "ResultFields"
1135 return getattr(aq_base(self), key, self.defaultResultFields)
1136
1137
1138 - def _wand(self, where, fmt, field, value):
1139 """
1140 >>> dmd.ZenEventManager._wand('where 1=1', '%s=%s', 'a', 'b')
1141 'where 1=1 and a=b'
1142 >>> dmd.ZenEventManager._wand('where a=5', '%s=%s', 'a', 'b')
1143 'where a=5'
1144 >>> dmd.ZenEventManager._wand('where b=a', '%s=%s', 'a', 'b')
1145 'where b=a'
1146 """
1147 if value != None and where.find(field) == -1:
1148 if where: where += " and "
1149 where += fmt % (field, value)
1150 return where
1151
1154 """
1155 Make a start and end date range that is at least one day long.
1156 returns a start and end date as a proper database element.
1157 """
1158 if enddate is None:
1159 enddate = DateTime.DateTime()-1
1160 if startdate is None:
1161 startdate = DateTime.DateTime()
1162 if type(enddate) == types.StringType:
1163 enddate = DateTime.DateTime(enddate, datefmt='us')
1164 enddate = enddate.latestTime()
1165 if type(startdate) == types.StringType:
1166 startdate = DateTime.DateTime(startdate, datefmt='us')
1167 startdate = startdate.earliestTime()
1168 startdate = self.dateDB(startdate)
1169 enddate = self.dateDB(enddate)
1170 return startdate, enddate
1171
1173 conn = self.connect()
1174 try:
1175 curs = conn.cursor()
1176 selstatement = ("SELECT AVG(CHAR_LENGTH(mycol))+20 FROM (SELECT %s AS "
1177 "mycol FROM %s WHERE %s IS NOT NULL LIMIT 500) AS "
1178 "a;") % (fieldname, self.statusTable, fieldname)
1179 curs.execute(selstatement)
1180 avglen = curs.fetchone()
1181 finally: self.close(conn)
1182 try: return float(avglen[0])
1183 except TypeError: return 10.
1184
1185
1186
1187
1188
1189
1190 security.declareProtected(ZEN_SEND_EVENTS, 'sendEvents')
1192 """Send a group of events to the backend.
1193 """
1194 count = 0
1195 for event in events:
1196 try:
1197 self.sendEvent(event)
1198 count += 1
1199 except Exception, ex:
1200 log.exception(ex)
1201 return count
1202
1203
1204 security.declareProtected(ZEN_SEND_EVENTS, 'sendEvent')
1206 """
1207 Send an event to the backend.
1208
1209 @param event: event
1210 @type event: event object
1211 @todo: implement
1212 """
1213 raise NotImplementedError
1214
1215
1216
1217
1218
1219
1233
1234
1235 security.declareProtected(ZEN_VIEW, "getFieldList")
1237 """Return a list of all fields in the status table of the backend.
1238 """
1239 if not getattr(self, '_fieldlist', None):
1240 self.loadSchema()
1241 return self._fieldlist
1242
1247
1249 """Return a list of possible event actions.
1250 """
1251 return self.eventActions
1252
1253 security.declareProtected(ZEN_COMMON,'getSeverities')
1255 """Return a list of tuples of severities [('Warning', 3), ...]
1256 """
1257 return self.severityConversions
1258
1260 """Return a string representation of the severity.
1261 """
1262 try:
1263 return self.severities[severity]
1264 except KeyError:
1265 return "Unknown"
1266
1268 """Return a list of tuples of priorities [('Warning', 3), ...]
1269 """
1270 return self.priorityConversions
1271
1273 """Return the priority name
1274 """
1275 try:
1276 return self.priorities[priority]
1277 except IndexError:
1278 return "Unknown"
1279
1280
1309
1310
1315
1316
1318 ''' Return the img source for a status number
1319 '''
1320 if status < 0:
1321 src = 'grey'
1322 elif status == 0:
1323 src = 'green'
1324 else:
1325 src = 'red'
1326 return '/zport/dmd/img/%s_dot.png' % src
1327
1328
1330 """return the css class name to be used for this event.
1331 """
1332 __pychecker__='no-constCond'
1333 value = severity < 0 and "unknown" or severity
1334 acked = acked and "acked" or "noack"
1335 return "zenevents_%s_%s %s" % (value, acked, acked)
1336
1337
1339 """Check to see if a column is of type date.
1340 """
1341 if not self._schema:
1342 self.getFieldList()
1343 return self._schema.get(colName, False)
1344
1345
1352
1353
1354
1356 """Convert a date to its database format.
1357 """
1358 if isinstance(value, DateTime.DateTime):
1359 return "%.3f" % value.timeTime()
1360 elif type(value) == types.StringTypes:
1361 return "%.3f" % DateTime.DateTime(value).timeTime()
1362 return value
1363
1364
1366 """
1367 Prepare string values for db by escaping special characters.
1368
1369 @param value: string
1370 @type value: string
1371 @todo: implement
1372 """
1373 raise NotImplementedError
1374
1375
1377 """Load schema from database. If field is a date set value to true."""
1378 schema = {}
1379 fieldlist = []
1380 sql = "describe %s;" % self.statusTable
1381 conn = self.connect()
1382 try:
1383 curs = conn.cursor()
1384 curs.execute(sql)
1385 for row in curs.fetchall():
1386 fieldlist.append(row[0])
1387 col = self.cleanstring(row[0])
1388 if self.backend == "mysql":
1389 type = row[1] in ("datetime", "timestamp", "double")
1390 schema[col] = type
1391 if schema: self._schema = schema
1392 self._fieldlist = fieldlist
1393 finally: self.close(conn)
1394
1395
1397 """Are there event controls on this event list.
1398 """
1399 if self.isManager() and self.statusTable in ["status","history"]:
1400 return 1
1401 return 0
1402
1403 - def updateEvents(self, stmt, whereClause, reason,
1404 table="status", toLog=True):
1405 userId = getSecurityManager().getUser().getId()
1406 insert = 'INSERT INTO log (evid, userName, text) ' + \
1407 'SELECT evid, "%s", "%s" ' % (userId, reason) + \
1408 'FROM %s ' % table + whereClause
1409 query = stmt + ' ' + whereClause
1410 conn = self.connect()
1411 try:
1412 curs = conn.cursor()
1413 if toLog: curs.execute(insert)
1414 curs.execute(query)
1415 finally: self.close(conn)
1416 self.clearCache()
1417 self.manage_clearCache()
1418
1419 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_addEvent')
1421 ''' Create an event from user supplied data
1422 '''
1423 eventDict = dict(
1424 summary = REQUEST.get('summary', ''),
1425 message = REQUEST.get('message', ''),
1426 device = REQUEST.get('device', ''),
1427 component = REQUEST.get('component', ''),
1428 severity = REQUEST.get('severity', ''),
1429 eventClassKey = REQUEST.get('eventClassKey', ''),
1430 )
1431
1432
1433 if REQUEST.get('eclass', None):
1434 eventDict['eventClass'] = REQUEST['eclass']
1435
1436 if not eventDict['device'] and not eventDict['component']:
1437 if REQUEST:
1438 messaging.IMessageSender(self).sendToBrowser(
1439 'Invalid Event',
1440 'You must specify a device and/or a component.',
1441 priority=messaging.WARNING
1442 )
1443 return self.callZenScreen(REQUEST)
1444 else:
1445 return
1446 self.sendEvent(eventDict)
1447 if REQUEST:
1448 REQUEST['RESPONSE'].redirect('/zport/dmd/Events/viewEvents')
1449
1450
1452 self.updateEvents('DELETE FROM status', whereClause, reason)
1453
1454
1455 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_deleteEvents')
1457 "Delete the given event ids"
1458 if type(evids) == type(''):
1459 evids = [evids]
1460 num = len(evids)
1461 if evids:
1462 evids = ",".join([ "'%s'" % evid for evid in evids])
1463 whereClause = ' where evid in (%s)' % evids
1464 self.deleteEvents(whereClause, 'Deleted by user')
1465 if REQUEST:
1466 messaging.IMessageSender(self).sendToBrowser(
1467 'Moved To History',
1468 '%s event%s have been moved to history.' % (
1469 num, (num != 1 and 's') or '')
1470 )
1471 return self.callZenScreen(REQUEST)
1472
1474 fields = ','.join( self.getFieldList() )
1475
1476 fields = fields.replace('clearid','NULL')
1477 self.updateEvents( 'INSERT status ' + \
1478 'SELECT %s FROM history' % fields,
1479 whereClause + \
1480 ' ON DUPLICATE KEY UPDATE status.count=status.count+history.count',
1481 reason, 'history', toLog=False)
1482 self.updateEvents( 'DELETE FROM history', whereClause, \
1483 reason, 'history')
1484
1485 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_undeleteEvents')
1487 "Move the given event ids into status and delete from history"
1488 if type(evids) == type(''):
1489 evids = [evids]
1490 num = len(evids)
1491 if evids:
1492 evids = ",".join([ "'%s'" % evid for evid in evids])
1493 whereClause = ' where evid in (%s)' % evids
1494 self.undeleteEvents(whereClause, 'Undeleted by user')
1495 if REQUEST:
1496 messaging.IMessageSender(self).sendToBrowser(
1497 'Undeleted',
1498 '%s events have been moved out of history.' % num
1499 )
1500 return self.callZenScreen(REQUEST)
1501
1502
1503 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_deleteAllEvents')
1514
1515
1516 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_deleteHistoricalEvents')
1519 """
1520 Delete historical events. If devices is given then only delete
1521 events for that device. If agedDays is given then only delete
1522 events that are older than that many days.
1523 devname and agedDays are mutually exclusive. No real reason for this
1524 other than there is no current need to use both in same call and I
1525 don't want to test the combination.
1526 This is an option during device deletion. It is also used
1527 by zenactions to keep history table clean.
1528
1529 NB: Device.deleteDevice() is not currently calling this when devices
1530 are deleted. See ticket #2996.
1531 """
1532 import subprocess
1533 import os
1534 import Products.ZenUtils.Utils as Utils
1535
1536 cmd = Utils.zenPath('Products', 'ZenUtils', 'ZenDeleteHistory.py')
1537 if devname:
1538 args = ['--device=%s' % devname]
1539 elif agedDays:
1540 args = ['--numDays=%s' % agedDays]
1541 else:
1542 return
1543 proc = subprocess.Popen(
1544 [cmd]+args, stdout=subprocess.PIPE,
1545 stderr=subprocess.STDOUT, env=os.environ)
1546
1547
1548
1549 unused(proc)
1550 if REQUEST:
1551 messaging.IMessageSender(self).sendToBrowser(
1552 'Events Deleted',
1553 'Historical events have been deleted.'
1554 )
1555 return self.callZenScreen(REQUEST)
1556
1557
1558 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_deleteHeartbeat')
1573
1574
1575 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_ackEvents')
1588
1589
1590 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_setEventStates')
1593 reason = None
1594 if eventState and evids:
1595 eventState = int(eventState)
1596 if eventState > 0 and not userid:
1597 userid = getSecurityManager().getUser()
1598 update = "update status set eventState=%s, ownerid='%s' " % (
1599 eventState, userid)
1600 whereClause = "where evid in ("
1601 whereClause += ",".join([ "'%s'" % evid for evid in evids]) + ")"
1602 reason = 'Event state changed to '
1603 try:
1604 reason += self.eventStateConversions[eventState][0]
1605 except KeyError:
1606 reason += 'unknown (%d)' % eventState
1607 self.updateEvents(update, whereClause, reason)
1608 if REQUEST:
1609 if not reason: reason = ''
1610 messaging.IMessageSender(self).sendToBrowser(
1611 'Event States Set',
1612 reason
1613 )
1614 return self.callZenScreen(REQUEST)
1615
1616
1617 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_setEventStates')
1620 """Create an event map from an event or list of events.
1621 """
1622 evclass = None
1623 evmap = None
1624 numCreated = 0
1625 numNotUnknown = 0
1626 numNoKey = 0
1627 if eventClass and evids:
1628 evclass = self.getDmdRoot("Events").getOrganizer(eventClass)
1629 sel = """select eventClassKey, eventClass, message
1630 from %s where evid in ('%s')"""
1631 sel = sel % (self.statusTable, "','".join(evids))
1632 conn = self.connect()
1633 try:
1634 curs = conn.cursor()
1635 curs.execute(sel);
1636 for row in curs.fetchall():
1637 evclasskey, curevclass, msg = row
1638 if curevclass != Unknown:
1639 numNotUnknown += 1
1640 continue
1641 if not evclasskey:
1642 numNoKey += 1
1643 continue
1644 evmap = evclass.createInstance(evclasskey)
1645 evmap.eventClassKey = evclasskey
1646 evmap.example = msg
1647 numCreated += 1
1648 evmap.index_object()
1649 finally: self.close(conn)
1650 elif REQUEST:
1651 if not evids:
1652 messaging.IMessageSender(self).sendToBrowser(
1653 'Error',
1654 'No events selected',
1655 priority=messaging.WARNING
1656 )
1657 elif not eventClass:
1658 messaging.IMessageSender(self).sendToBrowser(
1659 'Error',
1660 'No event class selected',
1661 priority=messaging.WARNING
1662 )
1663
1664 if REQUEST:
1665 msg = REQUEST.get('message', '')
1666 if numNotUnknown:
1667 msg += ((msg and ' ') +
1668 '%s event%s %s not class /Unknown.' % (
1669 numNotUnknown,
1670 (numNotUnknown != 1 and 's') or '',
1671 (numNotUnknown != 1 and 'are') or 'is'))
1672 if numNoKey:
1673 msg += ((msg and ' ') +
1674 '%s event%s %s not have an event class key.' % (
1675 numNoKey,
1676 (numNoKey != 1 and 's') or '',
1677 (numNoKey != 1 and 'do') or 'does'))
1678 msg += (msg and ' ') + 'Created %s event mapping%s.' % (
1679 numCreated,
1680 (numCreated != 1 and 's') or '')
1681
1682 messaging.IMessageSender(self).sendToBrowser('Event Map', msg)
1683
1684
1685 if getattr(REQUEST, 'dontRender', False):
1686 return ''
1687 if len(evids) == 1 and evmap:
1688 REQUEST['RESPONSE'].redirect(evmap.absolute_url())
1689 elif evclass and evmap:
1690 REQUEST['RESPONSE'].redirect(evclass.absolute_url())
1691
1692
1693 security.declareProtected(ZEN_MANAGE_EVENTMANAGER,'manage_refreshConversions')
1703
1704
1705 security.declareProtected(ZEN_MANAGE_EVENTMANAGER,'manage_editCache')
1707 """Reset cache values"""
1708 self.timeout = int(timeout)
1709 self.clearthresh = int(clearthresh)
1710 if REQUEST:
1711 message = "Cache parameters set"
1712 return self.editCache(self, REQUEST, manage_tabs_message=message)
1713
1714
1715 security.declareProtected(ZEN_MANAGE_EVENTMANAGER,'manage_clearCache')
1725
1726
1727 security.declareProtected(ZEN_MANAGE_EVENTMANAGER,'manage_editEventManager')
1729 ''' Call zmanage_editProperties then take care of saving a few
1730 values to ZenEventHistory
1731 '''
1732 assert(self == self.dmd.ZenEventManager)
1733 self.zmanage_editProperties(REQUEST)
1734 self.dmd.ZenEventHistory.timeout = REQUEST['history_timeout']
1735 self.dmd.ZenEventHistory.clearthresh = REQUEST['history_clearthresh']
1736 self.dmd.ZenEventHistory.username = self.dmd.ZenEventManager.username
1737 self.dmd.ZenEventHistory.password = self.dmd.ZenEventManager.password
1738 self.dmd.ZenEventHistory.database = self.dmd.ZenEventManager.database
1739 self.dmd.ZenEventHistory.host = self.dmd.ZenEventManager.host
1740 self.dmd.ZenEventHistory.port = self.dmd.ZenEventManager.port
1741 if REQUEST: return self.callZenScreen(REQUEST)
1742
1743
1744 security.declareProtected(ZEN_MANAGE_EVENTMANAGER,'manage_clearHeartbeats')
1757
1758 security.declareProtected(ZEN_MANAGE_EVENTMANAGER,'zmanage_editProperties')
1760 ''' Need to handle editing of history event fields differently
1761 '''
1762 assert(self == self.dmd.ZenEventManager)
1763 screenName = REQUEST.get('zenScreenName', '')
1764 if screenName == 'editEventManagerHistoryFields':
1765 obj = self.dmd.ZenEventHistory
1766 else:
1767 obj = self
1768 if screenName == 'editEventManager':
1769
1770
1771 if REQUEST.has_key('mysql_pass'):
1772 REQUEST.form['password'] = REQUEST['mysql_pass']
1773 editProperties = ZenModelRM.zmanage_editProperties
1774
1775 editProperties(obj, REQUEST)
1776 if REQUEST: return self.callZenScreen(REQUEST)
1777
1778 security.declareProtected(ZEN_MANAGE_EVENTS, 'manage_addLogMessage')
1780 """
1781 Add a log message to an event
1782 """
1783 if not evid:
1784 return
1785 userId = getSecurityManager().getUser().getId()
1786 conn = self.connect()
1787 try:
1788 curs = conn.cursor()
1789 insert = 'INSERT INTO log (evid, userName, text) '
1790 insert += 'VALUES ("%s", "%s", "%s")' % (evid,
1791 userId,
1792 conn.escape_string(message))
1793 curs.execute(insert)
1794 finally: self.close(conn)
1795 self.clearCache('evid' + evid)
1796 self.dmd.ZenEventHistory.clearCache('evid' + evid)
1797 if REQUEST: return self.callZenScreen(REQUEST)
1798
1799
1800 security.declareProtected(ZEN_MANAGE_EVENTMANAGER, 'manage_addCommand')
1828
1829
1830 security.declareProtected(ZEN_MANAGE_EVENTMANAGER, 'manage_deleteCommands')
1832 """
1833 Delete an EventCommand
1834
1835 @param ids: commands to delete
1836 @type ids: list of strings
1837 @param REQUEST: Zope REQUEST object
1838 @type REQUEST: Zope REQUEST object
1839 """
1840 for id in ids:
1841 self.commands._delObject(id)
1842 if REQUEST: return self.callZenScreen(REQUEST)
1843
1844
1845
1846
1847
1848
1850 """Install skins into portal.
1851 """
1852 from Products.CMFCore.utils import getToolByName
1853 from Products.CMFCore.DirectoryView import addDirectoryViews
1854 from cStringIO import StringIO
1855 import string
1856
1857 out = StringIO()
1858 skinstool = getToolByName(self, 'portal_skins')
1859 if 'zenevents' not in skinstool.objectIds():
1860 addDirectoryViews(skinstool, 'skins', globals())
1861 out.write("Added 'zenevents' directory view to portal_skins\n")
1862 skins = skinstool.getSkinSelections()
1863 for skin in skins:
1864 path = skinstool.getSkinPath(skin)
1865 path = map(string.strip, string.split(path,','))
1866 if 'zenevents' not in path:
1867 try: path.insert(path.index('zenmodel'), 'zenevents')
1868 except ValueError:
1869 path.append('zenevents')
1870 path = string.join(path, ', ')
1871 skinstool.addSkinSelection(skin, path)
1872 out.write("Added 'zenevents' to %s skin\n" % skin)
1873 else:
1874 out.write(
1875 "Skipping %s skin, 'zenevents' is already set up\n" % skin)
1876 return out.getvalue()
1877