Package Products :: Package ZenModel :: Module DeviceOrganizer |
[hide private]
[frames] | no frames]

# Source Code for Module Products.ZenModel.DeviceOrganizer

      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  __doc__ = """DeviceOrganizer
     15  Base class for device organizers
     16  """
     17
     18  from itertools import ifilter
     19  from types import StringTypes
     20
     21  from AccessControl import ClassSecurityInfo
     22  from Globals import InitializeClass
     23
     24  from Organizer import Organizer
     25  from DeviceManagerBase import DeviceManagerBase
     26  from Commandable import Commandable
     27  from ZenMenuable import ZenMenuable
     28  from MaintenanceWindowable import MaintenanceWindowable
     29  from AdministrativeRoleable import AdministrativeRoleable
     30
     31  from Products.CMFCore.utils import getToolByName
     32
     33  from Products.ZenRelations.RelSchema import *
     34  from Products.ZenWidgets.interfaces import IMessageSender
     35
     36  from ZenossSecurity import *
     37
     38  from Products.ZenUtils.Utils import unused
     39  from Products.ZenWidgets import messaging
     40
     41  import logging
     42  LOG = logging.getLogger('ZenModel.DeviceOrganizer')
     43
     44 -class DeviceOrganizer(Organizer, DeviceManagerBase, Commandable, ZenMenuable,
     45                          MaintenanceWindowable, AdministrativeRoleable):
     46      """
     47      DeviceOrganizer is the base class for device organizers.
     48      It has lots of methods for rolling up device statistics and information.
     49      """
     50
     51      security = ClassSecurityInfo()
     52
     53      # Screen action bindings (and tab definitions)
     54      factory_type_information = (
     55          {
     56              'immediate_view' : 'deviceOrganizerStatus',
     57              'actions'        :
     58              (
     59                  { 'id'            : 'status'
     60                  , 'name'          : 'Status'
     61                  , 'action'        : 'deviceOrganizerStatus'
     62                  , 'permissions'   : (ZEN_VIEW, )
     63                  },
     64                  { 'id'            : 'events'
     65                  , 'name'          : 'Events'
     66                  , 'action'        : 'viewEvents'
     67                  , 'permissions'   : (ZEN_VIEW, )
     68                  },
     69  #                { 'id'            : 'historyEvents'
     70  #                , 'name'          : 'History'
     71  #                , 'action'        : 'viewHistoryEvents'
     72  #                , 'permissions'   : (ZEN_VIEW, )
     73  #                },
     74                  { 'id'            : 'manage'
     75                  , 'name'          : 'Administration'
     76                  , 'action'        : 'deviceOrganizerManage'
     77                  , 'permissions'   : (ZEN_MANAGE_DMD,)
     78                  },
     79              )
     80           },
     81          )
     82
     83      _relations =  Organizer._relations + (
     84          ("maintenanceWindows", ToManyCont(
     85              ToOne, "Products.ZenModel.MaintenanceWindow", "productionState")),
     86          ("adminRoles", ToManyCont(
     87              ToOne,"Products.ZenModel.AdministrativeRole","managedObject")),
     88          ('userCommands', ToManyCont(
     89              ToOne, 'Products.ZenModel.UserCommand', 'commandable')),
     90          ('zenMenus', ToManyCont(
     91              ToOne, 'Products.ZenModel.ZenMenu', 'menuable')),
     92         )
     93
     94      security.declareProtected(ZEN_COMMON, "getSubDevices")
     95 -    def getSubDevices(self, devfilter=None):
     96          """
     97          Get all the devices under an instance of a DeviceOrganizer
     98
     99          @param devfilter: Filter function applied to returned list
    100          @type devfilter: function
    101          @return: Devices
    102          @rtype: list
    103
    104          """
    105          catalog = getToolByName(self.dmd.Devices, self.dmd.Devices.default_catalog)
    106
    107          if not 'path' in catalog.indexes():
    108              LOG.warn('Please run zenmigrate to create device path indexes.')
    109              return self.getSubDevices_recursive(devfilter)
    110
    111          brains = catalog(path="/".join(self.getPhysicalPath()))
    112          devices = (b.getObject() for b in brains)
    113          devices = ifilter(lambda dev:self.checkRemotePerm(ZEN_VIEW, dev),
    114                            devices)
    115          devices = ifilter(devfilter, devices)
    116          return list(devices)
    117
    118      security.declareProtected(ZEN_VIEW, "getSubDevicesGen")
    119 -    def getSubDevicesGen(self):
    120          """get all the devices under and instance of a DeviceGroup"""
    121          catalog = getToolByName(self.dmd.Devices, self.dmd.Devices.default_catalog)
    122
    123          if not 'path' in catalog.indexes():
    124              LOG.warn('Please run zenmigrate to create device path indexes.')
    125              yield self.getSubDevicesGen_recursive(devfilter)
    126
    127          brains = catalog(path="/".join(self.getPhysicalPath()))
    128          devices = (b.getObject() for b in brains)
    129          devices = ifilter(lambda dev:self.checkRemotePerm(ZEN_VIEW, dev),
    130                            devices)
    131          for device in devices:
    132              yield device
    133
    134      security.declareProtected(ZEN_COMMON, "getSubDevices_recursive")
    135 -    def getSubDevices_recursive(self, devfilter=None, devrel="devices"):
    136          devrelobj = getattr(self, devrel, None)
    137          if not devrelobj:
    138              raise AttributeError( "%s not found on %s" % (devrel, self.id) )
    139          devices = filter(devfilter, devrelobj())
    140          devices = [ dev for dev in devices
    141                      if self.checkRemotePerm(ZEN_VIEW, dev)]
    142          for subgroup in self.children(checkPerm=False):
    143              devices.extend(subgroup.getSubDevices_recursive(devfilter, devrel))
    144          return devices
    145
    146      security.declareProtected(ZEN_VIEW, "getSubDevicesGen")
    147 -    def getSubDevicesGen_recursive(self, devrel="devices"):
    148          """get all the devices under and instance of a DeviceGroup"""
    149          devrelobj = getattr(self, devrel, None)
    150          if not devrelobj:
    151              raise AttributeError( "%s not found on %s" % (devrel, self.id) )
    152          for dev in devrelobj.objectValuesGen():
    153              yield dev
    154          for subgroup in self.children():
    155              for dev in subgroup.getSubDevicesGen_recursive(devrel):
    156                  yield dev
    157
    158 -    def getSubDevicesGenTest(self, devrel="devices"):
    159          """get all the devices under and instance of a DeviceGroup"""
    160          devices = getattr(self, devrel, None)
    161          if not devices:
    162              raise AttributeError( "%s not found on %s" % (devrel, self.id) )
    163
    164
    165 -    def getMonitoredComponents(self):
    166          """Return monitored components for devices within this DeviceOrganizer.
    167          """
    168          cmps = []
    169          for dev in self.getSubDevicesGen():
    170              cmps.extend(dev.getMonitoredComponents())
    171          return cmps
    172
    173
    174 -    def getAllCounts(self, devrel="devices"):
    175          """Count all devices within a device group and get the
    176          ping and snmp counts as well"""
    177          devices = getattr(self, devrel)
    178          pingStatus = 0
    179          snmpStatus = 0
    180          devCount = devices.countObjects()
    181          for dev in devices():
    182              if dev.getPingStatusNumber() > 0:
    183                  pingStatus += 1
    184              if dev.getSnmpStatusNumber() > 0:
    185                  snmpStatus += 1
    186          counts = [devCount, pingStatus, snmpStatus]
    187          for group in self.children():
    188              sc = group.getAllCounts()
    189              for i in range(3): counts[i] += sc[i]
    190          return counts
    191
    192
    193 -    def countDevices(self, devrel="devices"):
    194          """count all devices with in a device group"""
    195          unused(devrel)
    196          count = self.devices.countObjects()
    197          for group in self.children():
    198              count += group.countDevices()
    199          return count
    200
    201
    202 -    def pingStatus(self, devrel="devices"):
    203          """aggrigate ping status for all devices in this group and below"""
    204          status = self._status("Ping", devrel)
    205          for group in self.children():
    206              status += group.pingStatus()
    207          return status
    208
    209
    210 -    def snmpStatus(self, devrel="devices"):
    211          """aggrigate snmp status for all devices in this group and below"""
    212          status = self._status("Snmp", devrel)
    213          for group in self.children():
    214              status += group.snmpStatus()
    215          return status
    216
    217
    218 -    def _buildDeviceList(self, deviceNames):
    219          """Build a device list for set methods"""
    220          if isinstance(deviceNames, basestring):
    221              deviceNames = [deviceNames]
    222          return [d.primaryAq() for d in self.getSubDevices()
    223                  if deviceNames is None or d.id in deviceNames
    224                  or d.getPrimaryId() in deviceNames]
    225
    226
    227 -    def deviceClassMoveTargets(self):
    228          """Return list of all organizers excluding our self."""
    229          targets = filter(lambda x: x != self.getOrganizerName(),
    230              self.dmd.Devices.getOrganizerNames())
    231          targets.sort(lambda x,y: cmp(x.lower(), y.lower()))
    232          return targets
    233
    234
    235 -    def moveDevicesToClass(self, moveTarget, deviceNames=None, REQUEST=None):
    236          """Move Devices from one DeviceClass to Another"""
    237          if deviceNames is None:
    238              if REQUEST:
    239                  messaging.IMessageSender(self).sendToBrowser(
    240                      'Error',
    241                      'No devices were selected',
    242                      priority=messaging.WARNING
    243                  )
    244              return self.callZenScreen(REQUEST)
    245          deviceNames = [ x.split('/')[-1] for x in deviceNames ]
    246          return self.dmd.Devices.moveDevices(moveTarget, deviceNames, REQUEST)
    247
    248
    249 -    def _handleOrganizerCall(self, arg=None, deviceNames=None, \
    250                                  isOrganizer=False, REQUEST=None, \
    251                                  deviceMethod=None):
    252          """ Handle the many many methods that simply call one
    253          method on device differently"""
    254          #check to see if we have the essentials to work with
    255          if not deviceMethod: return
    256          if deviceNames is None and not isOrganizer:
    257              if REQUEST:
    258                  messaging.IMessageSender(self).sendToBrowser(
    259                      'Error',
    260                      'No devices were selected',
    261                      priority=messaging.WARNING
    262                  )
    263              return self.callZenScreen(REQUEST)
    264          for dev in self._buildDeviceList(deviceNames):
    265              devMethod = getattr(dev, deviceMethod, None)
    266              if devMethod and arg:
    267                  devMethod(arg)
    268              elif devMethod:
    269                  devMethod()
    270
    271
    272 -    def _buildReturnMessage(self, title, message, paths=None, \
    273                                 checkPaths=False):
    274          """build the standard return message for the various set
    275          methods"""
    276          if checkPaths:
    277              if paths:
    278                  if type(paths) not in StringTypes:
    279                      paths = ", ".join(paths)
    280                  message += paths
    281              else:
    282                  message = "%s unset" % message.split(" ")[0]
    283          if self.REQUEST.has_key('oneKeyValueSoInstanceIsntEmptyAndEvalToFalse'):
    284              return message
    285          else:
    286              IMessageSender(self).sendToBrowser(title, message)
    287              return self.callZenScreen(self.REQUEST)
    288
    289
    290      security.declareProtected(ZEN_CHANGE_DEVICE_PRODSTATE, 'setProdState')
    291 -    def setProdState(self, state, deviceNames=None,
    292                          isOrganizer=False, REQUEST=None):
    293          """Set production state of all devices in this Organizer.
    294          """
    295          self._handleOrganizerCall(state, deviceNames, isOrganizer, \
    296                                      REQUEST, "setProdState")
    297          if REQUEST:
    298              statename = self.convertProdState(state)
    299              msg = "Production state set to %s for %s." % (statename,
    300                                                            " ".join(deviceNames))
    301              return self._buildReturnMessage("Production State Changed", msg)
    302
    303
    304 -    def setPriority(self, priority, deviceNames=None,
    305                      isOrganizer=False, REQUEST=None):
    306          """Set prioirty of all devices in this Organizer.
    307          """
    308          self._handleOrganizerCall(priority, deviceNames, isOrganizer, \
    309                                      REQUEST, "setPriority")
    310          if REQUEST:
    311              priname = self.convertPriority(priority)
    312              msg = "Priority set to %s for %s." % (priname,
    313                                                    " ".join(deviceNames))
    314              return self._buildReturnMessage('Priority Changed', msg)
    315
    316
    317 -    def setPerformanceMonitor(self, performanceMonitor=None, deviceNames=None,
    318                                  isOrganizer=False, REQUEST=None):
    319          """ Provide a method to set performance monitor from any organizer """
    320          if not performanceMonitor:
    321              if REQUEST:
    322                  messaging.IMessageSender(self).sendToBrowser(
    323                      'Error',
    324                      'No monitor was selected',
    325                      priority=messaging.WARNING
    326                  )
    327              return self.callZenScreen(REQUEST)
    328          self._handleOrganizerCall(performanceMonitor, deviceNames, isOrganizer, \
    329                                      REQUEST, "setPerformanceMonitor")
    330          if REQUEST:
    331              msg = "Collector set to %s" % (performanceMonitor)
    332              return self._buildReturnMessage('Collector Set', msg)
    333
    334
    335 -    def setGroups(self, groupPaths=None, deviceNames=None,
    336                      isOrganizer=False, REQUEST=None):
    337          """ Provide a method to set device groups from any organizer """
    338          if not groupPaths: groupPaths = []
    339          self._handleOrganizerCall(groupPaths, deviceNames, isOrganizer, \
    340                                      REQUEST, "setGroups")
    341          if REQUEST:
    342              msg = "Groups set to"
    343              return self._buildReturnMessage('Groups Set', msg, groupPaths, True)
    344
    345
    346 -    def setSystems(self, systemPaths=None, deviceNames=None,
    347                      isOrganizer=False, REQUEST=None):
    348          """ Provide a method to set device systems from any organizer """
    349          if not systemPaths: systemPaths = []
    350          self._handleOrganizerCall(systemPaths, deviceNames, isOrganizer, \
    351                                      REQUEST, "setSystems")
    352          if REQUEST:
    353              msg = "Systems set to"
    354              return self._buildReturnMessage('Systems Set', msg, systemPaths, True)
    355
    356 -    def setLocation(self, locationPath="", deviceNames=None,
    357                      isOrganizer=False, REQUEST=None):
    358          """ Provide a method to set device location from any organizer """
    359          self._handleOrganizerCall(locationPath, deviceNames, isOrganizer, \
    360                                      REQUEST, "setLocation")
    361          if REQUEST:
    362              msg = "Location set to %s" % locationPath
    363              return self._buildReturnMessage('Location Set', msg)
    364
    365 -    def unlockDevices(self, deviceNames=None, isOrganizer=False, REQUEST=None):
    366          """Unlock devices"""
    367          self._handleOrganizerCall(None, deviceNames, isOrganizer, \
    368                                      REQUEST, "unlock")
    369          if REQUEST:
    370              msg = "Devices unlocked"
    371              return self._buildReturnMessage('Devices Unlocked', msg)
    372
    373 -    def lockDevicesFromDeletion(self, deviceNames=None,
    374                      sendEventWhenBlocked=None, isOrganizer=False, REQUEST=None):
    375          """Lock devices from being deleted"""
    376          self._handleOrganizerCall(sendEventWhenBlocked, deviceNames, isOrganizer, \
    377                                      REQUEST, "lockFromDeletion")
    378          if REQUEST:
    379              msg = "Devices locked from deletion"
    380              return self._buildReturnMessage('Devices Locked', msg)
    381
    382 -    def lockDevicesFromUpdates(self, deviceNames=None,
    383                  sendEventWhenBlocked=None, isOrganizer=False, REQUEST=None):
    384          """Lock devices from being deleted or updated"""
    385          self._handleOrganizerCall(sendEventWhenBlocked, deviceNames, isOrganizer, \
    386                                      REQUEST, "lockFromUpdates")
    387          if REQUEST:
    388              msg = "Devices locked from updates and deletion"
    389              return self._buildReturnMessage('Devices Locked', msg)
    390
    391
    392 -    def index_object(self):
    393          """No action.
    394          Index of subdevices will happen in manage_addAdministrativeRole
    395          """
    396          pass
    397
    398 -    def unindex_object(self):
    399          """No action.
    400          Unindex of subdevices will happen in manage_deleteAdministrativeRole
    401          """
    402          pass
    403
    404 -    def manage_addAdministrativeRole(self, newId, REQUEST=None):
    405          """
    406          Overrides AdministrativeRoleable.manage_addAdministrativeRole
    407          Adds an administrator to this DeviceOrganizer
    408
    409          @param userid: User to make an administrator of this Organizer
    410          @type userid: string
    411          """
    412          AdministrativeRoleable.manage_addAdministrativeRole(self, newId)
    413          for dev in self.getSubDevices():
    414              dev = dev.primaryAq()
    415              dev.setAdminLocalRoles()
    416          if REQUEST:
    417              messaging.IMessageSender(self).sendToBrowser(
    418                  'Role Added',
    419                  'Administrative role %s was added.' % newId
    420              )
    421              return self.callZenScreen(REQUEST)
    422
    423
    424 -    def manage_editAdministrativeRoles(self, ids=(), role=(),
    425                                          level=(), REQUEST=None):
    426          """
    427          Overrides AdministrativeRoleable.manage_editAdministrativeRoles
    428          Edit the administrators to this DeviceOrganizer
    429          """
    430          AdministrativeRoleable.manage_editAdministrativeRoles(
    431                                           self,ids,role,level)
    432          for dev in self.getSubDevices():
    433              dev = dev.primaryAq()
    434              dev.setAdminLocalRoles()
    435          if REQUEST:
    436              messaging.IMessageSender(self).sendToBrowser(
    437                  'Role Added',
    438                  'Administrative roles were updated: %s' % ', '.join(ids)
    439              )
    440              return self.callZenScreen(REQUEST)
    441
    442
    443 -    def manage_deleteAdministrativeRole(self, delids=(), REQUEST=None):
    444          """
    445          Overrides AdministrativeRoleable.manage_deleteAdministrativeRole
    446          Deletes administrators to this DeviceOrganizer
    447
    448          @param delids: Users to delete from this Organizer
    449          @type delids: tuple of strings
    450          """
    451          AdministrativeRoleable.manage_deleteAdministrativeRole(self, delids)
    452          for dev in self.getSubDevices():
    453              dev = dev.primaryAq()
    454              dev.setAdminLocalRoles()
    455          if REQUEST:
    456              if delids:
    457                  messaging.IMessageSender(self).sendToBrowser(
    458                      'Roles Deleted',
    459                      'Administrative roles were deleted: %s' % ', '.join(delids)
    460                  )
    461              return self.callZenScreen(REQUEST)
    462
    463
    464 -    def manage_snmpCommunity(self, REQUEST=None):
    465          """reset Community on all devices in this Organizer.
    466          """
    467          [ d.manage_snmpCommunity() for d in self.getSubDevices() ]
    468          if REQUEST:
    469              return self.callZenScreen(REQUEST)
    470
    471 -    def setManageIp(self, REQUEST=None):
    472          """reset ip on all devices in this Organizer.
    473          """
    474          [ d.setManageIp() for d in self.getSubDevices() ]
    475          if REQUEST:
    476              return self.callZenScreen(REQUEST)
    477
    478 -    def collectDevice(self, REQUEST=None):
    479          """model all devices in this Organizer.
    480          """
    481          [ d.collectDevice() for d in self.getSubDevices() ]
    482          if REQUEST:
    483              return self.callZenScreen(REQUEST)
    484
    485 -    def _status(self, type, devrel="devices"):
    486          """build status info for device in this device group"""
    487          status = 0
    488          statatt = "get%sStatusNumber" % type
    489          devices = getattr(self, devrel, None)
    490          if not devices:
    491              raise AttributeError( "%s not found on %s" % (devrel, self.id) )
    492          for device in devices():
    493              if getattr(device, statatt, -1)() > 0:
    494                  status += 1
    495          return status
    496
    497 -    def statusColor(self, status):
    498          """colors for status fields for device groups"""
    499          retval = '#00ff00'
    500          if status == -1:
    501              retval = "#d02090"
    502          elif status == 1:
    503              retval = '#ffff00'
    504          elif status == 2:
    505              retval = '#ff9900'
    506          elif status > 2:
    507              retval = '#ff0000'
    508          return retval
    509
    510 -    def getUserCommandTargets(self):
    511          ''' Called by Commandable.doCommand() to ascertain objects on which
    512          a UserCommand should be executed.
    513          '''
    514          return self.getSubDevices()
    515
    516 -    def getUrlForUserCommands(self):
    517          return self.getPrimaryUrlPath() + '/deviceOrganizerManage'
    518
    519 -    def getLinks(self, recursive=True):
    520          """ Return all Links on all interfaces on all
    521              Devices in this Organizer
    522          """
    523          alllinks = []
    524          if recursive:
    525              devices = self.getSubDevicesGen()
    526          else:
    527              devices = self.devices.objectValuesGen()
    528          for device in devices:
    529              alllinks.extend(list(device.getLinks()))
    530          return alllinks
    531
    532      security.declareProtected(ZEN_VIEW, 'getIconPath')
    533 -    def getIconPath(self):
    534          """ Override the zProperty icon path and return a folder
    535          """
    536          return "/zport/dmd/img/icons/folder.png"
    537
    538      security.declareProtected(ZEN_VIEW, 'getPrettyLink')
    539 -    def getPrettyLink(self, noicon=False, shortDesc=False):
    540          """ Gets a link to this object, plus an icon """
    541          href = self.getPrimaryUrlPath().replace('%','%%')
    542          linktemplate = "<a href='"+href+"' class='prettylink'>%s</a>"
    543          icon = ("<div class='device-icon-container'> "
    544                  "<img class='device-icon' src='%s'/> "
    545                  "</div>") % self.getIconPath()
    546          name = self.getPrimaryDmdId()
    547          if noicon: icon=''
    548          if shortDesc: name = self.id
    549          rendered = icon + name
    550          if not self.checkRemotePerm("View", self):
    551              return rendered
    552          else:
    553              return linktemplate % rendered
    554
    555  InitializeClass(DeviceOrganizer)
    556