From: <sv...@ze...> - 2008-03-31 16:13:14
|
Author: ecn Date: 2008-03-31 12:13:21 -0400 (Mon, 31 Mar 2008) New Revision: 8742 Added: trunk/Products/ZenWin/tests/testWMIFail.py Modified: trunk/Products/ZenWin/WMIClient.py trunk/Products/ZenWin/WinCollector.py trunk/Products/ZenWin/zeneventlog.py trunk/Products/ZenWin/zenwin.py trunk/Products/ZenWin/zenwinmodeler.py Log: fixes #2885: recover bad WMI attempts upon restart * send start events after the reactor has started * send events at start-up if there are failure indicators * add decorator for saving device/method names to files * add unit test Modified: trunk/Products/ZenWin/WMIClient.py =================================================================== --- trunk/Products/ZenWin/WMIClient.py 2008-03-31 12:24:16 UTC (rev 8741) +++ trunk/Products/ZenWin/WMIClient.py 2008-03-31 16:13:21 UTC (rev 8742) @@ -11,9 +11,11 @@ # ########################################################################### +import os import socket import win32com.client import logging +from ProcessProxy import zenPath log = logging.getLogger("zen.WMIClient.WMIClient") locator = win32com.client.Dispatch("WbemScripting.SWbemLocator") @@ -24,7 +26,52 @@ """ refresher.refresh() -#class WMI(object): +import sys +BaseName = os.path.basename(sys.argv[0]) +MyName = None + +def _myname(): + global MyName + if not MyName: + import sys + MyName = BaseName.split('.')[0] + try: + os.mkdir(zenPath('var', _myname())) + except os.error: + pass + return MyName + +def _filename(device): + return zenPath('var', _myname(), device) + +def prepForFailure(device, operation): + fp = file(_filename(device), 'w') + fp.write('%s\n' % (operation,)) + fp.close() + +def success(device): + os.unlink(_filename(device)) + +def failures(clean=False): + result = [] + for path, dirs, files in os.walk(zenPath('var', _myname())): + for f in files: + fullname = os.path.join(path, f) + result.append( (f, file(fullname).read()[:-1]) ) + if clean: + os.unlink(fullname) + return result + +def watchForFailure(method): + def protect(self, *args, **kw): + try: + prepForFailure(self.name, method.func_name) + return method(self, *args, **kw) + finally: + success(self.name) + return protect + + class WMIClient(object): def __init__(self, device, datacollector=None, plugins=[]): @@ -50,8 +97,8 @@ #self._tabledata = {} self.results = [] - - + + @watchForFailure def connect(self): log.debug("connect to %s, user %s", self.host, self.user) self._wmi = locator.ConnectServer(self.host, @@ -68,6 +115,7 @@ del self._wmi + @watchForFailure def query(self, queries): if not hasattr(self, '_wmi'): raise ValueError("WMI connection is closed") @@ -123,6 +171,7 @@ return self._wmi.InstancesOf(classname) + @watchForFailure def watcher(self, wql=None): """Return a watcher object that can be called to check for new events. @@ -135,19 +184,20 @@ wql = """SELECT * from __InstanceCreationEvent WITHIN 1 where """\ """TargetInstance ISA 'Win32_NTLogEvent'""" log.debug(wql) - return _watcher(self._wmi.ExecNotificationQuery(wql)) + return _watcher(self._wmi.ExecNotificationQuery(wql), self.name) class _watcher(object): - def __init__(self, event): + def __init__(self, event, device): self.event = event + self.name = device + @watchForFailure def nextEvent(self, timeout=0): """Poll for next event wait timeout for response return value. """ return self.event.NextEvent(timeout).Properties_("TargetInstance").Value - Modified: trunk/Products/ZenWin/WinCollector.py =================================================================== --- trunk/Products/ZenWin/WinCollector.py 2008-03-31 12:24:16 UTC (rev 8741) +++ trunk/Products/ZenWin/WinCollector.py 2008-03-31 16:13:21 UTC (rev 8742) @@ -18,9 +18,10 @@ import Globals from Products.ZenHub.PBDaemon import FakeRemote, PBDaemon -from Products.ZenEvents.ZenEventClasses import App_Start, Clear +from Products.ZenEvents.ZenEventClasses import Error, App_Start, Clear, Status_Wmi_Conn from Products.ZenUtils.Driver import drive, driveLater from Products.ZenUtils.Utils import zenPath +from Products.ZenWin import WMIClient from Constants import ERROR_CODE_MAP @@ -65,6 +66,12 @@ device=self.options.monitor, severity=Clear, component=self.name)) + for device, where in WMIClient.failures(clean=True): + self.sendEvent(dict( + summary='Wmi communication failure during %s' % (where,), + eventClass=Status_Wmi_Conn, + device=device, + severity=Error)) def getProxy(self, filename, classname): filename = zenPath(filename) @@ -93,6 +100,7 @@ def startScan(self, unused=None): + self.start() drive(self.scanCycle) Added: trunk/Products/ZenWin/tests/testWMIFail.py Modified: trunk/Products/ZenWin/zeneventlog.py =================================================================== --- trunk/Products/ZenWin/zeneventlog.py 2008-03-31 12:24:16 UTC (rev 8741) +++ trunk/Products/ZenWin/zeneventlog.py 2008-03-31 16:13:21 UTC (rev 8742) @@ -38,8 +38,8 @@ def __init__(self): WinCollector.__init__(self) self.manager = getfqdn() - self.start() + def fetchDevices(self, driver): yield self.configService().callRemote('getDeviceListByMonitor', self.options.monitor) Modified: trunk/Products/ZenWin/zenwin.py =================================================================== --- trunk/Products/ZenWin/zenwin.py 2008-03-31 12:24:16 UTC (rev 8741) +++ trunk/Products/ZenWin/zenwin.py 2008-03-31 16:13:21 UTC (rev 8742) @@ -33,7 +33,6 @@ WinCollector.__init__(self) self.statmsg = "Windows Service '%s' is %s" self.winCycleInterval = 60 - self.start() def mkevt(self, devname, svcname, msg, sev): "Compose an event" Modified: trunk/Products/ZenWin/zenwinmodeler.py =================================================================== --- trunk/Products/ZenWin/zenwinmodeler.py 2008-03-31 12:24:16 UTC (rev 8741) +++ trunk/Products/ZenWin/zenwinmodeler.py 2008-03-31 16:13:21 UTC (rev 8742) @@ -62,7 +62,6 @@ self.lastRead = {} self.client = None self.collectorPlugins = {} - self.start() def selectPlugins(self, device, transport): |