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