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

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