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

Source Code for Module Products.ZenModel.Device

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