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", "severity":
881 if hasattr(state, name):
882 kw.setdefault(name, getattr(state, name))
883 for name in "startDate", "endDate":
884 if hasattr(state, name):
885 kw.setdefault(name, Time.ParseUSDate(getattr(state, name)))
886 kw.setdefault('startDate',
887 time.time() - 60*60*24*self.defaultAvailabilityDays)
888 return Availability.query(self.dmd, **kw)
889
890
891 - def getHeartbeat(self, failures=True, simple=False, limit=0, db=None):
892 """Return all heartbeat issues list of tuples (device, component, secs)
893 """
894 sel = """select device, component, lastTime from heartbeat """
895 if failures:
896 sel += "where DATE_ADD(lastTime, INTERVAL timeout SECOND) <= NOW();"
897
898 statusCache = self.checkCache(sel)
899 cleanup = lambda : None
900 if not statusCache:
901 statusCache = []
902 conn = self.connect()
903 try:
904 curs = conn.cursor()
905 curs.execute(sel)
906 res = list(curs.fetchall())
907 res.sort(lambda x,y: cmp(x[2],y[2]))
908 devclass = self.getDmdRoot("Devices")
909 for devname, comp, dtime in res:
910 dtime = "%d" % int(time.time()-dtime.timeTime())
911 dev = devclass.findDevice(devname)
912 if dev and not simple:
913 alink = "<a href='%s'>%s</a>" % (
914 dev.getPrimaryUrlPath(), dev.id)
915 else: alink = devname
916 statusCache.append([alink, comp, dtime, devname])
917 if limit:
918 statusCache = statusCache[:limit]
919 cleanup()
920 finally: self.close(conn)
921 return statusCache
922
923
925 beats = self.getHeartbeat(failures, simple, limit, db)
926 return [{'alink':b[0], 'comp':b[1], 'dtime':b[2], 'devId':b[3]}
927 for b in beats]
928
929
930 - def getAllComponentStatus(self,
931 statclass,
932 countField=None,
933 severity=3,
934 state=1,
935 where=""):
936 "Fetch the counts on all components matching statClass"
937 if countField == None: countField = self.countField
938 select = "select %s, %s, %s from %s where "\
939 % (self.deviceField, self.componentField, countField,
940 self.statusTable)
941 where = self._wand(where, "%s = '%s'", self.eventClassField, statclass)
942 where = self._wand(where, "%s >= %s", self.severityField, severity)
943 where = self._wand(where, "%s <= %s", self.stateField, state)
944 select += where
945 conn = self.connect()
946 try:
947 curs = conn.cursor()
948 curs.execute(select)
949 result = {}
950 for dev, comp, count in curs.fetchall():
951 dev = self.cleanstring(dev)
952 comp = self.cleanstring(comp)
953 result[dev,comp] = count
954 return result
955 finally:
956 self.close(conn)
957
958
975
976
977 - def getComponentStatus(self, device, component, statclass=None,
978 countField=None, severity=3, state=1, where=""):
979 """see IEventStatus
980 """
981 if countField == None: countField = self.countField
982 select = "select %s, %s, %s from %s where "\
983 % (self.deviceField, self.componentField, countField,
984 self.statusTable)
985 where = self._wand(where, "%s = '%s'", self.eventClassField, statclass)
986 where = self._wand(where, "%s >= %s", self.severityField, severity)
987 where = self._wand(where, "%s <= %s", self.stateField, state)
988 select += where
989 statusCache = self.checkCache(select)
990 if not statusCache:
991 conn = self.connect()
992 try:
993 curs = conn.cursor()
994 curs.execute(select)
995 statusCache ={}
996 for dev, comp, count in curs.fetchall():
997 dev = self.cleanstring(dev)
998 comp = self.cleanstring(comp)
999 statusCache[dev+comp] = count
1000 self.addToCache(select,statusCache)
1001 finally: self.close(conn)
1002 return statusCache.get(device+component, 0)
1003
1005 """
1006 Given a list of dicts with keys 'device', 'component', make a query to
1007 get an overall severity and device status for the group.
1008 """
1009 severity, state = 3, 1
1010 components = list(components)
1011
1012 def doQuery(query):
1013 conn = self.connect()
1014 data = None
1015 try:
1016 curs = conn.cursor()
1017 curs.execute(query)
1018 data = curs.fetchall()
1019 finally: self.close(conn)
1020 return data
1021
1022 select = "select MAX(%s) from %s where " % (self.severityField,
1023 self.statusTable)
1024 where = self._wand("", "%s >= %s", self.severityField, severity)
1025 where = self._wand(where, "%s <= %s", self.stateField, state)
1026 def componentWhere(device, component):
1027 return "device = '%s' and component= '%s'" % (device, component)
1028 cwheres = ' and ' + ' or '.join(['(%s)'% componentWhere(**comp)
1029 for comp in components])
1030 sevquery = select + where + cwheres
1031
1032 select = "select MAX(%s) from %s where " % (self.countField,
1033 self.statusTable)
1034 where = self._wand("", "%s >= %s", self.severityField, severity)
1035 where = self._wand(where, "%s <= %s", self.stateField, state)
1036 where = self._wand(where, "%s = '%s'", self.eventClassField,
1037 '/Status/Ping')
1038 devwhere = lambda d:"device = '%s'" % d
1039 dwheres = ' and ' + '(%s)' % (' or '.join(
1040 map(devwhere, [x['device'] for x in components])))
1041 statquery = select + where + dwheres
1042
1043 maxseverity = doQuery(sevquery)[0][0]
1044 maxstatus = doQuery(statquery)[0][0]
1045 return maxseverity, maxstatus
1046
1056
1057
1059 """Return a list of userids that correspond to the events in where.
1060 select distinct ownerid from status where
1061 device="win2k.confmon.loc" and eventState > 2
1062 """
1063 select ="select distinct ownerid from status where "
1064 where = self._wand(where, "%s >= %s", self.severityField, severity)
1065 where = self._wand(where, "%s <= %s", self.stateField, state)
1066 select += where
1067
1068 statusCache = self.checkCache(select)
1069 if statusCache: return statusCache
1070 conn = self.connect()
1071 try:
1072 curs = conn.cursor()
1073 curs.execute(select)
1074 statusCache = [ uid[0] for uid in curs.fetchall() if uid[0] ]
1075 self.addToCache(select,statusCache)
1076 finally: self.close(conn)
1077 return statusCache
1078
1079
1081 """
1082 Lookup and build where clause for managed entity.
1083
1084 @param me: managed entity
1085 @type me: object
1086 @return: where clause
1087 @rtype: string
1088 """
1089 key = me.event_key + "Where"
1090 wheretmpl = getattr(aq_base(self), key, False)
1091 if not wheretmpl:
1092 raise ValueError("No 'where' clause found for event_key %s" % me.event_key)
1093 return eval(wheretmpl,{'me':me})
1094
1095
1097 """
1098 Lookup database field for managed entity default
1099 using event_key.
1100
1101 @param event_key: event
1102 @type event_key: string
1103 @return: field for the managed entity
1104 @rtype: object
1105 """
1106 key = event_key + "Field"
1107 return getattr(aq_base(self), key, event_key)
1108
1109
1111 """
1112 Gets the column names that should be requested in an event query for
1113 this entity type.
1114
1115 Returns a set of result fields predefined for this entity type. If
1116 none have been defined, returns the default result fields.
1117
1118 >>> f = dmd.ZenEventManager.lookupManagedEntityResultFields('Device')
1119 >>> f==dmd.ZenEventManager.DeviceResultFields
1120 True
1121 >>> f = dmd.ZenEventManager.lookupManagedEntityResultFields('Robot')
1122 >>> f==dmd.ZenEventManager.defaultResultFields
1123 True
1124
1125 @param event_key: The event key of a managed entity.
1126 @type event_key: string
1127 @return: A tuple of strings representing columns in the database.
1128 """
1129 key = event_key + "ResultFields"
1130 return getattr(aq_base(self), key, self.defaultResultFields)
1131
1132
1133 - def _wand(self, where, fmt, field, value):
1134 """
1135 >>> dmd.ZenEventManager._wand('where 1=1', '%s=%s', 'a', 'b')
1136 'where 1=1 and a=b'
1137 >>> dmd.ZenEventManager._wand('where a=5', '%s=%s', 'a', 'b')
1138 'where a=5'
1139 >>> dmd.ZenEventManager._wand('where b=a', '%s=%s', 'a', 'b')
1140 'where b=a'
1141 """
1142 if value != None and where.find(field) == -1:
1143 if where: where += " and "
1144 where += fmt % (field, value)
1145 return where
1146
1149 """
1150 Make a start and end date range that is at least one day long.
1151 returns a start and end date as a proper database element.
1152 """
1153 if enddate is None:
1154 enddate = DateTime.DateTime()-1
1155 if startdate is None:
1156 startdate = DateTime.DateTime()
1157 if type(enddate) == types.StringType:
1158 enddate = DateTime.DateTime(enddate, datefmt='us')
1159 enddate = enddate.latestTime()
1160 if type(startdate) == types.StringType:
1161 startdate = DateTime.DateTime(startdate, datefmt='us')
1162 startdate = startdate.earliestTime()
1163 startdate = self.dateDB(startdate)
1164 enddate = self.dateDB(enddate)
1165 return startdate, enddate
1166
1168 conn = self.connect()
1169 try:
1170 curs = conn.cursor()
1171 selstatement = ("SELECT AVG(CHAR_LENGTH(mycol))+20 FROM (SELECT %s AS "
1172 "mycol FROM %s WHERE %s IS NOT NULL LIMIT 500) AS "
1173 "a;") % (fieldname, self.statusTable, fieldname)
1174 curs.execute(selstatement)
1175 avglen = curs.fetchone()
1176 finally: self.close(conn)
1177 try: return float(avglen[0])
1178 except TypeError: return 10.
1179
1180
1181
1182
1183
1184
1185 security.declareProtected(ZEN_SEND_EVENTS, 'sendEvents')
1187 """Send a group of events to the backend.
1188 """
1189 count = 0
1190 for event in events:
1191 try:
1192 self.sendEvent(event)
1193 count += 1
1194 except Exception, ex:
1195 log.exception(ex)
1196 return count
1197
1198
1199 security.declareProtected(ZEN_SEND_EVENTS, 'sendEvent')
1201 """
1202 Send an event to the backend.
1203
1204 @param event: event
1205 @type event: event object
1206 @todo: implement
1207 """
1208 raise NotImplementedError
1209
1210
1211
1212
1213
1214
1230
1231
1232 security.declareProtected(ZEN_VIEW, "getFieldList")
1234 """Return a list of all fields in the status table of the backend.
1235 """
1236 if not getattr(self, '_fieldlist', None):
1237 self.loadSchema()
1238 return self._fieldlist
1239
1244
1246 """Return a list of possible event actions.
1247 """
1248 return self.eventActions
1249
1250 security.declareProtected(ZEN_COMMON,'getSeverities')
1252 """Return a list of tuples of severities [('Warning', 3), ...]
1253 """
1254 return self.severityConversions
1255
1257 """Return a string representation of the severity.
1258 """
1259 try:
1260 return self.severities[severity]
1261 except KeyError:
1262 return "Unknown"
1263
1265 """Return a list of tuples of priorities [('Warning', 3), ...]
1266 """
1267 return self.priorityConversions
1268
1270 """Return the priority name
1271 """
1272 try:
1273 return self.priorities[priority]
1274 except IndexError:
1275 return "Unknown"
1276
1305
1306
1311
1312
1314 ''' Return the img source for a status number
1315 '''
1316 if status < 0:
1317 src = 'grey'
1318 elif status == 0:
1319 src = 'green'
1320 else:
1321 src = 'red'
1322 return '/zport/dmd/img/%s_dot.png' % src
1323
1324
1326 """return the css class name to be used for this event.
1327 """
1328 __pychecker__='no-constCond'
1329 value = severity < 0 and "unknown" or severity
1330 acked = acked and "acked" or "noack"
1331 return "zenevents_%s_%s %s" % (value, acked, acked)
1332
1333
1335 """Check to see if a column is of type date.
1336 """
1337 if not self._schema:
1338 self.getFieldList()
1339 return self._schema.get(colName, False)
1340
1341
1348
1349
1350
1352 """Convert a date to its database format.
1353 """
1354 if isinstance(value, DateTime.DateTime):
1355 return "%.3f" % value.timeTime()
1356 elif type(value) == types.StringTypes:
1357 return "%.3f" % DateTime.DateTime(value).timeTime()
1358 return value
1359
1360
1362 """
1363 Prepare string values for db by escaping special characters.
1364
1365 @param value: string
1366 @type value: string
1367 @todo: implement
1368 """
1369 raise NotImplementedError
1370
1371
1373 """Load schema from database. If field is a date set value to true."""
1374 schema = {}
1375 fieldlist = []
1376 sql = "describe %s;" % self.statusTable
1377 conn = self.connect()
1378 try:
1379 curs = conn.cursor()
1380 curs.execute(sql)
1381 for row in curs.fetchall():
1382 fieldlist.append(row[0])
1383 col = self.cleanstring(row[0])
1384 if self.backend == "mysql":
1385 type = row[1] in ("datetime", "timestamp", "double")
1386 schema[col] = type
1387 if schema: self._schema = schema
1388 self._fieldlist = fieldlist
1389 finally: self.close(conn)
1390
1391
1393 """Are there event controls on this event list.
1394 """
1395 if self.isManager() and self.statusTable in ["status","history"]:
1396 return 1
1397 return 0
1398
1399 - def updateEvents(self, stmt, whereClause, reason,
1400 table="status", toLog=True):
1401 userId = getSecurityManager().getUser().getId()
1402 insert = 'INSERT INTO log (evid, userName, text) ' + \
1403 'SELECT evid, "%s", "%s" ' % (userId, reason) + \
1404 'FROM %s ' % table + whereClause
1405 query = stmt + ' ' + whereClause
1406 conn = self.connect()
1407 try:
1408 curs = conn.cursor()
1409 if toLog: curs.execute(insert)
1410 curs.execute(query)
1411 finally: self.close(conn)
1412 self.clearCache()
1413 self.manage_clearCache()
1414
1415 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_addEvent')
1417 ''' Create an event from user supplied data
1418 '''
1419 eventDict = dict(
1420 summary = REQUEST.get('summary', ''),
1421 message = REQUEST.get('message', ''),
1422 device = REQUEST.get('device', ''),
1423 component = REQUEST.get('component', ''),
1424 severity = REQUEST.get('severity', ''),
1425 eventClassKey = REQUEST.get('eventClassKey', ''),
1426 )
1427
1428
1429 if REQUEST.get('eclass', None):
1430 eventDict['eventClass'] = REQUEST['eclass']
1431
1432 if not eventDict['device'] and not eventDict['component']:
1433 if REQUEST:
1434 messaging.IMessageSender(self).sendToBrowser(
1435 'Invalid Event',
1436 'You must specify a device and/or a component.',
1437 priority=messaging.WARNING
1438 )
1439 return self.callZenScreen(REQUEST)
1440 else:
1441 return
1442 self.sendEvent(eventDict)
1443 if REQUEST:
1444 REQUEST['RESPONSE'].redirect('/zport/dmd/Events/viewEvents')
1445
1446
1448 self.updateEvents('DELETE FROM status', whereClause, reason)
1449
1450
1451 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_deleteEvents')
1453 "Delete the given event ids"
1454 if type(evids) == type(''):
1455 evids = [evids]
1456 num = len(evids)
1457 if evids:
1458 evids = ",".join([ "'%s'" % evid for evid in evids])
1459 whereClause = ' where evid in (%s)' % evids
1460 self.deleteEvents(whereClause, 'Deleted by user')
1461 if REQUEST:
1462 messaging.IMessageSender(self).sendToBrowser(
1463 'Moved To History',
1464 '%s event%s have been moved to history.' % (
1465 num, (num != 1 and 's') or '')
1466 )
1467 return self.callZenScreen(REQUEST)
1468
1470 fields = ','.join( self.getFieldList() )
1471
1472 fields = fields.replace('clearid','NULL')
1473 self.updateEvents( 'INSERT status ' + \
1474 'SELECT %s FROM history' % fields,
1475 whereClause + \
1476 ' ON DUPLICATE KEY UPDATE status.count=status.count+history.count',
1477 reason, 'history', toLog=False)
1478 self.updateEvents( 'DELETE FROM history', whereClause, \
1479 reason, 'history')
1480
1481 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_undeleteEvents')
1483 "Move the given event ids into status and delete from history"
1484 if type(evids) == type(''):
1485 evids = [evids]
1486 num = len(evids)
1487 if evids:
1488 evids = ",".join([ "'%s'" % evid for evid in evids])
1489 whereClause = ' where evid in (%s)' % evids
1490 self.undeleteEvents(whereClause, 'Undeleted by user')
1491 if REQUEST:
1492 messaging.IMessageSender(self).sendToBrowser(
1493 'Undeleted',
1494 '%s events have been moved out of history.' % num
1495 )
1496 return self.callZenScreen(REQUEST)
1497
1498
1499 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_deleteAllEvents')
1510
1511
1512 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_deleteHistoricalEvents')
1515 """
1516 Delete historical events. If devices is given then only delete
1517 events for that device. If agedDays is given then only delete
1518 events that are older than that many days.
1519 devname and agedDays are mutually exclusive. No real reason for this
1520 other than there is no current need to use both in same call and I
1521 don't want to test the combination.
1522 This is an option during device deletion. It is also used
1523 by zenactions to keep history table clean.
1524
1525 NB: Device.deleteDevice() is not currently calling this when devices
1526 are deleted. See ticket #2996.
1527 """
1528 import subprocess
1529 import os
1530 import Products.ZenUtils.Utils as Utils
1531
1532 cmd = Utils.zenPath('Products', 'ZenUtils', 'ZenDeleteHistory.py')
1533 if devname:
1534 args = ['--device=%s' % devname]
1535 elif agedDays:
1536 args = ['--numDays=%s' % agedDays]
1537 else:
1538 return
1539 proc = subprocess.Popen(
1540 [cmd]+args, stdout=subprocess.PIPE,
1541 stderr=subprocess.STDOUT, env=os.environ)
1542
1543
1544
1545 unused(proc)
1546 if REQUEST:
1547 messaging.IMessageSender(self).sendToBrowser(
1548 'Events Deleted',
1549 'Historical events have been deleted.'
1550 )
1551 return self.callZenScreen(REQUEST)
1552
1553
1554 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_deleteHeartbeat')
1569
1570
1571 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_ackEvents')
1584
1585
1586 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_setEventStates')
1589 reason = None
1590 if eventState and evids:
1591 eventState = int(eventState)
1592 if eventState > 0 and not userid:
1593 userid = getSecurityManager().getUser()
1594 update = "update status set eventState=%s, ownerid='%s' " % (
1595 eventState, userid)
1596 whereClause = "where evid in ("
1597 whereClause += ",".join([ "'%s'" % evid for evid in evids]) + ")"
1598 reason = 'Event state changed to '
1599 try:
1600 reason += self.eventStateConversions[eventState][0]
1601 except KeyError:
1602 reason += 'unknown (%d)' % eventState
1603 self.updateEvents(update, whereClause, reason)
1604 if REQUEST:
1605 if not reason: reason = ''
1606 messaging.IMessageSender(self).sendToBrowser(
1607 'Event States Set',
1608 reason
1609 )
1610 return self.callZenScreen(REQUEST)
1611
1612
1613 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_setEventStates')
1616 """Create an event map from an event or list of events.
1617 """
1618 evclass = None
1619 evmap = None
1620 numCreated = 0
1621 numNotUnknown = 0
1622 numNoKey = 0
1623 if eventClass and evids:
1624 evclass = self.getDmdRoot("Events").getOrganizer(eventClass)
1625 sel = """select eventClassKey, eventClass, message
1626 from %s where evid in ('%s')"""
1627 sel = sel % (self.statusTable, "','".join(evids))
1628 conn = self.connect()
1629 try:
1630 curs = conn.cursor()
1631 curs.execute(sel);
1632 for row in curs.fetchall():
1633 evclasskey, curevclass, msg = row
1634 if curevclass != Unknown:
1635 numNotUnknown += 1
1636 continue
1637 if not evclasskey:
1638 numNoKey += 1
1639 continue
1640 evmap = evclass.createInstance(evclasskey)
1641 evmap.eventClassKey = evclasskey
1642 evmap.example = msg
1643 numCreated += 1
1644 evmap.index_object()
1645 finally: self.close(conn)
1646 elif REQUEST:
1647 if not evids:
1648 messaging.IMessageSender(self).sendToBrowser(
1649 'Error',
1650 'No events selected',
1651 priority=messaging.WARNING
1652 )
1653 elif not eventClass:
1654 messaging.IMessageSender(self).sendToBrowser(
1655 'Error',
1656 'No event class selected',
1657 priority=messaging.WARNING
1658 )
1659
1660 if REQUEST:
1661 msg = REQUEST.get('message', '')
1662 if numNotUnknown:
1663 msg += ((msg and ' ') +
1664 '%s event%s %s not class /Unknown.' % (
1665 numNotUnknown,
1666 (numNotUnknown != 1 and 's') or '',
1667 (numNotUnknown != 1 and 'are') or 'is'))
1668 if numNoKey:
1669 msg += ((msg and ' ') +
1670 '%s event%s %s not have an event class key.' % (
1671 numNoKey,
1672 (numNoKey != 1 and 's') or '',
1673 (numNoKey != 1 and 'do') or 'does'))
1674 msg += (msg and ' ') + 'Created %s event mapping%s.' % (
1675 numCreated,
1676 (numCreated != 1 and 's') or '')
1677
1678 messaging.IMessageSender(self).sendToBrowser('Event Map', msg)
1679
1680
1681 if getattr(REQUEST, 'dontRender', False):
1682 return ''
1683 if len(evids) == 1 and evmap:
1684 REQUEST['RESPONSE'].redirect(evmap.absolute_url())
1685 elif evclass and evmap:
1686 REQUEST['RESPONSE'].redirect(evclass.absolute_url())
1687
1688
1689 security.declareProtected(ZEN_MANAGE_EVENTMANAGER,'manage_refreshConversions')
1699
1700
1701 security.declareProtected(ZEN_MANAGE_EVENTMANAGER,'manage_editCache')
1703 """Reset cache values"""
1704 self.timeout = int(timeout)
1705 self.clearthresh = int(clearthresh)
1706 if REQUEST:
1707 message = "Cache parameters set"
1708 return self.editCache(self, REQUEST, manage_tabs_message=message)
1709
1710
1711 security.declareProtected(ZEN_MANAGE_EVENTMANAGER,'manage_clearCache')
1721
1722
1723 security.declareProtected(ZEN_MANAGE_EVENTMANAGER,'manage_editEventManager')
1725 ''' Call zmanage_editProperties then take care of saving a few
1726 values to ZenEventHistory
1727 '''
1728 assert(self == self.dmd.ZenEventManager)
1729 self.zmanage_editProperties(REQUEST)
1730 self.dmd.ZenEventHistory.timeout = REQUEST['history_timeout']
1731 self.dmd.ZenEventHistory.clearthresh = REQUEST['history_clearthresh']
1732 self.dmd.ZenEventHistory.username = self.dmd.ZenEventManager.username
1733 self.dmd.ZenEventHistory.password = self.dmd.ZenEventManager.password
1734 self.dmd.ZenEventHistory.database = self.dmd.ZenEventManager.database
1735 self.dmd.ZenEventHistory.host = self.dmd.ZenEventManager.host
1736 self.dmd.ZenEventHistory.port = self.dmd.ZenEventManager.port
1737 if REQUEST: return self.callZenScreen(REQUEST)
1738
1739
1740 security.declareProtected(ZEN_MANAGE_EVENTMANAGER,'manage_clearHeartbeats')
1753
1754 security.declareProtected(ZEN_MANAGE_EVENTMANAGER,'zmanage_editProperties')
1756 ''' Need to handle editing of history event fields differently
1757 '''
1758 assert(self == self.dmd.ZenEventManager)
1759 screenName = REQUEST.get('zenScreenName', '')
1760 if screenName == 'editEventManagerHistoryFields':
1761 obj = self.dmd.ZenEventHistory
1762 else:
1763 obj = self
1764 if screenName == 'editEventManager':
1765
1766
1767 if REQUEST.has_key('mysql_pass'):
1768 REQUEST.form['password'] = REQUEST['mysql_pass']
1769 editProperties = ZenModelRM.zmanage_editProperties
1770
1771 editProperties(obj, REQUEST)
1772 if REQUEST: return self.callZenScreen(REQUEST)
1773
1774 security.declareProtected(ZEN_MANAGE_EVENTS, 'manage_addLogMessage')
1776 """
1777 Add a log message to an event
1778 """
1779 if not evid:
1780 return
1781 userId = getSecurityManager().getUser().getId()
1782 conn = self.connect()
1783 try:
1784 curs = conn.cursor()
1785 insert = 'INSERT INTO log (evid, userName, text) '
1786 insert += 'VALUES ("%s", "%s", "%s")' % (evid,
1787 userId,
1788 conn.escape_string(message))
1789 curs.execute(insert)
1790 finally: self.close(conn)
1791 self.clearCache('evid' + evid)
1792 self.dmd.ZenEventHistory.clearCache('evid' + evid)
1793 if REQUEST: return self.callZenScreen(REQUEST)
1794
1795
1796 security.declareProtected(ZEN_MANAGE_EVENTMANAGER, 'manage_addCommand')
1824
1825
1826 security.declareProtected(ZEN_MANAGE_EVENTMANAGER, 'manage_deleteCommands')
1828 """
1829 Delete an EventCommand
1830
1831 @param ids: commands to delete
1832 @type ids: list of strings
1833 @param REQUEST: Zope REQUEST object
1834 @type REQUEST: Zope REQUEST object
1835 """
1836 for id in ids:
1837 self.commands._delObject(id)
1838 if REQUEST: return self.callZenScreen(REQUEST)
1839
1840
1841
1842
1843
1844
1846 """Install skins into portal.
1847 """
1848 from Products.CMFCore.utils import getToolByName
1849 from Products.CMFCore.DirectoryView import addDirectoryViews
1850 from cStringIO import StringIO
1851 import string
1852
1853 out = StringIO()
1854 skinstool = getToolByName(self, 'portal_skins')
1855 if 'zenevents' not in skinstool.objectIds():
1856 addDirectoryViews(skinstool, 'skins', globals())
1857 out.write("Added 'zenevents' directory view to portal_skins\n")
1858 skins = skinstool.getSkinSelections()
1859 for skin in skins:
1860 path = skinstool.getSkinPath(skin)
1861 path = map(string.strip, string.split(path,','))
1862 if 'zenevents' not in path:
1863 try: path.insert(path.index('zenmodel'), 'zenevents')
1864 except ValueError:
1865 path.append('zenevents')
1866 path = string.join(path, ', ')
1867 skinstool.addSkinSelection(skin, path)
1868 out.write("Added 'zenevents' to %s skin\n" % skin)
1869 else:
1870 out.write(
1871 "Skipping %s skin, 'zenevents' is already set up\n" % skin)
1872 return out.getvalue()
1873