1
2
3
4
5
6
7
8
9
10
11
12
13
14 import re
15 import json
16
17 from Products.Five.browser import BrowserView
18 from Products.AdvancedQuery import Eq, Or
19
20 from Products.ZenUtils.Utils import relative_time
21 from Products.Zuul import getFacade
22 from Products.ZenEvents.HeartbeatUtils import getHeartbeatObjects
23 from zenoss.protocols.services import ServiceException
24 from zenoss.protocols.services.zep import ZepConnectionError
25 from Products.ZenUtils.guid.interfaces import IGUIDManager
26 from Products.ZenUtils.jsonutils import json
27 from Products.ZenUtils.Utils import nocache, formreq, extractPostContent
28 from Products.ZenWidgets import messaging
29 from Products.ZenModel.Device import Device
30 from Products.ZenModel.ZenossSecurity import *
31 from Products.ZenEvents.browser.EventPillsAndSummaries import \
32 getDashboardObjectsEventSummary, \
33 ObjectsEventSummary, \
34 getEventPillME
35
36 import logging
37 log = logging.getLogger('zen.portlets')
41 def outer(func):
42 def inner(self, *args, **kwargs):
43 try:
44 return func(self, *args, **kwargs)
45 except ZepConnectionError, e:
46 msg = 'Connection refused. Check zeneventserver status on <a href="/zport/About/zenossInfo">Daemons</a>'
47 messaging.IMessageSender(self.context).sendToBrowser("ZEP connection error",
48 msg,
49 priority=messaging.CRITICAL,
50 sticky=True)
51 log.warn("Could not connect to ZEP")
52 return retval
53 return inner
54 return outer
55
57 """
58 Return JSON event summaries for a root organizer.
59 """
60 @nocache
61 @formreq
65
68
71 """
72 Return a map of device to production state in a format suitable for a
73 YUI data table.
74 """
75 @nocache
76 @formreq
79
80 @json
82 """
83 Return a map of device to production state in a format suitable for a
84 YUI data table.
85
86 @return: A JSON representation of a dictionary describing devices
87 @rtype: "{
88 'columns':['Device', 'Prod State'],
89 'data':[
90 {'Device':'<a href=/>', 'Prod State':'Production'},
91 {'Device':'<a href=/>', 'Prod State':'Maintenance'},
92 ]}"
93 """
94 devroot = self.context.dmd.Devices
95 if isinstance(prodStates, basestring):
96 prodStates = [prodStates]
97 orderby, orderdir = 'id', 'asc'
98 catalog = getattr(devroot, devroot.default_catalog)
99 queries = []
100 for state in prodStates:
101 queries.append(Eq('getProdState', state))
102 query = Or(*queries)
103 objects = catalog.evalAdvancedQuery(query, ((orderby, orderdir),))
104 devs = (x.getObject() for x in objects)
105 mydict = {'columns':['Device', 'Prod State'], 'data':[]}
106 for dev in devs:
107 if not self.context.checkRemotePerm(ZEN_VIEW, dev): continue
108 mydict['data'].append({
109 'Device' : dev.getPrettyLink(),
110 'Prod State' : dev.getProdState()
111 })
112 if len(mydict['data'])>=100:
113 break
114 return mydict
115
118 """
119 Accepts a list of paths to Zope objects which it then attempts to resolve.
120 If no list of paths is given, it will try to read them from the POST data
121 of the REQUEST object.
122
123 @param entities: A list of paths that should be resolved into objects
124 and passed to L{getDashboardObjectsEventSummaryJSON}.
125 @type entities: list
126 @return: A JSON-formatted string representation of the columns and rows
127 of the table
128 @rtype: string
129 """
130 @nocache
131 @formreq
134
135 @json
137 if entities is None:
138 entities = []
139 elif isinstance(entities, basestring):
140 entities = [entities]
141 def getob(e):
142 e = str(e)
143 try:
144 if not e.startswith('/zport/dmd'):
145 bigdev = '/zport/dmd' + e
146 obj = self.context.dmd.unrestrictedTraverse(bigdev)
147 except (AttributeError, KeyError):
148 obj = self.context.dmd.Devices.findDevice(e)
149 if self.context.has_permission("View", obj): return obj
150 entities = filter(lambda x:x is not None, map(getob, entities))
151 return getDashboardObjectsEventSummary(
152 self.context.dmd.ZenEventManager, entities)
153
156 """
157 A list of devices with issues.
158 """
159 @nocache
162
163 @json
165 """
166 Get devices with issues in a form suitable for a portlet on the
167 dashboard.
168
169 @return: A JSON representation of a dictionary describing devices
170 @rtype: "{
171 'columns':['Device', "Events'],
172 'data':[
173 {'Device':'<a href=/>', 'Events':'<div/>'},
174 {'Device':'<a href=/>', 'Events':'<div/>'},
175 ]}"
176 """
177 mydict = {'columns':[], 'data':[]}
178 mydict['columns'] = ['Device', 'Events']
179 deviceinfo = self.getDeviceDashboard()
180 for alink, pill in deviceinfo:
181 mydict['data'].append({'Device':alink,
182 'Events':pill})
183 return mydict
184
185 @zepConnectionError([])
187 """return device info for bad device to dashboard"""
188 zep = getFacade('zep')
189 manager = IGUIDManager(self.context.dmd)
190 deviceSeverities = zep.getDeviceIssuesDict()
191 zem = self.context.dmd.ZenEventManager
192
193 devdata = []
194 for uuid in deviceSeverities.keys():
195 dev = manager.getObject(uuid)
196 if dev and isinstance(dev, Device):
197 if (not zem.checkRemotePerm(ZEN_VIEW, dev)
198 or dev.productionState < zem.prodStateDashboardThresh
199 or dev.priority < zem.priorityDashboardThresh):
200 continue
201 alink = dev.getPrettyLink()
202 try:
203 severities = deviceSeverities[uuid]
204 severities = dict((zep.getSeverityName(sev).lower(), counts) for (sev, counts) in severities.iteritems())
205 pill = getEventPillME(dev, severities=severities)
206 except ServiceException:
207 continue
208 evts = [alink,pill]
209 devdata.append((evts, severities))
210 devdata.sort(key=lambda x:(x[1]['critical'], x[1]['error'], x[1]['warning']), reverse=True)
211 return [x[0] for x in devdata[:100]]
212
213
214 heartbeat_columns = ['Device', 'Daemon', 'Seconds']
217 """
218 Heartbeat issues in YUI table form, for the dashboard portlet
219 """
220 @nocache
223
224 @zepConnectionError({'columns': heartbeat_columns, 'data':[]})
225 @json
227 """
228 Get heartbeat issues in a form suitable for a portlet on the dashboard.
229
230 @return: A JSON representation of a dictionary describing heartbeats
231 @rtype: "{
232 'columns':['Device', 'Daemon', 'Seconds'],
233 'data':[
234 {'Device':'<a href=/>', 'Daemon':'zenhub', 'Seconds':10}
235 ]}"
236 """
237 data = getHeartbeatObjects(deviceRoot=self.context.dmd.Devices,
238 keys=heartbeat_columns)
239 return {'columns': heartbeat_columns, 'data': data}
240
243 """
244 User messages in YUI table form, for the dashboard portlet.
245 """
246 @nocache
247 @json
249 """
250 Get heartbeat issues in a form suitable for a portlet on the dashboard.
251
252 @return: A JSON representation of a dictionary describing heartbeats
253 @rtype: "{
254 'columns':['Device', 'Daemon', 'Seconds'],
255 'data':[
256 {'Device':'<a href=/>', 'Daemon':'zenhub', 'Seconds':10}
257 ]}"
258 """
259 ICONS = ['/zport/dmd/img/agt_action_success-32.png',
260 '/zport/dmd/img/messagebox_warning-32.png',
261 '/zport/dmd/img/agt_stop-32.png']
262 msgbox = messaging.IUserMessages(self.context)
263 msgs = msgbox.get_messages()
264 cols = ['Message']
265 res = []
266 for msg in msgs:
267 res.append(dict(
268 title = msg.title,
269 imgpath = ICONS[msg.priority],
270 body = msg.body,
271 ago = relative_time(msg.timestamp),
272 deletelink = msg.absolute_url_path() + '/delMsg'
273 ))
274 res.reverse()
275 return { 'columns': cols, 'data': res }
276