Package Products :: Package ZenEvents :: Module EventManagerBase
[hide private]
[frames] | no frames]

Source Code for Module Products.ZenEvents.EventManagerBase

   1  ########################################################################### 
   2  # 
   3  # This program is part of Zenoss Core, an open source monitoring platform. 
   4  # Copyright (C) 2007, Zenoss Inc. 
   5  # 
   6  # This program is free software; you can redistribute it and/or modify it 
   7  # under the terms of the GNU General Public License version 2 as published by 
   8  # the Free Software Foundation. 
   9  # 
  10  # For complete information please visit: http://www.zenoss.com/oss/ 
  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  import re 
  22  random.seed() 
  23  import logging 
  24  log = logging.getLogger("zen.Events") 
  25   
  26  from AccessControl import ClassSecurityInfo 
  27  from AccessControl import getSecurityManager 
  28  from Globals import DTMLFile 
  29  from Acquisition import aq_base 
  30  import DateTime 
  31  from Products.ZenModel.ZenossSecurity import * 
  32   
  33  from Products.ZenUtils.ObjectCache import ObjectCache 
  34  from Products.ZenUtils.jsonutils import unjson 
  35   
  36  from ZEvent import ZEvent 
  37  from EventDetail import EventDetail 
  38  from BetterEventDetail import BetterEventDetail 
  39  from EventCommand import EventCommand 
  40  from Products.ZenEvents.Exceptions import * 
  41  from Products.AdvancedQuery import MatchRegexp, In, And 
  42   
  43  from Products.ZenModel.ZenModelRM import ZenModelRM 
  44  from Products.ZenModel.ZenossSecurity import * 
  45  from Products.ZenRelations.RelSchema import * 
  46  from Products.ZenUtils import Time 
  47  from Products.ZenUtils.FakeRequest import FakeRequest 
  48  from Products.ZenEvents.ZenEventClasses import Status_Ping, Status_Wmi_Conn 
  49  from Products.ZenWidgets import messaging 
  50  from Products.ZenUI3.browser.eventconsole.columns import COLUMN_CONFIG 
  51   
  52  from ZenEventClasses import Unknown 
  53   
  54  from DbAccessBase import DbAccessBase 
  55   
  56  from Products.ZenUtils.Utils import unused 
  57   
  58  __pychecker__="maxargs=16"   
  59   
60 -def evtprep(evts):
61 """ 62 Prepares data from L{Products.ZenEvents.EventManagerBase.getEventSummary} 63 for rendering in the eventrainbow template macro. 64 65 Each cell of the old-style event rainbow needs a CSS class specified in 66 order to render its color, fill and border style. evtprep determines the 67 proper class and returns it, along with a string representation of the 68 number of live and acknowledged events. 69 70 >>> from Products.ZenEvents.EventManagerBase import evtprep 71 >>> evtprep(['zenevents_5_noack noack', 2, 2]) 72 {'cssclass': 'zenevents_5_noack noack empty thin', 'data': '2/2'} 73 >>> evtprep(['zenevents_5_noack noack', 1, 2]) 74 {'cssclass': 'zenevents_5_noack noack', 'data': '1/2'} 75 76 @param evts: A tuple of the form (Severity string, Number Acknowledged int, 77 Number Live int) 78 @type evts: tuple 79 @return: A dictionary of the form {'cssclass': Class string, 'data': Event 80 count representation string} 81 82 """ 83 evtsdata = "%d/%d" % (evts[1],evts[2]) 84 if evts[1]==evts[2] or evts[2]==0: 85 return {'cssclass':evts[0] + " empty thin", 86 'data':evtsdata} 87 else: 88 return {'cssclass':evts[0], 'data':evtsdata}
89 90
91 -class EventManagerBase(ZenModelRM, ObjectCache, DbAccessBase):
92 """ 93 Data connector to backend of the event management system. 94 """ 95 #implements(IEventList, IEventStatus, ISendEvents) 96 97 #FQDNID = hash(socket.getfqdn()) 98 99 eventStateConversions = ( 100 ('New', 0), 101 ('Acknowledged',1), 102 ('Suppressed', 2), 103 #('Bogus', 3), 104 ) 105 106 eventActions = ('status', 'history', 'drop') 107 108 severityConversions = ( 109 ('Critical', 5), 110 ('Error', 4), 111 ('Warning', 3), 112 ('Info', 2), 113 ('Debug', 1), 114 ('Clear', 0), 115 ) 116 severities = dict([(b, a) for a, b in severityConversions]) 117 118 priorityConversions = ( 119 ('None', -1), 120 ('Emergency', 0), 121 ('Alert', 1), 122 ('Critical', 2), 123 ('Error', 3), 124 ('Warning', 4), 125 ('Notice', 6), 126 ('Info', 8), 127 ('Debug', 10), 128 ) 129 priorities = dict([(b, a) for a, b in priorityConversions]) 130 131 statusTable = "status" 132 detailTable = "detail" 133 logTable = "log" 134 lastTimeField = "lastTime" 135 firstTimeField = "firstTime" 136 deviceField = "device" 137 componentField = "component" 138 eventClassField = "eventClass" 139 severityField = "severity" 140 stateField = "eventState" 141 countField = "count" 142 prodStateField = "prodState" 143 DeviceGroupField = "DeviceGroups" 144 SystemField = "Systems" 145 146 DeviceWhere = "\"device = '%s'\" % me.getDmdKey()" 147 DeviceResultFields = ("eventState", "severity", "component", "eventClass", 148 "summary", "firstTime", "lastTime", "count" ) 149 ComponentWhere = ("\"(device = '%s' and component = '%s')\"" 150 " % (me.device().getDmdKey(), me.name())") 151 ComponentResultFields = ("eventState", "severity", "eventClass", "summary", 152 "firstTime", "lastTime", "count" ) 153 IpAddressWhere = "\"ipAddress='%s'\" % (me.getId())" 154 EventClassWhere = "\"eventClass like '%s%%'\" % me.getDmdKey()" 155 EventClassInstWhere = """\"eventClass = '%s' and eventClassKey = '%s'\" % (\ 156 me.getEventClass(), me.eventClassKey)""" 157 DeviceClassWhere = "\"(DeviceClass = '%s' or DeviceClass like '%s/%%') \" % \ 158 ( me.getDmdKey(), me.getDmdKey() )" 159 160 LocationWhere = "\"Location like '%s%%'\" % me.getDmdKey()" 161 SystemWhere = "\"Systems like '%%|%s%%'\" % me.getDmdKey()" 162 DeviceGroupWhere = "\"DeviceGroups like '%%|%s%%'\" % me.getDmdKey()" 163 164 defaultResultFields = ("eventState", "severity", "device", "component", 165 "eventClass", "summary", "firstTime", "lastTime", 166 "count" ) 167 168 defaultFields = ('eventState', 'severity', 'evid') 169 170 defaultEventId = ('device', 'component', 'eventClass', 171 'eventKey', 'severity') 172 173 requiredEventFields = ('device', 'summary', 'severity') 174 175 refreshConversionsForm = DTMLFile('dtml/refreshNcoProduct', globals()) 176 177 defaultAvailabilityDays = 7 178 defaultPriority = 3 179 eventAgingHours = 4 180 eventAgingSeverity = 4 181 historyMaxAgeDays = 0 182 183 _properties = ( 184 {'id':'backend', 'type':'string','mode':'r', }, 185 {'id':'username', 'type':'string', 'mode':'w'}, 186 {'id':'password', 'type':'string', 'mode':'w'}, 187 {'id':'host', 'type':'string', 'mode':'w'}, 188 {'id':'database', 'type':'string', 'mode':'w'}, 189 {'id':'port', 'type':'int', 'mode':'w'}, 190 {'id':'defaultWhere', 'type':'text', 'mode':'w'}, 191 {'id':'defaultOrderby', 'type':'text', 'mode':'w'}, 192 {'id':'defaultResultFields', 'type':'lines', 'mode':'w'}, 193 {'id':'statusTable', 'type':'string', 'mode':'w'}, 194 {'id':'detailTable', 'type':'string', 'mode':'w'}, 195 {'id':'logTable', 'type':'string', 'mode':'w'}, 196 {'id':'lastTimeField', 'type':'string', 'mode':'w'}, 197 {'id':'firstTimeField', 'type':'string', 'mode':'w'}, 198 {'id':'deviceField', 'type':'string', 'mode':'w'}, 199 {'id':'componentField', 'type':'string', 'mode':'w'}, 200 {'id':'severityField', 'type':'string', 'mode':'w'}, 201 {'id':'countField', 'type':'string', 'mode':'w'}, 202 {'id':'DeviceGroupField', 'type':'string', 'mode':'w'}, 203 {'id':'SystemField', 'type':'string', 'mode':'w'}, 204 {'id':'DeviceWhere', 'type':'string', 'mode':'w'}, 205 {'id':'DeviceResultFields', 'type':'lines', 'mode':'w'}, 206 {'id':'ComponentResultFields', 'type':'lines', 'mode':'w'}, 207 {'id':'EventClassWhere', 'type':'string', 'mode':'w'}, 208 {'id':'EventClassInstWhere', 'type':'string', 'mode':'w'}, 209 {'id':'DeviceClassWhere', 'type':'string', 'mode':'w'}, 210 {'id':'LocationWhere', 'type':'string', 'mode':'w'}, 211 {'id':'SystemWhere', 'type':'string', 'mode':'w'}, 212 {'id':'DeviceGroupWhere', 'type':'string', 'mode':'w'}, 213 {'id':'requiredEventFields', 'type':'lines', 'mode':'w'}, 214 {'id':'defaultEventId', 'type':'lines', 'mode':'w'}, 215 {'id':'defaultFields', 'type':'lines', 'mode':'w'}, 216 {'id':'timeout', 'type':'int', 'mode':'w'}, 217 {'id':'clearthresh', 'type':'int', 'mode':'w'}, 218 {'id':'defaultAvailabilityDays', 'type':'int', 'mode':'w'}, 219 {'id':'defaultPriority', 'type':'int', 'mode':'w'}, 220 {'id':'eventAgingHours', 'type':'int', 'mode':'w'}, 221 {'id':'eventAgingSeverity', 'type':'int', 'mode':'w'}, 222 {'id':'historyMaxAgeDays', 'type':'int', 'mode':'w'}, 223 ) 224 225 _relations = ( 226 ("commands", ToManyCont(ToOne, "Products.ZenEvents.EventCommand", "eventManager")), 227 ) 228 229 factory_type_information = ( 230 { 231 'immediate_view' : 'editEventManager', 232 'actions' : 233 ( 234 { 'id' : 'edit' 235 , 'name' : 'Edit' 236 , 'action' : 'editEventManager' 237 , 'permissions' : ( "Manage DMD", ) 238 }, 239 { 'id' : 'edit' 240 , 'name' : 'Fields' 241 , 'action' : 'editEventManagerFields' 242 , 'permissions' : ( "Manage DMD", ) 243 }, 244 { 'id' : 'history_edit' 245 , 'name' : 'History Fields' 246 , 'action' : 'editEventManagerHistoryFields' 247 , 'permissions' : ( "Manage DMD", ) 248 }, 249 { 'id' : 'commands' 250 , 'name' : 'Commands' 251 , 'action' : 'listEventCommands' 252 , 'permissions' : ( "Manage DMD", ) 253 }, 254 { 'id' : 'changes' 255 , 'name' : 'Modifications' 256 , 'action' : 'viewNewHistory' 257 , 'permissions' : (ZEN_VIEW_MODIFICATIONS,) 258 }, 259 ) 260 }, 261 ) 262 263 security = ClassSecurityInfo() 264 265
266 - def __init__(self, id, title='', hostname='localhost', username='root', 267 password='', database='events', port=3306, 268 defaultWhere='',defaultOrderby='',defaultResultFields=[]):
269 """ 270 Sets up event database access and initializes the cache. 271 272 @param id: A unique id 273 @type id: string 274 @param title: A title 275 @type title: string 276 @param hostname: The hostname of the events database server 277 @type hostname: string 278 @param username: The name of a user with permissions to access the 279 events database 280 @type username: string 281 @param password: The password of the user 282 @type password: string 283 @param database: The name of the events database 284 @type database: string 285 @param port: The port on which the database server is listening 286 @type port: int 287 @param defaultWhere: The default where clause to use when building 288 queries 289 @type defaultWhere: string 290 @param defaultOrderby: The default order by clause to use when building 291 queries 292 @type defaultOrderby: string 293 @param defaultResultFields: DEPRECATED. Currently unused. 294 @type defaultResultFields: list 295 296 """ 297 unused(defaultOrderby, defaultResultFields) 298 self.id = id 299 self.title = title 300 self.username=username 301 self.password=password 302 self.database=database 303 self.host=hostname 304 self.port=port 305 DbAccessBase.__init__(self) 306 307 self.defaultWhere = defaultWhere 308 self.defaultOrderby="%s desc, %s desc" % ( 309 self.severityField, self.lastTimeField) 310 311 self._schema = {} 312 self._fieldlist = [] 313 self._colors = () 314 self._ackedcolors = () 315 ObjectCache.__init__(self) 316 self.initCache()
317 318 #========================================================================== 319 # Event query functions from IEventQuery 320 #========================================================================== 321 322
323 - def getEventResultFields(self, context):
324 """ 325 A wrapper for L{lookupManagedEntityResultFields} accepting an object 326 with an C{event_key} attribute. 327 328 >>> class dummy(object): 329 ... event_key = 'Device' 330 ... 331 >>> d = dummy() 332 >>> f = dmd.ZenEventManager.getEventResultFields(d) 333 >>> f==dmd.ZenEventManager.DeviceResultFields 334 True 335 >>> d.event_key = 'Robot' 336 >>> f = dmd.ZenEventManager.getEventResultFields(d) 337 >>> f==dmd.ZenEventManager.defaultResultFields 338 True 339 340 @param context: An object with an C{event_key} attribute. 341 @type context: L{ManagedEntity} 342 @return: A sequence of strings representing columns in the database. 343 @rtype: tuple 344 """ 345 return self.lookupManagedEntityResultFields(getattr(context, 346 'event_key', 'Default'))
347
348 - def getEventListME(self, me, **kwargs):
349 """ 350 Queries the database for events on a managed entity. 351 352 @param me: The object for which to fetch events 353 @type me: L{ManagedEntity} 354 @return: L{ZEvent} objects 355 @rtype: list 356 """ 357 where = "" 358 if hasattr(me, 'getWhere'): 359 where = me.getWhere() 360 else: 361 where = self.lookupManagedEntityWhere(me) 362 try: 363 resultFields = kwargs['resultFields']; del kwargs['resultFields'] 364 except KeyError: 365 resultFields = self.lookupManagedEntityResultFields(me.event_key) 366 return self.getEventList(resultFields=resultFields, where=where, 367 **kwargs)
368 369
370 - def filteredWhere(self, where, filters, values):
371 """ 372 Create SQL representing conditions that match passed filters and append 373 it to a given where clause. 374 375 Expressions are built using various criteria, including the type of 376 filter widget representing the column and factors specific to the 377 column itself. 378 379 All C{textfield} columns except C{count} will be matched as regular 380 expressions. 381 382 C{count} may be passed as a comparison expression such as ">=2", "=8", 383 "<10", etc., or an integer, in which case it will be evaluated as 384 ">=n". 385 386 C{firstTime} and C{lastTime} are turned into seconds since the epoch, 387 then evaluated as '>=n' and '<=n', respectively. 388 389 C{multiselectmenu} columns (prodState, severity, eventState, priority) 390 arrive as a list of values to match, and become 'and (field=v1 or 391 field=v2...)' where field is the column and vn is the value. 392 393 @param where: The where clause to which to append further conditions 394 @type where: str 395 @param filters: Values for which to create filters (e.g., 396 {'device':'^loc.*$', 'severity':[4, 5]}) 397 @type filters: dict or JSON str representing dict 398 @param values: Clause will be parameterized and the values list will be 399 populated with the values for the query 400 @type values: list 401 """ 402 queryValues = [] 403 newwhere = '' 404 if filters is None: filters = {} 405 elif isinstance(filters, basestring): 406 filters = unjson(filters) 407 for k,v in filters.items(): 408 ftype = COLUMN_CONFIG[k].get('filter', 'textfield') 409 if isinstance(ftype, dict): 410 ftype = ftype['xtype'] 411 if k=='device': 412 # get all list of devices where title match the search term 413 deviceids = self._getDeviceIdsMatching(v) 414 if deviceids: 415 newwhere += " and (device REGEXP %%s OR device IN ('%s')) " % "','".join(deviceids) 416 else: 417 newwhere += " and (%s REGEXP %%s) " % (k,) 418 queryValues.append(v) 419 elif k=='component': 420 componentWhere = "" 421 componentids = self._getComponentIdsMatching(v) 422 if componentids: 423 componentWhere = " OR component IN ('%s') " % "','".join(componentids) 424 # because components don't have to exist in the ZODB always search the 425 # database for them 426 newwhere += ' and ((%s REGEXP %%s) %s) ' % (k,componentWhere) 427 queryValues.append(v) 428 elif k=='count': 429 m = re.match(r'^(?P<condition>\>=|\<=|\>|\<|=)?\s*(?P<value>[0-9]+)$', v.strip()) 430 if m: 431 cond = m.group('condition') if m.group('condition') else '=' 432 queryValues.append(m.group('value')) 433 434 newwhere += ' and count %s %%s' % cond 435 else: 436 raise ValueError('%s is not a valid count' % v) 437 438 elif ftype=='textfield': 439 newwhere += ' and (%s REGEXP %%s) ' % (k,) 440 queryValues.append(v) 441 elif k=='firstTime': 442 v2 = Time.isoToTimestamp(v) 443 newwhere += ' and %s >= %%s ' % (k,) 444 queryValues.append(v2) 445 elif k=='lastTime': 446 v2 = Time.isoToTimestamp(v) 447 newwhere += ' and %s >= %%s ' % (k, ) 448 queryValues.append(v2) 449 elif ftype=='multiselectmenu': 450 if isinstance(v, basestring): v = (v,) 451 if len(v)>0: 452 sevstr = ' or '.join(['%s=%%s' % (k,) for s in v]) 453 queryValues.extend(v) 454 newwhere += ' and (%s) ' % sevstr 455 values.extend(queryValues) 456 return where + newwhere
457 458
459 - def _filterCatalogResultsForIds(self, catalog, querySet):
460 """ 461 Used by both the id matching sub queries 462 this gets brain results and returns a list of 463 ids 464 @param catalog: catalog we are searching 465 @param querySet: Advanced Query Search Terms 466 @return [string]: all the ids of the search results that match 467 the queryset 468 """ 469 try: 470 brains = catalog.evalAdvancedQuery(querySet) 471 except: 472 # they had an error in their regex, just return nothing they may still be working on it 473 return None 474 # return list of device ids for mysql to filter by 475 ids = [] 476 for brain in brains: 477 ids.append(brain.id) 478 return ids
479
480 - def _getComponentIdsMatching(self, searchTerm):
481 """ 482 This returns a list of component ids where the titleOrId 483 matches the searchTerm 484 @param searchTerm: query for which we want to search for (can be regex) 485 """ 486 catalog = self.dmd.global_catalog 487 querySet = [MatchRegexp('name', '.*%s.*' % searchTerm), 488 In('objectImplements', 489 'Products.ZenModel.DeviceComponent.DeviceComponent')] 490 return self._filterCatalogResultsForIds(catalog, And(*querySet))
491
492 - def _getDeviceIdsMatching(self, searchTerm, globSearch=True):
493 """ 494 This returns a list of device ids where the titleOrId 495 matches the searchTerm 496 @param searchTerm: query for which we want to search for (can be regex) 497 """ 498 catalog = self.dmd.Devices.deviceSearch 499 if globSearch: 500 searchTerm = '.*%s.*' % searchTerm 501 querySet = MatchRegexp('titleOrId', searchTerm) 502 return self._filterCatalogResultsForIds(catalog, querySet)
503
504 - def getEventBatchME(self, me, selectstatus=None, resultFields=[], 505 where="", orderby="", severity=None, state=2, 506 startdate=None, enddate=None, offset=0, rows=0, 507 getTotalCount=False, filter="", goodevids=[], 508 badevids=[], **kwargs):
509 """ 510 Returns a batch of events based on criteria from checked rows on the 511 event console. 512 513 The event console can show thousands of events, and we want to support a 514 "Select All" feature; enter this method. It builds a query based on the 515 select status from the console ("All", "None", "Acknowledged", 516 "Unacknowledged") and any checkboxes that have been modified manually. 517 518 @param me: The managed entity for which to query events. 519 @type me: L{ManagedEntity} 520 @param resultFields: The columns to return from the database. 521 @type resultFields: list 522 @param where: The base where clause to modify. 523 @type where: string 524 @param orderby: The "ORDER BY" string governing sort order. 525 @type orderby: string 526 @param severity: The minimum severity for which to query. 527 @type severity: int 528 @param state: The minimum state for which to query. 529 @type state: int 530 @param startdate: The early date limit 531 @type startdate: string, DateTime 532 @param enddate: The late date limit 533 @type enddate: string, DateTime 534 @param offset: The row at which to begin returning 535 @type offset: int 536 @param rows: DEPRECATED The number of rows to return (ignored). 537 @type rows: int 538 @param getTotalCount: Whether or not to return a count of the total 539 number of rows 540 @type getTotalCount: bool 541 @param filter: A glob by which to filter events 542 @type filter: string 543 @param goodevids: Ids of events that specifically should be included 544 @type goodevids: list 545 @param badevids: Ids of events that specifically should not be included 546 @type badevids: list 547 @return: Ids of matching events 548 @rtype: list 549 @todo: Remove unused parameters from the method definition 550 """ 551 unused(getTotalCount, rows) 552 newwhere = self.lookupManagedEntityWhere(me) 553 if where: newwhere = self._wand(newwhere, '%s%s', where, '') 554 where = newwhere 555 badevidsstr, goodevidsstr = '','' 556 if not isinstance(goodevids, (list, tuple)): goodevids = [goodevids] 557 if not isinstance(badevids, (list, tuple)): badevids = [badevids] 558 if badevids: badevidsstr = " and evid not in ('%s')" %( 559 "','".join(badevids)) 560 if goodevids: goodevidsstr = " and evid in ('%s')" %( 561 "','".join(goodevids)) 562 if selectstatus=='all': 563 where += badevidsstr 564 elif selectstatus=='none': 565 where += goodevidsstr or ' and 0' 566 elif selectstatus=='acked': 567 oper = bool(goodevidsstr) and ' or' or ' and' 568 where += goodevidsstr + oper + " (eventstate=1 %s) " % badevidsstr 569 elif selectstatus=='unacked': 570 oper = bool(goodevidsstr) and ' or' or 'and' 571 where += goodevidsstr + oper + " (eventstate=0 %s) " % badevidsstr 572 try: 573 resultFields = kwargs['resultFields']; del kwargs['resultFields'] 574 except KeyError: 575 resultFields = self.lookupManagedEntityResultFields(me.event_key) 576 events = self.getEventList( 577 filter=filter, 578 offset=offset, 579 getTotalCount=False, 580 startdate=startdate, 581 enddate=enddate, severity=severity, 582 state=state, orderby=orderby, 583 resultFields=resultFields, 584 where=where,**kwargs) 585 return [ev.evid for ev in events]
586
587 - def getEventIds(self, me, selectstatus=None, 588 orderby="", filters=None, evids=[], 589 excludeIds=[], asof=None):
590 """ 591 Returns a batch of events based on criteria from checked rows on the 592 event console. 593 594 The event console can show thousands of events, and we want to support a 595 "Select All" feature; enter this method. It builds a query based on the 596 select status from the console ("All", "New", "Acknowledged", 597 "Suppressed") and any checkboxes that have been modified manually. 598 599 @param me: The managed entity for which to query events. 600 @type me: L{ManagedEntity} 601 @param orderby: The "ORDER BY" string governing sort order. 602 @type orderby: string 603 @param filters: Values for which to create filters (e.g., 604 {'device':'^loc.*$', 'severity':[4, 5]}) 605 @type filters: dict or JSON str representing dict 606 @param evids: Ids of events that specifically should be included 607 @type evids: list 608 @param excludeIds: Ids of events that specifically should not be included 609 @type excludeIds: list 610 @return: Ids of matching events 611 @rtype: set 612 """ 613 where = self.lookupManagedEntityWhere(me) 614 eventids = set() 615 if evids: 616 eventids.update(evids) 617 if selectstatus: 618 if selectstatus != 'All': 619 eventStates= dict(self.eventStateConversions) 620 assert selectstatus in (eventStates.keys()) 621 where = self._wand(where, '%s = %s', self.stateField, 622 eventStates[selectstatus]) 623 if asof: 624 if where: where += ' and ' 625 where += (" not (stateChange>FROM_UNIXTIME(%s) " 626 "and eventState=0)" % self.dateDB(asof)) 627 events = self.getEventList( resultFields=['evid'], 628 filters=filters, 629 getTotalCount=False, 630 orderby=orderby, 631 where=where) 632 for ev in events: 633 eventids.add(ev.evid) 634 635 if eventids and excludeIds: 636 eventids.difference_update(excludeIds) 637 return eventids
638
639 - def restrictedUserFilter(self, where):
640 """This is a hook do not delete me!""" 641 return where
642
643 - def getEventList(self, resultFields=None, where="", orderby="", 644 severity=None, state=2, startdate=None, enddate=None, offset=0, 645 rows=0, getTotalCount=False, filter="", filters=None, 646 parameterizedWhere=None, **kwargs):
647 """ 648 Fetch a list of events from the database matching certain criteria. 649 650 @param resultFields: The columns to return from the database. 651 @type resultFields: list 652 @param where: The base where clause to modify. 653 @type where: string 654 @param orderby: The "ORDER BY" string governing sort order. 655 @type orderby: string 656 @param severity: The minimum severity for which to query. 657 @type severity: int 658 @param state: The minimum state for which to query. 659 @type state: int 660 @param startdate: The early date limit 661 @type startdate: string, DateTime 662 @param enddate: The late date limit 663 @type enddate: string, DateTime 664 @param offset: The row at which to begin returning 665 @type offset: int 666 @param rows: The number of rows to return. 667 @type rows: int 668 @param getTotalCount: Whether or not to return a count of the total 669 number of rows 670 @type getTotalCount: bool 671 @param filter: A glob by which to filter events 672 @type filter: string 673 @return: Matching events as L{ZEvent}s. 674 @rtype: list 675 @todo: Remove unused parameters from the method definition 676 """ 677 unused(kwargs) 678 paramValues = [] 679 try: 680 where = self.restrictedUserFilter(where) 681 if not resultFields: 682 resultFields = self.defaultResultFields 683 resultFields = list(resultFields) 684 resultFields.extend(self.defaultFields) 685 686 #validate all fields 687 fieldList = [x.lower() for x in self.getFieldList()] 688 for field in resultFields: 689 if field.lower() not in fieldList: 690 raise ('requested column %s is not valid' % field) 691 692 calcfoundrows = '' 693 if getTotalCount: 694 calcfoundrows = 'SQL_CALC_FOUND_ROWS' 695 select = ["select ", calcfoundrows, ','.join(resultFields), 696 "from %s where" % self.statusTable ] 697 if not where: 698 where = self.defaultWhere 699 700 #escape any % in the where clause because of format eval later 701 where = where.replace('%', '%%') 702 703 if parameterizedWhere is not None: 704 pwhere, pvals = parameterizedWhere 705 if where: where += " and " 706 where += pwhere 707 paramValues.extend(pvals) 708 709 def paramWhereAnd(where, fmt, field, value): 710 if value != None and where.find(field) == -1: 711 if where: where += " and " 712 where += fmt % (field,) 713 paramValues.append(value) 714 return where
715 716 where = paramWhereAnd(where, "%s >= %%s", self.severityField, severity) 717 where = paramWhereAnd(where, "%s <= %%s", self.stateField, state) 718 719 log.debug("filter is %s" % filter ) 720 if filter: 721 where += ' and (%s) ' % (' or '.join(['%s LIKE "%%%s%%"' % ( 722 x, filter) for x in resultFields])) 723 if startdate: 724 startdate, enddate = self._setupDateRange(startdate, enddate) 725 where = paramWhereAnd(where,"%s >= %%s",self.lastTimeField, startdate ) 726 where = paramWhereAnd(where,"%s <= %%s",self.firstTimeField, enddate ) 727 728 if filters is not None: 729 where = self.filteredWhere(where, filters, paramValues) 730 select.append(where) 731 if not orderby: 732 orderby = self.defaultOrderby 733 if orderby: 734 #validate orderby is a valid field 735 orderby = self._scrubOrderby(orderby) 736 select.append("order by") 737 select.append(orderby) 738 739 if rows: 740 #validate offset and rows are ints 741 int(offset) 742 int(rows) 743 select.append("limit %s, %s" % (offset, rows)) 744 select.append(';') 745 select = " ".join(select) 746 if getTotalCount: 747 try: retdata, totalCount = self.checkCache(select) 748 except TypeError: 749 retdata, totalCount = self.checkCache(select), 100 750 else: retdata = self.checkCache(select) 751 if not False: 752 conn = self.connect() 753 try: 754 curs = conn.cursor() 755 log.debug(select % tuple(paramValues)) 756 curs.execute(select, paramValues) 757 retdata = [] 758 # iterate through the data results and convert to python 759 # objects 760 if self.checkRemotePerm(ZEN_VIEW, self.dmd.Events): 761 eventPermission = True 762 else: 763 eventPermission = False 764 for row in curs.fetchall(): 765 row = map(self.convert, resultFields, row) 766 evt = ZEvent(self, resultFields, row, eventPermission) 767 retdata.append(evt) 768 if getTotalCount: 769 curs.execute("SELECT FOUND_ROWS()") 770 totalCount = curs.fetchone()[0] 771 finally: self.close(conn) 772 if getTotalCount: self.addToCache(select, (retdata, totalCount)) 773 else: self.addToCache(select, retdata) 774 self.cleanCache() 775 if getTotalCount: 776 return retdata, totalCount 777 else: return retdata 778 except: 779 log.exception("Failure querying events") 780 raise
781 782
783 - def getEventSummaryME(self, me, severity=1, state=1, prodState=None):
784 """ 785 Return the CSS class, number of acknowledged events, and number of 786 unacknowledged events, per severity, for a C{ManagedEntity}. 787 788 @param me: The object of the inquiry. 789 @type me: L{ManagedEntity} 790 @param severity: The minimum severity for which to retrieve events 791 @type severity: int 792 @param state: The minimum state for which to retrieve events 793 @type state: int 794 @param prodState: The minimum production state for which to retrieve 795 events 796 @type prodState: int 797 @return: List of lists of the form [class, acked count, unacked count]. 798 @rtype: list 799 """ 800 try: 801 where = self.lookupManagedEntityWhere(me) 802 return self.getEventSummary(where, severity, state, prodState) 803 except: 804 log.exception("event summary for %s failed" % me.getDmdKey()) 805 raise
806 807
808 - def getEventSummary(self, where="", severity=1, state=1, prodState=None):
809 """ 810 Return a list of tuples with number of events and the color of the 811 severity that the number represents. 812 813 This method should not be called directly, but overridden by subclasses. 814 815 @param where: The base where clause to modify. 816 @type where: string 817 @param severity: The minimum severity for which to retrieve events 818 @type severity: int 819 @param state: The minimum state for which to retrieve events 820 @type state: int 821 @param prodState: The minimum production state for which to retrieve 822 events 823 @type prodState: int 824 @return: List of lists of the form [class, acked count, unacked count]. 825 @rtype: list 826 """ 827 raise NotImplementedError
828 829
830 - def getEventDetailFromStatusOrHistory(self, evid=None, dedupid=None, 831 better=False):
832 try: 833 event = self.dmd.ZenEventManager.getEventDetail( 834 evid, dedupid, better) 835 except ZenEventNotFound: 836 event = self.dmd.ZenEventHistory.getEventDetail(evid, dedupid, 837 better) 838 return event
839 840
841 - def getEventDetail(self, evid=None, dedupid=None, better=False):
842 """ 843 Return an EventDetail object for a particular event. 844 845 @param evid: Event ID 846 @type evid: string 847 @param dedupid: string used to determine duplicates 848 @type dedupid: string 849 @param better: provide even more detail than normal? 850 @type better: boolean 851 @return: fields from the event 852 @rtype: EventDetail object 853 """ 854 idfield = evid and "evid" or "dedupid" 855 if not evid: evid = dedupid 856 cachekey = '%s%s' % (idfield, evid) 857 event = self.checkCache(cachekey) 858 if event: return event 859 fields = self.getFieldList() 860 evid = self.escape(evid) 861 selectevent = "select " 862 selectevent += ", ".join(fields) 863 selectevent += " from %s where" % self.statusTable 864 selectevent += " %s = '%s'" % (idfield, evid) 865 conn = self.connect() 866 try: 867 curs = conn.cursor() 868 curs.execute(selectevent) 869 evrow = curs.fetchone() 870 if not evrow: 871 raise ZenEventNotFound( "Event id '%s' not found" % evid) 872 evdata = map(self.convert, fields, evrow) 873 if better: 874 event = BetterEventDetail(self, fields, evdata) 875 else: 876 event = EventDetail(self, fields, evdata) 877 878 selectdetail = "select name, value from %s where" % self.detailTable 879 selectdetail += " evid = '%s'" % event.evid 880 #print selectdetail 881 curs.execute(selectdetail) 882 event._details = curs.fetchall() 883 884 selectlogs = "select userName, ctime, text" 885 selectlogs += " from %s where" % self.logTable 886 selectlogs += " evid = '%s' order by ctime desc" % event.evid 887 #print selectlogs 888 curs.execute(selectlogs) 889 jrows = curs.fetchall() 890 logs = [] 891 for row in jrows: 892 user = self.cleanstring(row[0]) 893 date = self.dateString(row[1]) 894 text = row[2] 895 logs.append((user, date, text)) 896 event._logs = logs 897 finally: self.close(conn) 898 899 self.addToCache(cachekey, event) 900 self.cleanCache() 901 return event
902 903
904 - def getStatusME(self, me, statusclass=None, **kwargs):
905 """ 906 """ 907 from Products.ZenModel.Organizer import Organizer 908 if me.event_key == "Device": 909 return self.getDeviceStatus(me.getId(), statusclass, **kwargs) 910 elif me.event_key == "Component": 911 return self.getComponentStatus(me.getParentDeviceName(), 912 me.getId(), statusclass, **kwargs) 913 elif isinstance(me, Organizer): 914 return self.getOrganizerStatus(me, statusclass=statusclass, 915 **kwargs) 916 else: 917 return self.getGenericStatus(me)
918 919
920 - def getGenericStatus(self, me):
921 """Return status based on a where clause defined for the me event_type. 922 No fancy caching done this might be a little slow if there are a lot 923 of events. Where clause is evaled 924 """ 925 where = self.lookupManagedEntityWhere(me) 926 select = "select count(*) from %s where %s" % (self.statusTable, where) 927 statusCount = self.checkCache(select) 928 if not statusCount: 929 conn = self.connect() 930 try: 931 curs = conn.cursor() 932 #print select 933 curs.execute(select) 934 statusCount = curs.fetchone()[0] 935 finally: self.close(conn) 936 937 self.addToCache(select,statusCount) 938 return statusCount
939 940
941 - def getOrganizerStatus(self, org, statusclass=None, severity=None, 942 state=0, where=""):
943 """see IEventStatus 944 """ 945 orgfield = self.lookupManagedEntityField(org.event_key) 946 select = "select %s from %s where " % (orgfield, self.statusTable) 947 where = self._wand(where, "%s = '%s'", self.eventClassField,statusclass) 948 where = self._wand(where, "%s >= %s", self.severityField, severity) 949 where = self._wand(where, "%s <= %s", self.stateField, state) 950 select += where 951 #print select 952 statusCache = self.checkCache(select) 953 if not statusCache: 954 conn = self.connect() 955 try: 956 curs = conn.cursor() 957 curs.execute(select) 958 statusCache=[] 959 orgdict={} 960 for row in curs.fetchall(): 961 orgfield = self.cleanstring(row[0]) 962 if not orgfield: continue 963 if orgfield.startswith("|"): orgfield = orgfield[1:] 964 for orgname in orgfield.split("|"): 965 orgdict.setdefault(orgname, 0) 966 orgdict[orgname] += 1 967 statusCache = orgdict.items() 968 self.addToCache(select,statusCache) 969 finally: self.close(conn) 970 countevts = 0 971 for key, value in statusCache: 972 if key.startswith(org.getOrganizerName()): 973 countevts += value 974 return countevts
975 976
977 - def getOrganizerStatusIssues(self, event_key,severity=4,state=0, 978 where="", limit=0):
979 """Return list of tuples (org, count) for all organizers with events. 980 """ 981 orgfield = self.lookupManagedEntityField(event_key) 982 select = "select %s, count from %s where " % (orgfield,self.statusTable) 983 where = self._wand(where, "%s >= %s", self.severityField, severity) 984 where = self._wand(where, "%s <= %s", self.stateField, state) 985 where = self._wand(where,"%s like '%s'",self.eventClassField,"/Status%") 986 select += where 987 statusCache = self.checkCache(select) 988 if not statusCache: 989 conn = self.connect() 990 try: 991 curs = conn.cursor() 992 curs.execute(select) 993 statusCache=[] 994 orgdict={} 995 for row in curs.fetchall(): 996 orgfield = self.cleanstring(row[0]) 997 if not orgfield: continue 998 if orgfield.startswith("|"): orgfield = orgfield[1:] 999 for orgname in orgfield.split("|"): 1000 if not orgname: continue 1001 count, total = orgdict.setdefault(orgname, (0,0)) 1002 count+=1 1003 total+=row[1] 1004 orgdict[orgname] = (count,total) 1005 statusCache = [ [n, c[0], int(c[1])] for n, c in orgdict.items() ] 1006 statusCache.sort(lambda x,y: cmp(x[1],y[1])) 1007 statusCache.reverse() 1008 if limit: 1009 statusCache = statusCache[:limit] 1010 self.addToCache(select,statusCache) 1011 finally: self.close(conn) 1012 return statusCache
1013 1014
1015 - def getDevicePingIssues(self, state=2, limit=0):
1016 """Return devices with ping problems. 1017 """ 1018 return self.getDeviceIssues(where="eventClass = '%s'" % Status_Ping, 1019 severity=3, 1020 state=state, 1021 limit=limit)
1022 1023
1024 - def getDeviceStatusIssues(self, severity=4, state=1, limit=0):
1025 """Return only status issues. 1026 """ 1027 return self.getDeviceIssues(where="eventClass like '/Status%'", 1028 severity=severity, state=state, limit=limit)
1029 1030
1031 - def getDeviceIssues(self,severity=1,state=0,where="",mincount=0,limit=0):
1032 """Return list of tuples (device, count, total) of events for 1033 all devices with events. 1034 """ 1035 where = self._wand(where, "%s >= %s", self.severityField, severity) 1036 where = self._wand(where, "%s <= %s", self.stateField, state) 1037 select = """select distinct device, count(device) as evcount, 1038 sum(count) from status where %s group by device 1039 having evcount > %s""" % (where, mincount) 1040 statusCache = self.checkCache(select) 1041 if not statusCache: 1042 try: 1043 conn = self.connect() 1044 try: 1045 curs = conn.cursor() 1046 curs.execute(select) 1047 statusCache = [ [d,int(c),int(s)] for d,c,s in curs.fetchall() ] 1048 #statusCache = list(curs.fetchall()) 1049 statusCache.sort(lambda x,y: cmp(x[1],y[1])) 1050 statusCache.reverse() 1051 if limit: 1052 statusCache = statusCache[:limit] 1053 finally: self.close(conn) 1054 except: 1055 log.exception(select) 1056 raise 1057 return statusCache
1058 1059
1060 - def getDeviceStatus(self, device, statclass=None, countField=None, 1061 severity=3, state=None, where=""):
1062 """see IEventStatus 1063 """ 1064 if countField == None: countField = self.countField 1065 select = "select %s, %s from %s where " % ( 1066 self.deviceField, self.countField, self.statusTable) 1067 where = self._wand(where, "%s = '%s'", self.eventClassField, statclass) 1068 where = self._wand(where, "%s >= %s", self.severityField, severity) 1069 where = self._wand(where, "%s <= %s", self.stateField, state) 1070 select += where 1071 #print select 1072 statusCache = self.checkCache(select) 1073 if not statusCache: 1074 try: 1075 conn = self.connect() 1076 try: 1077 curs = conn.cursor() 1078 curs.execute(select) 1079 statusCache = {} 1080 for dev, count in curs.fetchall(): 1081 dev = self.cleanstring(dev) 1082 statusCache[dev] = count 1083 self.addToCache(select,statusCache) 1084 finally: self.close(conn) 1085 except: 1086 log.exception("status failed for device %s", device) 1087 return -1 1088 return statusCache.get(device, 0)
1089 1090
1091 - def defaultAvailabilityStart(self):
1092 return Time.USDate(time.time() - 60*60*24*self.defaultAvailabilityDays)
1093 1094
1095 - def defaultAvailabilityEnd(self):
1096 return Time.USDate(time.time())
1097 1098
1099 - def getAvailability(self, state, **kw):
1100 import Availability 1101 allowedFilters = ( 1102 "device", "component", "eventClass", "systems", "severity", 1103 "prodState", "manager", "agent", "DeviceClass", "Location", 1104 "System", "DeviceGroup", "DevicePriority", "monitor") 1105 1106 for name in allowedFilters: 1107 if hasattr(state, name): 1108 kw.setdefault(name, getattr(state, name)) 1109 if getattr(state, 'startDate', None) is not None: 1110 kw.setdefault('startDate', Time.ParseUSDate(state.startDate)) 1111 if getattr(state, 'endDate', None) is not None: 1112 # End date needs to be inclusive of events that occurred on that 1113 # date. So we advance to the last second of the day. 1114 kw.setdefault('endDate', Time.getEndOfDay(Time.ParseUSDate( 1115 state.endDate))) 1116 kw.setdefault('startDate', 1117 time.time() - 60*60*24*self.defaultAvailabilityDays) 1118 return Availability.query(self.dmd, **kw)
1119 1120
1121 - def getHeartbeat(self, failures=True, simple=False, limit=0, db=None):
1122 """Return all heartbeat issues list of tuples (device, component, secs) 1123 """ 1124 sel = "select device, component, lastTime from heartbeat" 1125 if failures: 1126 sel += " where DATE_ADD(lastTime, INTERVAL timeout SECOND) <= NOW()" 1127 1128 statuses = [] 1129 conn = self.connect() 1130 try: 1131 curs = conn.cursor() 1132 curs.execute(sel) 1133 res = list(curs.fetchall()) 1134 res.sort(lambda x,y: cmp(x[2],y[2])) 1135 devclass = self.getDmdRoot("Devices") 1136 for devname, comp, lastTime in res: 1137 dtime = int(time.time() - lastTime.timeTime()) 1138 1139 alink = devname 1140 if not simple: 1141 dev = devclass.findDevice(devname) 1142 if dev: 1143 alink = "<a href='%s'>%s</a>" % ( 1144 dev.getPrimaryUrlPath(), dev.titleOrId()) 1145 1146 statuses.append([alink, comp, str(dtime), devname]) 1147 if limit: 1148 statuses = statuses[:limit] 1149 finally: 1150 self.close(conn) 1151 return statuses
1152
1153 - def getHeartbeatObjects(self, failures=True, simple=False, limit=0, db=None):
1154 beats = self.getHeartbeat(failures, simple, limit, db) 1155 return [{'alink':b[0], 'comp':b[1], 'dtime':b[2], 'devId':b[3]} 1156 for b in beats]
1157 1158
1159 - def getAllComponentStatus(self, 1160 statclass, 1161 countField=None, 1162 severity=3, 1163 state=1, 1164 where=""):
1165 "Fetch the counts on all components matching statClass" 1166 if countField == None: countField = self.countField 1167 select = "select %s, %s, %s from %s where "\ 1168 % (self.deviceField, self.componentField, countField, 1169 self.statusTable) 1170 where = self._wand(where, "%s = '%s'", self.eventClassField, statclass) 1171 where = self._wand(where, "%s >= %s", self.severityField, severity) 1172 where = self._wand(where, "%s <= %s", self.stateField, state) 1173 select += where 1174 conn = self.connect() 1175 try: 1176 curs = conn.cursor() 1177 curs.execute(select) 1178 result = {} 1179 for dev, comp, count in curs.fetchall(): 1180 dev = self.cleanstring(dev) 1181 comp = self.cleanstring(comp) 1182 result[dev,comp] = count 1183 return result 1184 finally: 1185 self.close(conn)
1186 1187
1188 - def getMaxSeverity(self, me):
1189 """ Returns the severity of the most severe event. """ 1190 where = self.lookupManagedEntityWhere(me.device()) 1191 if me.event_key == 'Component': 1192 where = self._wand(where, "%s = '%s'", 1193 self.componentField, me.id) 1194 select = "select max(%s) from %s where " % (self.severityField, 1195 self.statusTable) 1196 query = select + where 1197 conn = self.connect() 1198 try: 1199 curs = conn.cursor() 1200 curs.execute(query) 1201 severity = curs.fetchall()[0][0] 1202 finally: self.close(conn) 1203 return max(severity, 0)
1204 1205
1206 - def getComponentStatus(self, device, component, statclass=None, 1207 countField=None, severity=3, state=1, where=""):
1208 """see IEventStatus 1209 """ 1210 if countField == None: countField = self.countField 1211 select = "select %s, %s, %s from %s where "\ 1212 % (self.deviceField, self.componentField, countField, 1213 self.statusTable) 1214 where = self._wand(where, "%s = '%s'", self.eventClassField, statclass) 1215 where = self._wand(where, "%s >= %s", self.severityField, severity) 1216 where = self._wand(where, "%s <= %s", self.stateField, state) 1217 select += where 1218 statusCache = self.checkCache(select) 1219 if not statusCache: 1220 conn = self.connect() 1221 try: 1222 curs = conn.cursor() 1223 curs.execute(select) 1224 statusCache ={} 1225 for dev, comp, count in curs.fetchall(): 1226 dev = self.cleanstring(dev) 1227 comp = self.cleanstring(comp) 1228 statusCache[dev+comp] = count 1229 self.addToCache(select,statusCache) 1230 finally: self.close(conn) 1231 return statusCache.get(device+component, 0)
1232
1233 - def getBatchComponentInfo(self, components):
1234 """ 1235 Given a list of dicts with keys 'device', 'component', make a query to 1236 get an overall severity and device status for the group. 1237 """ 1238 severity, state = 3, 1 1239 components = list(components) # Sometimes a generator. We use it twice. 1240 1241 def doQuery(query): 1242 conn = self.connect() 1243 data = None 1244 try: 1245 curs = conn.cursor() 1246 curs.execute(query) 1247 data = curs.fetchall() 1248 finally: self.close(conn) 1249 return data
1250 1251 select = "select MAX(%s) from %s where " % (self.severityField, 1252 self.statusTable) 1253 where = self._wand("", "%s >= %s", self.severityField, severity) 1254 where = self._wand(where, "%s <= %s", self.stateField, state) 1255 def componentWhere(device, component): 1256 return "device = '%s' and component= '%s'" % (device, component) 1257 cwheres = ' and ' + ' or '.join(['(%s)'% componentWhere(**comp) 1258 for comp in components]) 1259 sevquery = select + where + cwheres 1260 1261 select = "select MAX(%s) from %s where " % (self.countField, 1262 self.statusTable) 1263 where = self._wand("", "%s >= %s", self.severityField, severity) 1264 where = self._wand(where, "%s <= %s", self.stateField, state) 1265 where = self._wand(where, "%s = '%s'", self.eventClassField, 1266 '/Status/Ping') 1267 devwhere = lambda d:"device = '%s'" % d 1268 dwheres = ' and ' + '(%s)' % (' or '.join( 1269 map(devwhere, [x['device'] for x in components]))) 1270 statquery = select + where + dwheres 1271 1272 maxseverity = doQuery(sevquery)[0][0] 1273 maxstatus = doQuery(statquery)[0][0] 1274 return maxseverity, maxstatus 1275
1276 - def getEventOwnerListME(self, me, severity=0, state=1):
1277 """Return list of event owners based on passed in managed entity. 1278 """ 1279 try: 1280 where = self.lookupManagedEntityWhere(me) 1281 return self.getEventOwnerList(where, severity, state) 1282 except: 1283 log.exception("event summary for %s failed" % me.getDmdKey()) 1284 raise
1285 1286
1287 - def getEventOwnerList(self, where="", severity=0, state=1):
1288 """Return a list of userids that correspond to the events in where. 1289 select distinct ownerid from status where 1290 device="win2k.confmon.loc" and eventState > 2 1291 """ 1292 select ="select distinct ownerid from status where " 1293 where = self._wand(where, "%s >= %s", self.severityField, severity) 1294 where = self._wand(where, "%s <= %s", self.stateField, state) 1295 select += where 1296 #print select 1297 statusCache = self.checkCache(select) 1298 if statusCache: return statusCache 1299 conn = self.connect() 1300 try: 1301 curs = conn.cursor() 1302 curs.execute(select) 1303 statusCache = [ uid[0] for uid in curs.fetchall() if uid[0] ] 1304 self.addToCache(select,statusCache) 1305 finally: self.close(conn) 1306 return statusCache
1307 1308
1309 - def lookupManagedEntityWhere(self, me):
1310 """ 1311 Lookup and build where clause for managed entity. 1312 1313 @param me: managed entity 1314 @type me: object 1315 @return: where clause 1316 @rtype: string 1317 """ 1318 key = me.event_key + "Where" 1319 wheretmpl = getattr(aq_base(self), key, False) 1320 if not wheretmpl: 1321 raise ValueError("No 'where' clause found for event_key %s" % me.event_key) 1322 1323 # This code snippet is meant to fake out the where requirement 1324 # We want no filter on the device so in effect "where 1" achieves 1325 # this in sql syntax 1326 if me.id == 'Devices': 1327 return '(DeviceCLass like \'/%\')' 1328 return eval(wheretmpl,{'me':me})
1329 1330
1331 - def lookupManagedEntityField(self, event_key):
1332 """ 1333 Lookup database field for managed entity default 1334 using event_key. 1335 1336 @param event_key: event 1337 @type event_key: string 1338 @return: field for the managed entity 1339 @rtype: object 1340 """ 1341 key = event_key + "Field" 1342 return getattr(aq_base(self), key, event_key)
1343 1344
1345 - def lookupManagedEntityResultFields(self, event_key):
1346 """ 1347 Gets the column names that should be requested in an event query for 1348 this entity type. 1349 1350 Returns a set of result fields predefined for this entity type. If 1351 none have been defined, returns the default result fields. 1352 1353 >>> f = dmd.ZenEventManager.lookupManagedEntityResultFields('Device') 1354 >>> f==dmd.ZenEventManager.DeviceResultFields 1355 True 1356 >>> f = dmd.ZenEventManager.lookupManagedEntityResultFields('Robot') 1357 >>> f==dmd.ZenEventManager.defaultResultFields 1358 True 1359 1360 @param event_key: The event key of a managed entity. 1361 @type event_key: string 1362 @return: A tuple of strings representing columns in the database. 1363 """ 1364 key = event_key + "ResultFields" 1365 fields = getattr(aq_base(self), key, self.defaultResultFields) 1366 return fields
1367 1368
1369 - def _wand(self, where, fmt, field, value):
1370 """ 1371 >>> dmd.ZenEventManager._wand('where 1=1', '%s=%s', 'a', 'b') 1372 'where 1=1 and a=b' 1373 >>> dmd.ZenEventManager._wand('where a=5', '%s=%s', 'a', 'b') 1374 'where a=5' 1375 >>> dmd.ZenEventManager._wand('where b=a', '%s=%s', 'a', 'b') 1376 'where b=a' 1377 """ 1378 if value != None and where.find(field) == -1: 1379 if where: where += " and " 1380 where += fmt % (field, value) 1381 return where
1382
1383 - def _setupDateRange(self, startdate=None, 1384 enddate=None):
1385 """ 1386 Make a start and end date range that is at least one day long. 1387 returns a start and end date as a proper database element. 1388 """ 1389 if enddate is None: 1390 enddate = DateTime.DateTime()-1 1391 if startdate is None: 1392 startdate = DateTime.DateTime() 1393 if type(enddate) == types.StringType: 1394 enddate = DateTime.DateTime(enddate, datefmt='us') 1395 enddate = enddate.latestTime() 1396 if type(startdate) == types.StringType: 1397 startdate = DateTime.DateTime(startdate, datefmt='us') 1398 startdate = startdate.earliestTime() 1399 startdate = self.dateDB(startdate) 1400 enddate = self.dateDB(enddate) 1401 return startdate, enddate
1402
1403 - def _scrubOrderby(self, orderby):
1404 """ 1405 validates the syntax and columns for an orderby used on the status and 1406 history tables. Also removes adjacent sorts of the same columns as an 1407 optimization 1408 @return: orderby by clause 1409 @raise exception: if order by clause is invalid 1410 """ 1411 sortValues = [] 1412 prevSortCol = None 1413 fieldList = [x.lower() for x in self.getFieldList()] 1414 log.debug("orderby is %s" % orderby) 1415 for x in orderby.split(','): 1416 col, dir = x.split() 1417 col = col.lower() 1418 dir = dir.upper() 1419 if dir not in ['DESC','ASC'] or col not in fieldList: 1420 raise ("order by value %s %s not valid" % (col, dir)) 1421 #remove adjacent sorts of same column; 1422 if not prevSortCol or prevSortCol != col: 1423 sortValues.append((col, dir)) 1424 prevSortCol = col 1425 1426 orderby = ', '.join([' '.join(x) for x in sortValues]) 1427 1428 log.debug("final orderby is %s" % orderby) 1429 return orderby
1430
1431 - def getAvgFieldLength(self, fieldname):
1432 conn = self.connect() 1433 try: 1434 curs = conn.cursor() 1435 selstatement = ("SELECT AVG(CHAR_LENGTH(mycol))+20 FROM (SELECT %s AS " 1436 "mycol FROM %s WHERE %s IS NOT NULL LIMIT 500) AS " 1437 "a;") % (fieldname, self.statusTable, fieldname) 1438 curs.execute(selstatement) 1439 avglen = curs.fetchone() 1440 finally: self.close(conn) 1441 try: return float(avglen[0]) 1442 except TypeError: return 10.
1443 1444 1445 #========================================================================== 1446 # Event sending functions 1447 #========================================================================== 1448 1449 security.declareProtected(ZEN_SEND_EVENTS, 'sendEvents')
1450 - def sendEvents(self, events):
1451 """Send a group of events to the backend. 1452 """ 1453 count = 0 1454 for event in events: 1455 try: 1456 self.sendEvent(event) 1457 count += 1 1458 except Exception, ex: 1459 log.exception(ex) 1460 return count
1461 1462 1463 security.declareProtected(ZEN_SEND_EVENTS, 'sendEvent')
1464 - def sendEvent(self, event):
1465 """ 1466 Send an event to the backend. 1467 1468 @param event: event 1469 @type event: event object 1470 @todo: implement 1471 """ 1472 raise NotImplementedError
1473 1474 1475 #========================================================================== 1476 # Schema management functions 1477 #========================================================================== 1478
1479 - def convert(self, field, value):
1480 """Perform convertion of value coming from database value if nessesary. 1481 """ 1482 value = self.cleanstring(value) 1483 #FIXME this is commented out because we often need severity as a 1484 # number (like in ZEvent.getCssClass) and sorting. Need to have 1485 # both fields at some point 1486 #if field == self.severityField: 1487 # idx = len(self.severityConversions) - value 1488 # value = self.severityConversions[idx][0] 1489 #elif field == 'prodState': 1490 # value = self.dmd.convertProdState(value) 1491 if self.isDate(field): 1492 value = self.dateString(value) 1493 return value
1494 1495 1496 security.declareProtected(ZEN_VIEW, "getFieldList")
1497 - def getFieldList(self):
1498 """Return a list of all fields in the status table of the backend. 1499 """ 1500 if not getattr(self, '_fieldlist', None): 1501 self.loadSchema() 1502 return self._fieldlist
1503
1504 - def getEventStates(self):
1505 """Return a list of possible event states. 1506 """ 1507 return self.eventStateConversions
1508
1509 - def getEventActions(self):
1510 """Return a list of possible event actions. 1511 """ 1512 return self.eventActions
1513 1514 security.declareProtected(ZEN_COMMON,'getSeverities')
1515 - def getSeverities(self):
1516 """Return a list of tuples of severities [('Warning', 3), ...] 1517 """ 1518 return self.severityConversions
1519
1520 - def getSeverityString(self, severity):
1521 """Return a string representation of the severity. 1522 """ 1523 try: 1524 return self.severities[severity] 1525 except KeyError: 1526 return "Unknown"
1527
1528 - def getPriorities(self):
1529 """Return a list of tuples of priorities [('Warning', 3), ...] 1530 """ 1531 return self.priorityConversions
1532
1533 - def getPriorityString(self, priority):
1534 """Return the priority name 1535 """ 1536 try: 1537 return self.priorities[priority] 1538 except IndexError: 1539 return "Unknown"
1540
1541 - def convertEventField(self, field, value, default=""):
1542 """ 1543 Convert numeric values commonly found in events to their textual 1544 representation. 1545 """ 1546 if value is None: return default 1547 try: 1548 value = int(value) 1549 except ValueError: 1550 return "unknown (%r)" % (value,) 1551 1552 if field == 'severity' and self.severities.has_key(value): 1553 return "%s (%d)" % (self.severities[value], value) 1554 elif field == "priority" and self.priorities.has_key(value): 1555 return "%s (%d)" % (self.priorities[value], value) 1556 elif field == 'eventState': 1557 if value < len(self.eventStateConversions): 1558 return "%s (%d)" % (self.eventStateConversions[value][0], value) 1559 elif field == "prodState": 1560 prodState = self.dmd.convertProdState(value) 1561 if isinstance(prodState, types.StringType): 1562 return "%s (%d)" % (prodState, value) 1563 elif field == "DevicePriority": 1564 priority = self.dmd.convertPriority(value) 1565 if isinstance(priority, types.StringType): 1566 return "%s (%d)" % (priority, value) 1567 1568 return "unknown (%r)" % (value,)
1569 1570
1571 - def getStatusCssClass(self, status):
1572 if status < 0: status = "unknown" 1573 elif status > 3: status = 3 1574 return "zenstatus_%s" % status
1575 1576
1577 - def getStatusImgSrc(self, status):
1578 ''' Return the img source for a status number 1579 ''' 1580 if status < 0: 1581 src = 'grey' 1582 elif status == 0: 1583 src = 'green' 1584 else: 1585 src = 'red' 1586 return '/zport/dmd/img/%s_dot.png' % src
1587 1588
1589 - def getEventCssClass(self, severity, acked=False):
1590 """return the css class name to be used for this event. 1591 """ 1592 __pychecker__='no-constCond' 1593 value = severity < 0 and "unknown" or severity 1594 acked = acked and "acked" or "noack" 1595 return "zenevents_%s_%s %s" % (value, acked, acked)
1596 1597
1598 - def isDate(self, colName):
1599 """Check to see if a column is of type date. 1600 """ 1601 if not self._schema: 1602 self.getFieldList() 1603 return self._schema.get(colName, False)
1604 1605
1606 - def dateString(self, value):
1607 """Convert a date from database format to string. 1608 """ 1609 if isinstance(value, DateTime.DateTime): 1610 value = value.timeTime() 1611 return Time.LocalDateTime(value)
1612 1613 1614
1615 - def dateDB(self, value):
1616 """Convert a date to its database format. 1617 """ 1618 if isinstance(value, DateTime.DateTime): 1619 return "%.3f" % value.timeTime() 1620 elif isinstance(value, basestring): 1621 return "%.3f" % DateTime.DateTime(value).timeTime() 1622 return value
1623 1624
1625 - def escape(self, value):
1626 """ 1627 Prepare string values for db by escaping special characters. 1628 1629 @param value: string 1630 @type value: string 1631 @todo: implement 1632 """ 1633 raise NotImplementedError
1634 1635
1636 - def loadSchema(self):
1637 """Load schema from database. If field is a date set value to true.""" 1638 schema = {} 1639 fieldlist = [] 1640 sql = "describe %s;" % self.statusTable 1641 conn = self.connect() 1642 try: 1643 curs = conn.cursor() 1644 curs.execute(sql) 1645 for row in curs.fetchall(): 1646 fieldlist.append(row[0]) 1647 col = self.cleanstring(row[0]) 1648 if self.backend == "mysql": 1649 type = row[1] in ("datetime", "timestamp", "double") 1650 schema[col] = type 1651 if schema: self._schema = schema 1652 self._fieldlist = fieldlist 1653 finally: self.close(conn)
1654 1655
1656 - def eventControls(self):
1657 """Are there event controls on this event list. 1658 """ 1659 if self.isManager() and self.statusTable in ["status","history"]: 1660 return 1 1661 return 0
1662
1663 - def updateEvents(self, stmt, whereClause, reason, 1664 table="status", toLog=True):
1665 userId = getSecurityManager().getUser().getId() 1666 insert = 'INSERT INTO log (evid, userName, text) ' + \ 1667 'SELECT evid, "%s", "%s" ' % (userId, reason) + \ 1668 'FROM %s ' % table + whereClause 1669 query = stmt + ' ' + whereClause 1670 conn = self.connect() 1671 try: 1672 curs = conn.cursor() 1673 if toLog: curs.execute(insert) 1674 curs.execute(query) 1675 finally: self.close(conn) 1676 self.clearCache() 1677 self.manage_clearCache()
1678 1679 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_addEvent')
1680 - def manage_addEvent(self, REQUEST=None):
1681 ''' Create an event from user supplied data 1682 ''' 1683 if REQUEST is None: 1684 return 1685 1686 defaultFields = set(self.dmd.ZenEventManager.getFieldList()) 1687 ignoreFields = set(['eventClass', 'count', 'clearid', 1688 'clearid', 'eventClassMapping', 'stateChange', 'evid', 1689 'eventState', 'lastTime', 'dedupid', 'firstTime', 'prodState', ]) 1690 eventDict = dict([(field, REQUEST.get(field, '')) \ 1691 for field in defaultFields - ignoreFields ]) 1692 1693 # We don't want to put empty eventClass into the dict because that 1694 # can keep the event from being mapped to /Unknown correctly. 1695 if REQUEST.get('eventClass', None): 1696 eventDict['eventClass'] = REQUEST['eventClass'] 1697 1698 try: 1699 evid = self.sendEvent(eventDict) 1700 except ZenEventError, ex: 1701 log.exception("Invalid event not processed = %s" % eventDict) 1702 messaging.IMessageSender(self).sendToBrowser( 1703 'Invalid Event', str(ex), 1704 priority=messaging.WARNING 1705 ) 1706 return self.callZenScreen(REQUEST) 1707 except ZenBackendFailure, ex: 1708 log.exception("Event not processed = %s" % eventDict) 1709 messaging.IMessageSender(self).sendToBrowser( 1710 'Unable to process Event', str(ex), 1711 priority=messaging.WARNING 1712 ) 1713 return self.callZenScreen(REQUEST) 1714 1715 if 'RESPONSE' in REQUEST: 1716 REQUEST['RESPONSE'].redirect('/zport/dmd/Events/viewEvents') 1717 else: 1718 return evid
1719 1720
1721 - def deleteEvents(self, whereClause, reason):
1722 self.updateEvents('DELETE FROM status', whereClause, reason)
1723 1724 1725 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_deleteEvents')
1726 - def manage_deleteEvents(self, evids=(), REQUEST=None):
1727 "Delete the given event ids" 1728 if type(evids) == type(''): 1729 evids = [evids] 1730 num = len(evids) 1731 if evids: 1732 evids = ",".join([ "'%s'" % evid for evid in evids]) 1733 userid = getSecurityManager().getUser() 1734 update = "update status set ownerid='%s' " % userid 1735 whereClause = ' where evid in (%s)' % evids 1736 self.updateEvents(update, whereClause, '', toLog=False) 1737 self.deleteEvents(whereClause, 'Deleted by user') 1738 if REQUEST: 1739 messaging.IMessageSender(self).sendToBrowser( 1740 'Moved To History', 1741 '%s event%s have been moved to history.' % ( 1742 num, (num != 1 and 's') or '') 1743 ) 1744 return self.callZenScreen(REQUEST)
1745
1746 - def undeleteEvents(self, whereClause, reason):
1747 fields = self.getFieldList() 1748 if 'deletedTime' in fields: 1749 fields.remove('deletedTime') 1750 fields = ','.join(fields) 1751 # Blank out clearid 1752 fields = fields.replace('clearid','NULL') 1753 evmgr = self.dmd.ZenEventManager 1754 evmgr.updateEvents('INSERT status ' + \ 1755 'SELECT %s FROM history' % fields, 1756 whereClause + ' ON DUPLICATE KEY UPDATE '+ 1757 'status.count=status.count+history.count', 1758 reason, 'history', toLog=False) 1759 evmgr.updateEvents('DELETE FROM history', whereClause, \ 1760 reason, 'history')
1761 1762 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_undeleteEvents')
1763 - def manage_undeleteEvents(self, evids=(), REQUEST=None):
1764 "Move the given event ids into status and delete from history" 1765 if type(evids) == type(''): 1766 evids = [evids] 1767 num = len(evids) 1768 if evids: 1769 evids = ",".join([ "'%s'" % evid for evid in evids]) 1770 whereClause = ' where evid in (%s)' % evids 1771 self.undeleteEvents(whereClause, 'Undeleted by user') 1772 if REQUEST: 1773 messaging.IMessageSender(self).sendToBrowser( 1774 'Undeleted', 1775 '%s events have been moved out of history.' % num 1776 ) 1777 return self.callZenScreen(REQUEST)
1778 1779 1780 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_deleteAllEvents')
1781 - def manage_deleteAllEvents(self, devname, REQUEST=None):
1782 "Delete the events for a given Device (used for deleting the device" 1783 whereClause = 'where device = "%s"' % devname 1784 self.deleteEvents(whereClause, 'Device deleted') 1785 if REQUEST: 1786 messaging.IMessageSender(self).sendToBrowser( 1787 'Events Deleted', 1788 'Deleted all events for %s' % devname 1789 ) 1790 return self.callZenScreen(REQUEST)
1791 1792 1793 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_deleteHistoricalEvents')
1794 - def manage_deleteHistoricalEvents(self, devname=None, agedDays=None, 1795 REQUEST=None):
1796 """ 1797 Delete historical events. If devices is given then only delete 1798 events for that device. If agedDays is given then only delete 1799 events that are older than that many days. 1800 devname and agedDays are mutually exclusive. No real reason for this 1801 other than there is no current need to use both in same call and I 1802 don't want to test the combination. 1803 This is an option during device deletion. It is also used 1804 by zenactions to keep history table clean. 1805 1806 NB: Device.deleteDevice() is not currently calling this when devices 1807 are deleted. See ticket #2996. 1808 """ 1809 import subprocess 1810 import os 1811 import Products.ZenUtils.Utils as Utils 1812 1813 cmd = Utils.zenPath('Products', 'ZenUtils', 'ZenDeleteHistory.py') 1814 if devname: 1815 args = ['--device=%s' % devname] 1816 elif agedDays: 1817 args = ['--numDays=%s' % agedDays] 1818 else: 1819 return 1820 proc = subprocess.Popen( 1821 [cmd]+args, stdout=subprocess.PIPE, 1822 stderr=subprocess.STDOUT, env=os.environ) 1823 # We are abandoning this proc to do it's thing. or not. We don't 1824 # want to block because we would delay user feedback on a device 1825 # delete when this might take a while to perform. 1826 if REQUEST: 1827 messaging.IMessageSender(self).sendToBrowser( 1828 'Events Deleted', 1829 'Historical events have been deleted.' 1830 ) 1831 return self.callZenScreen(REQUEST) 1832 else: 1833 # Maybe, just maybe, we might want to wait on the subprocess... 1834 return proc
1835 1836 1837 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_deleteHeartbeat')
1838 - def manage_deleteHeartbeat(self, devname, REQUEST=None):
1839 if devname: 1840 delete = "delete from heartbeat where device = '%s'" % devname 1841 conn = self.connect() 1842 try: 1843 curs = conn.cursor() 1844 curs.execute(delete); 1845 finally: self.close(conn) 1846 if REQUEST: 1847 messaging.IMessageSender(self).sendToBrowser( 1848 'Heartbeats Cleared', 1849 'Heartbeat events have been moved to the history.' 1850 ) 1851 return self.callZenScreen(REQUEST)
1852 1853 1854 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_ackEvents')
1855 - def manage_ackEvents(self, evids=(), REQUEST=None):
1856 "Ack the given event ids" 1857 if type(evids) == type(''): 1858 evids = [evids] 1859 request = FakeRequest() 1860 self.manage_setEventStates(1 , evids, REQUEST=request) 1861 if REQUEST: 1862 dest = '/zport/dmd/Events/evconsole' 1863 if request.get('message', ''): 1864 dest += '?message=%s' % request['message'] 1865 if not getattr(REQUEST, 'dontRedirect', False): 1866 REQUEST['RESPONSE'].redirect(dest)
1867 1868 1869 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_ackEvents')
1870 - def manage_unackEvents(self, evids=(), REQUEST=None):
1871 "Unacknowledge the given event ids" 1872 if type(evids) == type(''): 1873 evids = [evids] 1874 request = FakeRequest() 1875 self.manage_setEventStates(0 , evids, REQUEST=request) 1876 if REQUEST: 1877 dest = '/zport/dmd/Events/evconsole' 1878 if request.get('message', ''): 1879 dest += '?message=%s' % request['message'] 1880 if not getattr(REQUEST, 'dontRedirect', False): 1881 REQUEST['RESPONSE'].redirect(dest)
1882 1883 1884 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_setEventStates')
1885 - def manage_setEventStates(self, eventState=None, evids=(), 1886 userid="", REQUEST=None):
1887 reason = None 1888 if eventState is not None and evids: 1889 eventState = int(eventState) 1890 if eventState > 0 and not userid: 1891 userid = getSecurityManager().getUser().getId() 1892 update = "update status set eventState=%s, ownerid='%s' " % ( 1893 eventState, userid) 1894 whereClause = "where evid in (" 1895 whereClause += ",".join([ "'%s'" % evid for evid in evids]) + ")" 1896 reason = 'Event state changed to ' 1897 try: 1898 reason += self.eventStateConversions[eventState][0] 1899 except KeyError: 1900 reason += 'unknown (%d)' % eventState 1901 self.updateEvents(update, whereClause, reason) 1902 if REQUEST: 1903 return self.callZenScreen(REQUEST)
1904 1905 1906 security.declareProtected(ZEN_MANAGE_EVENTS,'manage_setEventStates')
1907 - def manage_createEventMap(self, eventClass=None, evids=(), 1908 REQUEST=None):
1909 """Create an event map from an event or list of events. 1910 """ 1911 evclass = None 1912 evmap = None 1913 numCreated = 0 1914 numNotUnknown = 0 1915 numNoKey = 0 1916 if eventClass and evids: 1917 evclass = self.getDmdRoot("Events").getOrganizer(eventClass) 1918 sel = """select eventClassKey, eventClass, message 1919 from %s where evid in ('%s')""" 1920 sel = sel % (self.statusTable, "','".join(evids)) 1921 conn = self.connect() 1922 try: 1923 curs = conn.cursor() 1924 curs.execute(sel); 1925 for row in curs.fetchall(): 1926 evclasskey, curevclass, msg = row 1927 if curevclass != Unknown: 1928 numNotUnknown += 1 1929 continue 1930 if not evclasskey: 1931 numNoKey += 1 1932 continue 1933 evmap = evclass.createInstance(evclasskey) 1934 evmap.eventClassKey = evclasskey 1935 evmap.example = msg 1936 numCreated += 1 1937 evmap.index_object() 1938 finally: self.close(conn) 1939 elif REQUEST: 1940 if not evids: 1941 messaging.IMessageSender(self).sendToBrowser( 1942 'Error', 1943 'No events selected', 1944 priority=messaging.WARNING 1945 ) 1946 elif not eventClass: 1947 messaging.IMessageSender(self).sendToBrowser( 1948 'Error', 1949 'No event class selected', 1950 priority=messaging.WARNING 1951 ) 1952 1953 msg = '' 1954 if numNotUnknown: 1955 msg += ((msg and ' ') + 1956 '%s event%s %s not class /Unknown.' % ( 1957 numNotUnknown, 1958 (numNotUnknown != 1 and 's') or '', 1959 (numNotUnknown != 1 and 'are') or 'is')) 1960 if numNoKey: 1961 msg += ((msg and ' ') + 1962 '%s event%s %s not have an event class key.' % ( 1963 numNoKey, 1964 (numNoKey != 1 and 's') or '', 1965 (numNoKey != 1 and 'do') or 'does')) 1966 msg += (msg and ' ') + 'Created %s event mapping%s.' % ( 1967 numCreated, 1968 (numCreated != 1 and 's') or '') 1969 1970 url = None 1971 if len(evids) == 1 and evmap: 1972 url = evmap.absolute_url() 1973 elif evclass and evmap: 1974 url = evclass.absolute_url() 1975 1976 if REQUEST: 1977 msg = REQUEST.get('message', '') + msg 1978 1979 messaging.IMessageSender(self).sendToBrowser('Event Map', msg) 1980 # EventView might pass a fake Request during an ajax call from 1981 # event console. Don't bother rendering anything in this case. 1982 if getattr(REQUEST, 'dontRender', False): 1983 return '' 1984 if url: 1985 REQUEST['RESPONSE'].redirect(url) 1986 else: 1987 return msg, url
1988 1989 1990 security.declareProtected(ZEN_MANAGE_EVENTMANAGER,'manage_refreshConversions')
1991 - def manage_refreshConversions(self, REQUEST=None):
1992 """get the conversion information from the database server""" 1993 assert(self == self.dmd.ZenEventManager) 1994 self.loadSchema() 1995 self.dmd.ZenEventHistory.loadSchema() 1996 if REQUEST: 1997 messaging.IMessageSender(self).sendToBrowser( 1998 'Event Schema', 'Event schema has been refreshed.') 1999 return self.callZenScreen(REQUEST)
2000 2001 2002 security.declareProtected(ZEN_MANAGE_EVENTMANAGER,'manage_editCache')
2003 - def manage_editCache(self, timeout=5, clearthresh=20, REQUEST=None):
2004 """Reset cache values""" 2005 self.timeout = int(timeout) 2006 self.clearthresh = int(clearthresh) 2007 if REQUEST: 2008 message = "Cache parameters set" 2009 return self.editCache(self, REQUEST, manage_tabs_message=message)
2010 2011 2012 security.declareProtected(ZEN_MANAGE_EVENTMANAGER,'manage_clearCache')
2013 - def manage_clearCache(self, REQUEST=None):
2014 """Reset cache values""" 2015 assert(self == self.dmd.ZenEventManager) 2016 self.cleanCache(force=1) 2017 self.dmd.ZenEventHistory.cleanCache(force=1) 2018 if REQUEST: 2019 messaging.IMessageSender(self).sendToBrowser( 2020 'Event Cache', 'Event cache has been cleared.') 2021 return self.callZenScreen(REQUEST)
2022 2023 2024 security.declareProtected(ZEN_MANAGE_EVENTMANAGER,'manage_editEventManager')
2025 - def manage_editEventManager(self, REQUEST=None):
2026 ''' Call zmanage_editProperties then take care of saving a few 2027 values to ZenEventHistory 2028 ''' 2029 assert(self == self.dmd.ZenEventManager) 2030 self.zmanage_editProperties(REQUEST) 2031 self.dmd.ZenEventHistory.timeout = REQUEST['history_timeout'] 2032 self.dmd.ZenEventHistory.clearthresh = REQUEST['history_clearthresh'] 2033 self.dmd.ZenEventHistory.username = self.dmd.ZenEventManager.username 2034 self.dmd.ZenEventHistory.password = self.dmd.ZenEventManager.password 2035 self.dmd.ZenEventHistory.database = self.dmd.ZenEventManager.database 2036 self.dmd.ZenEventHistory.host = self.dmd.ZenEventManager.host 2037 self.dmd.ZenEventHistory.port = self.dmd.ZenEventManager.port 2038 if REQUEST: return self.callZenScreen(REQUEST)
2039 2040 2041 security.declareProtected(ZEN_MANAGE_EVENTMANAGER,'manage_clearHeartbeats')
2042 - def manage_clearHeartbeats(self, REQUEST=None):
2043 """truncate heartbeat table""" 2044 conn = self.connect() 2045 try: 2046 curs = conn.cursor() 2047 sql = 'truncate table heartbeat' 2048 curs.execute(sql) 2049 finally: self.close(conn) 2050 if REQUEST: 2051 messaging.IMessageSender(self).sendToBrowser( 2052 'Heartbeats Cleared', 'Heartbeats have been cleared.') 2053 return self.callZenScreen(REQUEST)
2054 2055 security.declareProtected(ZEN_MANAGE_EVENTMANAGER,'zmanage_editProperties')
2056 - def zmanage_editProperties(self, REQUEST=None):
2057 ''' Need to handle editing of history event fields differently 2058 ''' 2059 assert(self == self.dmd.ZenEventManager) 2060 screenName = REQUEST.get('zenScreenName', '') 2061 if screenName.find('editEventManagerHistoryFields') != -1 : 2062 obj = self.dmd.ZenEventHistory 2063 else: 2064 obj = self 2065 if screenName == 'editEventManager.pt': 2066 # We renamed the password field to try to keep browsers from 2067 # asking user if they wanted to save the password. 2068 if REQUEST.has_key('mysql_pass'): 2069 REQUEST.form['password'] = REQUEST['mysql_pass'] 2070 editProperties = ZenModelRM.zmanage_editProperties 2071 # suppress 'self is not first method argument' from pychecker 2072 editProperties(obj, REQUEST) 2073 if REQUEST: return self.callZenScreen(REQUEST)
2074 2075 security.declareProtected(ZEN_MANAGE_EVENTS, 'manage_addLogMessage')
2076 - def manage_addLogMessage(self, evid=None, message='', REQUEST=None):
2077 """ 2078 Add a log message to an event 2079 """ 2080 if not evid: 2081 return 2082 userId = getSecurityManager().getUser().getId() 2083 conn = self.connect() 2084 try: 2085 curs = conn.cursor() 2086 insert = 'INSERT INTO log (evid, userName, text) ' 2087 insert += 'VALUES ("%s", "%s", "%s")' % (evid, 2088 userId, 2089 conn.escape_string(message)) 2090 curs.execute(insert) 2091 finally: self.close(conn) 2092 self.clearCache('evid' + evid) 2093 self.dmd.ZenEventHistory.clearCache('evid' + evid) 2094 if REQUEST: return self.callZenScreen(REQUEST)
2095 2096 2097 security.declareProtected(ZEN_MANAGE_EVENTMANAGER, 'manage_addCommand')
2098 - def manage_addCommand(self, id, REQUEST=None):
2099 """ 2100 Add a new EventCommand 2101 2102 @param id: new command name 2103 @type id: string 2104 @param REQUEST: Zope REQUEST object 2105 @type REQUEST: Zope REQUEST object 2106 """ 2107 if id is None: 2108 if REQUEST: 2109 return self.callZenScreen(REQUEST) 2110 return 2111 2112 if not isinstance(id, unicode): 2113 id = self.prepId(id) 2114 2115 id = id.strip() 2116 if id == '': 2117 if REQUEST: 2118 return self.callZenScreen(REQUEST) 2119 return 2120 2121 ec = EventCommand(id) 2122 self.commands._setObject(id, ec) 2123 if REQUEST: 2124 return self.callZenScreen(REQUEST)
2125 2126 2127 security.declareProtected(ZEN_MANAGE_EVENTMANAGER, 'manage_deleteCommands')
2128 - def manage_deleteCommands(self, ids=[], REQUEST=None):
2129 """ 2130 Delete an EventCommand 2131 2132 @param ids: commands to delete 2133 @type ids: list of strings 2134 @param REQUEST: Zope REQUEST object 2135 @type REQUEST: Zope REQUEST object 2136 """ 2137 for id in ids: 2138 self.commands._delObject(id) 2139 if REQUEST: return self.callZenScreen(REQUEST)
2140 2141 2142 #========================================================================== 2143 # Utility functions 2144 #========================================================================== 2145
2146 - def installIntoPortal(self):
2147 """Install skins into portal. 2148 """ 2149 from Products.CMFCore.utils import getToolByName 2150 from Products.CMFCore.DirectoryView import addDirectoryViews 2151 from cStringIO import StringIO 2152 import string 2153 2154 out = StringIO() 2155 skinstool = getToolByName(self, 'portal_skins') 2156 if 'zenevents' not in skinstool.objectIds(): 2157 addDirectoryViews(skinstool, 'skins', globals()) 2158 out.write("Added 'zenevents' directory view to portal_skins\n") 2159 skins = skinstool.getSkinSelections() 2160 for skin in skins: 2161 path = skinstool.getSkinPath(skin) 2162 path = map(string.strip, string.split(path,',')) 2163 if 'zenevents' not in path: 2164 try: path.insert(path.index('zenmodel'), 'zenevents') 2165 except ValueError: 2166 path.append('zenevents') 2167 path = string.join(path, ', ') 2168 skinstool.addSkinSelection(skin, path) 2169 out.write("Added 'zenevents' to %s skin\n" % skin) 2170 else: 2171 out.write( 2172 "Skipping %s skin, 'zenevents' is already set up\n" % skin) 2173 return out.getvalue()
2174