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

# Source Code for Module Products.ZenWidgets.browser.Portlets

      1  ###########################################################################
      2  #
      3  # This program is part of Zenoss Core, an open source monitoring platform.
      4  # Copyright (C) 2007, Zenoss Inc.
      5  #
      6  # This program is free software; you can redistribute it and/or modify it
      7  # under the terms of the GNU General Public License version 2 as published by
      8  # the Free Software Foundation.
      9  #
     10  # For complete information please visit: http://www.zenoss.com/oss/
     11  #
     12  ###########################################################################
     13
     14  import re
     15  import simplejson
     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.ZenUtils.json import json
     22  from Products.ZenUtils.Utils import formreq, extractPostContent
     23  from Products.ZenWidgets import messaging
     24  from Products.ZenModel.ZenossSecurity import *
     25  from Products.ZenEvents.browser.EventPillsAndSummaries import \
     26                                     getDashboardObjectsEventSummary, \
     27                                     ObjectsEventSummary,    \
     28                                     getEventPillME
     29
     30
     31 -class TopLevelOrganizerPortletView(ObjectsEventSummary):
     32      """
     33      Return JSON event summaries for a root organizer.
     34      """
     35      @formreq
     36 -    def __call__(self, dataRoot):
     37          self.dataRoot = dataRoot
     38          return super(TopLevelOrganizerPortletView, self).__call__()
     39
     40 -    def _getObs(self):
     41          return self.context.dmd.getDmdRoot(self.dataRoot).children()
     42
     43
     44 -class ProductionStatePortletView(BrowserView):
     45      """
     46      Return a map of device to production state in a format suitable for a
     47      YUI data table.
     48      """
     49      @formreq
     50 -    def __call__(self, *args, **kwargs):
     51          return self.getDevProdStateJSON(*args, **kwargs)
     52
     53      @json
     54 -    def getDevProdStateJSON(self, prodStates=['Maintenance']):
     55          """
     56          Return a map of device to production state in a format suitable for a
     57          YUI data table.
     58
     59          @return: A JSON representation of a dictionary describing devices
     60          @rtype: "{
     61              'columns':['Device', 'Prod State'],
     62              'data':[
     63                  {'Device':'<a href=/>', 'Prod State':'Production'},
     64                  {'Device':'<a href=/>', 'Prod State':'Maintenance'},
     65              ]}"
     66          """
     67          devroot = self.context.dmd.Devices
     68          if type(prodStates)==type(''):
     69              prodStates = [prodStates]
     70          orderby, orderdir = 'id', 'asc'
     71          catalog = getattr(devroot, devroot.default_catalog)
     72          queries = []
     73          for state in prodStates:
     74              queries.append(Eq('getProdState', state))
     75          query = Or(*queries)
     76          objects = catalog.evalAdvancedQuery(query, ((orderby, orderdir),))
     77          devs = (x.getObject() for x in objects)
     78          mydict = {'columns':['Device', 'Prod State'], 'data':[]}
     79          for dev in devs:
     80              if not self.context.checkRemotePerm(ZEN_VIEW, dev): continue
     81              mydict['data'].append({
     82                  'Device' : dev.getPrettyLink(),
     83                  'Prod State' : dev.getProdState()
     84              })
     85          mydict['data'] = mydict['data'][:100]
     86          return mydict
     87
     88
     89 -class WatchListPortletView(BrowserView):
     90      """
     91      Accepts a list of paths to Zope objects which it then attempts to resolve.
     92      If no list of paths is given, it will try to read them from the POST data
     93      of the REQUEST object.
     94
     95      @param entities: A list of paths that should be resolved into objects
     96          and passed to L{getDashboardObjectsEventSummaryJSON}.
     97      @type entities: list
     98      @return: A JSON-formatted string representation of the columns and rows
     99          of the table
    100      @rtype: string
    101      """
    102      @formreq
    103 -    def __call__(self, *args, **kwargs):
    104          return self.getEntityListEventSummary(*args, **kwargs)
    105
    106      @json
    107 -    def getEntityListEventSummary(self, entities=None):
    108          if entities is None:
    109              entities = []
    110          elif isinstance(entities, basestring):
    111              entities = [entities]
    112          def getob(e):
    113              e = str(e)
    114              try:
    115                  if not e.startswith('/zport/dmd'):
    116                      bigdev = '/zport/dmd' + e
    117                  obj = self.context.dmd.unrestrictedTraverse(bigdev)
    118              except (AttributeError, KeyError):
    119                  obj = self.context.dmd.Devices.findDevice(e)
    120              if self.context.has_permission("View", obj): return obj
    121          entities = filter(lambda x:x is not None, map(getob, entities))
    122          return getDashboardObjectsEventSummary(
    123              self.context.dmd.ZenEventManager, entities)
    124
    125
    126 -class DeviceIssuesPortletView(BrowserView):
    127      """
    128      A list of devices with issues.
    129      """
    130 -    def __call__(self):
    131          return self.getDeviceIssuesJSON()
    132
    133      @json
    134 -    def getDeviceIssuesJSON(self):
    135          """
    136          Get devices with issues in a form suitable for a portlet on the
    137          dashboard.
    138
    139          @return: A JSON representation of a dictionary describing devices
    140          @rtype: "{
    141              'columns':['Device', "Events'],
    142              'data':[
    143                  {'Device':'<a href=/>', 'Events':'<div/>'},
    144                  {'Device':'<a href=/>', 'Events':'<div/>'},
    145              ]}"
    146          """
    147          mydict = {'columns':[], 'data':[]}
    148          mydict['columns'] = ['Device', 'Events']
    149          deviceinfo = self.getDeviceDashboard()
    150          for alink, pill in deviceinfo:
    151              mydict['data'].append({'Device':alink,
    152                                     'Events':pill})
    153          return mydict
    154
    155 -    def getDeviceDashboard(self):
    156          """return device info for bad device to dashboard"""
    157          zem = self.context.dmd.ZenEventManager
    158          devices = [d[0] for d in zem.getDeviceIssues(
    159                              severity=4, state=1)]
    160          devdata = []
    161          devclass = zem.getDmdRoot("Devices")
    162          getcolor = re.compile(r'class=\"evpill-(.*?)\"', re.S|re.I|re.M).search
    163          colors = "red orange yellow blue grey green".split()
    164          def pillcompare(a,b):
    165              a, b = map(lambda x:getcolor(x[1]), (a, b))
    166              def getindex(x):
    167                  try:
    168                      color = x.groups()[0]
    169                      smallcolor = x.groups()[0].replace('-acked','')
    170                      isacked = 'acked' in color
    171                      index = colors.index(x.groups()[0].replace('-acked',''))
    172                      if isacked: index += .5
    173                      return index
    174                  except: return 5
    175              a, b = map(getindex, (a, b))
    176              return cmp(a, b)
    177          for devname in devices:
    178              dev = devclass.findDevice(devname)
    179              if dev and ( dev.id == devname or dev.titleOrId() == devname ):
    180                  if (not zem.checkRemotePerm(ZEN_VIEW, dev)
    181                      or dev.productionState < zem.prodStateDashboardThresh
    182                      or dev.priority < zem.priorityDashboardThresh):
    183                      continue
    184                  alink = dev.getPrettyLink()
    185                  try:
    186                      pill = getEventPillME(zem, dev)[0]
    187                  except IndexError:
    188                      continue
    189                  evts = [alink,pill]
    190                  devdata.append(evts)
    191          devdata.sort(pillcompare)
    192          return devdata[:100]
    193
    194
    195 -class HeartbeatPortletView(BrowserView):
    196      """
    197      Heartbeat issues in YUI table form, for the dashboard portlet
    198      """
    199 -    def __call__(self):
    200          return self.getHeartbeatIssuesJSON()
    201
    202      @json
    203 -    def getHeartbeatIssuesJSON(self):
    204          """
    205          Get heartbeat issues in a form suitable for a portlet on the dashboard.
    206
    207          @return: A JSON representation of a dictionary describing heartbeats
    208          @rtype: "{
    209              'columns':['Device', 'Daemon', 'Seconds'],
    210              'data':[
    211                  {'Device':'<a href=/>', 'Daemon':'zenhub', 'Seconds':10}
    212              ]}"
    213          """
    214          mydict = {'columns':[], 'data':[]}
    215          mydict['columns'] = ['Device', 'Daemon', 'Seconds']
    216          heartbeats = self.context.dmd.ZenEventManager.getHeartbeat()
    217          for Device, Daemon, Seconds, dummy in heartbeats:
    218              mydict['data'].append({'Device':Device,
    219                  'Daemon':Daemon, 'Seconds':Seconds})
    220          return mydict
    221
    222
    223 -class UserMessagesPortletView(BrowserView):
    224      """
    225      User messages in YUI table form, for the dashboard portlet.
    226      """
    227      @json
    228 -    def __call__(self):
    229          """
    230          Get heartbeat issues in a form suitable for a portlet on the dashboard.
    231
    232          @return: A JSON representation of a dictionary describing heartbeats
    233          @rtype: "{
    234              'columns':['Device', 'Daemon', 'Seconds'],
    235              'data':[
    236                  {'Device':'<a href=/>', 'Daemon':'zenhub', 'Seconds':10}
    237              ]}"
    238          """
    239          ICONS = ['/zport/dmd/img/agt_action_success-32.png',
    240                   '/zport/dmd/img/messagebox_warning-32.png',
    241                   '/zport/dmd/img/agt_stop-32.png']
    242          msgbox = messaging.IUserMessages(self.context)
    243          msgs = msgbox.get_messages()
    244          cols = ['Message']
    245          res = []
    246          for msg in msgs:
    247              res.append(dict(
    248                  title = msg.title,
    249                  imgpath = ICONS[msg.priority],
    250                  body = msg.body,
    251                  ago = relative_time(msg.timestamp),
    252                  deletelink = msg.absolute_url_path() + '/delMsg'
    253              ))
    254          res.reverse()
    255          return { 'columns': cols, 'data': res }
    256