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, 2008 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 queryTimeout = self.wmiqueryTimeout 143 if hasattr( self.options, "queryTimeout") and \ 144 self.options.queryTimeout is not None: 145 queryTimeout = int(self.options.queryTimeout) 146 self.log.debug("Querying %s (queryTimeout = %d ms)" % ( 147 device.id, queryTimeout)) 148 while True: 149 yield w.getEvents(queryTimeout, 1) 150 serviceEvents = driver.next() 151 if not serviceEvents: break 152 for s in serviceEvents: 153 s = s.targetinstance 154 if s.state: 155 if s.state == 'Stopped': 156 self.serviceStopped(device, s.name) 157 if s.state == 'Running': 158 self.serviceRunning(device, s.name) 159 self.deviceUp(device) 160 self.reportServices(device) 161 except WError, ex: 162 if ex.werror != 0x000006be: 163 raise 164 self.log.info("%s: Ignoring event %s " 165 "and restarting connection", device.id, ex) 166 cleanup() 167 except Exception, ex: 168 self.log.exception(ex) 169 raise 170 self.niceDoggie(self.cycleInterval()) 171 if not device.plugins: 172 return defer.succeed(None) 173 d = timeout(drive(inner), timeoutSecs) 174 d.addErrback(cleanup) 175 return d 176 177
178 - def updateConfig(self, cfg):
179 WinCollector.updateConfig(self, cfg) 180 self.heartbeatTimeout = self.winCycleInterval * 3
181 182
183 - def fetchDevices(self, driver):
184 yield self.configService().callRemote('getDeviceListByMonitor', 185 self.options.monitor) 186 yield self.configService().callRemote('getDeviceConfigAndWinServices', 187 driver.next()) 188 self.updateDevices(driver.next())
189 190
191 - def cycleInterval(self):
192 return self.winCycleInterval
193 194 195 if __name__ == "__main__": 196 zw = zenwin() 197 zw.run() 198