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

# Source Code for Module Products.ZenModel.Organizer

      1  ##############################################################################
      2  #
      3  # Copyright (C) Zenoss, Inc. 2007, all rights reserved.
      4  #
      5  # This content is made available according to terms specified in
      6  # License.zenoss under the directory where your Zenoss product is installed.
      7  #
      8  ##############################################################################
      9
     10
     11  __doc__ = """Organizer
     12  Base class for all Zenoss organizers
     13  """
     14
     15  from Globals import InitializeClass
     16  from Acquisition import aq_parent
     17  from AccessControl import ClassSecurityInfo, getSecurityManager
     18
     19  from Products.ZenRelations.RelSchema import *
     20  from Products.ZenUtils.Exceptions import ZentinelException
     21  from Products.ZenWidgets import messaging
     22  from Products.ZenMessaging.audit import audit
     23  from Products.ZenUtils.Utils import getDisplayType, getDisplayName
     24  from Products.ZenUtils.deprecated import deprecated
     25
     26  from EventView import EventView
     27  from ZenModelRM import ZenModelRM
     28  from ZenossSecurity import *
     29
     30 -class Organizer(ZenModelRM, EventView):
     31      """
     32      The base for all hierarchical organization classes.  It allows Organizers
     33      to be addressed and created with file system like paths like
     34      /Devices/Servers.  Organizers have a containment relation called children.
     35      Subclasses must define the attribute:
     36
     37      dmdRootName - root in the dmd database for this organizer
     38      """
     39
     40      _properties = (
     41                      {'id':'description', 'type':'string', 'mode':'w'},
     42                     )
     43
     44      _relations = ZenModelRM._relations
     45
     46      security = ClassSecurityInfo()
     47      security.declareObjectProtected(ZEN_VIEW)
     48
     49 -    def __init__(self, id, description = ''):
     50          """
     51          @param id: Name of this organizer
     52          @type id: string
     53          @param description: A decription of this organizer
     54          @type description: string
     55          @rtype: Organizer
     56          """
     57          ZenModelRM.__init__(self, id)
     58          self.description = description
     59
     60 -    def urlLink(self, text=None, url=None, attrs={}):
     61          """
     62          Override urlLink to return a link with the full path of the organizer.
     63
     64          >>> dmd.Devices.Server.urlLink()
     65          '<a href="/zport/dmd/Devices/Server">/Server</a>'
     66          """
     67          if text is None: text = self.getOrganizerName()
     68          return ZenModelRM.urlLink(self, text=text, url=url, attrs=attrs)
     69
     70
     71 -    def childMoveTargets(self):
     72          """
     73          Returns a list of all organizer names
     74          under the same root excluding ourselves
     75
     76          @return: A list of organizers excluding our self.
     77          @rtype: list
     78          @todo: We should be using either deviceMoveTargets or childMoveTargets
     79
     80          >>> dmd.Events.getOrganizerName() in dmd.Events.childMoveTargets()
     81          False
     82          """
     83          myname = self.getOrganizerName()
     84          return filter(lambda x: x != myname,
     85                      self.getDmdRoot(self.dmdRootName).getOrganizerNames())
     86
     87 -    def getChildMoveTarget(self, moveTargetName):
     88          """
     89          Returns an organizer under the same root.
     90
     91          @param moveTargetName: Name of the organizer
     92          @type moveTargetName: string
     93          @rtype: Organizer
     94
     95          >>> dmd.Devices.getChildMoveTarget('Server')
     96          <DeviceClass at /zport/dmd/Devices/Server>
     97          """
     98          return self.getDmdRoot(self.dmdRootName).getOrganizer(moveTargetName)
     99
    100
    101      security.declareProtected(ZEN_COMMON, "children")
    102 -    def children(self, sort=False, checkPerm=True, spec=None):
    103          """
    104          Returns the immediate children of an organizer
    105
    106          @param sort: If True, sorts the returned children.
    107          @type sort: boolean
    108          @param checkPerm: If True, checks if the user has the permission
    109              to view each child.
    110          @type checkPerm: boolean
    111          @param spec: If set, returns children of the specified meta_type.
    112          @type spec: string
    113          @return: A list of children of the organizer
    114          @rtype: list
    115          @permission: ZEN_COMMON
    116
    117          >>> dmd.Devices.Printer.children()
    118          [<DeviceClass at /zport/dmd/Devices/Printer/Laser>,
    119          <DeviceClass at /zport/dmd/Devices/Printer/InkJet>]
    120          """
    121          if spec is None:
    122              spec = self.meta_type
    123          kids = self.objectValues(spec=spec)
    124          if checkPerm:
    125              kids = [ kid for kid in kids if self.checkRemotePerm(ZEN_VIEW, kid)]
    126          if sort:
    127              kids.sort(key=lambda x: x.primarySortKey())
    128          return kids
    129
    130
    131 -    def childIds(self, spec=None):
    132          """
    133          Returns the ids of the immediate children of an organizer
    134
    135          @param spec: If set, returns children of the specified meta_type.
    136          @type spec: string
    137          @return: Ids of children within our organizer
    138          @rtype: list
    139
    140          >>> 'Discovered' in dmd.Devices.childIds()
    141          True
    142          """
    143          if spec is None:
    144              spec = self.meta_type
    145              #spec = self.getDefaultSpecForChildren()
    146          return self.objectIds(spec=spec)
    147
    148
    149      security.declareProtected(ZEN_COMMON, "countChildren")
    150 -    def countChildren(self, spec=None):
    151          """
    152          Returns the number of all the children underneath an organizer
    153
    154          @param spec: If set, returns children of the specified meta_type.
    155          @type spec: string
    156          @return: A count of all our contained children.
    157          @rtype: integer
    158          @permission: ZEN_COMMON
    159
    160          """
    161          if spec is None:
    162              spec = self.meta_type
    163              #spec = self.getDefaultSpecForChildren()
    164          count = len(self.objectIds(spec=spec))
    165          for child in self.children(spec=spec):
    166              count += child.countChildren(spec=spec)
    167          return count
    168
    169
    170      security.declareProtected(ZEN_ADD, 'manage_addOrganizer')
    171 -    def manage_addOrganizer(self, newPath, factory=None, REQUEST=None):
    172          """
    173          Adds a new organizer under this organizer. if given a fully qualified
    174          path it will create an organizer at that path
    175
    176          @param newPath: Path of the organizer to be created
    177          @type newPath:  string
    178          @raise: ZentinelException
    179          @permission: ZEN_ADD
    180
    181          >>> dmd.Devices.manage_addOrganizer('/Devices/DocTest')
    182          """
    183          if factory is None:
    184              factory = self.__class__
    185          if not newPath: return self.callZenScreen(REQUEST)
    186          try:
    187              if newPath.startswith("/"):
    188                  org = self.createOrganizer(newPath)
    189              else:
    190                  org = factory(newPath)
    191                  self._setObject(org.id, org)
    192          except ZentinelException, e:
    193              if REQUEST:
    194                  messaging.IMessageSender(self).sendToBrowser(
    195                      'Error', e, priority=messaging.WARNING)
    196                  return self.callZenScreen(REQUEST)
    197          if REQUEST:
    198              audit(('UI', getDisplayType(org), 'Add'), org)
    199              messaging.IMessageSender(self).sendToBrowser(
    200                  'Organizer Added',
    201                  '%s "%s" was created.' % (getDisplayType(self), newPath)
    202              )
    203              return self.callZenScreen(REQUEST)
    204
    205
    206      security.declareProtected(ZEN_DELETE, 'manage_deleteOrganizer')
    207      @deprecated
    208 -    def manage_deleteOrganizer(self, orgname, REQUEST=None):
    209          """
    210          Deletes an organizer underneath this organizer
    211
    212          @param orgname: Name of the organizer to delete
    213          @type orgname: string
    214          @raise: KeyError
    215          @permission: ZEN_DELETE
    216
    217          >>> dmd.Devices.manage_deleteOrganizer('/Devices/Server/Linux')
    218          """
    219          if REQUEST:
    220              audit(('UI', getDisplayType(self), 'Delete'), orgname)
    221          if orgname.startswith("/"):
    222              try:
    223                  orgroot = self.getDmdRoot(self.dmdRootName)
    224                  organizer = orgroot.getOrganizer(orgname)
    225                  parent = aq_parent(organizer)
    226                  parent._delObject(organizer.getId())
    227              except KeyError:
    228                  pass  # we may have already deleted a sub object
    229          else:
    230              self._delObject(orgname)
    231          if REQUEST:
    232              messaging.IMessageSender(self).sendToBrowser(
    233                  'Organizer Deleted',
    234                  '%s "%s" was deleted.' % (getDisplayType(self), orgname)
    235              )
    236              return self.callZenScreen(REQUEST)
    237
    238
    239      security.declareProtected(ZEN_DELETE, 'manage_deleteOrganizers')
    240 -    def manage_deleteOrganizers(self, organizerPaths=None, REQUEST=None):
    241          """
    242          Delete a list of Organizers from the database using their ids.
    243
    244          @param organizerPaths: Names of organizer to be deleted
    245          @type organizerPaths: list
    246          @permission: ZEN_DELETE
    247
    248          >>> dmd.Devices.manage_deleteOrganizers(['/Devices/Server/Linux',
    249          ... '/Devices/Server/Windows'])
    250          """
    251          if not organizerPaths:
    252              messaging.IMessageSender(self).sendToBrowser(
    253                  'Error',
    254                  'No organizers were specified.',
    255                  priority=messaging.WARNING
    256              )
    257              return self.callZenScreen(REQUEST)
    258          for organizerName in organizerPaths:
    259              if REQUEST:
    260                  audit(('UI',getDisplayType(self),'Delete'), organizerName)
    261              self.manage_deleteOrganizer(organizerName)
    262          if REQUEST:
    263              plural = ''
    264              if len(organizerPaths) > 1: plural = 's'
    265              messaging.IMessageSender(self).sendToBrowser(
    266                  'Organizers Deleted',
    267                  '%s%s %s were deleted.' % (getDisplayType(self),
    268                                      plural, ', '.join(organizerPaths))
    269              )
    270              return self.callZenScreen(REQUEST)
    271
    272
    273 -    def deviceMoveTargets(self):
    274          """
    275          DEPRECATED - see childMoveTargets
    276          Return list of all organizers excluding our self.
    277
    278          @return: A sorted list of organizers excluding our self.
    279          @rtype: list
    280          @todo: We should be using either deviceMoveTargets or childMoveTargets
    281          """
    282          targets = filter(lambda x: x != self.getOrganizerName(),
    283                  self.getDmdRoot(self.dmdRootName).getOrganizerNames())
    284          return sorted(targets, key=lambda x: x.lower())
    285
    286
    287 -    def moveOrganizer(self, moveTarget, organizerPaths=None, REQUEST=None):
    288          """
    289          Move organizers under this organizer to another organizer
    290
    291          @param moveTarget: Name of the destination organizer
    292          @type moveTarget: string
    293          @param organizerPaths: Paths of organizers to be moved
    294          @type organizerPaths: list
    295
    296          >>> dmd.Events.Status.moveOrganizer('/Events/Ignore',
    297          ... ['Ping', 'Snmp'])
    298          """
    299          if not moveTarget or not organizerPaths: return self()
    300          target = self.getDmdRoot(self.dmdRootName).getOrganizer(moveTarget)
    301          movedStuff = False
    302          for organizerName in organizerPaths:
    303              if moveTarget.find(organizerName) > -1: continue
    304              obj = self._getOb(organizerName, None)
    305              if obj is None: continue
    306              obj._operation = 1 #move object
    307              self._delObject(organizerName)
    308              target._setObject(organizerName, obj)
    309              movedStuff = True
    310          if REQUEST:
    311              if movedStuff:
    312                  plural = ''
    313                  if len(organizerPaths) > 1: plural = 's'
    314                  for organizerName in organizerPaths:
    315                      audit(('UI', getDisplayType(self), 'Move'), organizerName, data_={'from':getDisplayName(self), 'to':getDisplayName(target)})
    316                  messaging.IMessageSender(self).sendToBrowser(
    317                      'Organizers Moved',
    318                      '%s%s %s were moved to %s.' % (getDisplayType(self),
    319                                  plural, ', '.join(organizerPaths), moveTarget)
    320                  )
    321              else:
    322                  messaging.IMessageSender(self).sendToBrowser(
    323                      'Error',
    324                      'No %s were moved.' % getDisplayType(self),
    325                      priority=messaging.WARNING
    326                  )
    327              return target.callZenScreen(REQUEST)
    328
    329
    330 -    def createOrganizer(self, path):
    331          """
    332          Creates an organizer with a specified path.
    333          Use manage_addOrganizer instead
    334
    335          @param path: Path of the organizer to create
    336          @type path: string
    337          @return: Organizer created with the specified path
    338          @rtype: Organizer
    339          """
    340          return self.createHierarchyObj(self.getDmdRoot(self.dmdRootName),
    341                                             path,self.__class__)
    342
    343
    344 -    def getOrganizer(self, path):
    345          """
    346          Get an organizer by path under the same root
    347
    348          @param path: Path of the organizer to retrieve
    349          @type path: string
    350          @return: Organizer with the specified path
    351          @rtype: Organizer
    352
    353          >>> dmd.Events.Status.getOrganizer('/Status/Snmp')
    354          <EventClass at /zport/dmd/Events/Status/Snmp>
    355          >>> dmd.Events.Status.getOrganizer('Status/Snmp')
    356          <EventClass at /zport/dmd/Events/Status/Snmp>
    357          >>> dmd.Events.Status.getOrganizer('/Events/Status/Snmp')
    358          <EventClass at /zport/dmd/Events/Status/Snmp>
    359          """
    360          if path.startswith("/"): path = path[1:]
    361          return self.getDmdRoot(self.dmdRootName).unrestrictedTraverse(path)
    362
    363
    364      security.declareProtected(ZEN_COMMON, "getOrganizerName")
    365 -    def getOrganizerName(self):
    366          """
    367          Return the DMD path of an Organizer without its dmdSubRel names.
    368
    369          @return: Name of this organizer
    370          @rtype: string
    371          @permission: ZEN_COMMON
    372
    373          >>> dmd.Events.Status.Snmp.getOrganizerName()
    374          '/Status/Snmp'
    375          """
    376          return self.getPrimaryDmdId(self.dmdRootName)
    377      getDmdKey = getOrganizerName
    378
    379
    380      security.declareProtected(ZEN_COMMON, "getOrganizerNames")
    381 -    def getOrganizerNames(self, addblank=False, checkPerm=True):
    382          """
    383          Returns a list of all organizer names under this organizer
    384
    385          @param addblank: If True, add a blank item in the list.
    386          @type addblank: boolean
    387          @return: The DMD paths of all Organizers below this instance.
    388          @rtype: list
    389          @permission: ZEN_COMMON
    390
    391          >>> dmd.Events.Security.getOrganizerNames()
    392          ['/Security', '/Security/Auth', '/Security/Conn',
    393          '/Security/Conn/Close', '/Security/Conn/Open', '/Security/Login',
    394          '/Security/Login/BadPass', '/Security/Login/Fail', '/Security/Sudo',
    395          '/Security/Virus']
    396          """
    397          groupNames = []
    398          user = getSecurityManager().getUser()
    399          if user.has_permission(ZEN_VIEW, self) or not checkPerm:
    400              groupNames.append(self.getOrganizerName())
    401          for subgroup in self.children(checkPerm=False):
    402              groupNames.extend(subgroup.getOrganizerNames())
    403          if self.id == self.dmdRootName:
    404              if addblank: groupNames.append("")
    405          groupNames.sort(key=lambda x: x.lower())
    406          return groupNames
    407
    408
    409 -    def _getCatalog(self):
    410          """
    411          Returns a catalog instance for this organizer.
    412
    413          @return: The catalog instance for this Organizer.
    414          @rtype: ZCatalog
    415          @note: Catalog is found using the attribute default_catalog.
    416          """
    417          catalog = None
    418          if hasattr(self, self.default_catalog):
    419              catalog = getattr(self, self.default_catalog)
    420          return catalog
    421
    422
    423      security.declareProtected(ZEN_COMMON, "getSubOrganizers")
    424 -    def getSubOrganizers(self):
    425          """
    426          Returns all the organizers under this organizer
    427
    428          @return: Organizers below this instance
    429          @rtype: list
    430          @permission: ZEN_COMMON
    431
    432          >>> dmd.Events.Security.getSubOrganizers()
    433          [<EventClass at /zport/dmd/Events/Security/Login>,
    434          <EventClass at /zport/dmd/Events/Security/Sudo>,
    435          <EventClass at /zport/dmd/Events/Security/Conn>,
    436          <EventClass at /zport/dmd/Events/Security/Virus>,
    437          <EventClass at /zport/dmd/Events/Security/Auth>,
    438          <EventClass at /zport/dmd/Events/Security/Login/BadPass>,
    439          <EventClass at /zport/dmd/Events/Security/Login/Fail>,
    440          <EventClass at /zport/dmd/Events/Security/Conn/Open>,
    441          <EventClass at /zport/dmd/Events/Security/Conn/Close>]
    442          """
    443          orgs = self.children()
    444          for child in self.children():
    445              orgs.extend(child.getSubOrganizers())
    446          return orgs
    447
    448      security.declareProtected(ZEN_COMMON, "getSubInstances")
    449 -    def getSubInstanceIds(self, rel):
    450          """
    451          Returns the object ids of all the instances of a specific relation
    452          under this organizer
    453
    454          @param rel: The name of the relation to traverse
    455          @type rel: string
    456          @return: The object ids of instances under an relation of this org
    457          @rtype: list
    458          @raise: AttributeError
    459          @permission: ZEN_COMMON
    460
    461          >>> dmd.Events.Security.Login.getSubInstanceIds('instances')
    462          ['MSExchangeIS Mailbox Store_1009', 'MSExchangeIS Mailbox Store_1011',
    463          'defaultmapping', 'dropbear', 'sshd', 'MSFTPSVC_100', 'W3SVC_100',
    464          'dropbear', 'remote(pam_unix)']
    465          """
    466          relobj = getattr(self, rel, None)
    467          if not relobj:
    468              raise AttributeError( "%s not found on %s" % (rel, self.id) )
    469          objs = relobj.objectIds()
    470          for suborg in self.children():
    471              objs.extend(suborg.getSubInstanceIds(rel))
    472          return objs
    473
    474      security.declareProtected(ZEN_COMMON, "getSubInstances")
    475 -    def getSubInstances(self, rel):
    476          """
    477          Returns the object isntances of a specific relation
    478          under this organizer
    479
    480          @param rel: The name of the relation to traverse
    481          @type rel: string
    482          @return: The object instances under an relation of this org
    483          @rtype: list
    484          @raise: AttributeError
    485          @permission: ZEN_COMMON
    486
    487          >>> dmd.Events.Security.Login.getSubInstances('instances')
    488          [<EventClassInst at /zport/dmd/Events/Security/Login/instances/MSExchangeIS Mailbox Store_1009>,
    489          <EventClassInst at /zport/dmd/Events/Security/Login/instances/MSExchangeIS Mailbox Store_1011>,
    490          <EventClassInst at /zport/dmd/Events/Security/Login/instances/defaultmapping>,
    491          <EventClassInst at /zport/dmd/Events/Security/Login/BadPass/instances/dropbear>,
    492          <EventClassInst at /zport/dmd/Events/Security/Login/BadPass/instances/sshd>,
    493          <EventClassInst at /zport/dmd/Events/Security/Login/Fail/instances/MSFTPSVC_100>,
    494          <EventClassInst at /zport/dmd/Events/Security/Login/Fail/instances/W3SVC_100>,
    495          <EventClassInst at /zport/dmd/Events/Security/Login/Fail/instances/dropbear>,
    496          <EventClassInst at /zport/dmd/Events/Security/Login/Fail/instances/remote(pam_unix)>]
    497          """
    498          relobj = getattr(self, rel, None)
    499          if not relobj:
    500              raise AttributeError( "%s not found on %s" % (rel, self.id) )
    501          objs = relobj()
    502          if not objs: objs = []
    503          for suborg in self.children():
    504              objs.extend(suborg.getSubInstances(rel))
    505          return objs
    506
    507      security.declareProtected(ZEN_COMMON, "getSubInstancesGen")
    508 -    def getSubInstancesGen(self, rel):
    509          """
    510          Returns the object isntances of a specific relation
    511          under this organizer
    512
    513          @param rel: The name of the relation to traverse
    514          @type rel: string
    515          @return: The object ids of instances under an relation of this org
    516          @rtype: generator
    517          @raise: AttributeError
    518          @permission: ZEN_COMMON
    519          """
    520          relobj = getattr(self, rel, None)
    521          if not relobj:
    522              raise AttributeError( "%s not found on %s" % (rel, self.id) )
    523          for obj in relobj.objectValuesGen():
    524              yield obj
    525          for suborg in self.children():
    526              for obj in suborg.getSubInstancesGen(rel):
    527                  yield obj
    528
    529 -    def exportXmlHook(self, ofile, ignorerels):
    530          """
    531          Calls exportXml on the children of this organizer
    532
    533          @param ofile: The file to output
    534          @type ofile: File
    535          @param ignorerels: Relations to ignore
    536          @type ignorerels: list
    537          """
    538          map(lambda o: o.exportXml(ofile, ignorerels), self.children())
    539
    540
    541  InitializeClass(Organizer)
    542