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

# Source Code for Module Products.ZenModel.Device

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