1
2
3
4
5
6
7
8
9
10
11
12
13
14 import time
15
16 from Globals import InitializeClass
17 from Products.ZenUtils import Map
18 from Products.ZenEvents.ZenEventClasses import Status_Ping, Status_Snmp
19 from Products.ZenEvents.ZenEventClasses import Status_OSProcess
20
21 from AccessControl import ClassSecurityInfo
22
23 CACHE_TIME = 60.
24
25 _cache = Map.Locked(Map.Timed({}, CACHE_TIME))
26
30
36
38 security = ClassSecurityInfo()
39 security.setDefaultAccess('allow')
40
41 "Simple record for holding availability information"
42 - def __init__(self, device, component, downtime, total, systems=''):
52
55
58
61
64
67
71
74
81
87
88 InitializeClass(Availability)
89
91 "Determine availability by counting the amount of time down"
92
93 - def __init__(self,
94 startDate = None,
95 endDate = None,
96 eventClass=Status_Ping,
97 severity=5,
98 device=None,
99 component='',
100 prodState=1000,
101 manager=None,
102 agent=None,
103 DeviceClass=None,
104 Location=None,
105 System=None,
106 DeviceGroup=None,
107 DevicePriority=None,
108 monitor=None):
124
126 return (
127 self.startDate, self.endDate, self.eventClass, self.severity,
128 self.device, self.component, self.prodState, self.manager,
129 self.agent, self.DeviceClass, self.Location, self.System,
130 self.DeviceGroup, self.DevicePriority, self.monitor)
131
133 return hash(self.tuple())
134
137
138
139 - def run(self, dmd):
140 """Run the report, returning an Availability object for each device"""
141
142
143 __pychecker__='no-local'
144 zem = dmd.ZenEventManager
145 cols = 'device, component, firstTime, lastTime'
146 endDate = self.endDate or time.time()
147 startDate = self.startDate
148 if not startDate:
149 days = zem.defaultAvailabilityDays
150 startDate = time.time() - days*60*60*24
151 env = self.__dict__.copy()
152 env.update(locals())
153 w = ' WHERE severity >= %(severity)s '
154 w += ' AND lastTime > %(startDate)s '
155 w += ' AND firstTime <= %(endDate)s '
156 w += ' AND firstTime != lastTime '
157 w += " AND (eventClass = '%s' OR eventClass LIKE '%s/%%%%') " % (self.eventClass,
158 self.eventClass.rstrip('/'))
159 w += " AND prodState >= %(prodState)s "
160 if self.device:
161 w += " AND device = '%(device)s' "
162 if self.component:
163 w += " AND component like '%%%(component)s%%' "
164 if self.manager is not None:
165 w += " AND manager = '%(manager)s' "
166 if self.agent is not None:
167 w += " AND agent = '%(agent)s' "
168 if self.DeviceClass is not None:
169 w += " AND (DeviceClass = '%s' " % self.DeviceClass
170 w += " OR DeviceClass LIKE '%s/%%%%') " % self.DeviceClass.rstrip('/')
171 if self.Location is not None:
172 w += " AND (Location = '%s' " % self.Location
173 w += " OR Location LIKE '%s/%%%%') " % self.Location.rstrip('/')
174 if self.System is not None:
175 w += " AND Systems LIKE '%%%(System)s%%' "
176 if self.DeviceGroup is not None:
177 w += " AND DeviceGroups LIKE '%%%(DeviceGroup)s%%' "
178 if self.DevicePriority is not None:
179 w += " AND DevicePriority = %(DevicePriority)s "
180 if self.monitor is not None:
181 w += " AND monitor = '%(monitor)s' "
182 env['w'] = w % env
183 s = ('SELECT %(cols)s FROM ( '
184 ' SELECT %(cols)s FROM history %(w)s '
185 ' UNION '
186 ' SELECT %(cols)s FROM status %(w)s '
187 ') AS U ' % env)
188
189 devices = {}
190 conn = zem.connect()
191 try:
192 curs = conn.cursor()
193 curs.execute(s)
194 while 1:
195 rows = curs.fetchmany()
196 if not rows: break
197 for row in rows:
198 device, component, first, last = row
199 last = min(last, endDate)
200 first = max(first, startDate)
201
202
203
204 k = None
205 if self.component:
206 k = (device, component)
207 else:
208 k = (device, '')
209
210 try:
211 devices[k] += last - first
212 except KeyError:
213 devices[k] = last - first
214 finally: zem.close(conn)
215 total = endDate - startDate
216 if self.device:
217 deviceList = []
218 device = dmd.Devices.findDevice(self.device)
219 if device:
220 deviceList = [device]
221 devices.setdefault( (self.device, self.component), 0)
222 else:
223 deviceList = []
224 if not self.DeviceClass and not self.Location \
225 and not self.System and not self.DeviceGroup:
226 deviceList = dmd.Devices.getSubDevices()
227 else:
228 allDevices = {}
229 for d in dmd.Devices.getSubDevices():
230 allDevices[d.id] = d
231
232 deviceClassDevices = set()
233 if self.DeviceClass:
234 try:
235 org = dmd.Devices.getOrganizer(self.DeviceClass)
236 for d in org.getSubDevices():
237 deviceClassDevices.add(d.id)
238 except KeyError:
239 pass
240 else:
241 deviceClassDevices = set(allDevices.keys())
242
243 locationDevices = set()
244 if self.Location:
245 try:
246 org = dmd.Locations.getOrganizer(self.Location)
247 for d in org.getSubDevices():
248 locationDevices.add(d.id)
249 except KeyError:
250 pass
251 else:
252 locationDevices = set(allDevices.keys())
253
254 systemDevices = set()
255 if self.System:
256 try:
257 org = dmd.Systems.getOrganizer(self.System)
258 for d in org.getSubDevices():
259 systemDevices.add(d.id)
260 except KeyError:
261 pass
262 else:
263 systemDevices = set(allDevices.keys())
264
265 deviceGroupDevices = set()
266 if self.DeviceGroup:
267 try:
268 org = dmd.Groups.getOrganizer(self.DeviceGroup)
269 for d in org.getSubDevices():
270 deviceGroupDevices.add(d.id)
271 except KeyError:
272 pass
273 else:
274 deviceGroupDevices = set(allDevices.keys())
275
276
277 for deviceId in (deviceClassDevices & locationDevices & \
278 systemDevices & deviceGroupDevices):
279 deviceList.append(allDevices[deviceId])
280
281 if not self.component:
282 for d in dmd.Devices.getSubDevices():
283 devices.setdefault( (d.id, self.component), 0)
284 deviceLookup = dict([(d.id, d) for d in deviceList])
285 result = []
286 for (d, c), v in devices.items():
287 dev = deviceLookup.get(d, None)
288 if dev is None:
289 continue
290 sys = dev.getSystemNamesString()
291 result.append( Availability(d, c, v, total, sys) )
292
293 if self.component:
294 for d in deviceList:
295 for c in d.getMonitoredComponents():
296 if c.name().find(self.component) >= 0:
297 a = Availability(d.id, c.name(), 0, total,
298 d.getSystemNamesString())
299 result.append(a)
300 return result
301
302
303 -def query(dmd, *args, **kwargs):
311
312
313 if __name__ == '__main__':
314 import pprint
315 r = Report(time.time() - 60*60*24*30)
316 start = time.time() - 60*60*24*30
317
318 r.component = None
319 r.eventClass = Status_Snmp
320 r.severity = 3
321 from Products.ZenUtils.ZCmdBase import ZCmdBase
322 z = ZCmdBase()
323 pprint.pprint(r.run(z.dmd))
324 a = query(z.dmd, start, device='gate.zenoss.loc', eventClass=Status_Ping)
325 assert 0 <= float(a[0]) <= 1.
326 b = query(z.dmd, start, device='gate.zenoss.loc', eventClass=Status_Ping)
327 assert a == b
328 assert id(a) == id(b)
329 pprint.pprint(r.run(z.dmd))
330 r.component = 'httpd'
331 r.eventClass = Status_OSProcess
332 r.severity = 4
333 pprint.pprint(r.run(z.dmd))
334 r.device = 'gate.zenoss.loc'
335 r.component = ''
336 r.eventClass = Status_Ping
337 r.severity = 4
338 pprint.pprint(r.run(z.dmd))
339