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  from zope.event import notify
     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  from Products.Zuul.catalog.events import IndexingEvent
     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, getObjectsFromCatalog
     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          devices = getObjectsFromCatalog(catalog, {
    112              'path': "/".join(self.getPhysicalPath())}, LOG)
    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          devices = getObjectsFromCatalog(catalog, {
    128              'path': "/".join(self.getPhysicalPath())}, LOG)
    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
    413          AdministrativeRoleable.manage_addAdministrativeRole(self, newId)
    414          for dev in self.getSubDevices():
    415              dev = dev.primaryAq()
    416              dev.setAdminLocalRoles()
    417
    418          notify(IndexingEvent(self, ('allowedRolesAndUsers',), False))
    419          if REQUEST:
    420              messaging.IMessageSender(self).sendToBrowser(
    421                  'Role Added',
    422                  'Administrative role %s was added.' % newId
    423              )
    424              return self.callZenScreen(REQUEST)
    425
    426
    427 -    def manage_editAdministrativeRoles(self, ids=(), role=(),
    428                                          level=(), REQUEST=None):
    429          """
    430          Overrides AdministrativeRoleable.manage_editAdministrativeRoles
    431          Edit the administrators to this DeviceOrganizer
    432          """
    433          AdministrativeRoleable.manage_editAdministrativeRoles(
    434                                           self,ids,role,level)
    435          for dev in self.getSubDevices():
    436              dev = dev.primaryAq()
    437              dev.setAdminLocalRoles()
    438
    439          notify(IndexingEvent(self, ('allowedRolesAndUsers',), False))
    440          if REQUEST:
    441              messaging.IMessageSender(self).sendToBrowser(
    442                  'Role Added',
    443                  'Administrative roles were updated: %s' % ', '.join(ids)
    444              )
    445              return self.callZenScreen(REQUEST)
    446
    447
    448 -    def manage_deleteAdministrativeRole(self, delids=(), REQUEST=None):
    449          """
    450          Overrides AdministrativeRoleable.manage_deleteAdministrativeRole
    451          Deletes administrators to this DeviceOrganizer
    452
    453          @param delids: Users to delete from this Organizer
    454          @type delids: tuple of strings
    455          """
    456          AdministrativeRoleable.manage_deleteAdministrativeRole(self, delids)
    457          for dev in self.getSubDevices():
    458              dev = dev.primaryAq()
    459              dev.setAdminLocalRoles()
    460
    461          notify(IndexingEvent(self, ('allowedRolesAndUsers',), False))
    462          if REQUEST:
    463              if delids:
    464                  messaging.IMessageSender(self).sendToBrowser(
    465                      'Roles Deleted',
    466                      'Administrative roles were deleted: %s' % ', '.join(delids)
    467                  )
    468              return self.callZenScreen(REQUEST)
    469
    470
    471 -    def manage_snmpCommunity(self, REQUEST=None):
    472          """reset Community on all devices in this Organizer.
    473          """
    474          [ d.manage_snmpCommunity() for d in self.getSubDevices() ]
    475          if REQUEST:
    476              return self.callZenScreen(REQUEST)
    477
    478 -    def setManageIp(self, REQUEST=None):
    479          """reset ip on all devices in this Organizer.
    480          """
    481          [ d.setManageIp() for d in self.getSubDevices() ]
    482          if REQUEST:
    483              return self.callZenScreen(REQUEST)
    484
    485 -    def collectDevice(self, REQUEST=None):
    486          """model all devices in this Organizer.
    487          """
    488          [ d.collectDevice() for d in self.getSubDevices() ]
    489          if REQUEST:
    490              return self.callZenScreen(REQUEST)
    491
    492 -    def _status(self, type, devrel="devices"):
    493          """build status info for device in this device group"""
    494          status = 0
    495          statatt = "get%sStatusNumber" % type
    496          devices = getattr(self, devrel, None)
    497          if not devices:
    498              raise AttributeError( "%s not found on %s" % (devrel, self.id) )
    499          for device in devices():
    500              if getattr(device, statatt, -1)() > 0:
    501                  status += 1
    502          return status
    503
    504 -    def statusColor(self, status):
    505          """colors for status fields for device groups"""
    506          retval = '#00ff00'
    507          if status == -1:
    508              retval = "#d02090"
    509          elif status == 1:
    510              retval = '#ffff00'
    511          elif status == 2:
    512              retval = '#ff9900'
    513          elif status > 2:
    514              retval = '#ff0000'
    515          return retval
    516
    517 -    def getUserCommandTargets(self):
    518          ''' Called by Commandable.doCommand() to ascertain objects on which
    519          a UserCommand should be executed.
    520          '''
    521          return self.getSubDevices()
    522
    523 -    def getUrlForUserCommands(self):
    524          return self.getPrimaryUrlPath() + '/deviceOrganizerManage'
    525
    526 -    def getLinks(self, recursive=True):
    527          """ Return all Links on all interfaces on all
    528              Devices in this Organizer
    529          """
    530          alllinks = []
    531          if recursive:
    532              devices = self.getSubDevicesGen()
    533          else:
    534              devices = self.devices.objectValuesGen()
    535          for device in devices:
    536              alllinks.extend(list(device.getLinks()))
    537          return alllinks
    538
    539      security.declareProtected(ZEN_VIEW, 'getIconPath')
    540 -    def getIconPath(self):
    541          """ Override the zProperty icon path and return a folder
    542          """
    543          return "/zport/dmd/img/icons/folder.png"
    544
    545      security.declareProtected(ZEN_VIEW, 'getPrettyLink')
    546 -    def getPrettyLink(self, noicon=False, shortDesc=False):
    547          """ Gets a link to this object, plus an icon """
    548          href = self.getPrimaryUrlPath().replace('%','%%')
    549          linktemplate = "<a href='"+href+"' class='prettylink'>%s</a>"
    550          icon = ("<div class='device-icon-container'> "
    551                  "<img class='device-icon' src='%s'/> "
    552                  "</div>") % self.getIconPath()
    553          name = self.getPrimaryDmdId()
    554          if noicon: icon=''
    555          if shortDesc: name = self.id
    556          rendered = icon + name
    557          if not self.checkRemotePerm("View", self):
    558              return rendered
    559          else:
    560              return linktemplate % rendered
    561
    562  InitializeClass(DeviceOrganizer)
    563