| Trees | Indices | Help |
|
|---|
|
|
1 ###########################################################################
2 #
3 # This program is part of Zenoss Core, an open source monitoring platform.
4 # Copyright (C) 2007, 2010 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 or (at your
8 # option) any later version as published by the Free Software Foundation.
9 #
10 # For complete information please visit: http://www.zenoss.com/oss/
11 #
12 ###########################################################################
13
14 __doc__ = '''CommandPerformanceConfig
15
16 Provides configuration to zencommand clients.
17 '''
18 import logging
19 log = logging.getLogger('zen.HubService.CommandPerformanceConfig')
20 import traceback
21
22 import Globals
23 from ZODB.POSException import ConflictError
24
25 from Products.ZenCollector.services.config import CollectorConfigService
26 from Products.ZenRRD.zencommand import Cmd, DataPointConfig
27 from Products.DataCollector.Plugins import getParserLoader
28 from Products.ZenEvents.ZenEventClasses import Error, Clear, Cmd_Fail
29
30
32 dsType = 'COMMAND'
33
35 deviceProxyAttributes = ('zCommandPort',
36 'zCommandUsername',
37 'zCommandPassword',
38 'zCommandLoginTimeout',
39 'zCommandCommandTimeout',
40 'zKeyPath',
41 'zSshConcurrentSessions',
42 )
43 CollectorConfigService.__init__(self, dmd, instance,
44 deviceProxyAttributes)
45
46 # Use case: create a dummy device to act as a placeholder to execute commands
47 # So don't filter out devices that don't have IP addresses.
48
50 """
51 Given a component a data source, gather its data points
52 """
53 parser = ploader.create()
54 points = []
55 component_name = ds.getComponent(comp)
56 basepath = comp.rrdPath()
57 for dp in ds.getRRDDataPoints():
58 dpc = DataPointConfig()
59 dpc.id = dp.id
60 dpc.component = component_name
61 dpc.rrdPath = "/".join((basepath, dp.name()))
62 dpc.rrdType = dp.rrdtype
63 dpc.rrdCreateCommand = dp.getRRDCreateCommand(perfServer)
64 dpc.rrdMin = dp.rrdmin
65 dpc.rrdMax = dp.rrdmax
66 dpc.data = parser.dataForParser(comp, dp)
67 points.append(dpc)
68
69 return points
70
72 cycleTime = 300
73 try:
74 cycleTime = int(ds.cycletime)
75 except ValueError:
76 message = "Unable to convert the cycle time '%s' to an " \
77 "integer for %s/%s on %s" \
78 " -- setting to 300 seconds" % (
79 ds.cycletime, templ.id, ds.id, comp.device().id)
80 log.error(message)
81 component = ds.getPrimaryUrlPath()
82 dedupid = "Unable to convert cycletime for %s" % component
83 self.sendEvent(dict(
84 device=comp.device().id, component=component,
85 eventClass='/Cmd', severity=Warning, summary=message,
86 dedupid=dedupid,
87 ))
88 return cycleTime
89
92 """
93 Catchall wrapper for things not caught at previous levels
94 """
95 if not comp.monitorDevice():
96 return None
97
98 try:
99 threshs = self._getComponentConfig(comp, device, perfServer, commands)
100 if threshs:
101 thresholds.extend(threshs)
102 except ConflictError: raise
103 except Exception, ex:
104 msg = "Unable to process %s datasource(s) for device %s -- skipping" % (
105 self.dsType, device.id)
106 log.exception(msg)
107 details = dict(traceback=traceback.format_exc(),
108 msg=msg)
109 self._sendCmdEvent(device.id, details)
110
112 for templ in comp.getRRDTemplates():
113 for ds in templ.getRRDDataSources(self.dsType):
114 if not ds.enabled:
115 continue
116
117 # Ignore SSH datasources if no username set
118 useSsh = getattr(ds, 'usessh', False)
119 if useSsh and not device.zCommandUsername:
120 self._warnUsernameNotSet(device)
121 continue
122
123 parserName = getattr(ds, "parser", "Auto")
124 ploader = getParserLoader(self.dmd, parserName)
125 if ploader is None:
126 log.error("Could not load %s plugin", parserName)
127 continue
128
129 cmd = Cmd()
130 cmd.useSsh = useSsh
131 cmd.name = "%s/%s" % (templ.id, ds.id)
132 cmd.cycleTime = self._getDsCycleTime(comp, templ, ds)
133 cmd.component = ds.getComponent(comp)
134 cmd.eventClass = ds.eventClass
135 cmd.eventKey = ds.eventKey or ds.id
136 cmd.severity = ds.severity
137 cmd.parser = ploader
138 cmd.ds = ds.titleOrId()
139 cmd.points = self._getDsDatapoints(comp, ds, ploader, perfServer)
140
141 # If the datasource supports an environment dictionary, use it
142 cmd.env = getattr(ds, 'env', None)
143
144 try:
145 cmd.command = ds.getCommand(comp)
146 except ConflictError: raise
147 except Exception: # TALES error
148 msg = "TALES error for device %s datasource %s" % (
149 device.id, ds.id)
150 details = dict(
151 msg=msg,
152 template=templ.id,
153 datasource=ds.id,
154 affected_device=device.id,
155 affected_component=comp.id,
156 resolution='Could not create a command to send to zencommand' \
157 ' because TALES evaluation failed. The most likely' \
158 ' cause is unescaped special characters in the command.' \
159 ' eg $ or %')
160 # This error might occur many, many times
161 self._sendCmdEvent('localhost', details)
162 continue
163
164 self.enrich(cmd, templ, ds)
165 cmds.add(cmd)
166
167 return comp.getThresholdInstances(self.dsType)
168
174
176 proxy = CollectorConfigService._createDeviceProxy(self, device)
177
178 proxy.configCycleInterval = self._prefs.perfsnmpCycleInterval
179 proxy.name = device.id
180 proxy.device = device.id
181 proxy.lastmodeltime = device.getLastChangeString()
182 proxy.lastChangeTime = float(device.getLastChange())
183
184 # Only send one event per warning type
185 self._sentNoUsernameSetWarning = False
186 self._sentNoUsernameSetClear = False
187
188 perfServer = device.getPerformanceServer()
189 commands = set()
190
191 # First for the device....
192 proxy.thresholds = []
193 self._safeGetComponentConfig(device, device, perfServer,
194 commands, proxy.thresholds)
195
196 # And now for its components
197 for comp in device.getMonitoredComponents(collector='zencommand'):
198 self._safeGetComponentConfig(comp, device, perfServer,
199 commands, proxy.thresholds)
200
201 if commands:
202 proxy.datasources = list(commands)
203 return proxy
204 return None
205
207 msg = 'zCommandUsername is not set so SSH-based commands will not run'
208 ev = dict(
209 device=name,
210 eventClass=Cmd_Fail,
211 eventKey='zCommandUsername',
212 severity=Error,
213 component='zencommand',
214 summary=msg,
215 )
216 if details:
217 ev.update(details)
218 self.sendEvent(ev)
219
221 """
222 Warn that the username is not set for device and the SSH command cannot be
223 executed.
224 """
225 if self._sentNoUsernameSetWarning:
226 return
227
228 msg = 'zCommandUsername is not set so SSH-based commands will not run'
229 name = device.titleOrId()
230 log.error('%s for %s', msg, name)
231 self._sendCmdEvent(name)
232 self._sentNoUsernameSetWarning = True
233
235 if self._sentNoUsernameSetClear:
236 return
237
238 self._sendCmdEvent(device.titleOrId(), {'severity':Clear})
239 self._sentNoUsernameSetClear = True
240
241 if __name__ == '__main__':
242 from Products.ZenHub.ServiceTester import ServiceTester
243 tester = ServiceTester(CommandPerformanceConfig)
250 tester.printDeviceProxy = printer
251 tester.showDeviceInfo()
252
| Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1.1812 on Tue Oct 11 12:51:43 2011 | http://epydoc.sourceforge.net |