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

# Source Code for Module Products.ZenModel.Device

       1
       2  ###########################################################################
       3  #
       4  # This program is part of Zenoss Core, an open source monitoring platform.
       5  # Copyright (C) 2007, Zenoss Inc.
       6  #
       7  # This program is free software; you can redistribute it and/or modify it
       8  # under the terms of the GNU General Public License version 2 as published by
       9  # the Free Software Foundation.
      10  #
      11  # For complete information please visit: http://www.zenoss.com/oss/
      12  #
      13  ###########################################################################
      14
      15  __doc__ = """Device
      16  Base device (remote computer) class
      17  """
      18
      19  import os
      20  import shutil
      21  import time
      22  import types
      23  import socket
      24  import logging
      25  log = logging.getLogger("zen.Device")
      26
      27  from _mysql_exceptions import OperationalError
      28
      29  from urllib import quote as urlquote
      30
      31  from zope.event import notify
      32  from Products.Zuul.catalog.events import IndexingEvent
      33  from Products.ZenUtils.Utils import isXmlRpc, unused, getObjectsFromCatalog
      34  from Products.ZenUtils import Time
      35  import RRDView
      36  from Products.ZenUtils.IpUtil import checkip, IpAddressError, maskToBits
      37  from Products.ZenModel.interfaces import IIndexed
      38
      39  # base classes for device
      40  from ManagedEntity import ManagedEntity
      41
      42  from AccessControl import ClassSecurityInfo
      43  from Globals import DTMLFile
      44  from Globals import InitializeClass
      45  from DateTime import DateTime
      46  from zExceptions import NotFound
      47
      48  from ZODB.POSException import POSError
      49
      50
      51  #from Products.SnmpCollector.SnmpCollector import findSnmpCommunity
      52  from Products.DataCollector.ApplyDataMap import ApplyDataMap
      53
      54  from Products.ZenRelations.RelSchema import *
      55  from Commandable import Commandable
      56  from Lockable import Lockable
      57  from MaintenanceWindowable import MaintenanceWindowable
      58  from AdministrativeRoleable import AdministrativeRoleable
      59  from ZenMenuable import ZenMenuable
      60
      61  from OperatingSystem import OperatingSystem
      62  from DeviceHW import DeviceHW
      63
      64  from ZenStatus import ZenStatus
      65  from Products.ZenModel.Exceptions import *
      66  from ZenossSecurity import *
      67  from Products.ZenUtils.FakeRequest import FakeRequest
      68  from Products.ZenUtils.Utils import edgesToXML
      69  from Products.ZenUtils import NetworkTree
      70
      71  from zope.interface import implements
      72  from EventView import IEventView
      73  from Products.ZenWidgets.interfaces import IMessageSender
      74  from Products.ZenWidgets import messaging
      75  from Products.ZenEvents.browser.EventPillsAndSummaries import getEventPillME
      76  from OFS.CopySupport import CopyError # Yuck, a string exception
      77
      78
      79 -def getNetworkRoot(context, performanceMonitor):
      80      """
      81      Return the default network root.
      82      """
      83      return context.getDmdRoot('Networks')
      84
      85
      86 -def checkDeviceExists(context, deviceName, ip, performanceMonitor):
      87      mon = context.Monitors.getPerformanceMonitor(performanceMonitor)
      88      netroot = mon.getNetworkRoot()
      89      if ip:
      90          ipobj = netroot.findIp(ip)
      91          if ipobj:
      92              dev = ipobj.device()
      93              if dev:
      94                  raise DeviceExistsError("Ip %s exists on %s" % (ip, dev.id),dev)
      95
      96      if deviceName:
      97          dev = context.getDmdRoot('Devices').findDeviceByIdExact(deviceName)
      98          if dev:
      99              raise DeviceExistsError("Device %s already exists" %
     100                                      deviceName, dev)
     101      if ip:
     102          dev = mon.findDevice(ip)
     103          if dev:
     104              raise DeviceExistsError("Manage IP %s already exists" % ip, dev)
     105      return deviceName, ip
     106
     107
     108 -def manage_createDevice(context, deviceName, devicePath="/Discovered",
     109              tag="", serialNumber="",
     110              zSnmpCommunity="", zSnmpPort=161, zSnmpVer="",
     111              rackSlot="", productionState=1000, comments="",
     112              hwManufacturer="", hwProductName="",
     113              osManufacturer="", osProductName="",
     114              locationPath="", groupPaths=[], systemPaths=[],
     115              performanceMonitor="localhost",
     116              discoverProto="snmp", priority=3, manageIp="",
     117              zProperties=None, title=None):
     118      """
     119      Device factory creates a device and sets up its relations and collects its
     120      configuration. SNMP Community discovery also happens here. If an IP is
     121      passed for deviceName it will be used for collection and the device name
     122      will be set to the SNMP SysName (or ptr if SNMP Fails and ptr is valid)
     123
     124      @rtype: Device
     125      """
     126      manageIp = manageIp.replace(' ', '')
     127      checkDeviceExists(context, deviceName, manageIp, performanceMonitor)
     128      deviceName = context.prepId(deviceName)
     129      log.info("device name '%s' for ip '%s'", deviceName, manageIp)
     130      deviceClass = context.getDmdRoot("Devices").createOrganizer(devicePath)
     131      deviceName = context.prepId(deviceName)
     132      device = deviceClass.createInstance(deviceName)
     133      device.setManageIp(manageIp)
     134      device.manage_editDevice(
     135                  tag, serialNumber,
     136                  zSnmpCommunity, zSnmpPort, zSnmpVer,
     137                  rackSlot, productionState, comments,
     138                  hwManufacturer, hwProductName,
     139                  osManufacturer, osProductName,
     140                  locationPath, groupPaths, systemPaths,
     141                  performanceMonitor, priority, zProperties,
     142                  title)
     143      return device
     144
     145
     146 -def findCommunity(context, ip, devicePath,
     147                    community="", port=None, version=None):
     148      """
     149      Find the SNMP community and version for an ip address using zSnmpCommunities.
     150
     151      @rtype: tuple of (community, port, version, device name)
     152      """
     153      from pynetsnmp.SnmpSession import SnmpSession
     154
     155      devroot = context.getDmdRoot('Devices').createOrganizer(devicePath)
     156      communities = []
     157      if community: communities.append(community)
     158      communities.extend(getattr(devroot, "zSnmpCommunities", []))
     159      if not port: port = getattr(devroot, "zSnmpPort", 161)
     160      versions = ('v2c', 'v1')
     161      if not version: version = getattr(devroot, 'zSnmpVer', None)
     162      if version: versions = (version,)
     163      timeout = getattr(devroot, "zSnmpTimeout", 2)
     164      retries = getattr(devroot, "zSnmpTries", 2)
     165      session = SnmpSession(ip, timeout=timeout, port=port, retries=retries)
     166      oid = '.1.3.6.1.2.1.1.5.0'
     167      goodcommunity = ""
     168      goodversion = ""
     169      devname = ""
     170      for version in versions:
     171          session.setVersion(version)
     172          for community in communities:
     173              session.community = community
     174              try:
     175                  devname = session.get(oid).values()[0]
     176                  goodcommunity = session.community
     177                  goodversion = version
     178                  break
     179              except (SystemExit, KeyboardInterrupt, POSError): raise
     180              except: pass #keep trying until we run out
     181          if goodcommunity:
     182                  break
     183      else:
     184          raise NoSnmp("No SNMP found for IP = %s" % ip)
     185      return (goodcommunity, port, goodversion, devname)
     186
     187 -def manage_addDevice(context, id, REQUEST = None):
     188      """
     189      Creates a device
     190      """
     191      serv = Device(id)
     192      context._setObject(serv.id, serv)
     193      if REQUEST is not None:
     194          messaging.IMessageSender(self).sendToBrowser(
     195              'Device Added',
     196              'Device %s has been created.' % id
     197          )
     198          REQUEST['RESPONSE'].redirect(context.absolute_url()+'/manage_main')
     199
     200  addDevice = DTMLFile('dtml/addDevice',globals())
     201
     202
     203 -class NoNetMask(Exception): pass
     204
     205 -class Device(ManagedEntity, Commandable, Lockable, MaintenanceWindowable,
     206              AdministrativeRoleable, ZenMenuable):
     207      """
     208      Device is a base class that represents the idea of a single computer system
     209      that is made up of software running on hardware. It currently must be IP
     210      enabled but maybe this will change.
     211      """
     212
     213      implements(IEventView, IIndexed)
     214
     215      event_key = portal_type = meta_type = 'Device'
     216
     217      default_catalog = "deviceSearch" #device ZCatalog
     218
     219      relationshipManagerPathRestriction = '/Devices'
     220
     221      manageIp = ""
     222      productionState = 1000
     223      preMWProductionState = productionState
     224      snmpAgent = ""
     225      snmpDescr = ""
     226      snmpOid = ""
     227      snmpContact = ""
     228      snmpSysName = ""
     229      snmpLocation = ""
     230      rackSlot = ""
     231      comments = ""
     232      sysedgeLicenseMode = ""
     233      priority = 3
     234
     235      # Flag indicating whether device is in process of creation
     236      _temp_device = False
     237
     238      _properties = ManagedEntity._properties + (
     239          {'id':'manageIp', 'type':'string', 'mode':'w'},
     240          {'id':'productionState', 'type':'keyedselection', 'mode':'w',
     241             'select_variable':'getProdStateConversions','setter':'setProdState'},
     242          {'id':'preMWProductionState', 'type':'keyedselection', 'mode':'w',
     243             'select_variable':'getProdStateConversions','setter':'setProdState'},
     244          {'id':'snmpAgent', 'type':'string', 'mode':'w'},
     245          {'id':'snmpDescr', 'type':'string', 'mode':''},
     246          {'id':'snmpOid', 'type':'string', 'mode':''},
     247          {'id':'snmpContact', 'type':'string', 'mode':''},
     248          {'id':'snmpSysName', 'type':'string', 'mode':''},
     249          {'id':'snmpLocation', 'type':'string', 'mode':''},
     250          {'id':'snmpLastCollection', 'type':'date', 'mode':''},
     251          {'id':'snmpAgent', 'type':'string', 'mode':''},
     252          {'id':'rackSlot', 'type':'string', 'mode':'w'},
     253          {'id':'comments', 'type':'text', 'mode':'w'},
     254          {'id':'sysedgeLicenseMode', 'type':'string', 'mode':''},
     255          {'id':'priority', 'type':'int', 'mode':'w'},
     256          )
     257
     258      _relations = ManagedEntity._relations + (
     259          ("deviceClass", ToOne(ToManyCont, "Products.ZenModel.DeviceClass",
     260              "devices")),
     261          ("perfServer", ToOne(ToMany, "Products.ZenModel.PerformanceConf",
     262              "devices")),
     263          ("location", ToOne(ToMany, "Products.ZenModel.Location", "devices")),
     264          ("systems", ToMany(ToMany, "Products.ZenModel.System", "devices")),
     265          ("groups", ToMany(ToMany, "Products.ZenModel.DeviceGroup", "devices")),
     266          ("maintenanceWindows",ToManyCont(ToOne,
     267              "Products.ZenModel.MaintenanceWindow", "productionState")),
     268          ("adminRoles", ToManyCont(ToOne,"Products.ZenModel.AdministrativeRole",
     269              "managedObject")),
     270          ('userCommands', ToManyCont(ToOne, 'Products.ZenModel.UserCommand',
     271              'commandable')),
     272          # unused:
     273          ('monitors', ToMany(ToMany, 'Products.ZenModel.StatusMonitorConf',
     274              'devices')),
     275          )
     276
     277      # Screen action bindings (and tab definitions)
     278      factory_type_information = (
     279          {
     280              'id'             : 'Device',
     281              'meta_type'      : 'Device',
     282              'description'    : """Base class for all devices""",
     283              'icon'           : 'Device_icon.gif',
     284              'product'        : 'ZenModel',
     285              'factory'        : 'manage_addDevice',
     286              'immediate_view' : 'devicedetail',
     287              'actions'        :
     288              (
     289                  { 'id'            : 'status'
     290                  , 'name'          : 'Status'
     291                  , 'action'        : 'deviceStatus'
     292                  , 'permissions'   : (ZEN_VIEW, )
     293                  },
     294                  { 'id'            : 'osdetail'
     295                  , 'name'          : 'OS'
     296                  , 'action'        : 'deviceOsDetail'
     297                  , 'permissions'   : (ZEN_VIEW, )
     298                  },
     299                  { 'id'            : 'swdetail'
     300                  , 'name'          : 'Software'
     301                  , 'action'        : 'deviceSoftwareDetail'
     302                  , 'permissions'   : (ZEN_VIEW, )
     303                  },
     304                  { 'id'            : 'events'
     305                  , 'name'          : 'Events'
     306                  , 'action'        : 'viewEvents'
     307                  , 'permissions'   : (ZEN_VIEW, )
     308                  },
     309  #                { 'id'            : 'historyEvents'
     310  #                , 'name'          : 'History'
     311  #                , 'action'        : 'viewHistoryEvents'
     312  #                , 'permissions'   : (ZEN_VIEW, )
     313  #                },
     314                  { 'id'            : 'perfServer'
     315                  , 'name'          : 'Graphs'
     316                  , 'action'        : 'viewDevicePerformance'
     317                  , 'permissions'   : (ZEN_VIEW, )
     318                  },
     319  #                { 'id'            : 'perfConf'
     320  #                , 'name'          : 'PerfConf'
     321  #                , 'action'        : 'objTemplates'
     322  #                , 'permissions'   : ("Change Device", )
     323  #                },
     324                  { 'id'            : 'edit'
     325                  , 'name'          : 'Edit'
     326                  , 'action'        : 'editDevice'
     327                  , 'permissions'   : ("Change Device",)
     328                  },
     329  #                { 'id'            : 'management'
     330  #                , 'name'          : 'Administration'
     331  #                , 'action'        : 'deviceManagement'
     332  #                , 'permissions'   : ("Change Device",)
     333  #                },
     334  #                { 'id'            : 'custom'
     335  #                , 'name'          : 'Custom'
     336  #                , 'action'        : 'deviceCustomEdit'
     337  #                , 'permissions'   : (ZEN_VIEW, )
     338  #                },
     339  #                { 'id'            : 'config'
     340  #                , 'name'          : 'zProperties'
     341  #                , 'action'        : 'zPropertyEdit'
     342  #                , 'permissions'   : (ZEN_VIEW,)
     343  #                },
     344  #                { 'id'            : 'viewHistory'
     345  #                , 'name'          : 'Modifications'
     346  #                , 'action'        : 'viewHistory'
     347  #                , 'permissions'   : (ZEN_VIEW, )
     348  #                },
     349  #                { 'id'            : 'zProperties'
     350  #                , 'name'          : 'zProperties'
     351  #                , 'action'        : 'zPropertyEdit'
     352  #                , 'permissions'   : (  ZEN_VIEW, )
     353  #                },
     354              )
     355           },
     356          )
     357
     358      security = ClassSecurityInfo()
     359
     360 -    def __init__(self, id, buildRelations=True):
     361          ManagedEntity.__init__(self, id, buildRelations=buildRelations)
     362          os = OperatingSystem()
     363          self._setObject(os.id, os)
     364          hw = DeviceHW()
     365          self._setObject(hw.id, hw)
     366          #self.commandStatus = "Not Tested"
     367          self._lastPollSnmpUpTime = ZenStatus(0)
     368          self._snmpLastCollection = 0
     369          self._lastChange = 0
     370
     371 -    def isTempDevice(self):
     372          flag = getattr(self, '_temp_device', None)
     373          if flag is None:
     374              flag = self._temp_device = False
     375          return flag
     376
     377 -    def name(self):
     378          """
     379          Return the name of this device.  Default is titleOrId.
     380          """
     381          return self.titleOrId()
     382
     383
     384      security.declareProtected(ZEN_MANAGE_DMD, 'changeDeviceClass')
     385 -    def changeDeviceClass(self, deviceClassPath, REQUEST=None):
     386          """
     387          Wrapper for DeviceClass.moveDevices. The primary reason to use this
     388          method instead of that one is that this one returns the new path to the
     389          device.
     390
     391          @param deviceClassPath: device class in DMD path
     392          @type deviceClassPath: string
     393          @param REQUEST: Zope REQUEST object
     394          @type REQUEST: Zope REQUEST object
     395          """
     396          self.deviceClass().moveDevices(deviceClassPath, (self.id,))
     397          device = self.getDmdRoot('Devices').findDevice(self.id)
     398          return device.absolute_url_path()
     399
     400 -    def getRRDTemplate(self):
     401          """
     402          DEPRECATED
     403          """
     404          import warnings
     405          warnings.warn('Device.getRRDTemplate is deprecated',
     406                           DeprecationWarning)
     407          return ManagedEntity.getRRDTemplate(self)
     408
     409 -    def getRRDTemplates(self):
     410          """
     411          Returns all the templates bound to this Device
     412
     413          @rtype: list
     414
     415          >>> from Products.ZenModel.Device import manage_addDevice
     416          >>> manage_addDevice(devices, 'test')
     417          >>> devices.test.getRRDTemplates()
     418          [<RRDTemplate at /zport/dmd/Devices/rrdTemplates/Device>]
     419          """
     420          if not hasattr(self, 'zDeviceTemplates'):
     421              return ManagedEntity.getRRDTemplates(self)
     422          result = []
     423          for name in self.zDeviceTemplates:
     424              template = self.getRRDTemplateByName(name)
     425              if template:
     426                  result.append(template)
     427          return result
     428
     429
     430 -    def getRRDNames(self):
     431          return ['sysUpTime']
     432
     433
     434 -    def getDataSourceOptions(self):
     435          """
     436          Returns the available DataSource options. DataSource options
     437          are used to populate the dropdown when adding a new DataSource
     438          and is a string.  See L{RRDTemplate.RRDTemplate.getDataSourceOptions}
     439          for more information.
     440
     441          @rtype: list
     442          @return: [(displayName, dsOption),]
     443          """
     444          # This is an unfortunate hack.  Called from the device templates
     445          # page where we show multiple templates now.  This only really
     446          # works because getDataSourceOptions() returns the same values
     447          # for every template.  Ideally we would be able to pass some sort
     448          # of context to the Add DataSource dialog that calls this method.
     449          templates = self.getRRDTemplates()
     450          if templates:
     451              return templates[0].getDataSourceOptions()
     452          return []
     453
     454      # security.declareProtected('Manage DMD', 'manage_resequenceRRDGraphs')
     455      # def manage_resequenceRRDGraphs(self, templateId, seqmap=(), origseq=(), REQUEST=None):
     456      #     """Reorder the sequecne of the RRDGraphs.
     457      #     """
     458      #     template = self.getRRDTemplateByName(templateId)
     459      #     return template.manage_resequenceRRDGraphs(seqmap, origseq, REQUEST)
     460
     461
     462 -    def sysUpTime(self):
     463          """
     464          Returns the cached sysUpTime for this device
     465
     466          @rtype: int
     467          """
     468          try:
     469              return self.cacheRRDValue('sysUpTime', -1)
     470          except Exception:
     471              log.exception("failed getting sysUpTime")
     472              return -1
     473
     474
     475 -    def availability(self, *args, **kw):
     476          """
     477          Returns the uptime of this device
     478
     479          @rtype: string
     480          @todo: Performance enhancement: Should move import outside of method
     481          """
     482          from Products.ZenEvents import Availability
     483          results = Availability.query(self.dmd, device=self.id, *args, **kw)
     484          if results:
     485              return results[0]
     486          else:
     487              return None
     488
     489
     490      # FIXME: cleanup --force option #2660
     491 -    def __getattr__(self, name):
     492          """
     493          Override from object to handle lastPollSnmpUpTime and
     494          snmpLastCollection
     495
     496          @todo: Not sure this is needed, see getLastPollSnmpUpTime and
     497          getSnmpLastCollection
     498          """
     499          if name == 'lastPollSnmpUpTime':
     500              return self._lastPollSnmpUpTime.getStatus()
     501          elif name == 'snmpLastCollection':
     502              return DateTime(self._snmpLastCollection)
     503          else:
     504              raise AttributeError( name )
     505
     506
     507 -    def _setPropValue(self, id, value):
     508          """
     509          Override from PropertyManager to handle checks and ip creation
     510
     511          @todo: Not sure this is needed, see setSnmpLastCollection
     512          """
     513          self._wrapperCheck(value)
     514          if id == 'snmpLastCollection':
     515              self._snmpLastCollection = float(value)
     516          else:
     517              ManagedEntity._setPropValue(self, id, value)
     518
     519
     520 -    def applyDataMap(self, datamap, relname="", compname="", modname=""):
     521          """
     522          Apply a datamap passed as a list of dicts through XML-RPC.
     523          """
     524          adm = ApplyDataMap()
     525          adm.applyDataMap(self, datamap, relname=relname,
     526                           compname=compname, modname=modname)
     527
     528
     529 -    def path(self):
     530          """
     531          Return a sequence of path tuples suitable for indexing by
     532          a MultiPathIndex.
     533          """
     534          orgs = (
     535                  self.systems() +
     536                  self.groups() +
     537                  [self.location()] +
     538                  [self.deviceClass()]
     539                 )
     540          orgs = filter(None, orgs)
     541          paths = []
     542          myPrimaryId = self.getPrimaryId()
     543          myId = self.getId()
     544          for org in orgs:
     545              rel = org.primaryAq().devices
     546              try:
     547                  orgself = rel._getOb(myPrimaryId)
     548              except AttributeError:
     549                  # Device class wants an id, not a path
     550                  try:
     551                      orgself = rel._getOb(myId)
     552                  except AttributeError:
     553                      log.warn("Unable to find %s (%s) in organizer %s",
     554                          myId, myPrimaryId,
     555                          '/'.join(org.getPrimaryPath()[3:]))
     556                      continue
     557              paths.append(orgself.getPhysicalPath())
     558
     559          return paths
     560
     561
     562 -    def traceRoute(self, target, ippath=None):
     563          """
     564          Trace the route to target using our routing table.
     565          Wrapper method of OperatingSystem.traceRoute
     566
     567          @param target: Device name
     568          @type target: string
     569          @param ippath: IP addesses
     570          @type ippath: list
     571          @return: IP Addresses
     572          @rtype: list
     573          """
     574          if ippath is None: ippath=[]
     575          if type(target) in types.StringTypes:
     576              target = self.findDevice(target)
     577              if not target: raise ValueError("Target %s not found in DMD" % target)
     578          return self.os.traceRoute(target, ippath)
     579
     580
     581 -    def getMonitoredComponents(self, collector=None, type=None):
     582          """
     583          Return list of monitored DeviceComponents on this device.
     584          Wrapper method for getDeviceComponents
     585          """
     586          return self.getDeviceComponents(monitored=True,
     587                                          collector=collector, type=type)
     588
     589
     590      security.declareProtected(ZEN_VIEW, 'getReportableComponents')
     591 -    def getReportableComponents(self, collector=None, type=None):
     592          """
     593          Return a list of DeviceComponents on this device that should be
     594          considered for reporting.
     595
     596          @type collector: string
     597          @type type: string
     598          @permission: ZEN_VIEW
     599          @rtype: list
     600          """
     601          return self.getMonitoredComponents(collector=collector, type=type);
     602
     603
     604      security.declareProtected(ZEN_VIEW, 'getDeviceComponents')
     605 -    def getDeviceComponents(self, monitored=None, collector=None, type=None):
     606          """
     607          Return list of all DeviceComponents on this device.
     608
     609          @type monitored: boolean
     610          @type collector: string
     611          @type type: string
     612          @permission: ZEN_VIEW
     613          @rtype: list
     614          """
     615          # The getParentDeviceName index was added in 2.2.  During migrates
     616          # this code could execute before the 2.2 migrate steps are run, so we
     617          # need to properly cope with this case.
     618          # See ticket #2787
     619          if not self.componentSearch._catalog.indexes.has_key('getParentDeviceName'):
     620              return self.getDeviceComponentsNoIndexGen()
     621
     622          query = {
     623              'getParentDeviceName':self.id,
     624              }
     625          if collector is not None:
     626              query['getCollectors'] = collector
     627          if monitored is not None:
     628              query['monitored'] = monitored
     629          if type is not None:
     630              query['meta_type'] = type
     631
     632          return list(getObjectsFromCatalog(self.componentSearch, query, log))
     633
     634
     635 -    def getDeviceComponentsNoIndexGen(self):
     636          """
     637          Return a list of all device components by walking relations.  This is
     638          much slower then the normal getDeviceComponents method which uses the
     639          component index.  It is used when rebuilding the device indexes.
     640          """
     641          from DeviceComponent import DeviceComponent
     642          for baseObject in (self, self.os, self.hw):
     643              for rel in baseObject.getRelationships():
     644                  if rel.meta_type != "ToManyContRelationship": continue
     645                  for obj in rel():
     646                      if not isinstance(obj, DeviceComponent): break
     647                      yield obj
     648
     649
     650 -    def getSnmpConnInfo(self):
     651          """
     652          Returns an object containing SNMP Connection Info
     653
     654          @rtype: SnmpConnInfo object
     655          """
     656          from Products.ZenHub.services.PerformanceConfig import SnmpConnInfo
     657          return SnmpConnInfo(self)
     658
     659
     660 -    def getHWManufacturerName(self):
     661          """
     662          DEPRECATED - Return the hardware manufacturer name of this device.
     663
     664          @rtype: string
     665          @todo: Remove this method and remove the call from testDevice.py
     666          """
     667          return self.hw.getManufacturerName()
     668
     669
     670 -    def getHWProductName(self):
     671          """
     672          Return the hardware product name of this device.
     673
     674          @rtype: string
     675          """
     676          return self.hw.getProductName()
     677
     678
     679 -    def getHWProductKey(self):
     680          """
     681          DEPRECATED - Return the productKey of the device hardware.
     682
     683          @rtype: string
     684          @todo: Remove this method and remove the call from testDevice.py
     685          """
     686          return self.hw.getProductKey()
     687
     688
     689 -    def getOSManufacturerName(self):
     690          """
     691          DEPRECATED - Return the OS manufacturer name of this device.
     692
     693          @rtype: string
     694          @todo: Remove this method and remove the call from testDevice.py
     695          """
     696          return self.os.getManufacturerName()
     697
     698
     699 -    def getOSProductName(self):
     700          """
     701          DEPRECATED - Return the OS product name of this device.
     702
     703          @rtype: string
     704          @todo: Remove this method and remove the call from testDevice.py
     705          """
     706          return self.os.getProductName()
     707
     708
     709 -    def getOSProductKey(self):
     710          """
     711          DEPRECATED - Return the productKey of the device OS.
     712
     713          @rtype: string
     714          @todo: Remove this method and remove the call from testDevice.py
     715          """
     716          return self.os.getProductKey()
     717
     718
     719 -    def setOSProductKey(self, prodKey, manufacturer=None):
     720          """
     721          Set the productKey of the device OS.
     722          """
     723          self.os.setProductKey(prodKey, manufacturer)
     724
     725
     726 -    def getHWTag(self):
     727          """
     728          DEPRECATED - Return the tag of the device HW.
     729
     730          @rtype: string
     731          @todo: remove this method and remove the call from testDevice.py
     732          """
     733          return self.hw.tag
     734
     735
     736 -    def setHWTag(self, assettag):
     737          """
     738          Set the asset tag of the device hardware.
     739          """
     740          self.hw.tag = assettag
     741
     742
     743 -    def setHWProductKey(self, prodKey, manufacturer=None):
     744          """
     745          Set the productKey of the device hardware.
     746          """
     747          self.hw.setProductKey(prodKey, manufacturer)
     748
     749
     750 -    def setHWSerialNumber(self, number):
     751          """
     752          Set the hardware serial number.
     753          """
     754          self.hw.serialNumber = number
     755
     756
     757 -    def getHWSerialNumber(self):
     758          """
     759          DEPRECATED - Return the hardware serial number.
     760
     761          @rtype: string
     762          @todo: Remove this method and remove the call from testDevice.py
     763          """
     764          return self.hw.serialNumber
     765
     766
     767 -    def followNextHopIps(self):
     768          """
     769          Return the ips that our indirect routs point to which aren't currently
     770          connected to devices.
     771
     772          @todo: Can be moved to zendisc.py
     773          """
     774          ips = []
     775          for r in self.os.routes():
     776              ipobj = r.nexthop()
     777              #if ipobj and not ipobj.device():
     778              if ipobj: ips.append(ipobj.id)
     779          return ips
     780
     781
     782      security.declareProtected(ZEN_VIEW, 'getLocationName')
     783 -    def getLocationName(self):
     784          """
     785          Return the full location name ie /Location/SubLocation/Rack
     786
     787          @rtype: string
     788          @permission: ZEN_VIEW
     789          """
     790          loc = self.location()
     791          if loc: return loc.getOrganizerName()
     792          return ""
     793
     794      security.declareProtected(ZEN_VIEW, 'getLocationLink')
     795 -    def getLocationLink(self):
     796          """
     797          Return a link to the device's location.
     798
     799          @rtype: string
     800          @permission: ZEN_VIEW
     801          """
     802          loc = self.location()
     803          if loc:
     804              if self.checkRemotePerm(ZEN_VIEW, loc):
     805                  return "<a href='%s'>%s</a>" % (loc.getPrimaryUrlPath(),
     806                                                  loc.getOrganizerName())
     807              else:
     808                  return loc.getOrganizerName()
     809          return "None"
     810
     811
     812      security.declareProtected(ZEN_VIEW, 'getSystemNames')
     813 -    def getSystemNames(self):
     814          """
     815          Return the system names for this device
     816
     817          @rtype: list
     818          @permission: ZEN_VIEW
     819          """
     820          return map(lambda x: x.getOrganizerName(), self.systems())
     821
     822
     823      security.declareProtected(ZEN_VIEW, 'getSystemNamesString')
     824 -    def getSystemNamesString(self, sep=', '):
     825          """
     826          Return the system names for this device as a string
     827
     828          @rtype: string
     829          @permission: ZEN_VIEW
     830          """
     831          return sep.join(self.getSystemNames())
     832
     833
     834      security.declareProtected(ZEN_VIEW, 'getDeviceGroupNames')
     835 -    def getDeviceGroupNames(self):
     836          """
     837          Return the device group names for this device
     838
     839          @rtype: list
     840          @permission: ZEN_VIEW
     841          """
     842          return map(lambda x: x.getOrganizerName(), self.groups())
     843
     844
     845      security.declareProtected(ZEN_VIEW, 'getPerformanceServer')
     846 -    def getPerformanceServer(self):
     847          """
     848          Return the device performance server
     849
     850          @rtype: PerformanceMonitor
     851          @permission: ZEN_VIEW
     852          """
     853          return self.perfServer()
     854
     855
     856      security.declareProtected(ZEN_VIEW, 'getPerformanceServerName')
     857 -    def getPerformanceServerName(self):
     858          """
     859          Return the device performance server name
     860
     861          @rtype: string
     862          @permission: ZEN_VIEW
     863          """
     864          cr = self.perfServer()
     865          if cr: return cr.getId()
     866          return ''
     867
     868
     869 -    def getNetworkRoot(self):
     870          """Return the network root object
     871          """
     872          return self.getDmdRoot('Networks')
     873
     874      security.declareProtected(ZEN_VIEW, 'getLastChange')
     875 -    def getLastChange(self):
     876          """
     877          Return DateTime of last change detected on this device.
     878
     879          @rtype: DateTime
     880          @permission: ZEN_VIEW
     881          """
     882          return DateTime(float(self._lastChange))
     883
     884
     885      security.declareProtected(ZEN_VIEW, 'getLastChangeString')
     886 -    def getLastChangeString(self):
     887          """
     888          Return date string of last change detected on this device.
     889
     890          @rtype: string
     891          @permission: ZEN_VIEW
     892          """
     893          return Time.LocalDateTimeSecsResolution(float(self._lastChange))
     894
     895
     896      security.declareProtected(ZEN_VIEW, 'getSnmpLastCollection')
     897 -    def getSnmpLastCollection(self):
     898          """
     899          Return DateTime of last SNMP collection on this device.
     900
     901          @rtype: DateTime
     902          @permission: ZEN_VIEW
     903          """
     904          return DateTime(float(self._snmpLastCollection))
     905
     906
     907      security.declareProtected(ZEN_VIEW, 'getSnmpLastCollectionString')
     908 -    def getSnmpLastCollectionString(self):
     909          """
     910          Return date string of last SNMP collection on this device.
     911
     912          @rtype: string
     913          @permission: ZEN_VIEW
     914          """
     915          return Time.LocalDateTimeSecsResolution(float(self._snmpLastCollection))
     916
     917
     918 -    def _sanitizeIPaddress(self, ip):
     919          try:
     920              if not ip:
     921                  pass # Forcing a reset with a blank IP
     922              elif ip.find("/") > -1:
     923                  ipWithoutNetmask, netmask = ip.split("/",1)
     924                  checkip(ipWithoutNetmask)
     925                  # Also check for valid netmask if they give us one
     926                  if maskToBits(netmask) is None:
     927                      raise NoNetMask()
     928              else:
     929                  checkip(ip)
     930          except (IpAddressError, ValueError, NoNetMask), ex:
     931              log.warn("%s is an invalid IP address", ip)
     932              ip = ''
     933          return ip
     934
     935 -    def _isDuplicateIp(self, ip):
     936          ipMatch = self.getNetworkRoot().findIp(ip)
     937          if ipMatch:
     938              dev = ipMatch.device()
     939              if dev and self.id != dev.id:
     940                  return True
     941          return False
     942
     943      security.declareProtected(ZEN_ADMIN_DEVICE, 'setManageIp')
     944 -    def setManageIp(self, ip="", REQUEST=None):
     945          """
     946          Set the manage IP, if IP is not passed perform DNS lookup.
     947          If there is an error with the IP address format, the IP address
     948          will be reset to the result of a DNS lookup.
     949
     950          @rtype: string
     951          @permission: ZEN_ADMIN_DEVICE
     952          """
     953          message = ''
     954          ip = ip.replace(' ', '')
     955          origip = ip
     956          ip = self._sanitizeIPaddress(ip)
     957
     958          if not ip: # What if they put in a DNS name?
     959              try:
     960                  ip = socket.gethostbyname(origip)
     961                  if ip == '0.0.0.0':
     962                      # Host resolution failed
     963                      ip = ''
     964              except socket.error:
     965                  ip = ''
     966
     967          if not ip:
     968              try:
     969                  ip = socket.gethostbyname(self.id)
     970              except socket.error:
     971                  ip = ''
     972                  if origip:
     973                      message = ("%s is an invalid IP address, "
     974                        "and no appropriate IP could"
     975                        " be found via DNS for %s") % (origip, self.id)
     976                      log.warn(message)
     977                  else:
     978                      message = "DNS lookup of '%s' failed to return an IP" % \
     979                                 self.id
     980
     981          if ip:
     982              if self._isDuplicateIp(ip):
     983                  message = "The IP address %s is already assigned" % ip
     984                  log.warn(message)
     985
     986              else:
     987                  self.manageIp = ip
     988                  self.index_object()
     989                  notify(IndexingEvent(self, ('ipAddress',), True))
     990                  log.info("%s's IP address has been set to %s.",
     991                           self.id, ip)
     992
     993          return message
     994
     995
     996      security.declareProtected(ZEN_VIEW, 'getManageIp')
     997 -    def getManageIp(self):
     998          """
     999          Return the management ip for this device.
    1000
    1001          @rtype: string
    1002          @permission: ZEN_VIEW
    1003          """
    1004          return self.manageIp
    1005
    1006
    1007 -    def getManageIpObj(self):
    1008          """
    1009          DEPRECATED - Return the management ipobject for this device.
    1010
    1011          @rtype: IpAddress
    1012          @todo: This method may not be called anywhere, remove it.
    1013          """
    1014          if self.manageIp:
    1015              return self.Networks.findIp(self.manageIp)
    1016
    1017
    1018      security.declareProtected(ZEN_VIEW, 'getManageInterface')
    1019 -    def getManageInterface(self):
    1020          """
    1021          Return the management interface of a device based on its manageIp.
    1022
    1023          @rtype: IpInterface
    1024          @permission: ZEN_VIEW
    1025          """
    1026          ipobj = self.Networks.findIp(self.manageIp)
    1027          if ipobj: return ipobj.interface()
    1028
    1029
    1030      security.declareProtected(ZEN_VIEW, 'uptimeStr')
    1031 -    def uptimeStr(self):
    1032          """
    1033          Return the SNMP uptime
    1034
    1035          @rtype: string
    1036          @permission: ZEN_VIEW
    1037          """
    1038          ut = self.sysUpTime()
    1039          # test if less than 0 or NaN
    1040          if ut < 0 or ut != ut:
    1041              return "Unknown"
    1042          elif ut == 0:
    1043              return "0d:0h:0m:0s"
    1044          ut = float(ut)/100.
    1045          days = int(ut/86400)
    1046          hour = int((ut%86400)/3600)
    1047          mins = int((ut%3600)/60)
    1048          secs = int(ut%60)
    1049          return "%02dd:%02dh:%02dm:%02ds" % (
    1050              days, hour, mins, secs)
    1051
    1052
    1053 -    def getPeerDeviceClassNames(self):
    1054          """
    1055          Build a list of all device paths that have the python class pyclass
    1056
    1057          @rtype: list
    1058          """
    1059          dclass = self.getDmdRoot("Devices")
    1060          return dclass.getPeerDeviceClassNames(self.__class__)
    1061
    1062
    1063      ####################################################################
    1064      # Edit functions used to manage device relations and other attributes
    1065      ####################################################################
    1066
    1067      security.declareProtected(ZEN_CHANGE_DEVICE, 'manage_snmpCommunity')
    1068 -    def manage_snmpCommunity(self):
    1069          """
    1070          Reset the snmp community using the zSnmpCommunities variable.
    1071
    1072          @permission: ZEN_CHANGE_DEVICE
    1073          """
    1074          try:
    1075              zSnmpCommunity, zSnmpPort, zSnmpVer, snmpname = \
    1076                  findCommunity(self, self.manageIp, self.getDeviceClassPath(),
    1077                              port=self.zSnmpPort, version=self.zSnmpVer)
    1078          except NoSnmp:
    1079              pass
    1080          else:
    1081              if self.zSnmpCommunity != zSnmpCommunity:
    1082                  self.setZenProperty("zSnmpCommunity", zSnmpCommunity)
    1083              if self.zSnmpPort != zSnmpPort:
    1084                  self.setZenProperty("zSnmpPort", zSnmpPort)
    1085              if self.zSnmpVer != zSnmpVer:
    1086                  self.setZenProperty("zSnmpVer", zSnmpVer)
    1087
    1088 -    def setProductInfo(self, hwManufacturer="", hwProductName="",
    1089                            osManufacturer="", osProductName=""):
    1090          if hwManufacturer and hwProductName:
    1091              # updateDevice uses the sentinel value "_no_change" to indicate
    1092              # that we really don't want change this value
    1093              if hwManufacturer != "_no_change" and hwProductName != "_no_change":
    1094                  log.info("setting hardware manufacturer to %r productName to %r"
    1095                                  % (hwManufacturer, hwProductName))
    1096                  self.hw.setProduct(hwProductName, hwManufacturer)
    1097          else:
    1098              self.hw.productClass.removeRelation()
    1099
    1100          if osManufacturer and osProductName:
    1101              # updateDevice uses the sentinel value "_no_change" to indicate
    1102              # that we really don't want change this value
    1103              if osManufacturer != "_no_change" and osProductName != "_no_change":
    1104                  log.info("setting os manufacturer to %r productName to %r"
    1105                                  % (osManufacturer, osProductName))
    1106                  self.os.setProduct(osProductName, osManufacturer)
    1107                  self.os.productClass().isOS = True
    1108          else:
    1109              self.os.productClass.removeRelation()
    1110
    1111
    1112      security.declareProtected(ZEN_CHANGE_DEVICE, 'updateDevice')
    1113 -    def updateDevice(self,**kwargs):
    1114          """
    1115          Update the device relation and attributes, if passed. If any parameter
    1116          is not passed it will not be updated; the value of any unpassed device
    1117          propeties will remain the same.
    1118
    1119          @permission: ZEN_CHANGE_DEVICE
    1120          Keyword arguments:
    1121            title              -- device title [string]
    1122            tag                -- tag number [string]
    1123            serialNumber       -- serial number [string]
    1124            zProperties        -- dict of zProperties [dict]
    1125            zSnmpCommunity     -- snmp community (overrides corresponding value is zProperties) [string]
    1126            zSnmpPort          -- snmp port (overrides corresponding value in zProperties) [string]
    1127            zSnmpVer           -- snmp version (overrides corresponding value in zProperties) [string]
    1128            rackSlot           -- rack slot number [integer]
    1129            productionState    -- production state of device [integer]
    1130            priority           -- device priority [integer]
    1131            comment            -- device comment [string]
    1132            hwManufacturer     -- hardware manufacturer [string]
    1133            hwProductName      -- hardware product name [string]
    1134            osManufacturer     -- operating system manufacturer [string]
    1135            osProductName      -- operating system name [string]
    1136            locationPath       -- location [string]
    1137            groupPaths         -- group paths [list]
    1138            systemPaths        -- systen paths [list]
    1139            performanceMonitor -- collector name [string]
    1140
    1141          """
    1142          if kwargs.has_key("title") and kwargs['title'] is not None:
    1143              log.info("setting title to %r" % kwargs["title"])
    1144              self.title = kwargs["title"]
    1145          if kwargs.has_key("tag") and kwargs["tag"] is not None:
    1146              log.info("setting tag to %r" % kwargs["tag"])
    1147              self.hw.tag = kwargs["tag"]
    1148          if kwargs.has_key("serialNumber") and kwargs["serialNumber"] is not None:
    1149              log.info("setting serialNumber to %r" % kwargs["serialNumber"])
    1150              self.hw.serialNumber = kwargs["serialNumber"]
    1151
    1152          # Set zProperties passed in intelligently
    1153          if kwargs.has_key("zProperties") and kwargs["zProperties"] is not None:
    1154              zProperties = kwargs["zProperties"]
    1155          else:
    1156              zProperties = {}
    1157          # override any snmp properties that may be in zProperties
    1158          if kwargs.has_key("zSnmpCommunity"):
    1159              zProperties.update({"zSnmpCommunity":kwargs["zSnmpCommunity"]});
    1160          if kwargs.has_key("zSnmpPort"):
    1161              zProperties.update({"zSnmpPort":kwargs["zSnmpPort"]});
    1162          if kwargs.has_key("zSnmpVer"):
    1163              zProperties.update({"zSnmpVer":kwargs["zSnmpVer"]});
    1164
    1165          for prop, value in zProperties.items():
    1166              if value and getattr(self, prop) != value:
    1167                  self.setZenProperty(prop, value)
    1168
    1169          if kwargs.has_key("rackSlot"):
    1170              log.info("setting rackSlot to %r" % kwargs["rackSlot"])
    1171              self.rackSlot = kwargs["rackSlot"]
    1172
    1173          if kwargs.has_key("productionState"):
    1174              log.info("setting productionState to %r" % kwargs["productionState"])
    1175              self.setProdState(kwargs["productionState"])
    1176
    1177          if kwargs.has_key("priority"):
    1178              log.info("setting priority to %r" % kwargs["priority"])
    1179              self.setPriority(kwargs["priority"])
    1180
    1181          if kwargs.has_key("comments"):
    1182              log.info("setting comments to %r" % kwargs["comments"])
    1183              self.comments = kwargs["comments"]
    1184
    1185          self.setProductInfo(hwManufacturer=kwargs.get("hwManufacturer","_no_change"),
    1186                              hwProductName=kwargs.get("hwProductName","_no_change"),
    1187                              osManufacturer=kwargs.get("osManufacturer","_no_change"),
    1188                              osProductName=kwargs.get("osProductName","_no_change"))
    1189
    1190          if kwargs.get("locationPath", False):
    1191              log.info("setting location to %r" % kwargs["locationPath"])
    1192              self.setLocation(kwargs["locationPath"])
    1193
    1194          if kwargs.get("groupPaths",False):
    1195              log.info("setting group %r" % kwargs["groupPaths"])
    1196              self.setGroups(kwargs["groupPaths"])
    1197
    1198          if kwargs.get("systemPaths",False):
    1199              log.info("setting system %r" % kwargs["systemPaths"])
    1200              self.setSystems(kwargs["systemPaths"])
    1201
    1202          if kwargs.has_key("performanceMonitor") and \
    1203              kwargs["performanceMonitor"] != self.getPerformanceServerName():
    1204              log.info("setting performance monitor to %r" \
    1205                       % kwargs["performanceMonitor"])
    1206              self.setPerformanceMonitor(kwargs["performanceMonitor"])
    1207
    1208          self.setLastChange()
    1209          self.index_object()
    1210          notify(IndexingEvent(self))
    1211
    1212      security.declareProtected(ZEN_CHANGE_DEVICE, 'manage_editDevice')
    1213 -    def manage_editDevice(self,
    1214                  tag="", serialNumber="",
    1215                  zSnmpCommunity="", zSnmpPort=161, zSnmpVer="",
    1216                  rackSlot="", productionState=1000, comments="",
    1217                  hwManufacturer="", hwProductName="",
    1218                  osManufacturer="", osProductName="",
    1219                  locationPath="", groupPaths=[], systemPaths=[],
    1220                  performanceMonitor="localhost", priority=3,
    1221                  zProperties=None, title=None, REQUEST=None):
    1222          """
    1223          Edit the device relation and attributes. This method will update device
    1224          properties because of the default values that are passed. Calling this
    1225          method using a **kwargs dict will result in default values being set for
    1226          many device properties. To update only a subset of these properties use
    1227          updateDevice(**kwargs).
    1228
    1229          @param locationPath: path to a Location
    1230          @type locationPath: string
    1231          @param groupPaths: paths to DeviceGroups
    1232          @type groupPaths: list
    1233          @param systemPaths: paths to Systems
    1234          @type systemPaths: list
    1235          @param performanceMonitor: name of PerformanceMonitor
    1236          @type performanceMonitor: string
    1237          @permission: ZEN_CHANGE_DEVICE
    1238          """
    1239          self.updateDevice(
    1240                  tag=tag, serialNumber=serialNumber,
    1241                  zSnmpCommunity=zSnmpCommunity, zSnmpPort=zSnmpPort, zSnmpVer=zSnmpVer,
    1242                  rackSlot=rackSlot, productionState=productionState, comments=comments,
    1243                  hwManufacturer=hwManufacturer, hwProductName=hwProductName,
    1244                  osManufacturer=osManufacturer, osProductName=osProductName,
    1245                  locationPath=locationPath, groupPaths=groupPaths, systemPaths=systemPaths,
    1246                  performanceMonitor=performanceMonitor, priority=priority,
    1247                  zProperties=zProperties, title=title, REQUEST=REQUEST)
    1248          if REQUEST:
    1249              from Products.ZenUtils.Time import SaveMessage
    1250              IMessageSender(self).sendToBrowser("Saved", SaveMessage())
    1251              return self.callZenScreen(REQUEST)
    1252
    1253
    1254 -    def setTitle(self, newTitle):
    1255          """
    1256          Changes the title to newTitle and reindexes the object
    1257          """
    1258          super(Device, self).setTitle(newTitle)
    1259          self.index_object()
    1260          notify(IndexingEvent(self, ('name',), True))
    1261
    1262 -    def monitorDevice(self):
    1263          """
    1264          Returns true if the device production state >= zProdStateThreshold.
    1265
    1266          @rtype: boolean
    1267          """
    1268          return self.productionState >= self.zProdStateThreshold
    1269
    1270
    1271 -    def snmpMonitorDevice(self):
    1272          """
    1273          Returns true if the device is subject to SNMP monitoring
    1274
    1275          @rtype: boolean
    1276          """
    1277          return (self.monitorDevice()
    1278                  and self.getManageIp()
    1279                  and not self.zSnmpMonitorIgnore)
    1280
    1281
    1282 -    def getProductionStateString(self):
    1283          """
    1284          Return the prodstate as a string.
    1285
    1286          @rtype: string
    1287          """
    1288          return self.convertProdState(self.productionState)
    1289
    1290
    1291 -    def getPriority(self):
    1292          """
    1293          Return the numeric device priority.
    1294
    1295          @rtype: int
    1296          """
    1297          return self.priority
    1298
    1299
    1300 -    def getPriorityString(self):
    1301          """
    1302          Return the device priority as a string.
    1303
    1304          @rtype: string
    1305          """
    1306          return self.convertPriority(self.priority)
    1307
    1308 -    def getPingStatusString(self):
    1309          """
    1310          Return the pingStatus as a string
    1311
    1312          @rtype: string
    1313          """
    1314          return self.convertStatus(self.getPingStatus())
    1315
    1316 -    def getSnmpStatusString(self):
    1317          """
    1318          Return the snmpStatus as a string
    1319
    1320          @rtype: string
    1321          """
    1322          return self.convertStatus(self.getSnmpStatus())
    1323
    1324      security.declareProtected(ZEN_CHANGE_DEVICE_PRODSTATE, 'setProdState')
    1325 -    def setProdState(self, state, maintWindowChange=False, REQUEST=None):
    1326          """
    1327          Set the device's production state.
    1328
    1329          @parameter state: new production state
    1330          @type state: int
    1331          @parameter maintWindowChange: are we resetting state from inside a MW?
    1332          @type maintWindowChange: boolean
    1333          @permission: ZEN_CHANGE_DEVICE
    1334          """
    1335          self.productionState = int(state)
    1336          self.primaryAq().index_object()
    1337          notify(IndexingEvent(self.primaryAq(), ('productionState',), True))
    1338          if not maintWindowChange:
    1339              # Saves our production state for use at the end of the
    1340              # maintenance window.
    1341              self.preMWProductionState = self.productionState
    1342
    1343          try:
    1344              zem = self.dmd.ZenEventManager
    1345              conn = zem.connect()
    1346              try:
    1347                  curs = conn.cursor()
    1348                  curs.execute(
    1349                      "update status set prodState=%d where device='%s'" % (
    1350                      self.productionState, self.id))
    1351              finally: zem.close(conn)
    1352          except OperationalError:
    1353              msg = "Failed to update events for %s with new prodState %s" % (
    1354                          self.id, state)
    1355              log.exception(msg)
    1356              if REQUEST:
    1357                  IMessageSender(self).sendToBrowser(
    1358                      "Update Failed",
    1359                      msg,
    1360                      priority=messaging.WARNING
    1361                  )
    1362                  return self.callZenScreen(REQUEST)
    1363
    1364          if REQUEST:
    1365              IMessageSender(self).sendToBrowser(
    1366                  "Production State Set",
    1367                  "%s's production state was set to %s." % (self.id,
    1368                                        self.getProductionStateString())
    1369              )
    1370              return self.callZenScreen(REQUEST)
    1371
    1372      security.declareProtected(ZEN_CHANGE_DEVICE, 'setPriority')
    1373 -    def setPriority(self, priority, REQUEST=None):
    1374          """
    1375          Set the device's priority
    1376
    1377          @type priority: int
    1378          @permission: ZEN_CHANGE_DEVICE
    1379          """
    1380          self.priority = int(priority)
    1381          try:
    1382              zem = self.dmd.ZenEventManager
    1383              conn = zem.connect()
    1384              try:
    1385                  curs = conn.cursor()
    1386                  curs.execute("update status set DevicePriority=%d where device='%s'" % (
    1387                                  self.priority, self.id))
    1388              finally: zem.close(conn)
    1389          except OperationalError:
    1390              log.exception("failed to update events with new priority")
    1391              if REQUEST:
    1392                  messaging.IMessageSender(self).sendToBrowser(
    1393                      'Update Failed',
    1394                      "Failed to update events with new priority",
    1395                      priority=messaging.WARNING
    1396                  )
    1397                  return self.callZenScreen(REQUEST)
    1398
    1399          if REQUEST:
    1400              messaging.IMessageSender(self).sendToBrowser(
    1401                  'Priority Udpdated',
    1402                  "Device priority has been set to %s." % (
    1403                      self.getPriorityString())
    1404              )
    1405              return self.callZenScreen(REQUEST)
    1406
    1407      security.declareProtected(ZEN_CHANGE_DEVICE, 'setLastChange')
    1408 -    def setLastChange(self, value=None):
    1409          """
    1410          Set the changed datetime for this device.
    1411
    1412          @param value: secs since the epoch, default is now
    1413          @type value: float
    1414          @permission: ZEN_CHANGE_DEVICE
    1415          """
    1416          if value is None:
    1417              value = time.time()
    1418          self._lastChange = float(value)
    1419
    1420      security.declareProtected(ZEN_CHANGE_DEVICE, 'setSnmpLastCollection')
    1421 -    def setSnmpLastCollection(self, value=None):
    1422          """
    1423          Set the last time snmp collection occurred.
    1424
    1425          @param value: secs since the epoch, default is now
    1426          @type value: float
    1427          @permission: ZEN_CHANGE_DEVICE
    1428          """
    1429          if value is None:
    1430              value = time.time()
    1431          self._snmpLastCollection = float(value)
    1432
    1433
    1434      security.declareProtected(ZEN_CHANGE_DEVICE, 'addManufacturer')
    1435 -    def addManufacturer(self, newHWManufacturerName=None,
    1436                          newSWManufacturerName=None, REQUEST=None):
    1437          """
    1438          DEPRECATED -
    1439          Add either a hardware or software manufacturer to the database.
    1440
    1441          @permission: ZEN_CHANGE_DEVICE
    1442          @todo: Doesn't really do work on a device object.
    1443          Already exists on ZDeviceLoader
    1444          """
    1445          mname = newHWManufacturerName
    1446          field = 'hwManufacturer'
    1447          if not mname:
    1448              mname = newSWManufacturerName
    1449              field = 'osManufacturer'
    1450          self.getDmdRoot("Manufacturers").createManufacturer(mname)
    1451          if REQUEST:
    1452              REQUEST[field] = mname
    1453              messaging.IMessageSender(self).sendToBrowser(
    1454                  'Manufacturer Added',
    1455                  'The %s manufacturer has been created.' % mname
    1456              )
    1457              return self.callZenScreen(REQUEST)
    1458
    1459
    1460      security.declareProtected(ZEN_CHANGE_DEVICE, 'setHWProduct')
    1461 -    def setHWProduct(self, newHWProductName=None, hwManufacturer=None,
    1462                          REQUEST=None):
    1463          """
    1464          DEPRECATED -
    1465          Adds a new hardware product
    1466
    1467          @permission: ZEN_CHANGE_DEVICE
    1468          @todo: Doesn't really do work on a device object.
    1469          Already exists on ZDeviceLoader
    1470          """
    1471          added = False
    1472          if newHWProductName and hwManufacturer:
    1473              self.getDmdRoot("Manufacturers").createHardwareProduct(
    1474                                          newHWProductName, hwManufacturer)
    1475              added = True
    1476          if REQUEST:
    1477              if added:
    1478                  messaging.IMessageSender(self).sendToBrowser(
    1479                      'Product Set',
    1480                      'Hardware product has been set to %s.' % newHWProductName
    1481                  )
    1482                  REQUEST['hwProductName'] = newHWProductName
    1483              else:
    1484                  messaging.IMessageSender(self).sendToBrowser(
    1485                      'Set Product Failed',
    1486                      'Hardware product could not be set to %s.'%newHWProductName,
    1487                      priority=messaging.WARNING
    1488                  )
    1489              return self.callZenScreen(REQUEST)
    1490
    1491
    1492      security.declareProtected(ZEN_CHANGE_DEVICE, 'setOSProduct')
    1493 -    def setOSProduct(self, newOSProductName=None, osManufacturer=None, REQUEST=None):
    1494          """
    1495          DEPRECATED
    1496          Adds a new os product
    1497
    1498          @permission: ZEN_CHANGE_DEVICE
    1499          @todo: Doesn't really do work on a device object.
    1500          Already exists on ZDeviceLoader
    1501          """
    1502          if newOSProductName:
    1503              self.getDmdRoot("Manufacturers").createSoftwareProduct(
    1504                                          newOSProductName, osManufacturer, isOS=True)
    1505          if REQUEST:
    1506              if newOSProductName:
    1507                  messaging.IMessageSender(self).sendToBrowser(
    1508                      'Product Set',
    1509                      'OS product has been set to %s.' % newOSProductName
    1510                  )
    1511                  REQUEST['osProductName'] = newOSProductName
    1512              else:
    1513                  messaging.IMessageSender(self).sendToBrowser(
    1514                      'Set Product Failed',
    1515                      'OS product could not be set to %s.' % newOSProductName,
    1516                      priority=messaging.WARNING
    1517                  )
    1518              return self.callZenScreen(REQUEST)
    1519
    1520
    1521      security.declareProtected(ZEN_CHANGE_DEVICE, 'setLocation')
    1522 -    def setLocation(self, locationPath, REQUEST=None):
    1523          """
    1524          Set the location of a device. If the location is new it will be created.
    1525
    1526          @permission: ZEN_CHANGE_DEVICE
    1527          """
    1528          if not locationPath:
    1529              self.location.removeRelation()
    1530          else:
    1531              locobj = self.getDmdRoot("Locations").createOrganizer(locationPath)
    1532              self.addRelation("location", locobj)
    1533          self.setAdminLocalRoles()
    1534          self.index_object()
    1535          notify(IndexingEvent(self, 'path', False))
    1536
    1537
    1538 -    def addLocation(self, newLocationPath, REQUEST=None):
    1539          """
    1540          DEPRECATED
    1541          Add a new location and relate it to this device
    1542
    1543          @todo: Doesn't really do work on a device object.
    1544          Already exists on ZDeviceLoader
    1545          """
    1546          self.getDmdRoot("Locations").createOrganizer(newLocationPath)
    1547          if REQUEST:
    1548              REQUEST['locationPath'] = newLocationPath
    1549              messaging.IMessageSender(self).sendToBrowser(
    1550                  'Location Added',
    1551                  'Location %s has been created.' % newLocationPath
    1552              )
    1553              return self.callZenScreen(REQUEST)
    1554
    1555
    1556      security.declareProtected(ZEN_CHANGE_DEVICE, 'setPerformanceMonitor')
    1557 -    def setPerformanceMonitor(self, performanceMonitor,
    1558                              newPerformanceMonitor=None, REQUEST=None):
    1559          """
    1560          Set the performance monitor for this device.
    1561          If newPerformanceMonitor is passed in create it
    1562
    1563          @permission: ZEN_CHANGE_DEVICE
    1564          """
    1565          if newPerformanceMonitor:
    1566              #self.dmd.RenderServer.moveRRDFiles(self.id,
    1567              #    newPerformanceMonitor, performanceMonitor, REQUEST)
    1568              performanceMonitor = newPerformanceMonitor
    1569
    1570          obj = self.getDmdRoot("Monitors").getPerformanceMonitor(
    1571                                                      performanceMonitor)
    1572          self.addRelation("perfServer", obj)
    1573          self.setLastChange()
    1574
    1575          if REQUEST:
    1576              messaging.IMessageSender(self).sendToBrowser(
    1577                  'Monitor Changed',
    1578                  'Performance monitor has been set to %s.' % performanceMonitor
    1579              )
    1580              return self.callZenScreen(REQUEST)
    1581
    1582
    1583      security.declareProtected(ZEN_CHANGE_DEVICE, 'setGroups')
    1584 -    def setGroups(self, groupPaths):
    1585          """
    1586          Set the list of groups for this device based on a list of paths
    1587
    1588          @permission: ZEN_CHANGE_DEVICE
    1589          """
    1590          objGetter = self.getDmdRoot("Groups").createOrganizer
    1591          self._setRelations("groups", objGetter, groupPaths)
    1592          self.index_object()
    1593          notify(IndexingEvent(self, 'path', False))
    1594
    1595
    1596      security.declareProtected(ZEN_CHANGE_DEVICE, 'addDeviceGroup')
    1597 -    def addDeviceGroup(self, newDeviceGroupPath, REQUEST=None):
    1598          """
    1599          DEPRECATED?
    1600          Add a device group to the database and this device
    1601
    1602          @permission: ZEN_CHANGE_DEVICE
    1603          @todo: Already exists on ZDeviceLoader
    1604          """
    1605          group = self.getDmdRoot("Groups").createOrganizer(newDeviceGroupPath)
    1606          self.addRelation("groups", group)
    1607          if REQUEST:
    1608              messaging.IMessageSender(self).sendToBrowser(
    1609                  'Group Added',
    1610                  'Group %s has been created.' % newDeviceGroupPath
    1611              )
    1612              return self.callZenScreen(REQUEST)
    1613
    1614
    1615      security.declareProtected(ZEN_CHANGE_DEVICE, 'setSystems')
    1616 -    def setSystems(self, systemPaths):
    1617          """
    1618          Set a list of systems to this device using their system paths
    1619
    1620          @permission: ZEN_CHANGE_DEVICE
    1621          """
    1622          objGetter = self.getDmdRoot("Systems").createOrganizer
    1623          self._setRelations("systems", objGetter, systemPaths)
    1624          self.index_object()
    1625          notify(IndexingEvent(self, 'path', False))
    1626
    1627
    1628      security.declareProtected(ZEN_CHANGE_DEVICE, 'addSystem')
    1629 -    def addSystem(self, newSystemPath, REQUEST=None):
    1630          """
    1631          DEPRECATED?
    1632          Add a systems to this device using its system path
    1633
    1634          @permission: ZEN_CHANGE_DEVICE
    1635          @todo: Already exists on ZDeviceLoader
    1636          """
    1637          sys = self.getDmdRoot("Systems").createOrganizer(newSystemPath)
    1638          self.addRelation("systems", sys)
    1639          if REQUEST:
    1640              messaging.IMessageSender(self).sendToBrowser(
    1641                  'System Added',
    1642                  'System %s has been created.' % newSystemPath
    1643              )
    1644              return self.callZenScreen(REQUEST)
    1645
    1646
    1647      security.declareProtected(ZEN_CHANGE_DEVICE, 'setTerminalServer')
    1648 -    def setTerminalServer(self, termservername):
    1649          """
    1650          Set the terminal server of this device
    1651
    1652          @param termservername: device name of terminal server
    1653          @permission: ZEN_CHANGE_DEVICE
    1654          """
    1655          termserver = self.findDevice(termservername)
    1656          if termserver:
    1657              self.addRelation('termserver', termserver)
    1658
    1659
    1660 -    def _setRelations(self, relName, objGetter, relPaths):
    1661          """
    1662          Set related objects to this device
    1663
    1664          @param relName: name of the relation to set
    1665          @param objGetter: method to get the relation
    1666          @param relPaths: list of relationship paths
    1667          """
    1668          if type(relPaths) != type([]) and type(relPaths) != type(()):
    1669              relPaths = [relPaths,]
    1670          relPaths = filter(lambda x: x.strip(), relPaths)
    1671          rel = getattr(self, relName, None)
    1672          if not rel:
    1673              raise AttributeError( "Relation %s not found" % relName)
    1674          curRelIds = {}
    1675          for value in rel.objectValuesAll():
    1676              curRelIds[value.getOrganizerName()] = value
    1677          for path in relPaths:
    1678              if not curRelIds.has_key(path):
    1679                  robj = objGetter(path)
    1680                  self.addRelation(relName, robj)
    1681              else:
    1682                  del curRelIds[path]
    1683          for obj in curRelIds.values():
    1684              self.removeRelation(relName, obj)
    1685          self.setAdminLocalRoles()
    1686
    1687
    1688 -    def getExpandedLinks(self):
    1689          """
    1690          Return the expanded zComment property
    1691
    1692          @rtype: HTML output
    1693          """
    1694          from Products.ZenUtils.ZenTales import talesEval
    1695          try:
    1696              return talesEval('string:' + self.zLinks, self)
    1697          except Exception, ex:
    1698              import cgi
    1699              return "<i class='errortitle'>%s</i>" % cgi.escape(str(ex))
    1700
    1701      ####################################################################
    1702      # Private getter functions that implement DeviceResultInt
    1703      ####################################################################
    1704
    1705      security.declareProtected(ZEN_VIEW, 'device')
    1706 -    def device(self):
    1707          """
    1708          Support DeviceResultInt mixin class. Returns itself
    1709
    1710          @permission: ZEN_VIEW
    1711          """
    1712          return self
    1713
    1714
    1715      ####################################################################
    1716      # Status Management Functions used by status monitors
    1717      ####################################################################
    1718
    1719
    1720 -    def pastSnmpMaxFailures(self):
    1721          """
    1722          Returns true if the device has more SNMP failures
    1723          than maxFailures on its status mon.
    1724
    1725          @rtype: boolean
    1726          """
    1727          statusmon = self.monitors()
    1728          if len(statusmon) > 0:
    1729              statusmon = statusmon[0]
    1730              return statusmon.maxFailures < self.getSnmpStatusNumber()
    1731          return False
    1732
    1733
    1734      # FIXME: cleanup --force option #2660
    1735      security.declareProtected(ZEN_MANAGE_DEVICE_STATUS,
    1736          'getLastPollSnmpUpTime')
    1737 -    def getLastPollSnmpUpTime(self):
    1738          """
    1739          Get the value of the snmpUpTime status object
    1740
    1741          @permission: ZEN_MANAGE_DEVICE_STATUS
    1742          """
    1743          return self._lastPollSnmpUpTime.getStatus()
    1744
    1745
    1746      # FIXME: cleanup --force option #2660
    1747      security.declareProtected(ZEN_MANAGE_DEVICE_STATUS,
    1748          'setLastPollSnmpUpTime')
    1749 -    def setLastPollSnmpUpTime(self, value):
    1750          """
    1751          Set the value of the snmpUpTime status object
    1752
    1753          @permission: ZEN_MANAGE_DEVICE_STATUS
    1754          """
    1755          self._lastPollSnmpUpTime.setStatus(value)
    1756
    1757
    1758 -    def snmpAgeCheck(self, hours):
    1759          """
    1760          Returns True if SNMP data was collected more than 24 hours ago
    1761          """
    1762          lastcoll = self.getSnmpLastCollection()
    1763          hours = hours/24.0
    1764          if DateTime() > lastcoll + hours: return 1
    1765
    1766
    1767 -    def applyProductContext(self):
    1768          """
    1769          Apply zProperties inherited from Product Contexts.
    1770          """
    1771          self._applyProdContext(self.hw.getProductContext())
    1772          self._applyProdContext(self.os.getProductContext())
    1773          for soft in self.os.software():
    1774              self._applyProdContext(soft.getProductContext())
    1775
    1776
    1777 -    def _applyProdContext(self, context):
    1778          """
    1779          Apply zProperties taken for the product context passed in.
    1780
    1781          @param context: list of tuples returned from
    1782          getProductContext on a MEProduct.
    1783          """
    1784          for name, value in context:
    1785              if name == "zDeviceClass" and value:
    1786                  log.info("move device to %s", value)
    1787                  self.moveDevices(value, self.id)
    1788              elif name == "zDeviceGroup" and value:
    1789                  log.info("add device to group %s", value)
    1790                  self.addDeviceGroup(value)
    1791              elif name == "zSystem" and value:
    1792                  log.info("add device to system %s", value)
    1793                  self.addSystem(value)
    1794
    1795
    1796
    1797      ####################################################################
    1798      # Management Functions
    1799      ####################################################################
    1800
    1801      security.declareProtected(ZEN_MANAGE_DEVICE, 'collectDevice')
    1802 -    def collectDevice(self, setlog=True, REQUEST=None, generateEvents=False,
    1803                        background=False, write=None):
    1804          """
    1805          Collect the configuration of this device AKA Model Device
    1806
    1807          @param setlog: If true, set up the output log of this process
    1808          @permission: ZEN_MANAGE_DEVICE
    1809          @todo: generateEvents param is not being used.
    1810          """
    1811          unused(generateEvents)
    1812          xmlrpc = isXmlRpc(REQUEST)
    1813          perfConf = self.getPerformanceServer()
    1814          perfConf.collectDevice(self, setlog, REQUEST, generateEvents,
    1815                                 background, write)
    1816
    1817          if xmlrpc: return 0
    1818
    1819
    1820      security.declareProtected(ZEN_DELETE_DEVICE, 'deleteDevice')
    1821 -    def deleteDevice(self, deleteStatus=False, deleteHistory=False,
    1822                      deletePerf=False, REQUEST=None):
    1823          """
    1824          Delete device from the database
    1825
    1826          NB: deleteHistory is disabled for the 2.2 release.  In some
    1827          circumstances it was causing many subprocesses to be spawned
    1828          and creating a gridlock situation.
    1829
    1830          @permission: ZEN_ADMIN_DEVICE
    1831          """
    1832          parent = self.getPrimaryParent()
    1833          if deleteStatus:
    1834              self.getEventManager().manage_deleteHeartbeat(self.getId())
    1835              self.getEventManager().manage_deleteAllEvents(self.getId())
    1836          # if deleteHistory:
    1837          #     self.getEventManager().manage_deleteHistoricalEvents(self.getId())
    1838          if deletePerf:
    1839              perfserv = self.getPerformanceServer()
    1840              if perfserv:
    1841                  perfserv.deleteRRDFiles(self.id)
    1842          parent._delObject(self.getId())
    1843          if REQUEST:
    1844              if parent.getId()=='devices':
    1845                  parent = parent.getPrimaryParent()
    1846              REQUEST['RESPONSE'].redirect(parent.absolute_url() +
    1847                                              "/deviceOrganizerStatus"
    1848                                              '?message=Device deleted')
    1849
    1850
    1851      security.declareProtected(ZEN_MANAGE_DEVICE, 'manage_deleteHeartbeat')
    1852 -    def manage_deleteHeartbeat(self, REQUEST=None):
    1853          """
    1854          Delete this device's heartbeats.
    1855
    1856          @permission: ZEN_MANAGE_DEVICE
    1857          """
    1858          self.getEventManager().manage_deleteHeartbeat(self.getId())
    1859          if REQUEST:
    1860              messaging.IMessageSender(self).sendToBrowser(
    1861                  'Heartbeats cleared',
    1862                  "Cleared heartbeat events for %s." % self.id
    1863              )
    1864          return self.callZenScreen(REQUEST)
    1865
    1866
    1867      security.declareProtected(ZEN_ADMIN_DEVICE, 'renameDevice')
    1868 -    def renameDevice(self, newId=None, REQUEST=None):
    1869          """
    1870          Rename device from the DMD.  Disallow assignment of
    1871          an id that already exists in the system.
    1872
    1873          @permission: ZEN_ADMIN_DEVICE
    1874          @param newId: new name
    1875          @type newId: string
    1876          @param REQUEST: Zope REQUEST object
    1877          @type REQUEST: Zope REQUEST object
    1878          """
    1879          parent = self.getPrimaryParent()
    1880          path = self.absolute_url_path()
    1881          oldId = self.getId()
    1882          if newId is None:
    1883              return path
    1884
    1885          if not isinstance(newId, unicode):
    1886              newId = self.prepId(newId)
    1887
    1888          newId = newId.strip()
    1889
    1890          if newId == '' or newId == oldId:
    1891              return path
    1892
    1893          device = self.dmd.Devices.findDeviceByIdExact( newId )
    1894          if device:
    1895              message = 'Device already exists with id %s' % newId
    1896              raise DeviceExistsError( message, device )
    1897
    1898          # side effect: self.getId() will return newId after this call
    1899          try:
    1900              # If there is a title, change the title to the newId
    1901              # (ticket #5443).  manage_renameObject will reindex.
    1902              if self.title:
    1903                  self.title = newId
    1904              parent.manage_renameObject(oldId, newId)
    1905              self.renameDeviceInEvents(oldId, newId)
    1906              self.renameDeviceInPerformance(oldId, newId)
    1907              self.setLastChange()
    1908
    1909              return self.absolute_url_path()
    1910
    1911          except CopyError, e:
    1912              raise Exception("Device rename failed.")
    1913
    1914
    1915 -    def renameDeviceInEvents(self, old, new):
    1916          """update the device column in the status and history tables for rows
    1917             associated with this device"""
    1918          zem=self.dmd.ZenEventManager
    1919          query="update %%s set device='%s' where device='%s';"%(new, old)
    1920          sqlscript=''.join([query%t for t in ('status', 'history')])
    1921          args=['mysql',
    1922                '-h%s'%zem.host,
    1923                '-P%s'%zem.port,
    1924                '-u%s'%zem.username,
    1925                '-p%s'%zem.password,
    1926                '-e%s'%sqlscript,
    1927                zem.database,
    1928                ]
    1929          if not os.fork(): os.execvp('mysql', args)
    1930
    1931 -    def renameDeviceInPerformance(self, old, new):
    1932          """
    1933          Rename the directory that holds performance data for this device.
    1934
    1935          @param old: old performance directory name
    1936          @type old: string
    1937          @param new: new performance directory name
    1938          @type new: string
    1939          """
    1940          root = os.path.dirname(self.fullRRDPath())
    1941          oldpath = os.path.join(root, old)
    1942          newpath = os.path.join(root, new)
    1943          perfsvr = self.getPerformanceServer()
    1944          if hasattr(perfsvr, 'isLocalHost') and not perfsvr.isLocalHost():
    1945              command = 'mv "%s" "%s"' % (oldpath, newpath)
    1946              perfsvr.executeCommand(command, 'zenoss')
    1947          elif os.path.exists(oldpath):
    1948              if os.path.exists(newpath):
    1949                  shutil.rmtree(newpath)
    1950              shutil.move(oldpath, newpath)
    1951
    1952
    1953 -    def index_object(self):
    1954          """
    1955          Override so ips get indexed on move.
    1956          """
    1957          super(Device, self).index_object()
    1958          for iface in self.os.interfaces():
    1959              for ip in iface.ipaddresses():
    1960                  ip.index_object()
    1961
    1962
    1963 -    def unindex_object(self):
    1964          """
    1965          Override so ips get unindexed as well.
    1966          """
    1967          self.unindex_ips()
    1968          super(Device, self).unindex_object()
    1969
    1970
    1971 -    def unindex_ips(self):
    1972          """
    1973          IpAddresses aren't contained underneath Device, so manage_beforeDelete
    1974          won't propagate. Thus we must remove those links explicitly.
    1975          """
    1976          cat = self.dmd.ZenLinkManager._getCatalog(layer=3)
    1977          brains = cat(deviceId=self.id)
    1978          for brain in brains:
    1979              brain.getObject().unindex_links()
    1980
    1981
    1982 -    def cacheComponents(self):
    1983          """
    1984          Read current RRD values for all of a device's components
    1985          """
    1986          paths = self.getRRDPaths()[:]
    1987          #FIXME need better way to scope and need to get DataSources
    1988          # from RRDTemplates
    1989          #for c in self.os.interfaces(): paths.extend(c.getRRDPaths())
    1990          for c in self.os.filesystems(): paths.extend(c.getRRDPaths())
    1991          #for c in self.hw.harddisks(): paths.extend(c.getRRDPaths())
    1992          objpaq = self.primaryAq()
    1993          perfServer = objpaq.getPerformanceServer()
    1994          if perfServer:
    1995              try:
    1996                  result = perfServer.currentValues(paths)
    1997                  if result:
    1998                      RRDView.updateCache(zip(paths, result))
    1999              except Exception:
    2000                  log.exception("Unable to cache values for %s", self.id);
    2001
    2002
    2003 -    def getUserCommandTargets(self):
    2004          """
    2005          Called by Commandable.doCommand() to ascertain objects on which
    2006          a UserCommand should be executed.
    2007          """
    2008          return [self]
    2009
    2010 -    def getUserCommandEnvironment(self):
    2011          """
    2012          Returns the tales environment used to evaluate the command
    2013          """
    2014          environ = Commandable.getUserCommandEnvironment(self)
    2015          context = self.primaryAq()
    2016          environ.update({'dev': context,  'device': context,})
    2017          return environ
    2018
    2019 -    def getUrlForUserCommands(self):
    2020          """
    2021          Returns a URL to redirect to after a command has executed
    2022          used by Commandable
    2023          """
    2024          return self.getPrimaryUrlPath() + '/deviceManagement'
    2025
    2026 -    def getHTMLEventSummary(self, severity=4):
    2027          """
    2028          Returns HTML Event Summary of a device
    2029          """
    2030          html = []
    2031          html.append("<table width='100%' cellspacing='1' cellpadding='3'>")
    2032          html.append("<tr>")
    2033          def evsummarycell(ev):
    2034              if ev[1]-ev[2]>=0: klass = '%s empty thin' % ev[0]
    2035              else: klass = '%s thin' % ev[0]
    2036              h = '<th align="center" width="16%%" class="%s">%s/%s</th>' % (
    2037                  klass, ev[1], ev[2])
    2038              return h
    2039          info = self.getEventSummary(severity)
    2040          html += map(evsummarycell, info)
    2041          html.append('</tr></table>')
    2042          return '\n'.join(html)
    2043
    2044 -    def getDataForJSON(self, minSeverity=0):
    2045          """
    2046          Returns data ready for serialization
    2047          """
    2048          url, classurl = map(urlquote,
    2049                      (self.getDeviceUrl(), self.getDeviceClassPath()))
    2050          id = '<a class="tablevalues" href="%s">%s</a>' % (
    2051                              url, self.titleOrId())
    2052          ip = self.getDeviceIp()
    2053          if self.checkRemotePerm(ZEN_VIEW, self.deviceClass()):
    2054              path = '<a href="/zport/dmd/Devices%s">%s</a>' % (classurl,classurl)
    2055          else:
    2056              path = classurl
    2057          prod = self.getProdState()
    2058          zem = self.dmd.ZenEventManager
    2059          evsum = getEventPillME(zem, self, 1, minSeverity)[0]
    2060          return [id, ip, path, prod, evsum, self.id]
    2061
    2062 -    def exportXmlHook(self, ofile, ignorerels):
    2063          """
    2064          Add export of our child objects.
    2065          """
    2066          map(lambda o: o.exportXml(ofile, ignorerels), (self.hw, self.os))
    2067
    2068 -    def zenPropertyOptions(self, propname):
    2069          """
    2070          Returns a list of possible options for a given zProperty
    2071          """
    2072          if propname == 'zCollectorPlugins':
    2073              from Products.DataCollector.Plugins import loadPlugins
    2074              names = [ldr.pluginName for ldr in loadPlugins(self.dmd)]
    2075              names.sort()
    2076              return names
    2077          if propname == 'zCommandProtocol':
    2078              return ['ssh', 'telnet']
    2079          if propname == 'zSnmpVer':
    2080              return ['v1', 'v2c', 'v3']
    2081          if propname == 'zSnmpAuthType':
    2082              return ['', 'MD5', 'SHA']
    2083          if propname == 'zSnmpPrivType':
    2084              return ['', 'DES', 'AES']
    2085          return ManagedEntity.zenPropertyOptions(self, propname)
    2086
    2087      security.declareProtected(ZEN_MANAGE_DEVICE, 'pushConfig')
    2088 -    def pushConfig(self, REQUEST=None):
    2089          """
    2090          This will result in a push of all the devices to live collectors
    2091
    2092          @permission: ZEN_MANAGE_DEVICE
    2093          """
    2094          self._p_changed = True
    2095          if REQUEST:
    2096              messaging.IMessageSender(self).sendToBrowser(
    2097                  'Changes Pushed',
    2098                  'Changes to %s pushed to collectors.' % self.id
    2099              )
    2100              return self.callZenScreen(REQUEST)
    2101
    2102      security.declareProtected(ZEN_EDIT_LOCAL_TEMPLATES, 'bindTemplates')
    2103 -    def bindTemplates(self, ids=(), REQUEST=None):
    2104          """
    2105          This will bind available templates to the zDeviceTemplates
    2106
    2107          @permission: ZEN_EDIT_LOCAL_TEMPLATES
    2108          """
    2109          return self.setZenProperty('zDeviceTemplates', ids, REQUEST)
    2110
    2111      security.declareProtected(ZEN_EDIT_LOCAL_TEMPLATES, 'removeZDeviceTemplates')
    2112 -    def removeZDeviceTemplates(self, REQUEST=None):
    2113          """
    2114          Deletes the local zProperty, zDeviceTemplates
    2115
    2116          @permission: ZEN_EDIT_LOCAL_TEMPLATES
    2117          """
    2118          for id in self.zDeviceTemplates:
    2119              self.removeLocalRRDTemplate(id)
    2120          from Products.ZenRelations.ZenPropertyManager import ZenPropertyDoesNotExist
    2121          try:
    2122              return self.deleteZenProperty('zDeviceTemplates', REQUEST)
    2123          except ZenPropertyDoesNotExist:
    2124              if REQUEST: return self.callZenScreen(REQUEST)
    2125
    2126      security.declareProtected(ZEN_EDIT_LOCAL_TEMPLATES, 'addLocalTemplate')
    2127 -    def addLocalTemplate(self, id, REQUEST=None):
    2128          """
    2129          Create a local template on a device
    2130
    2131          @permission: ZEN_EDIT_LOCAL_TEMPLATES
    2132          """
    2133          from Products.ZenModel.RRDTemplate import manage_addRRDTemplate
    2134          manage_addRRDTemplate(self, id)
    2135          if id not in self.zDeviceTemplates:
    2136              self.bindTemplates(self.zDeviceTemplates+[id])
    2137          if REQUEST:
    2138              messaging.IMessageSender(self).sendToBrowser(
    2139                  'Local Template Added',
    2140                  'Added template %s to %s.' % (id, self.id)
    2141              )
    2142              return self.callZenScreen(REQUEST)
    2143
    2144 -    def getAvailableTemplates(self):
    2145          """
    2146          Returns all available templates for this device
    2147          """
    2148          # All templates defined on this device are available
    2149          templates = self.objectValues('RRDTemplate')
    2150          # Any templates available to the class that aren't overridden locally
    2151          # are also available
    2152          templates += [t for t in self.deviceClass().getRRDTemplates()
    2153                          if t.id not in [r.id for r in templates]]
    2154          def cmpTemplates(a, b):
    2155              return cmp(a.id.lower(), b.id.lower())
    2156          templates.sort(cmpTemplates)
    2157          return [ t for t in templates
    2158              if isinstance(self, t.getTargetPythonClass()) ]
    2159
    2160
    2161      security.declareProtected(ZEN_VIEW, 'getLinks')
    2162 -    def getLinks(self, OSI_layer='3'):
    2163          """
    2164          Returns all Links on this Device's interfaces
    2165
    2166          @permission: ZEN_VIEW
    2167          """
    2168          if OSI_layer=='3':
    2169              from Products.ZenUtils.NetworkTree import getDeviceNetworkLinks
    2170              for link in getDeviceNetworkLinks(self):
    2171                  yield link
    2172          else:
    2173              for iface in self.os.interfaces.objectValuesGen():
    2174                  for link in iface.links.objectValuesGen():
    2175                      yield link
    2176
    2177      security.declareProtected(ZEN_VIEW, 'getXMLEdges')
    2178 -    def getXMLEdges(self, depth=3, filter="/", start=()):
    2179          """
    2180          Gets XML
    2181          """
    2182          if not start: start=self.id
    2183          edges = NetworkTree.get_edges(self, depth,
    2184                                        withIcons=True, filter=filter)
    2185          return edgesToXML(edges, start)
    2186
    2187      security.declareProtected(ZEN_VIEW, 'getPrettyLink')
    2188 -    def getPrettyLink(self, target=None, altHref=""):
    2189          """
    2190          Gets a link to this device, plus an icon
    2191
    2192          @rtype: HTML text
    2193          @permission: ZEN_VIEW
    2194          """
    2195          template = ("<div class='device-icon-container'>"
    2196                      "<img class='device-icon' src='%s'/> "
    2197                      "</div>%s")
    2198          icon = self.getIconPath()
    2199          href = altHref if altHref else self.getPrimaryUrlPath().replace('%','%%')
    2200          name = self.titleOrId()
    2201
    2202          rendered = template % (icon, name)
    2203
    2204          if not self.checkRemotePerm(ZEN_VIEW, self):
    2205              return rendered
    2206          else:
    2207              return "<a %s href='%s' class='prettylink'>%s</a>" % \
    2208                      ('target=' + target if target else '', href, rendered)
    2209
    2210
    2211 -    def getOSProcessMatchers(self):
    2212          """
    2213          Get a list of dictionaries containing everything needed to match
    2214          processes against the global list of process classes. Used by process
    2215          modeler plugins.
    2216          """
    2217          matchers = []
    2218          for pc in self.getDmdRoot("Processes").getSubOSProcessClassesSorted():
    2219              matchers.append({
    2220                  'regex': pc.regex,
    2221                  'ignoreParameters': pc.ignoreParameters,
    2222                  'getPrimaryDmdId': pc.getPrimaryDmdId(),
    2223                  })
    2224
    2225          return matchers
    2226
    2227
    2228 -    def updateProcesses(self, relmaps):
    2229          "Uses ProcessClasses to create processes to monitor"
    2230
    2231          from Products.DataCollector.ApplyDataMap import ApplyDataMap
    2232
    2233          processes = self.getDmdRoot("Processes")
    2234          pcs = list(processes.getSubOSProcessClassesGen())
    2235          log.debug("zenoss processes: %s" % pcs)
    2236          pcs.sort(lambda a, b: cmp(a.sequence,b.sequence))
    2237
    2238          #some debug output
    2239          procs = Set()
    2240          if log.isEnabledFor(10):
    2241              log.debug("=== snmp process information received ===")
    2242              for p in scanResults:
    2243                  log.debug("process: %s" % p)
    2244              log.debug("=== processes stored/defined in Zenoss ===")
    2245              for p in pcs:
    2246                  log.debug("%s\t%s" % (p.id, p.regex))
    2247
    2248          procs = Set()
    2249
    2250          #get the processes defined in Zenoss
    2251          processes = self.getDmdRoot("Processes")
    2252          pcs = list(processes.getSubOSProcessClassesGen())
    2253          log.debug("zenoss processes: %s" % pcs)
    2254          pcs.sort(lambda a, b: cmp(a.sequence,b.sequence))
    2255
    2256          #some debug output
    2257          if log.isEnabledFor(10):
    2258              log.debug("=== snmp process information received ===")
    2259              for p in scanResults:
    2260                  log.debug("process: %s" % p)
    2261
    2262              log.debug("=== processes stored/defined in Zenoss ===")
    2263              for p in pcs:
    2264                  log.debug("%s\t%s" % (p.id, p.regex))
    2265
    2266          maps = []
    2267          for om in relmap.maps:
    2268              om = ObjectMap(proc)
    2269              fullname = (om.procName + " " + om.parameters).rstrip()
    2270              log.debug("current process: %s" % fullname)
    2271
    2272              for pc in pcs:
    2273                  if pc.match(fullname):
    2274                      om.setOSProcessClass = pc.getPrimaryDmdId()
    2275                      id = om.procName
    2276                      parameters = om.parameters.strip()
    2277                      if parameters and not pc.ignoreParameters:
    2278                          parameters = md5.md5(parameters).hexdigest()
    2279                          id += ' ' + parameters
    2280                      om.id = self.prepId(id)
    2281                      if id not in procs:
    2282                          procs.add(id)
    2283                          log.debug("adding %s" % fullname)
    2284                          maps.append(om)
    2285                      break
    2286          relmap.maps = maps
    2287
    2288          adm = ApplyDataMap()
    2289          return adm._applyDataMap(self, relmap)
    2290
    2291  InitializeClass(Device)
    2292