1
2
3
4
5
6
7
8
9
10
11
12
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
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
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
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
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
124
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
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
144 if ex.werror != 0x000006be:
145
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
155
156
157 d = drive(inner)
158 d.addErrback(cleanup)
159 return d
160
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
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
205 elif lrec.eventtype == 2:
206 sev = Warning
207 elif lrec.eventtype in (3, 4, 5):
208 sev = Info
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
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