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

# Source Code for Module Products.ZenModel.PerformanceConf

      1  #! /usr/bin/env python
      2  # -*- coding: utf-8 -*-
      3  # ##########################################################################
      4  #
      5  # This program is part of Zenoss Core, an open source monitoring platform.
      6  # Copyright (C) 2006-2009 Zenoss Inc.
      7  #
      8  # This program is free software; you can redistribute it and/or modify it
      9  # under the terms of the GNU General Public License version 2 as published by
     10  # the Free Software Foundation.
     11  #
     12  # For complete information please visit: http://www.zenoss.com/oss/
     13  #
     14  # ##########################################################################
     15
     16  __doc__ = """PerformanceConf
     17  The configuration object for Performance servers
     18  """
     19
     20  import os
     21  import zlib
     22  import socket
     23  import logging
     24  log = logging.getLogger('zen.PerformanceConf')
     25
     26  try:
     27      from base64 import urlsafe_b64encode
     28      raise ImportError
     29  except ImportError:
     30
     31
     32 -    def urlsafe_b64encode(s):
     33          """
     34          Encode a string so that it's okay to be used in an URL
     35
     36          @param s: possibly unsafe string passed in by the user
     37          @type s: string
     38          @return: sanitized, url-safe version of the string
     39          @rtype: string
     40          """
     41
     42          import base64
     43          s = base64.encodestring(s)
     44          s = s.replace('+', '-')
     45          s = s.replace('/', '_')
     46          s = s.replace('\n', '')
     47          return s
     48
     49
     50  import xmlrpclib
     51
     52  from AccessControl import ClassSecurityInfo
     53  from AccessControl import Permissions as permissions
     54  from Globals import DTMLFile
     55  from Globals import InitializeClass
     56  from Monitor import Monitor
     57  from Products.PythonScripts.standard import url_quote
     58  from Products.Jobber.jobs import ShellCommandJob
     59  from Products.ZenModel.ZenossSecurity import *
     60  from Products.ZenRelations.RelSchema import *
     61  from Products.ZenUtils.Utils import basicAuthUrl, zenPath, binPath
     62  from Products.ZenUtils.Utils import unused
     63  from Products.ZenUtils.Utils import isXmlRpc
     64  from Products.ZenUtils.Utils import setupLoggingHeader
     65  from Products.ZenUtils.Utils import executeCommand
     66  from Products.ZenUtils.Utils import clearWebLoggingStream
     67  from Products.ZenModel.Device import manage_createDevice
     68  from Products.ZenModel.ZDeviceLoader import DeviceCreationJob
     69  from Products.ZenWidgets import messaging
     70  from StatusColor import StatusColor
     71
     72  PERF_ROOT = None
     73
     74
     75 -def performancePath(target):
     76      """
     77      Return the base directory where RRD performance files are kept.
     78
     79      @param target: path to performance file
     80      @type target: string
     81      @return: sanitized path to performance file
     82      @rtype: string
     83      """
     84      global PERF_ROOT
     85      if PERF_ROOT is None:
     86          PERF_ROOT = zenPath('perf')
     87      if target.startswith('/'):
     88          target = target[1:]
     89      return os.path.join(PERF_ROOT, target)
     90
     91
     92 -def manage_addPerformanceConf(context, id, title=None, REQUEST=None,):
     93      """
     94      Make a device class
     95
     96      @param context: Where you are in the Zope acquisition path
     97      @type context: Zope context object
     98      @param id: unique identifier
     99      @type id: string
    100      @param title: user readable label (unused)
    101      @type title: string
    102      @param REQUEST: Zope REQUEST object
    103      @type REQUEST: Zope REQUEST object
    104      @return:
    105      @rtype:
    106      """
    107      unused(title)
    108      dc = PerformanceConf(id)
    109      context._setObject(id, dc)
    110
    111      if REQUEST is not None:
    112          REQUEST['RESPONSE'].redirect(context.absolute_url()
    113                   + '/manage_main')
    114
    115
    116  addPerformanceConf = DTMLFile('dtml/addPerformanceConf', globals())
    117
    118
    119 -class PerformanceConf(Monitor, StatusColor):
    120      """
    121      Configuration for Performance servers
    122      """
    123      portal_type = meta_type = 'PerformanceConf'
    124
    125      monitorRootName = 'Performance'
    126
    127      security = ClassSecurityInfo()
    128      security.setDefaultAccess('allow')
    129
    130      eventlogCycleInterval = 60
    131      perfsnmpCycleInterval = 300
    132      processCycleInterval = 180
    133      statusCycleInterval = 60
    134      winCycleInterval = 60
    135      wmibatchSize = 10
    136      wmiqueryTimeout = 100
    137      configCycleInterval = 6 * 60
    138
    139      zenProcessParallelJobs = 10
    140
    141      pingTimeOut = 1.5
    142      pingTries = 2
    143      pingChunk = 75
    144      pingCycleInterval = 60
    145      maxPingFailures = 1440
    146
    147      modelerCycleInterval = 720
    148
    149      renderurl = '/zport/RenderServer'
    150      renderuser = ''
    151      renderpass = ''
    152
    153      discoveryNetworks = ()
    154
    155      # make the default rrdfile size smaller
    156      # we need the space to live within the disk cache
    157      defaultRRDCreateCommand = (
    158          'RRA:AVERAGE:0.5:1:600',   # every 5 mins for 2 days
    159          'RRA:AVERAGE:0.5:6:600',   # every 30 mins for 12 days
    160          'RRA:AVERAGE:0.5:24:600',  # every 2 hours for 50 days
    161          'RRA:AVERAGE:0.5:288:600', # every day for 600 days
    162          'RRA:MAX:0.5:6:600',
    163          'RRA:MAX:0.5:24:600',
    164          'RRA:MAX:0.5:288:600',
    165          )
    166
    167      _properties = (
    168          {'id': 'eventlogCycleInterval', 'type': 'int', 'mode': 'w'},
    169          {'id': 'perfsnmpCycleInterval', 'type': 'int', 'mode': 'w'},
    170          {'id': 'processCycleInterval', 'type': 'int', 'mode': 'w'},
    171          {'id': 'statusCycleInterval', 'type': 'int', 'mode': 'w'},
    172          {'id': 'winCycleInterval', 'type': 'int', 'mode': 'w'},
    173          {'id': 'wmibatchSize', 'type': 'int', 'mode': 'w',
    174           'description':"Number of data objects to retrieve in a single WMI query",},
    175          {'id': 'wmiqueryTimeout', 'type': 'int', 'mode': 'w',
    176           'description':"Number of milliseconds to wait for WMI query to respond",},
    177          {'id': 'configCycleInterval', 'type': 'int', 'mode': 'w'},
    178          {'id': 'renderurl', 'type': 'string', 'mode': 'w'},
    179          {'id': 'renderuser', 'type': 'string', 'mode': 'w'},
    180          {'id': 'renderpass', 'type': 'string', 'mode': 'w'},
    181          {'id': 'defaultRRDCreateCommand', 'type': 'lines', 'mode': 'w'
    182           },
    183          {'id': 'zenProcessParallelJobs', 'type': 'int', 'mode': 'w'},
    184          {'id': 'pingTimeOut', 'type': 'float', 'mode': 'w'},
    185          {'id': 'pingTries', 'type': 'int', 'mode': 'w'},
    186          {'id': 'pingChunk', 'type': 'int', 'mode': 'w'},
    187          {'id': 'pingCycleInterval', 'type': 'int', 'mode': 'w'},
    188          {'id': 'maxPingFailures', 'type': 'int', 'mode': 'w'},
    189          {'id': 'modelerCycleInterval', 'type': 'int', 'mode': 'w'},
    190          {'id': 'discoveryNetworks', 'type': 'lines', 'mode': 'w'},
    191          )
    192
    193      _relations = Monitor._relations + (
    194          ("devices", ToMany(ToOne,"Products.ZenModel.Device","perfServer")),
    195          )
    196
    197      # Screen action bindings (and tab definitions)
    198      factory_type_information = (
    199          {
    200              'immediate_view' : 'viewPerformanceConfOverview',
    201              'actions'        :
    202              (
    203                  { 'id'            : 'overview'
    204                  , 'name'          : 'Overview'
    205                  , 'action'        : 'viewPerformanceConfOverview'
    206                  , 'permissions'   : (
    207                    permissions.view, )
    208                  },
    209                  { 'id'            : 'edit'
    210                  , 'name'          : 'Edit'
    211                  , 'action'        : 'editPerformanceConf'
    212                  , 'permissions'   : ("Manage DMD",)
    213                  },
    214                  { 'id'            : 'performance'
    215                  , 'name'          : 'Performance'
    216                  , 'action'        : 'viewDaemonPerformance'
    217                  , 'permissions'   : (permissions.view,)
    218                  },
    219                  { 'id'            : 'viewHistory'
    220                  , 'name'          : 'Modifications'
    221                  , 'action'        : 'viewNewHistory'
    222                  , 'permissions'   : (ZEN_VIEW_MODIFICATIONS,)
    223                  },
    224              )
    225            },
    226          )
    227
    228
    229      security.declareProtected('View', 'getDefaultRRDCreateCommand')
    230 -    def getDefaultRRDCreateCommand(self):
    231          """
    232          Get the default RRD Create Command, as a string.
    233          For example:
    234          '''RRA:AVERAGE:0.5:1:600
    235          RRA:AVERAGE:0.5:6:600
    236          RRA:AVERAGE:0.5:24:600
    237          RRA:AVERAGE:0.5:288:600
    238          RRA:MAX:0.5:288:600'''
    239
    240          @return: RRD create command
    241          @rtype: string
    242          """
    243          return '\n'.join(self.defaultRRDCreateCommand)
    244
    245
    246 -    def findDevice(self, deviceName):
    247          """
    248          Return the object given the name
    249
    250          @param deviceName: Name of a device
    251          @type deviceName: string
    252          @return: device corresponding to the name, or None
    253          @rtype: device object
    254          """
    255          brains = self.dmd.Devices._findDevice(deviceName)
    256          if brains:
    257              return brains[0].getObject()
    258
    259
    260 -    def getNetworkRoot(self):
    261          """
    262          Get the root of the Network object in the DMD
    263
    264          @return: base DMD Network object
    265          @rtype: Network object
    266          """
    267          return self.dmd.Networks
    268
    269
    270 -    def buildGraphUrlFromCommands(self, gopts, drange):
    271          """
    272          Return an URL for the given graph options and date range
    273
    274          @param gopts: graph options
    275          @type gopts: string
    276          @param drange: time range to use
    277          @type drange: string
    278          @return: URL to a graphic
    279          @rtype: string
    280          """
    281          newOpts = []
    282          width = 0
    283          for o in gopts:
    284              if o.startswith('--width'):
    285                  width = o.split('=')[1].strip()
    286                  continue
    287              newOpts.append(o)
    288          encodedOpts = urlsafe_b64encode(
    289                           zlib.compress('|'.join(newOpts), 9))
    290          url = '%s/render?gopts=%s&drange=%d&width=%s' % (
    291                   self.renderurl, encodedOpts, drange, width)
    292          if self.renderurl.startswith('proxy'):
    293              url = url.replace('proxy', 'http')
    294              return '/zport/RenderServer/render?remoteUrl=%s&gopts=%s&drange=%d&width=%s' % (
    295                   url_quote(url), encodedOpts, drange, width)
    296          else:
    297              return url
    298
    299
    300 -    def performanceGraphUrl(self, context, targetpath, targettype, view, drange):
    301          """
    302          Set the full path of the target and send to view
    303
    304          @param context: Where you are in the Zope acquisition path
    305          @type context: Zope context object
    306          @param targetpath: device path of performance metric
    307          @type targetpath: string
    308          @param targettype: unused
    309          @type targettype: string
    310          @param view: view object
    311          @type view: Zope object
    312          @param drange: date range
    313          @type drange: string
    314          @return: URL to graph
    315          @rtype: string
    316          """
    317          unused(targettype)
    318          targetpath = performancePath(targetpath)
    319          gopts = view.getGraphCmds(context, targetpath)
    320          return self.buildGraphUrlFromCommands(gopts, drange)
    321
    322
    323 -    def performanceMGraphUrl(self, context, targetsmap, view, drange):
    324          """
    325          Set the full paths for all targts in map and send to view
    326
    327          @param context: Where you are in the Zope acquisition path
    328          @type context: Zope context object
    329          @param targetsmap: list of (target, targettype) tuples
    330          @type targetsmap: list
    331          @param view: view object
    332          @type view: Zope object
    333          @param drange: date range
    334          @type drange: string
    335          @return: URL to graph
    336          @rtype: string
    337          """
    338          ntm = []
    339          for (target, targettype) in targetsmap:
    340              if target.find('.rrd') == -1:
    341                  target += '.rrd'
    342              fulltarget = performancePath(target)
    343              ntm.append((fulltarget, targettype))
    344          gopts = view.multiGraphOpts(context, ntm)
    345          gopts = url_quote('|'.join(gopts))
    346          url = '%s/render?gopts=%s&drange=%d' % (self.renderurl, gopts, drange)
    347          if self.renderurl.startswith('http'):
    348              return '/zport/RenderServer/render?remoteUrl=%s&gopts=%s&drange=%d' % (
    349                   url_quote(url), gopts, drange)
    350          else:
    351              return url
    352
    353
    354 -    def renderCustomUrl(self, gopts, drange):
    355          """
    356          Return the URL for a list of custom gopts for a graph
    357
    358          @param gopts: graph options
    359          @type gopts: string
    360          @param drange: date range
    361          @type drange: string
    362          @return: URL to graph
    363          @rtype: string
    364          """
    365          gopts = self._fullPerformancePath(gopts)
    366          gopts = url_quote('|'.join(gopts))
    367          url = '%s/render?gopts=%s&drange=%d' % (self.renderurl, gopts,
    368                  drange)
    369          if self.renderurl.startswith('http'):
    370              return '/zport/RenderServer/render?remoteUrl=%s&gopts=%s&drange=%d'\
    371                   % (url_quote(url), gopts, drange)
    372          else:
    373              return url
    374
    375
    376 -    def performanceCustomSummary(self, gopts):
    377          """
    378          Fill out full path for custom gopts and call to server
    379
    380          @param gopts: graph options
    381          @type gopts: string
    382          @return: URL
    383          @rtype: string
    384          """
    385          gopts = self._fullPerformancePath(gopts)
    386          renderurl = str(self.renderurl)
    387          if renderurl.startswith('proxy'):
    388              renderurl = self.renderurl.replace('proxy', 'http')
    389          if renderurl.startswith('http'):
    390              url = basicAuthUrl(str(self.renderuser),
    391                                 str(self.renderpass), renderurl)
    392              server = xmlrpclib.Server(url)
    393          else:
    394              server = self.getObjByPath(renderurl)
    395          return server.summary(gopts)
    396
    397
    398 -    def fetchValues(self, paths, cf, resolution, start, end=""):
    399          """
    400          Return values
    401
    402          @param paths: paths to performance metrics
    403          @type paths: list
    404          @param cf: RRD CF
    405          @type cf: string
    406          @param resolution: resolution
    407          @type resolution: string
    408          @param start: start time
    409          @type start: string
    410          @param end: end time
    411          @type end: string
    412          @return: values
    413          @rtype: list
    414          """
    415          url = self.renderurl
    416          if url.startswith("http"):
    417              url = basicAuthUrl(self.renderuser, self.renderpass, self.renderurl)
    418              server = xmlrpclib.Server(url, allow_none=True)
    419          else:
    420              if not self.renderurl:
    421                  raise KeyError
    422              server = self.getObjByPath(self.renderurl)
    423          return server.fetchValues(map(performancePath, paths), cf,
    424                                    resolution, start, end)
    425
    426
    427 -    def currentValues(self, paths):
    428          """
    429          Fill out full path and call to server
    430
    431          @param paths: paths to performance metrics
    432          @type paths: list
    433          @return: values
    434          @rtype: list
    435          """
    436          url = self.renderurl
    437          if url.startswith('proxy'):
    438              url = self.renderurl.replace('proxy', 'http')
    439          if url.startswith('http'):
    440              url = basicAuthUrl(self.renderuser, self.renderpass,
    441                                 self.renderurl)
    442              server = xmlrpclib.Server(url)
    443          else:
    444              if not self.renderurl:
    445                  raise KeyError
    446              server = self.getObjByPath(self.renderurl)
    447          return server.currentValues(map(performancePath, paths))
    448
    449
    450 -    def _fullPerformancePath(self, gopts):
    451          """
    452          Add full path to a list of custom graph options
    453
    454          @param gopts: graph options
    455          @type gopts: string
    456          @return: full path + graph options
    457          @rtype: string
    458          """
    459          for i in range(len(gopts)):
    460              opt = gopts[i]
    461              if opt.find('DEF') == 0:
    462                  opt = opt.split(':')
    463                  (var, file) = opt[1].split('=')
    464                  file = performancePath(file)
    465                  opt[1] = '%s=%s' % (var, file)
    466                  opt = ':'.join(opt)
    467                  gopts[i] = opt
    468          return gopts
    469
    470
    471      security.declareProtected('View', 'performanceDeviceList')
    472 -    def performanceDeviceList(self, force=True):
    473          """
    474          Return a list of URLs that point to our managed devices
    475
    476          @param force: unused
    477          @type force: boolean
    478          @return: list of device objects
    479          @rtype: list
    480          """
    481          unused(force)
    482          devlist = []
    483          for dev in self.devices():
    484              dev = dev.primaryAq()
    485              if not dev.pastSnmpMaxFailures() and dev.monitorDevice():
    486                  devlist.append(dev.getPrimaryUrlPath(full=True))
    487          return devlist
    488
    489
    490      security.declareProtected('View', 'performanceDataSources')
    491 -    def performanceDataSources(self):
    492          """
    493          Return a string that has all the definitions for the performance DS's.
    494
    495          @return: list of Data Sources
    496          @rtype: string
    497          """
    498          dses = []
    499          oidtmpl = 'OID %s %s'
    500          dstmpl = """datasource %s
    501          rrd-ds-type = %s
    502          ds-source = snmp://%%snmp%%/%s%s
    503          """
    504          rrdconfig = self.getDmdRoot('Devices').rrdconfig
    505          for ds in rrdconfig.objectValues(spec='RRDDataSource'):
    506              if ds.isrow:
    507                  inst = '.%inst%'
    508              else:
    509                  inst = ''
    510              dses.append(oidtmpl % (ds.getName(), ds.oid))
    511              dses.append(dstmpl % (ds.getName(), ds.rrdtype,
    512                          ds.getName(), inst))
    513          return '\n'.join(dses)
    514
    515 -    def deleteRRDFiles(self, device, datasource=None, datapoint=None):
    516          """
    517          Remove RRD performance data files
    518
    519          @param device: Name of a device or entry in DMD
    520          @type device: string
    521          @param datasource: datasource name
    522          @type datasource: string
    523          @param datapoint: datapoint name
    524          @type datapoint: string
    525          """
    526          remoteUrl = None
    527          if self.renderurl.startswith('http'):
    528              if datapoint:
    529                  remoteUrl = '%s/deleteRRDFiles?device=%s&datapoint=%s' % (
    530                       self.renderurl, device, datapoint)
    531              elif datasource:
    532                  remoteUrl = '%s/deleteRRDFiles?device=%s&datasource=%s' % (
    533                       self.renderurl, device, datasource)
    534              else:
    535                  remoteUrl = '%s/deleteRRDFiles?device=%s' % (
    536                       self.renderurl, device)
    537          rs = self.getDmd().getParentNode().RenderServer
    538          rs.deleteRRDFiles(device, datasource, datapoint, remoteUrl)
    539
    540
    541 -    def setPerformanceMonitor(self, performanceMonitor=None, deviceNames=None, REQUEST=None):
    542          """
    543          Provide a method to set performance monitor from any organizer
    544
    545          @param performanceMonitor: DMD object that collects from a device
    546          @type performanceMonitor: DMD object
    547          @param deviceNames: list of device names
    548          @type deviceNames: list
    549          @param REQUEST: Zope REQUEST object
    550          @type REQUEST: Zope REQUEST object
    551          """
    552          if not performanceMonitor:
    553              if REQUEST:
    554                  messaging.IMessageSender(self).sendToBrowser('Error',
    555                          'No monitor was selected.',
    556                          priority=messaging.WARNING)
    557              return self.callZenScreen(REQUEST)
    558          if deviceNames is None:
    559              if REQUEST:
    560                  messaging.IMessageSender(self).sendToBrowser('Error',
    561                          'No devices were selected.',
    562                          priority=messaging.WARNING)
    563              return self.callZenScreen(REQUEST)
    564          for devName in deviceNames:
    565              dev = self.devices._getOb(devName)
    566              dev = dev.primaryAq()
    567              dev.setPerformanceMonitor(performanceMonitor)
    568          if REQUEST:
    569              messaging.IMessageSender(self).sendToBrowser('Monitor Set',
    570                      'Performance monitor was set to %s.'
    571                       % performanceMonitor)
    572              if REQUEST.has_key('oneKeyValueSoInstanceIsntEmptyAndEvalToFalse'):
    573                  return REQUEST['message']
    574              else:
    575                  return self.callZenScreen(REQUEST)
    576
    577
    578      security.declareProtected('View', 'getPingDevices')
    579 -    def getPingDevices(self):
    580          """
    581          Return devices associated with this monitor configuration.
    582
    583          @return: list of devices for this monitor
    584          @rtype: list
    585          """
    586          devices = []
    587          for dev in self.devices.objectValuesAll():
    588              dev = dev.primaryAq()
    589              if dev.monitorDevice() and not dev.zPingMonitorIgnore:
    590                  devices.append(dev)
    591          return devices
    592
    593 -    def addDeviceCreationJob(self, deviceName, devicePath, title=None,
    594                               discoverProto="none",
    595                               performanceMonitor='localhost',
    596                               rackSlot=0, productionState=1000, comments="",
    597                               hwManufacturer="", hwProductName="",
    598                               osManufacturer="", osProductName="", priority = 3,
    599                               tag="", serialNumber="", zProperties={}):
    600
    601          zendiscCmd = self._getZenDiscCommand(deviceName, devicePath,
    602                                               performanceMonitor)
    603
    604          jobStatus = self.dmd.JobManager.addJob(DeviceCreationJob,
    605                                          deviceName=deviceName,
    606                                          devicePath=devicePath,
    607                                          title=title,
    608                                          discoverProto=discoverProto,
    609                                          performanceMonitor=performanceMonitor,
    610                                          rackSlot=rackSlot,
    611                                          productionState=productionState,
    612                                          comments=comments,
    613                                          hwManufacturer=hwManufacturer,
    614                                          hwProductName=hwProductName,
    615                                          osManufacturer=osManufacturer,
    616                                          osProductName=osProductName,
    617                                          priority=priority,
    618                                          tag=tag,
    619                                          serialNumber=serialNumber,
    620                                          zProperties=zProperties,
    621                                          zendiscCmd=zendiscCmd)
    622          return jobStatus
    623
    624 -    def _executeZenDiscCommand(self, deviceName, devicePath= "/Discovered",
    625                                 performanceMonitor="localhost",
    626                                 background=False, REQUEST=None):
    627          """
    628          Execute zendisc on the new device and return result
    629
    630          @param deviceName: Name of a device
    631          @type deviceName: string
    632          @param devicePath: DMD path to create the new device in
    633          @type devicePath: string
    634          @param performanceMonitor: DMD object that collects from a device
    635          @type performanceMonitor: DMD object
    636          @param background: should command be scheduled job?
    637          @type background: boolean
    638          @param REQUEST: Zope REQUEST object
    639          @type REQUEST: Zope REQUEST object
    640          @return:
    641          @rtype:
    642          """
    643          zendiscCmd = self._getZenDiscCommand(deviceName, devicePath,
    644                                               performanceMonitor, REQUEST)
    645          if background:
    646              log.info('queued job: %s', " ".join(zendiscCmd))
    647              result = self.dmd.JobManager.addJob(ShellCommandJob,
    648                                                      zendiscCmd)
    649          else:
    650              result = executeCommand(zendiscCmd, REQUEST)
    651          return result
    652
    653 -    def _getZenDiscCommand(self, deviceName, devicePath,
    654                             performanceMonitor, REQUEST=None):
    655
    656          zm = binPath('zendisc')
    657          zendiscCmd = [zm]
    658          zendiscOptions = ['run', '--now','-d', deviceName,
    659                       '--monitor', performanceMonitor,
    660                       '--deviceclass', devicePath]
    661          if REQUEST:
    662              zendiscOptions.append("--weblog")
    663          zendiscCmd.extend(zendiscOptions)
    664          log.info('local zendiscCmd is "%s"' % ' '.join(zendiscCmd))
    665          return zendiscCmd
    666
    667 -    def getCollectorCommand(self, command):
    668          return [binPath(command)]
    669
    670 -    def executeCollectorCommand(self, command, args, REQUEST=None):
    671          """
    672          Executes the collector based daemon command.
    673
    674          @param command: the collector daemon to run, should not include path
    675          @type command: string
    676          @param args: list of arguments for the command
    677          @type args: list of strings
    678          @param REQUEST: Zope REQUEST object
    679          @type REQUEST: Zope REQUEST object
    680          @return: result of the command
    681          @rtype: string
    682          """
    683          cmd = binPath(command)
    684          daemonCmd = [cmd]
    685          daemonCmd.extend(args)
    686          result = executeCommand(daemonCmd, REQUEST)
    687          return result
    688
    689
    690 -    def collectDevice(self, device=None, setlog=True, REQUEST=None,
    691          generateEvents=False, background=False, write=None):
    692          """
    693          Collect the configuration of this device AKA Model Device
    694
    695          @permission: ZEN_MANAGE_DEVICE
    696          @param device: Name of a device or entry in DMD
    697          @type device: string
    698          @param setlog: If true, set up the output log of this process
    699          @type setlog: boolean
    700          @param REQUEST: Zope REQUEST object
    701          @type REQUEST: Zope REQUEST object
    702          @param generateEvents: unused
    703          @type generateEvents: string
    704          """
    705          xmlrpc = isXmlRpc(REQUEST)
    706          zenmodelerOpts = ['run', '--now', '--monitor', self.id,
    707                              '-F', '-d', device.id]
    708          result = self._executeZenModelerCommand(zenmodelerOpts, background,
    709                                                  REQUEST, write)
    710          if result and xmlrpc:
    711              return result
    712          log.info('configuration collected')
    713
    714          if xmlrpc:
    715              return 0
    716
    717
    718 -    def _executeZenModelerCommand(self, zenmodelerOpts, background=False,
    719                                    REQUEST=None, write=None):
    720          """
    721          Execute zenmodeler and return result
    722
    723          @param zenmodelerOpts: zenmodeler command-line options
    724          @type zenmodelerOpts: string
    725          @param REQUEST: Zope REQUEST object
    726          @type REQUEST: Zope REQUEST object
    727          @return: results of command
    728          @rtype: string
    729          """
    730          zm = binPath('zenmodeler')
    731          zenmodelerCmd = [zm]
    732          zenmodelerCmd.extend(zenmodelerOpts)
    733          if background:
    734              log.info('queued job: %s', " ".join(zenmodelerCmd))
    735              result = self.dmd.JobManager.addJob(ShellCommandJob,zenmodelerCmd)
    736          else:
    737              result = executeCommand(zenmodelerCmd, REQUEST, write)
    738          return result
    739
    740
    741  InitializeClass(PerformanceConf)
    742