Package ZenWin :: Module zeneventlog
[hide private]
[frames] | no frames]

Source Code for Module ZenWin.zeneventlog

  1  #! /usr/bin/env python 
  2  # -*- coding: utf-8 -*- 
  3  # ########################################################################## 
  4  # 
  5  # This program is part of Zenoss Core, an open source monitoring platform. 
  6  # Copyright (C) 2006-2009 Zenoss Inc. 
  7  # 
  8  # This program is free software; you can redistribute it and/or modify it 
  9  # under the terms of the GNU General Public License version 2 as published by 
 10  # the Free Software Foundation. 
 11  # 
 12  # For complete information please visit: http://www.zenoss.com/oss/ 
 13  # 
 14  # ########################################################################## 
 15   
 16  __doc__ = """zeneventlog 
 17      Connect using WMI to gather the Windows Event Log and create 
 18      Zenoss events. 
 19  """ 
 20   
 21  import time 
 22  import Globals 
 23  from Products.ZenWin.Watcher import Watcher 
 24  from Products.ZenWin.WinCollector import WinCollector 
 25  from Products.ZenUtils.Driver import drive 
 26  from Products.ZenEvents.ZenEventClasses import Error, Warning, Info, \ 
 27      Debug 
 28  from pysamba.library import WError 
 29   
 30  from twisted.python import failure 
 31   
 32   
33 -class zeneventlog(WinCollector):
34 """ 35 Connect using WMI to gather the Windows Event Log and create 36 Zenoss events. 37 """ 38 name = agent = 'zeneventlog' 39 whatIDo = 'read the Windows event log' 40 eventlogCycleInterval = 5 * 60 41 attributes = WinCollector.attributes + ('eventlogCycleInterval', ) 42 deviceAttributes = WinCollector.deviceAttributes + ( 43 'zWinEventlog', 'zWinEventlogMinSeverity') 44 events = 0 45
46 - def fetchDevices(self, driver):
47 """ 48 Generator function to return the list of devices to gather 49 Event log information. 50 51 @param driver: driver 52 @type driver: driver object 53 @return: objects 54 @rtype: object 55 """ 56 yield self.configService().callRemote('getDeviceListByMonitor', 57 self.options.monitor) 58 yield self.configService().callRemote('getDeviceConfigForEventlog', 59 driver.next()) 60 self.updateDevices(driver.next())
61
62 - def processDevice(self, device, timeoutSecs):
63 """ 64 Scan a single device. 65 66 @param device: device to interrogate 67 @type device: device object 68 @param timeoutSecs: timeoutSecs 69 @type timeoutSecs: int 70 @return: objects 71 @rtype: objects 72 """ 73 self.log.debug('Polling %s' % device.id) 74 wql = "SELECT * FROM __InstanceCreationEvent where TargetInstance ISA 'Win32_NTLogEvent' and TargetInstance.EventType <= %d"\ 75 % device.zWinEventlogMinSeverity 76 77 # FIXME: this code looks very similar to the code in zenwin 78 def cleanup(result=None): 79 """ 80 Set a device to be down on failure conditions 81 """ 82 if isinstance(result, failure.Failure): 83 self.deviceDown(device, result.getErrorMessage())
84 85 def inner(driver): 86 """ 87 inner 88 89 @param driver: driver 90 @type driver: string 91 @return: objects 92 @rtype: objects 93 """ 94 processingStart = time.time() 95 cycleInterval = self.cycleInterval() 96 try: 97 self.niceDoggie(cycleInterval) 98 w = self.watchers.get(device.id, None) 99 if not w: 100 self.log.debug('Creating watcher of %s', device.id) 101 w = Watcher(device, wql) 102 self.log.info('Connecting to %s', device.id) 103 yield w.connect() 104 driver.next() 105 self.log.info('Connected to %s', device.id) 106 self.watchers[device.id] = w 107 108 while True: 109 batchSize = self.wmibatchSize 110 if hasattr(self.options, "batchSize") and \ 111 self.options.batchSize is not None: 112 batchSize = int(self.options.batchSize) 113 114 queryTimeout = self.wmiqueryTimeout 115 if hasattr(self.options, "queryTimeout") and \ 116 self.options.queryTimeout is not None: 117 queryTimeout = int(self.options.queryTimeout) 118 119 yield w.getEvents(queryTimeout, batchSize) 120 events = driver.next() 121 self.log.debug('Got %d events', len(events)) 122 123 # break out of the loop if either a) we've got no events 124 # right now, or b) we've exceeded the cycle time 125 if not events: 126 break 127 128 delay = time.time() - processingStart 129 if cycleInterval - delay < 0: 130 self.log.info("processDevice: cycle time exceeded "\ 131 + "for device %s; breaking out of loop", 132 device.id) 133 break 134 135 # process all of the fetched events 136 for lrec in events: 137 self.events += 1 138 self.sendEvent(self.makeEvent(device.id, lrec)) 139 140 self.deviceUp(device) 141 142 except WError, ex: 143 # TODO: verify this error code is still valid 144 if ex.werror != 0x000006be: 145 # OPERATION_COULD_NOT_BE_COMPLETED 146 raise 147 self.log.info('%s: Ignoring event %s and restarting connection', 148 device.id, ex) 149 cleanup() 150 except Exception, ex: 151 self.log.exception('Exception getting windows events: %s', ex) 152 raise
153 154 # Don't worry about an overall timeout for the inner function since the 155 # RPC layer has a built-in timeout of 60 seconds and each Watcher loop 156 # will break out if the cycle time has been exceeded. 157 d = drive(inner) 158 d.addErrback(cleanup) 159 return d 160
161 - def processLoop(self, devices, timeoutSecs):
162 """ 163 Kick off the main loop of collecting data 164 165 @param devices: devices 166 @type devices: string 167 @param timeoutSecs: timeoutSecs 168 @type timeoutSecs: string 169 @return: defered 170 @rtype: Twisted defered 171 """ 172 def postStats(result): 173 """ 174 Twisted callback to report evnets 175 176 @param result: result of operation 177 @type result: string 178 @return: result 179 @rtype: string 180 """ 181 self.sendEvents(self.rrdStats.counter('events', 182 self.cycleInterval(), self.events)) 183 return result
184 185 d = WinCollector.processLoop(self, devices, timeoutSecs) 186 d.addBoth(postStats) 187 return d 188
189 - def makeEvent(self, name, lrec):
190 """ 191 Put event in the queue to be sent to the ZenEventManager. 192 193 @param name: name of the device 194 @type name: string 195 @param lrec: log record 196 @type lrec: log record object 197 @return: dictionary with event keys and values 198 @rtype: dictionary 199 """ 200 lrec = lrec.targetinstance 201 evtkey = '%s_%s' % (lrec.sourcename, lrec.eventcode) 202 sev = Debug 203 if lrec.eventtype == 1: 204 sev = Error # error 205 elif lrec.eventtype == 2: 206 sev = Warning # warning 207 elif lrec.eventtype in (3, 4, 5): 208 sev = Info # information, security audit success & failure 209 210 self.log.debug( "---- log record info --------------" ) 211 for item in dir(lrec): 212 if item[0] == '_': 213 continue 214 self.log.info("%s = %s" % (item, getattr(lrec, item, ''))) 215 self.log.debug( "---- log record info --------------" ) 216 217 ts= lrec.timegenerated 218 try: 219 date_ts = '/'.join( [ ts[0:4], ts[4:6], ts[6:8] ]) 220 time_ts = ':'.join( [ts[8:10], ts[10:12], ts[12:14] ]) 221 ts = date_ts + ' ' + time_ts 222 except: 223 pass 224 225 event_message = str(lrec.message).strip() 226 if not event_message or event_message == 'None': 227 event_message = "Message text from Windows not available." + \ 228 " See source system's event log." 229 230 evt = dict( 231 device=name, 232 eventClassKey=evtkey, 233 eventGroup=lrec.logfile, 234 component=lrec.sourcename, 235 ntevid=lrec.eventcode, 236 summary=event_message, 237 agent='zeneventlog', 238 severity=sev, 239 monitor=self.options.monitor, 240 user=lrec.user, 241 categorystring=lrec.categorystring, 242 originaltime=ts, 243 computername=lrec.computername, 244 eventidentifier=lrec.eventidentifier, 245 ) 246 self.log.debug("Device:%s msg:'%s'", name, lrec.message) 247 return evt
248
249 - def cycleInterval(self):
250 """ 251 Return the length of the cycleInterval 252 253 @return: number of seconds to repeat a collection cycle 254 @rtype: int 255 """ 256 return self.eventlogCycleInterval
257 258 259 if __name__ == '__main__': 260 zw = zeneventlog() 261 zw.run() 262