Package Products :: Package ZenWidgets :: Package browser :: Module Portlets
[hide private]
[frames] | no frames]

Source Code for Module Products.ZenWidgets.browser.Portlets

  1  ############################################################################## 
  2  #  
  3  # Copyright (C) Zenoss, Inc. 2007, 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  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') 
35 36 37 -def zepConnectionError(retval=None):
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
53 -class TopLevelOrganizerPortletView(ObjectsEventSummary):
54 """ 55 Return JSON event summaries for a root organizer. 56 """ 57 @nocache 58 @formreq
59 - def __call__(self, dataRoot):
60 self.dataRoot = dataRoot 61 return super(TopLevelOrganizerPortletView, self).__call__()
62
63 - def _getObs(self):
64 return self.context.dmd.getDmdRoot(self.dataRoot).children()
65
66 67 -class ProductionStatePortletView(BrowserView):
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
74 - def __call__(self, *args, **kwargs):
75 return self.getDevProdStateJSON(*args, **kwargs)
76 77 @json
78 - def getDevProdStateJSON(self, prodStates=['Maintenance']):
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
113 114 -class WatchListPortletView(BrowserView):
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
129 - def __call__(self, *args, **kwargs):
130 return self.getEntityListEventSummary(*args, **kwargs)
131 132 @json
133 - def getEntityListEventSummary(self, entities=None):
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
151 152 -class DeviceIssuesPortletView(BrowserView):
153 """ 154 A list of devices with issues. 155 """ 156 @nocache
157 - def __call__(self):
158 return self.getDeviceIssuesJSON()
159 160 @json
161 - def getDeviceIssuesJSON(self):
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([])
183 - def getDeviceDashboard(self):
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']
212 213 -class HeartbeatPortletView(BrowserView):
214 """ 215 Heartbeat issues in YUI table form, for the dashboard portlet 216 """ 217 @nocache
218 - def __call__(self):
219 return self.getHeartbeatIssuesJSON()
220 221 @zepConnectionError({'columns': heartbeat_columns, 'data':[]}) 222 @json
223 - def getHeartbeatIssuesJSON(self):
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
238 239 -class UserMessagesPortletView(BrowserView):
240 """ 241 User messages in YUI table form, for the dashboard portlet. 242 """ 243 @nocache 244 @json
245 - def __call__(self):
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