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