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