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