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