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

Source Code for Module ZenWin.zenwin

  1  ########################################################################### 
  2  # 
  3  # This program is part of Zenoss Core, an open source monitoring platform. 
  4  # Copyright (C) 2007-2009 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  import Globals 
 15  from Products.ZenWin.WMIClient import WMIClient 
 16  from Products.ZenWin.WinCollector import WinCollector 
 17  from Products.ZenWin.Watcher import Watcher 
 18  from Products.ZenEvents.ZenEventClasses import Status_WinService 
 19  from Products.ZenUtils.Driver import drive 
 20  from Products.ZenUtils.Timeout import timeout 
 21  from pysamba.library import WError 
 22   
 23  from sets import Set 
 24   
 25  from twisted.internet import defer 
 26  from twisted.python import failure 
 27   
28 -class zenwin(WinCollector):
29 30 name = agent = "zenwin" 31 whatIDo = "read the status of Windows services" 32 attributes = WinCollector.attributes + ('winCycleInterval',) 33 34
35 - def __init__(self):
36 WinCollector.__init__(self) 37 self.statmsg = "Windows Service '%s' is %s" 38 self.winCycleInterval = 60
39 40
41 - def makeEvent(self, devname, svcname, msg, sev):
42 "Compose an event" 43 evt = dict(summary=msg, 44 eventClass=Status_WinService, 45 device=devname, 46 severity=sev, 47 agent=self.agent, 48 component=svcname, 49 eventGroup= "StatusTest") 50 logmsg = "%s on %s" % (msg, devname) 51 if sev > 0: 52 self.log.critical(logmsg) 53 else: 54 self.log.info(logmsg) 55 return evt
56 57
58 - def serviceStopped(self, device, name):
59 self.log.warning('%s: %s stopped' % (device.id, name)) 60 if name not in device.services: return 61 status, severity = device.services[name] 62 #status less than 0 is the monitor off state 63 if status < 0 : 64 self.log.debug('monitor is off, ignoring stopped service %s on %s'\ 65 % (name, device.id)) 66 return 67 device.services[name] = status + 1, severity
68 69
70 - def serviceRunning(self, device, name):
71 if name not in device.services: return 72 status, severity = device.services[name] 73 #status less than 0 is the monitor off state 74 if status < 0 : 75 self.log.debug('monitor is off, ignoring enabled service %s on %s'\ 76 % (name, device.id)) 77 return 78 device.services[name] = 0, severity
79 80
81 - def reportServices(self, device):
82 for name, (status, severity) in device.services.items(): 83 if status == 0: 84 msg = self.statmsg % (name, "up") 85 sev = 0 86 else: 87 msg = self.statmsg % (name, "down") 88 sev = severity 89 self.sendEvent(self.makeEvent(device.id, name, msg, sev))
90 91
92 - def scanDevice(self, device):
93 "Fetch the current state of the services on a device" 94 def inner(driver): 95 try: 96 if not device.services: 97 driver.finish(None) 98 self.log.info("Scanning %s", device.id) 99 wql = "select Name from Win32_Service where State='Running'" 100 wmic = WMIClient(device) 101 yield wmic.connect() 102 driver.next() 103 yield wmic.query(dict(query=wql)) 104 q = driver.next() 105 running = Set([ svc.name for svc in q['query'] ]) 106 monitored = Set(device.services.keys()) 107 self.log.debug("services: %s", monitored) 108 for name in monitored - running: 109 self.serviceStopped(device, name) 110 for name in monitored & running: 111 self.serviceRunning(device, name) 112 wmic.close() 113 self.log.info("Finished scanning %s", device.id) 114 except Exception, ex: 115 self.log.exception(ex) 116 raise
117 return drive(inner)
118 119
120 - def processDevice(self, device, timeoutSecs):
121 """Run WMI queries in two stages. First get the current state, 122 then incremental updates thereafter. 123 """ 124 wql = ("""SELECT * FROM __InstanceModificationEvent within 5 where """ 125 """TargetInstance ISA 'Win32_Service' """) 126 # FIXME: this code looks very similar to the code in zeneventlog 127 def cleanup(result=None): 128 if isinstance(result, failure.Failure): 129 self.deviceDown(device, result.getErrorMessage())
130 def inner(driver): 131 try: 132 self.niceDoggie(self.cycleInterval()) 133 w = self.watchers.get(device.id, None) 134 if not w: 135 yield self.scanDevice(device) 136 driver.next() 137 w = Watcher(device, wql) 138 yield w.connect() 139 driver.next() 140 self.watchers[device.id] = w 141 else: 142 batchSize = self.wmibatchSize 143 if hasattr(self.options, "batchSize") and \ 144 self.options.batchSize is not None: 145 batchSize = int(self.options.batchSize) 146 147 queryTimeout = self.wmiqueryTimeout 148 if hasattr(self.options, "queryTimeout") and \ 149 self.options.queryTimeout is not None: 150 queryTimeout = int(self.options.queryTimeout) 151 152 self.log.debug("Querying %s (queryTimeout = %d ms, batchSize = %d)", 153 device.id, queryTimeout, batchSize) 154 155 while True: 156 yield w.getEvents(queryTimeout, batchSize) 157 serviceEvents = driver.next() 158 if not serviceEvents: break 159 for s in serviceEvents: 160 s = s.targetinstance 161 if s.state: 162 if s.state == 'Stopped': 163 self.serviceStopped(device, s.name) 164 if s.state == 'Running': 165 self.serviceRunning(device, s.name) 166 self.deviceUp(device) 167 self.reportServices(device) 168 except WError, ex: 169 # TODO: validate that this error code is still OK 170 if ex.werror != 0x000006be: 171 raise 172 self.log.info("%s: Ignoring event %s " 173 "and restarting connection", device.id, ex) 174 cleanup() 175 except Exception, ex: 176 self.log.exception(ex) 177 raise 178 self.niceDoggie(self.cycleInterval()) 179 if not device.plugins: 180 return defer.succeed(None) 181 d = timeout(drive(inner), timeoutSecs) 182 d.addErrback(cleanup) 183 return d 184 185
186 - def updateConfig(self, cfg):
187 WinCollector.updateConfig(self, cfg) 188 self.heartbeatTimeout = self.winCycleInterval * 3
189 190
191 - def fetchDevices(self, driver):
192 yield self.configService().callRemote('getDeviceListByMonitor', 193 self.options.monitor) 194 yield self.configService().callRemote('getDeviceConfigAndWinServices', 195 driver.next()) 196 self.updateDevices(driver.next())
197 198
199 - def cycleInterval(self):
200 return self.winCycleInterval
201 202 203 if __name__ == "__main__": 204 zw = zenwin() 205 zw.run() 206