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