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

# Source Code for Module Products.ZenModel.DeviceClass

      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__="""DeviceClass
     15  The primary organizer of device objects, managing zProperties and
     16  their acquisition.
     17  """
     18
     19  import types
     20  import time
     21  import transaction
     22  import logging
     23  log = logging.getLogger('zen.DeviceClass')
     24
     25  import DateTime
     26  from Globals import DTMLFile
     27  from Globals import InitializeClass
     28  from Acquisition import aq_base, aq_chain
     29  from AccessControl import ClassSecurityInfo
     30  from AccessControl import Permissions as permissions
     31
     32  from Products.AdvancedQuery import MatchGlob, Or, Eq, RankByQueries_Max
     33  from Products.CMFCore.utils import getToolByName
     34
     35  from Products.ZenModel.ZenossSecurity import *
     36  from Products.ZenRelations.RelSchema import *
     37  from Products.ZenRelations.ZenPropertyManager import Z_PROPERTIES
     38  from Products.ZenUtils.Search import makeCaseInsensitiveFieldIndex
     39  from Products.ZenUtils.Search import makeCaseInsensitiveKeywordIndex
     40  from Products.ZenUtils.Search import makePathIndex, makeMultiPathIndex
     41  from Products.ZenUtils.Utils import importClass, zenPath
     42  from Products.ZenWidgets import messaging
     43
     44  from Products.ZenUtils.FakeRequest import FakeRequest
     45
     46  import RRDTemplate
     47  from DeviceOrganizer import DeviceOrganizer
     48  from ZenPackable import ZenPackable
     49  from TemplateContainer import TemplateContainer
     50
     51  _marker = "__MARKER___"
     52
     53 -def manage_addDeviceClass(context, id, title = None, REQUEST = None):
     54      """make a device class"""
     55      dc = DeviceClass(id, title)
     56      context._setObject(id, dc)
     57      if REQUEST is not None:
     58          REQUEST['RESPONSE'].redirect(context.absolute_url() + '/manage_main')
     59
     60
     61  addDeviceClass = DTMLFile('dtml/addDeviceClass',globals())
     62
     63
     64 -class DeviceClass(DeviceOrganizer, ZenPackable, TemplateContainer):
     65      """
     66      DeviceClass is a device organizer that manages the primary classification
     67      of device objects within the Zenoss system.  It manages properties
     68      that are inherited through acquisition that modify the behavior of
     69      many different sub systems within Zenoss.
     70      It also handles the creation of new devices in the system.
     71      """
     72
     73      # Organizer configuration
     74      dmdRootName = "Devices"
     75
     76      manageDeviceSearch = DTMLFile('dtml/manageDeviceSearch',globals())
     77      manageDeviceSearchResults = DTMLFile('dtml/manageDeviceSearchResults',
     78                                              globals())
     79
     80      portal_type = meta_type = event_key = "DeviceClass"
     81
     82      default_catalog = 'deviceSearch'
     83
     84      _properties = DeviceOrganizer._properties + (
     85                      {'id':'devtypes', 'type':'lines', 'mode':'w'},
     86                     )
     87
     88      _relations = DeviceOrganizer._relations + ZenPackable._relations + \
     89                  TemplateContainer._relations + (
     90          ("devices", ToManyCont(ToOne,"Products.ZenModel.Device","deviceClass")),
     91          )
     92
     93      # Screen action bindings (and tab definitions)
     94      factory_type_information = (
     95          {
     96              'id'             : 'DeviceClass',
     97              'meta_type'      : 'DeviceClass',
     98              'description'    : """Base class for all devices""",
     99              'icon'           : 'DeviceClass_icon.gif',
    100              'product'        : 'ZenModel',
    101              'factory'        : 'manage_addDeviceClass',
    102              'immediate_view' : 'deviceOrganizerStatus',
    103              'actions'        :
    104              (
    105                  { 'name'          : 'Classes'
    106                  , 'action'        : 'deviceOrganizerStatus'
    107                  , 'permissions'   : ( permissions.view, )
    108                  },
    109                  { 'name'          : 'Events'
    110                  , 'action'        : 'viewEvents'
    111                  , 'permissions'   : (  permissions.view, )
    112                  },
    113                  { 'name'          : 'zProperties'
    114                  , 'action'        : 'zPropertyEdit'
    115                  , 'permissions'   : (permissions.view,)
    116                  },
    117                  { 'name'          : 'Templates'
    118                  , 'action'        : 'perfConfig'
    119                  , 'permissions'   : ('Manage DMD',)
    120                  },
    121              )
    122           },
    123          )
    124
    125      security = ClassSecurityInfo()
    126
    127 -    def getPeerDeviceClassNames(self, pyclass=None):
    128          """
    129          Return a list of all device paths that have the Python class pyclass
    130
    131          @param pyclass: Python class (default is this class)
    132          @type pyclass: Python class
    133          @return: list of device paths
    134          @rtype: list of strings
    135          """
    136          dcnames = []
    137          if pyclass == None:
    138              pyclass = self.getPythonDeviceClass()
    139          dclass = self.getDmdRoot("Devices")
    140          for orgname in dclass.getOrganizerNames():
    141              org = dclass.getOrganizer(orgname)
    142              if pyclass == org.getPythonDeviceClass():
    143                  dcnames.append(orgname)
    144          dcnames.sort(lambda a, b: cmp(a.lower(), b.lower()))
    145          return dcnames
    146
    147      deviceMoveTargets = getPeerDeviceClassNames
    148      childMoveTargets = getPeerDeviceClassNames
    149
    150
    151 -    def createInstance(self, id):
    152          """
    153          Create an instance based on its location in the device tree
    154          walk up the primary aq path looking for a python instance class that
    155          matches the name of the closest node in the device tree.
    156
    157          @param id: id in DMD path
    158          @type id: string
    159          @return: new device object
    160          @rtype: device object
    161          """
    162          pyClass = self.getPythonDeviceClass()
    163          dev = pyClass(id)
    164          self.devices._setObject(id, dev)
    165          return self.devices._getOb(id)
    166
    167
    168 -    def getPythonDeviceClass(self):
    169          """
    170          Return the Python class object to be used for device instances in this
    171          device class.  This is done by walking up the aq_chain of a deviceclass
    172          to find a node that has the same name as a Python class or has an
    173          attribute named zPythonClass that matches a Python class.
    174
    175          @return: device class
    176          @rtype: device class
    177          """
    178          from Device import Device
    179          cname = getattr(self, "zPythonClass", None)
    180          if cname:
    181              try:
    182                  return importClass(cname)
    183              except ImportError:
    184                  log.exception("Unable to import class " + cname)
    185          return Device
    186
    187
    188 -    def moveDevices(self, moveTarget, deviceNames=None, REQUEST=None):
    189          """
    190          Override default moveDevices because this is a contained relation.
    191          If the Python class bound to a DeviceClass is different we convert to
    192          the new Python class adding / removing relationships as needed.
    193
    194          @param moveTarget: organizer in DMD path
    195          @type moveTarget: string
    196          @param deviceNames: devices to move
    197          @type deviceNames: list of stringa
    198          @param REQUEST: Zope REQUEST object
    199          @type REQUEST: Zope REQUEST object
    200          """
    201          if not moveTarget or not deviceNames: return self()
    202          target = self.getDmdRoot(self.dmdRootName).getOrganizer(moveTarget)
    203          if type(deviceNames) == types.StringType: deviceNames = (deviceNames,)
    204          for devname in deviceNames:
    205              dev = self.findDeviceByIdExact(devname)
    206              if not dev: continue
    207              source = dev.deviceClass().primaryAq()
    208              if dev.__class__ != target.getPythonDeviceClass():
    209                  import StringIO
    210                  from Products.ZenRelations.ImportRM import NoLoginImportRM
    211
    212                  def switchClass(o, module, klass):
    213                      """
    214                      Create an XML string representing the module in a
    215                      new class.
    216
    217                      @param o: file-type object
    218                      @type o: file-type object
    219                      @param module: location in DMD
    220                      @type module: string
    221                      @param klass: class name
    222                      @type klass: string
    223                      @return: XML representation of the class
    224                      @rtype: string
    225                      """
    226                      o.seek(0)
    227                      l = o.readline()
    228                      al = l[1:-2].split()
    229                      for i in range(len(al)):
    230                          if al[i].startswith('module'):
    231                              al[i] = "module='%s'" % module
    232                          elif al[i].startswith('class'):
    233                              al[i] = "class='%s'" % klass
    234                      nl = "<" + " ".join(al) + ">\n"
    235                      o.seek(0)
    236                      nf = ["<objects>", nl]
    237                      nf.extend(o.readlines()[1:])
    238                      nf.append('</objects>')
    239                      return StringIO.StringIO("".join(nf))
    240
    241                  def devExport(d, module, klass):
    242                      """
    243                      Create an XML string representing the device d
    244                      at the DMD location module of type klass.
    245
    246                      @param module: location in DMD
    247                      @type module: string
    248                      @param klass: class name
    249                      @type klass: string
    250                      @return: XML representation of the class
    251                      @rtype: string
    252                      """
    253                      o = StringIO.StringIO()
    254                      d.exportXml(o)
    255                      return switchClass(o, module, klass)
    256
    257                  def devImport(xmlfile):
    258                      """
    259                      Load a new device from a file.
    260
    261                      @param xmlfile: file type object
    262                      @type xmlfile: file type object
    263                      """
    264                      im = NoLoginImportRM(target.devices)
    265                      im.loadObjectFromXML(xmlfile)
    266
    267                  module = target.zPythonClass
    268                  if module:
    269                      klass = target.zPythonClass.split('.')[-1]
    270                  else:
    271                      module = 'Products.ZenModel.Device'
    272                      klass = 'Device'
    273                  xmlfile = devExport(dev, module,klass)
    274                  source.devices._delObject(devname)
    275                  devImport(xmlfile)
    276              else:
    277                  dev._operation = 1
    278                  source.devices._delObject(devname)
    279                  target.devices._setObject(devname, dev)
    280              dev = target.devices._getOb(devname)
    281              dev.setLastChange()
    282              dev.setAdminLocalRoles()
    283              dev.index_object()
    284              transaction.commit()
    285          if REQUEST:
    286              messaging.IMessageSender(self).sendToBrowser(title='Devices Moved',
    287                                     body="Devices were moved to %s." % moveTarget)
    288              REQUEST['message'] = "Devices moved to %s" % moveTarget
    289              if not isinstance(REQUEST, FakeRequest):
    290                  REQUEST['RESPONSE'].redirect(target.getPrimaryUrlPath())
    291              else:
    292                  if REQUEST.has_key('oneKeyValueSoInstanceIsntEmptyAndEvalToFalse'):
    293                      return REQUEST['message']
    294                  else:
    295                      return self.callZenScreen(REQUEST)
    296
    297
    298      security.declareProtected(ZEN_DELETE_DEVICE, 'removeDevices')
    299 -    def removeDevices(self, deviceNames=None, deleteStatus=False,
    300                      deleteHistory=False, deletePerf=False,REQUEST=None):
    301          """
    302          See IManageDevice overrides DeviceManagerBase.removeDevices
    303          """
    304          if not deviceNames: return self()
    305          if type(deviceNames) in types.StringTypes: deviceNames = (deviceNames,)
    306          for devname in deviceNames:
    307              dev = self.findDevice(devname)
    308              dev.deleteDevice(deleteStatus=deleteStatus,
    309                          deleteHistory=deleteHistory, deletePerf=deletePerf)
    310          if REQUEST:
    311              messaging.IMessageSender(self).sendToBrowser(
    312                  'Devices Deleted',
    313                  "Devices were deleted: %s." % ', '.join(deviceNames)
    314              )
    315              if REQUEST.has_key('oneKeyValueSoInstanceIsntEmptyAndEvalToFalse'):
    316                  return 'Devices were deleted: %s.' % ', '.join(deviceNames)
    317              else:
    318                  return self.callZenScreen(REQUEST)
    319
    320
    321      security.declareProtected('View', 'getEventDeviceInfo')
    322 -    def getEventDeviceInfo(self):
    323          """
    324          getEventDeviceInfo() -> return the info for NcoEventPopulator
    325          """
    326          deviceInfo = {}
    327          for device in self.getSubDevices():
    328              systemNames = []
    329              for sys in device.systems.objectValuesAll():
    330                  systemNames.append(sys.getOrganizerName())
    331              systemNames = "|".join(systemNames)
    332              location = device.getLocationName()
    333              if not location: location = "Unknown"
    334              deviceInfo[device.id] = (systemNames, location,
    335                                      device.productionState,
    336                                      device.getDeviceClassPath())
    337          return deviceInfo
    338
    339
    340      security.declareProtected('View', 'getDeviceWinInfo')
    341 -    def getDeviceWinInfo(self, lastPoll=0, eventlog=False):
    342          """
    343          Return list of (devname,user,passwd,url) for each device.
    344          user and passwd are used to connect via wmi.
    345          """
    346          ffunc = None
    347          starttime = time.time()
    348          if lastPoll > 0:
    349              lastPoll = DateTime.DateTime(lastPoll)
    350              ffunc = lambda x: x.getSnmpLastCollection() > lastPoll
    351          if eventlog:
    352              ffunc = lambda x: x.zWinEventlog
    353          devinfo = []
    354          for dev in self.getSubDevices(devfilter=ffunc):
    355              if not dev.monitorDevice(): continue
    356              if dev.getProperty('zWmiMonitorIgnore', False): continue
    357              user = dev.getProperty('zWinUser','')
    358              passwd = dev.getProperty( 'zWinPassword', '')
    359              sev = dev.getProperty( 'zWinEventlogMinSeverity', '')
    360              devinfo.append((dev.id, str(user), str(passwd), sev, dev.absolute_url()))
    361          return starttime, devinfo
    362
    363
    364 -    def getWinServices(self):
    365          """
    366          Return a list of (devname, user, passwd, {'EvtSys':0,'Exchange':0})
    367          """
    368          svcinfo = []
    369          allsvcs = {}
    370          for s in self.getSubComponents("WinService"):
    371              svcs=allsvcs.setdefault(s.hostname(),{})
    372              name = s.name()
    373              if type(name) == type(u''):
    374                  name = name.encode(s.zCollectorDecoding)
    375              svcs[name] = (s.getStatus(), s.getAqProperty('zFailSeverity'))
    376          for dev in self.getSubDevices():
    377              if not dev.monitorDevice(): continue
    378              if dev.getProperty( 'zWmiMonitorIgnore', False): continue
    379              svcs = allsvcs.get(dev.getId(), {})
    380              if not svcs and not dev.zWinEventlog: continue
    381              user = dev.getProperty('zWinUser','')
    382              passwd = dev.getProperty( 'zWinPassword', '')
    383              svcinfo.append((dev.id, str(user), str(passwd), svcs))
    384          return svcinfo
    385
    386
    387      security.declareProtected('View', 'searchDeviceSummary')
    388 -    def searchDeviceSummary(self, query):
    389          """
    390          Search device summary index and return device objects
    391          """
    392          if not query: return []
    393          zcatalog = self._getCatalog()
    394          if not zcatalog: return []
    395          results = zcatalog({'summary':query})
    396          return self._convertResultsToObj(results)
    397
    398
    399      security.declareProtected('View', 'searchInterfaces')
    400 -    def searchInterfaces(self, query):
    401          """
    402          Search interfaces index and return interface objects
    403          """
    404          if not query: return []
    405          zcatalog = getattr(self, 'interfaceSearch', None)
    406          if not zcatalog: return []
    407          results = zcatalog(query)
    408          return self._convertResultsToObj(results)
    409
    410
    411 -    def _convertResultsToObj(self, results):
    412          devices = []
    413          for brain in results:
    414              try:
    415                  devobj = self.getObjByPath(brain.getPrimaryId)
    416                  devices.append(devobj)
    417              except KeyError:
    418                  log.warn("bad path '%s' in index" % brain.getPrimaryId)
    419
    420          return devices
    421
    422 -    def _findDevice(self, devicename, useTitle=True):
    423          """
    424          Returns all devices whose ip/id/title match devicename.
    425          ip/id matches are at the front of the list.
    426
    427          @rtype: list of brains
    428          """
    429          idIpQuery = Or( MatchGlob('id', devicename),
    430                          Eq('getDeviceIp', devicename) )
    431          if useTitle:
    432              titleOrIdQuery = MatchGlob('titleOrId', devicename)
    433              query = Or( idIpQuery, titleOrIdQuery )
    434              rankSort = RankByQueries_Max( ( idIpQuery, 16 ),
    435                                            ( titleOrIdQuery, 8 ) )
    436              devices = self._getCatalog().evalAdvancedQuery(query, (rankSort,))
    437          else:
    438              devices = self._getCatalog().evalAdvancedQuery(idIpQuery)
    439          return devices
    440
    441 -    def findDevicePath(self, devicename):
    442          """
    443          Look up a device and return its path
    444          """
    445          ret = self._findDevice(devicename)
    446          if not ret: return ""
    447          return ret[0].getPrimaryId
    448
    449 -    def findDevice(self, devicename):
    450          """
    451          Returns the first device whose ip/id matches devicename.  If
    452          there is no ip/id match, return the first device whose title
    453          matches devicename.
    454          """
    455          ret = self._findDevice(devicename)
    456          if ret: return ret[0].getObject()
    457
    458 -    def findDeviceByIdOrIp(self, devicename):
    459          """
    460          Returns the first device that has an ip/id that matches devicename
    461          """
    462          ret = self._findDevice( devicename, False )
    463          if ret: return ret[0].getObject()
    464
    465 -    def findDeviceByIdExact(self, devicename):
    466          """
    467          Look up device in catalog and return it.  devicename
    468          must match device id exactly
    469          """
    470          for brains in self._getCatalog()(id=devicename):
    471              dev = brains.getObject()
    472              if dev.id == devicename:
    473                  return dev
    474
    475 -    def findDevicePingStatus(self, devicename):
    476          """
    477          look up device in catalog and return its pingStatus
    478          """
    479          dev = self.findDevice(devicename)
    480          if dev: return dev.getPingStatusNumber()
    481
    482
    483 -    def getSubComponents(self, meta_type="", monitored=True):
    484          """
    485          Return generator of components, by meta_type if specified
    486          """
    487          zcat = self.componentSearch
    488          res = zcat({'meta_type': meta_type, 'monitored': monitored})
    489          for b in res:
    490              try:
    491                  c = self.getObjByPath(b.getPrimaryId)
    492                  if self.checkRemotePerm("View", c):
    493                      yield c
    494              except KeyError:
    495                  log.warn("bad path '%s' in index 'componentSearch'",
    496                              b.getPrimaryId)
    497
    498
    499      security.declareProtected("ZenCommon", "getMonitoredComponents")
    500 -    def getMonitoredComponents(self):
    501          """
    502          Return monitored components for devices within this DeviceDeviceClass
    503          """
    504          return self.getSubComponents()
    505
    506
    507      security.declareProtected('View', 'getRRDTemplates')
    508 -    def getRRDTemplates(self, context=None):
    509          """
    510          Return the actual RRDTemplate instances.
    511          """
    512          templates = {}
    513          if not context: context = self
    514          mychain = aq_chain(context)
    515          mychain.reverse()
    516          for obj in mychain:
    517              try:
    518                  templates.update(dict([(t.id, t) for t in obj.rrdTemplates()]))
    519              except AttributeError:
    520                  pass
    521          return templates.values()
    522
    523
    524 -    def getAvailableTemplates(self):
    525          """
    526          Returns all available templates
    527          """
    528          def cmpTemplates(a, b):
    529              return cmp(a.id.lower(), b.id.lower())
    530          templates = self.getRRDTemplates()
    531          templates.sort(cmpTemplates)
    532          pdc = self.getPythonDeviceClass()
    533          return [ t for t in templates
    534              if issubclass(pdc, t.getTargetPythonClass()) ]
    535
    536
    537 -    def bindTemplates(self, ids=(), REQUEST=None):
    538          """
    539          This will bind available templates to the zDeviceTemplates
    540          """
    541          return self.setZenProperty('zDeviceTemplates', ids, REQUEST)
    542
    543 -    def removeZDeviceTemplates(self, REQUEST=None):
    544          """
    545          Deletes the local zProperty, zDeviceTemplates
    546          """
    547          if self.getPrimaryPath()[-2:] == ('dmd', 'Devices'):
    548              self.setZenProperty('zDeviceTemplates', ['Device'])
    549          else:
    550              self.deleteZenProperty('zDeviceTemplates')
    551          messaging.IMessageSender(self).sendToBrowser(
    552              'Bindings Reset',
    553              'Template bindings for this class were reset.'
    554          )
    555          return self.callZenScreen(REQUEST)
    556
    557
    558 -    def getAllRRDTemplates(self, rrdts=None):
    559          """
    560          Return all RRDTemplates at this level and below in the object tree.
    561          If rrdts is provided then it must be a list of RRDTemplates which
    562          will be extended with the templates from here and returned.
    563
    564          The original getAllRRDTemplates() method has been renamed
    565          getAllRRDTemplatesPainfully().  It walks the object tree looking
    566          for templates which is a very slow way of going about things.
    567          The newer RRDTemplate.YieldAllRRDTemplate() method uses the
    568          searchRRDTemplates catalog to speed things up dramatically.
    569          YieldAllRRDTemplates is smart enough to revert to
    570          getAllRRDTemplatesPainfully if the catalog is not present.
    571
    572          The searchRRDTemplates catalog was added in 2.2
    573          """
    574          if rrdts == None:
    575              rrdts = []
    576          rrdts.extend(RRDTemplate.YieldAllRRDTemplates(self))
    577          return rrdts
    578
    579
    580 -    def getAllRRDTemplatesPainfully(self, rrdts=None):
    581          """
    582          RRDTemplate.YieldAllRRDTemplates() is probably what you want.
    583          It takes advantage of the searchRRDTemplates catalog to get
    584          much better performance.  This method iterates over objects looking
    585          for templates which is a slow, painful process.
    586          """
    587          if rrdts is None: rrdts = []
    588          rrdts.extend(self.rrdTemplates())
    589          for dev in self.devices():
    590              rrdts += dev.objectValues('RRDTemplate')
    591              for comps in dev.getDeviceComponents():
    592                  rrdts += comps.objectValues('RRDTemplate')
    593          for child in self.children():
    594              child.getAllRRDTemplatesPainfully(rrdts)
    595          return rrdts
    596
    597
    598      security.declareProtected('Add DMD Objects', 'manage_addRRDTemplate')
    599 -    def manage_addRRDTemplate(self, id, REQUEST=None):
    600          """
    601          Add an RRDTemplate to this DeviceClass.
    602          """
    603          if not id: return self.callZenScreen(REQUEST)
    604          id = self.prepId(id)
    605          org = RRDTemplate.RRDTemplate(id)
    606          self.rrdTemplates._setObject(org.id, org)
    607          if REQUEST:
    608              messaging.IMessageSender(self).sendToBrowser(
    609                  'Template Added',
    610                  'The "%s" template has been created.' % id
    611              )
    612              return self.callZenScreen(REQUEST)
    613
    614
    615      security.declareProtected(ZEN_EDIT_LOCAL_TEMPLATES,
    616                                'manage_copyRRDTemplates')
    617 -    def manage_copyRRDTemplates(self, ids=(), REQUEST=None):
    618          """
    619          Put a reference to the objects named in ids in the clip board
    620          """
    621          if not ids: return self.callZenScreen(REQUEST)
    622          ids = [ id for id in ids if self.rrdTemplates._getOb(id, None) != None]
    623          if not ids: return self.callZenScreen(REQUEST)
    624          cp = self.rrdTemplates.manage_copyObjects(ids)
    625          if REQUEST:
    626              resp=REQUEST['RESPONSE']
    627              resp.setCookie('__cp', cp, path='/zport/dmd')
    628              REQUEST['__cp'] = cp
    629              messaging.IMessageSender(self).sendToBrowser(
    630                  'Templates Copied',
    631                  'Templates have been copied: %s' % ', '.join(ids)
    632              )
    633              return self.callZenScreen(REQUEST)
    634          return cp
    635
    636
    637      security.declareProtected(ZEN_EDIT_LOCAL_TEMPLATES,
    638                                'manage_pasteRRDTemplates')
    639 -    def manage_pasteRRDTemplates(self, moveTarget=None, cb_copy_data=None, REQUEST=None):
    640          """
    641          Paste RRDTemplates that have been copied before.
    642          """
    643          cp = None
    644          if cb_copy_data: cp = cb_copy_data
    645          elif REQUEST:
    646              cp = REQUEST.get("__cp",None)
    647
    648          if cp:
    649              if moveTarget:
    650                  target = self.getDmdRoot(self.dmdRootName).getOrganizer(moveTarget)
    651              else:
    652                  target = self
    653              target.rrdTemplates.manage_pasteObjects(cp)
    654          else:
    655              target = None
    656
    657          if REQUEST:
    658              REQUEST['RESPONSE'].setCookie('__cp', 'deleted', path='/zport/dmd',
    659                              expires='Wed, 31-Dec-97 23:59:59 GMT')
    660              REQUEST['__cp'] = None
    661              if target:
    662                  message = "Template(s) copied to %s" % moveTarget
    663              else:
    664                  message = None
    665              messaging.IMessageSender(self).sendToBrowser(
    666                  'Template(s) Copied',
    667                  message
    668              )
    669              if not isinstance(REQUEST, FakeRequest):
    670                  url = target.getPrimaryUrlPath() + '/perfConfig'
    671                  if message:
    672                      url += '?message=%s' % message
    673                  REQUEST['RESPONSE'].redirect(url)
    674              else:
    675                  return self.callZenScreen(REQUEST)
    676
    677
    678      security.declareProtected(ZEN_EDIT_LOCAL_TEMPLATES,
    679                                'manage_copyAndPasteRRDTemplates')
    680 -    def manage_copyAndPasteRRDTemplates(self, ids=(), copyTarget=None, REQUEST=None):
    681          """
    682          Copy the selected templates into the specified device class.
    683          """
    684          if not ids:
    685              messaging.IMessageSender(self).sendToBrowser(
    686                  'Invalid',
    687                  'No templates were selected.',
    688                  priority=messaging.WARNING
    689              )
    690              return self.callZenScreen(REQUEST)
    691          if copyTarget is None:
    692              messaging.IMessageSender(self).sendToBrowser(
    693                  'Invalid',
    694                  'No target was selected.',
    695                  priority=messaging.WARNING
    696              )
    697              return self.callZenScreen(REQUEST)
    698          cp = self.manage_copyRRDTemplates(ids)
    699          return self.manage_pasteRRDTemplates(copyTarget, cp, REQUEST)
    700
    701
    702      security.declareProtected(ZEN_EDIT_LOCAL_TEMPLATES,
    703                                'manage_deleteRRDTemplates')
    704 -    def manage_deleteRRDTemplates(self, ids=(), paths=(), REQUEST=None):
    705          """
    706          Delete RRDTemplates from this DeviceClass
    707          (skips ones in other Classes)
    708          """
    709          if not ids and not paths:
    710              return self.callZenScreen(REQUEST)
    711          for id in ids:
    712              if (getattr(aq_base(self), 'rrdTemplates', False)
    713                  and getattr(aq_base(self.rrdTemplates),id,False)):
    714                  self.rrdTemplates._delObject(id)
    715          for path in paths:
    716              temp = self.dmd.getObjByPath(path)
    717              if temp.deviceClass():
    718                  temp.deviceClass().rrdTemplates._delObject(temp.id)
    719              else:
    720                  temp.device()._delObject(temp.id)
    721          if REQUEST:
    722              messaging.IMessageSender(self).sendToBrowser(
    723                  'Templates Deleted',
    724                  'Templates were deleted: %s' % ", ".join(ids)
    725              )
    726              return self.callZenScreen(REQUEST)
    727
    728
    729 -    def createCatalog(self):
    730          """
    731          Make the catalog for device searching
    732          """
    733          from Products.ZCatalog.ZCatalog import manage_addZCatalog
    734
    735          # Make catalog for Devices
    736          manage_addZCatalog(self, self.default_catalog,
    737              self.default_catalog)
    738          zcat = self._getOb(self.default_catalog)
    739          cat = zcat._catalog
    740          for idxname in ['id',
    741              'getDeviceIp','getDeviceClassPath','getProdState','titleOrId']:
    742              cat.addIndex(idxname, makeCaseInsensitiveFieldIndex(idxname))
    743          cat.addIndex('getPhysicalPath', makePathIndex('getPhysicalPath'))
    744          cat.addIndex('path', makeMultiPathIndex('path'))
    745          zcat.addColumn('getPrimaryId')
    746          zcat.addColumn('id')
    747          zcat.addColumn('path')
    748
    749          # make catalog for device components
    750          manage_addZCatalog(self, "componentSearch", "componentSearch")
    751          zcat = self._getOb("componentSearch")
    752          cat = zcat._catalog
    753          cat.addIndex('meta_type', makeCaseInsensitiveFieldIndex('meta_type'))
    754          cat.addIndex('getParentDeviceName',
    755              makeCaseInsensitiveFieldIndex('getParentDeviceName'))
    756          cat.addIndex('getCollectors',
    757              makeCaseInsensitiveKeywordIndex('getCollectors'))
    758          # XXX still using regular FieldIndex here for now, since this contains
    759          # binary information
    760          zcat.addIndex('monitored', 'FieldIndex')
    761          zcat.addColumn('getPrimaryId')
    762          zcat.addColumn('meta_type')
    763
    764
    765 -    def reIndex(self):
    766          """
    767          Go through all devices in this tree and reindex them.
    768          """
    769          zcat = getToolByName(self, self.default_catalog)
    770          zcat.manage_catalogClear()
    771          self.componentSearch.manage_catalogClear()
    772          transaction.savepoint()
    773          for dev in self.getSubDevicesGen_recursive():
    774              dev.index_object()
    775              for comp in dev.getDeviceComponentsNoIndexGen():
    776                  comp.index_object()
    777              transaction.savepoint()
    778
    779
    780 -    def buildDeviceTreeProperties(self):
    781          """
    782          Create a new device tree with a default configuration
    783          """
    784          devs = self.getDmdRoot("Devices")
    785          for id, value, type in Z_PROPERTIES:
    786              if not devs.hasProperty(id):
    787                  devs._setProperty(id, value, type)
    788
    789 -    def zenPropertyOptions(self, propname):
    790          """
    791          Provide a set of default options for a zProperty
    792
    793          @param propname: zProperty name
    794          @type propname: string
    795          @return: list of zProperty options
    796          @rtype: list
    797          """
    798          if propname == 'zCollectorPlugins':
    799              from Products.DataCollector.Plugins import loadPlugins
    800              names = [ldr.pluginName for ldr in loadPlugins(self.dmd)]
    801              names.sort()
    802              return names
    803          if propname == 'zCommandProtocol':
    804              return ['ssh', 'telnet']
    805          if propname == 'zSnmpVer':
    806              return ['v1', 'v2c', 'v3']
    807          if propname == 'zSnmpAuthType':
    808              return ['', 'MD5', 'SHA']
    809          if propname == 'zSnmpPrivType':
    810              return ['', 'DES', 'AES']
    811          return DeviceOrganizer.zenPropertyOptions(self, propname)
    812
    813
    814 -    def pushConfig(self, REQUEST=None):
    815          """
    816          This will result in a push of all the devices to live collectors
    817
    818          @param REQUEST: Zope REQUEST object
    819          @type REQUEST: Zope REQUEST object
    820          """
    821          self._p_changed = True
    822          if REQUEST:
    823              messaging.IMessageSender(self).sendToBrowser(
    824                  'Pushed Changes',
    825                  'Changes to %s were pushed to collectors.' % self.id
    826              )
    827              return self.callZenScreen(REQUEST)
    828
    829
    830      security.declareProtected('Change Device', 'setLastChange')
    831 -    def setLastChange(self, value=None):
    832          """
    833          Set the changed datetime for this device.
    834
    835          @param value: changed datetime. Default is now.
    836          @type value: number
    837          """
    838          if value is None:
    839              value = time.time()
    840          self._lastChange = float(value)
    841
    842 -    def register_devtype(self, description, protocol):
    843          """
    844          Define this class in terms of a description of the devices it should
    845          contain and the protocol by which they would normally be monitored.
    846          """
    847          t = (description, protocol)
    848          if not hasattr(self, 'devtypes'):
    849              self._setProperty('devtypes', [], 'lines')
    850          if t not in self.devtypes:
    851              self.devtypes.append(t)
    852              self._p_changed = True
    853
    854 -    def unregister_devtype(self, description, protocol):
    855          t = (description, protocol)
    856          if hasattr(self, 'devtypes'):
    857              if t in self.devtypes:
    858                  self.devtypes.remove(t)
    859                  self._p_changed = True
    860
    861
    862  InitializeClass(DeviceClass)
    863