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

Source Code for Module Products.ZenModel.DeviceClass

  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 or (at your 
  8  # option) any later version as published by the Free Software Foundation. 
  9  # 
 10  # For complete information please visit: http://www.zenoss.com/oss/ 
 11  # 
 12  ########################################################################### 
 13   
 14  __doc__="""DeviceClass 
 15  The primary organizer of device objects, managing zProperties and 
 16  their acquisition. 
 17  """ 
 18   
 19  import time 
 20  from cStringIO import StringIO 
 21  import transaction 
 22  import logging 
 23  log = logging.getLogger('zen.DeviceClass') 
 24   
 25  import DateTime 
 26  from zope.event import notify 
 27  from zope.container.contained import ObjectMovedEvent 
 28  from Globals import DTMLFile 
 29  from Globals import InitializeClass 
 30  from Acquisition import aq_base, aq_chain 
 31  from AccessControl import ClassSecurityInfo 
 32  from AccessControl import Permissions as permissions 
 33  from ZODB.transact import transact 
 34   
 35  from Products.AdvancedQuery import MatchGlob, Or, Eq, RankByQueries_Max 
 36  from Products.CMFCore.utils import getToolByName 
 37  from Products.ZenMessaging.ChangeEvents.events import DeviceClassMovedEvent 
 38  from Products.ZenModel.ZenossSecurity import * 
 39  from Products.ZenRelations.RelSchema import * 
 40  from Products.ZenRelations.ZenPropertyManager import Z_PROPERTIES 
 41  from Products.ZenUtils.Search import makeCaseInsensitiveFieldIndex, makeCaseInsensitiveFieldIndex, makeCaseSensitiveKeywordIndex 
 42  from Products.ZenUtils.Search import makeCaseInsensitiveKeywordIndex 
 43  from Products.ZenUtils.Search import makePathIndex, makeMultiPathIndex 
 44  from Products.ZenUtils.Utils import importClass, zenPath 
 45  from Products.ZenUtils.guid.interfaces import IGlobalIdentifier 
 46  from Products.ZenWidgets import messaging 
 47  from Products.ZenUtils.FakeRequest import FakeRequest 
 48  from Products.Zuul.catalog.events import IndexingEvent 
 49   
 50  import RRDTemplate 
 51  from DeviceOrganizer import DeviceOrganizer 
 52  from ZenPackable import ZenPackable 
 53  from TemplateContainer import TemplateContainer 
 54   
 55  _marker = "__MARKER___" 
56 57 -def manage_addDeviceClass(context, id, title = None, REQUEST = None):
58 """make a device class""" 59 dc = DeviceClass(id, title) 60 context._setObject(id, dc) 61 if REQUEST is not None: 62 REQUEST['RESPONSE'].redirect(context.absolute_url() + '/manage_main')
63 64 65 addDeviceClass = DTMLFile('dtml/addDeviceClass',globals())
66 67 68 -class DeviceClass(DeviceOrganizer, ZenPackable, TemplateContainer):
69 """ 70 DeviceClass is a device organizer that manages the primary classification 71 of device objects within the Zenoss system. It manages properties 72 that are inherited through acquisition that modify the behavior of 73 many different sub systems within Zenoss. 74 It also handles the creation of new devices in the system. 75 """ 76 77 # Organizer configuration 78 dmdRootName = "Devices" 79 80 manageDeviceSearch = DTMLFile('dtml/manageDeviceSearch',globals()) 81 manageDeviceSearchResults = DTMLFile('dtml/manageDeviceSearchResults', 82 globals()) 83 84 portal_type = meta_type = event_key = "DeviceClass" 85 86 default_catalog = 'deviceSearch' 87 88 _properties = DeviceOrganizer._properties + ( 89 {'id':'devtypes', 'type':'lines', 'mode':'w'}, 90 ) 91 92 _relations = DeviceOrganizer._relations + ZenPackable._relations + \ 93 TemplateContainer._relations + ( 94 ("devices", ToManyCont(ToOne,"Products.ZenModel.Device","deviceClass")), 95 ) 96 97 # Screen action bindings (and tab definitions) 98 factory_type_information = ( 99 { 100 'id' : 'DeviceClass', 101 'meta_type' : 'DeviceClass', 102 'description' : """Base class for all devices""", 103 'icon' : 'DeviceClass_icon.gif', 104 'product' : 'ZenModel', 105 'factory' : 'manage_addDeviceClass', 106 'immediate_view' : 'deviceOrganizerStatus', 107 'actions' : 108 ( 109 { 'name' : 'Classes' 110 , 'action' : 'deviceOrganizerStatus' 111 , 'permissions' : ( permissions.view, ) 112 }, 113 { 'name' : 'Events' 114 , 'action' : 'viewEvents' 115 , 'permissions' : ( permissions.view, ) 116 }, 117 { 'name' : 'Configuration Properties' 118 , 'action' : 'zPropertyEdit' 119 , 'permissions' : (permissions.view,) 120 }, 121 { 'name' : 'Templates' 122 , 'action' : 'perfConfig' 123 , 'permissions' : ('Manage DMD',) 124 }, 125 ) 126 }, 127 ) 128 129 security = ClassSecurityInfo() 130
131 - def getPeerDeviceClassNames(self, pyclass=None):
132 """ 133 Return a list of all device paths that have the Python class pyclass 134 135 @param pyclass: Python class (default is this class) 136 @type pyclass: Python class 137 @return: list of device paths 138 @rtype: list of strings 139 """ 140 dcnames = [] 141 if pyclass == None: 142 pyclass = self.getPythonDeviceClass() 143 dclass = self.getDmdRoot("Devices") 144 for orgname in dclass.getOrganizerNames(): 145 org = dclass.getOrganizer(orgname) 146 if issubclass(org.getPythonDeviceClass(), pyclass): 147 dcnames.append(orgname) 148 dcnames.sort(lambda a, b: cmp(a.lower(), b.lower())) 149 return dcnames
150 151 deviceMoveTargets = getPeerDeviceClassNames 152 childMoveTargets = getPeerDeviceClassNames 153 154
155 - def createInstance(self, id):
156 """ 157 Create an instance based on its location in the device tree 158 walk up the primary aq path looking for a python instance class that 159 matches the name of the closest node in the device tree. 160 161 @param id: id in DMD path 162 @type id: string 163 @return: new device object 164 @rtype: device object 165 """ 166 pyClass = self.getPythonDeviceClass() 167 dev = pyClass(id) 168 self.devices._setObject(id, dev) 169 return self.devices._getOb(id)
170 171
172 - def getPythonDeviceClass(self):
173 """ 174 Return the Python class object to be used for device instances in this 175 device class. This is done by walking up the aq_chain of a deviceclass 176 to find a node that has the same name as a Python class or has an 177 attribute named zPythonClass that matches a Python class. 178 179 @return: device class 180 @rtype: device class 181 """ 182 from Device import Device 183 cname = getattr(self, "zPythonClass", None) 184 if cname: 185 try: 186 return importClass(cname) 187 except ImportError: 188 log.exception("Unable to import class " + cname) 189 return Device
190 191 @transact
192 - def _moveDevice(self, devname, target, targetClass):
193 dev = self.findDeviceByIdExact(devname) 194 if not dev: 195 return 196 guid = IGlobalIdentifier(dev).create() 197 source = dev.deviceClass().primaryAq() 198 199 notify(DeviceClassMovedEvent(dev, dev.deviceClass().primaryAq(), target)) 200 201 exported = False 202 oldPath = source.absolute_url_path() + '/' 203 if dev.__class__ != targetClass: 204 from Products.ZenRelations.ImportRM import NoLoginImportRM 205 206 def switchClass(o, module, klass): 207 """ 208 Create an XML string representing the module in a 209 new class. 210 211 @param o: file-type object 212 @type o: file-type object 213 @param module: location in DMD 214 @type module: string 215 @param klass: class name 216 @type klass: string 217 @return: XML representation of the class 218 @rtype: string 219 """ 220 from xml.dom.minidom import parse 221 222 # Note: strips almost everything out of the move 223 # as the new class may not have the same relations etc. 224 # For example, moving SNMP host to a VMware class. 225 o.seek(0) 226 dom = parse(o) 227 root = dom.childNodes[0] 228 root.setAttribute('module', module) 229 root.setAttribute('class', klass) 230 for obj in root.childNodes: 231 if obj.nodeType != obj.ELEMENT_NODE: 232 continue # Keep XML-tree baggage 233 234 name = obj.getAttribute('id') 235 if obj.tagName == 'property': 236 # Only remove modeler plugins, templates 237 # and z*Ignore zprops 238 if name in ('zCollectorPlugins', 'zDeviceTemplates') or \ 239 name.endswith('Ignore'): 240 root.removeChild(obj) 241 242 elif obj.tagName == 'toone' and \ 243 name in ('perfServer', 'location'): 244 pass # Preserve collector name and location 245 246 elif obj.tagName == 'tomany' and \ 247 name in ('systems', 'groups'): 248 pass # Preserve the Groups and Systems groupings 249 250 elif obj.tagName == 'tomanycont' and \ 251 name in ('maintenanceWindows', 252 'adminRoles', 253 'userCommands'): 254 pass # Preserve maintenance windows, admins, commands 255 256 else: 257 log.debug("Removing %s element id='%s'", 258 obj.tagName, name) 259 root.removeChild(obj) 260 261 importFile = StringIO() 262 dom.writexml(importFile) 263 importFile.seek(0) 264 return importFile
265 266 def devExport(d, module, klass): 267 """ 268 Create an XML string representing the device d 269 at the DMD location module of type klass. 270 271 @param module: location in DMD 272 @type module: string 273 @param klass: class name 274 @type klass: string 275 @return: XML representation of the class 276 @rtype: string 277 """ 278 o = StringIO() 279 d.exportXml(o) 280 return switchClass(o, module, klass)
281 282 def devImport(xmlfile): 283 """ 284 Load a new device from a file. 285 286 @param xmlfile: file type object 287 @type xmlfile: file type object 288 """ 289 im = NoLoginImportRM(target.devices) 290 im.loadObjectFromXML(xmlfile) 291 im.processLinks() 292 293 module = target.zPythonClass 294 if module: 295 klass = target.zPythonClass.split('.')[-1] 296 else: 297 module = 'Products.ZenModel.Device' 298 klass = 'Device' 299 log.debug('Exporting device %s from %s', devname, source) 300 xmlfile = devExport(dev, module, klass) 301 log.debug('Removing device %s from %s', devname, source) 302 source.devices._delObject(devname) 303 log.debug('Importing device %s to %s', devname, target) 304 devImport(xmlfile) 305 exported = True 306 else: 307 dev._operation = 1 308 source.devices._delObject(devname) 309 target.devices._setObject(devname, dev) 310 dev = target.devices._getOb(devname) 311 IGlobalIdentifier(dev).guid = guid 312 dev.setLastChange() 313 dev.setAdminLocalRoles() 314 dev.index_object() 315 notify(IndexingEvent(dev, idxs=('path', 'searchKeywords'), 316 update_metadata=True)) 317 318 return exported 319
320 - def moveDevices(self, moveTarget, deviceNames=None, REQUEST=None):
321 """ 322 Override default moveDevices because this is a contained relation. 323 If the Python class bound to a DeviceClass is different we convert to 324 the new Python class adding / removing relationships as needed. 325 326 @param moveTarget: organizer in DMD path 327 @type moveTarget: string 328 @param deviceNames: devices to move 329 @type deviceNames: list of stringa 330 @param REQUEST: Zope REQUEST object 331 @type REQUEST: Zope REQUEST object 332 """ 333 if not moveTarget or not deviceNames: return self() 334 target = self.getDmdRoot(self.dmdRootName).getOrganizer(moveTarget) 335 if isinstance(deviceNames, basestring): deviceNames = (deviceNames,) 336 targetClass = target.getPythonDeviceClass() 337 numExports = 0 338 for devname in deviceNames: 339 devicewasExported = self._moveDevice(devname, target, targetClass) 340 if devicewasExported: 341 numExports += 1 342 return numExports
343 344 345 security.declareProtected(ZEN_DELETE_DEVICE, 'removeDevices')
346 - def removeDevices(self, deviceNames=None, deleteStatus=False, 347 deleteHistory=False, deletePerf=False,REQUEST=None):
348 """ 349 See IManageDevice overrides DeviceManagerBase.removeDevices 350 """ 351 if not deviceNames: return self() 352 if isinstance(deviceNames, basestring): deviceNames = (deviceNames,) 353 for devname in deviceNames: 354 dev = self.findDevice(devname) 355 dev.deleteDevice(deleteStatus=deleteStatus, 356 deleteHistory=deleteHistory, deletePerf=deletePerf) 357 if REQUEST: 358 messaging.IMessageSender(self).sendToBrowser( 359 'Devices Deleted', 360 "Devices were deleted: %s." % ', '.join(deviceNames) 361 ) 362 if REQUEST.has_key('oneKeyValueSoInstanceIsntEmptyAndEvalToFalse'): 363 return 'Devices were deleted: %s.' % ', '.join(deviceNames) 364 else: 365 return self.callZenScreen(REQUEST)
366 367 368 security.declareProtected('View', 'getEventDeviceInfo')
369 - def getEventDeviceInfo(self):
370 """ 371 getEventDeviceInfo() -> return the info for NcoEventPopulator 372 """ 373 deviceInfo = {} 374 for device in self.getSubDevices(): 375 systemNames = [] 376 for sys in device.systems.objectValuesAll(): 377 systemNames.append(sys.getOrganizerName()) 378 systemNames = "|".join(systemNames) 379 location = device.getLocationName() 380 if not location: location = "Unknown" 381 deviceInfo[device.id] = (systemNames, location, 382 device.productionState, 383 device.getDeviceClassPath()) 384 return deviceInfo
385 386 387 security.declareProtected('View', 'getDeviceWinInfo')
388 - def getDeviceWinInfo(self, lastPoll=0, eventlog=False):
389 """ 390 Return list of (devname,user,passwd,url) for each device. 391 user and passwd are used to connect via wmi. 392 """ 393 ffunc = None 394 starttime = time.time() 395 if lastPoll > 0: 396 lastPoll = DateTime.DateTime(lastPoll) 397 ffunc = lambda x: x.getSnmpLastCollection() > lastPoll 398 if eventlog: 399 ffunc = lambda x: x.zWinEventlog 400 devinfo = [] 401 for dev in self.getSubDevices(devfilter=ffunc): 402 if not dev.monitorDevice(): continue 403 if dev.getProperty('zWmiMonitorIgnore', False): continue 404 user = dev.getProperty('zWinUser','') 405 passwd = dev.getProperty( 'zWinPassword', '') 406 sev = dev.getProperty( 'zWinEventlogMinSeverity', '') 407 devinfo.append((dev.id, str(user), str(passwd), sev, dev.absolute_url())) 408 return starttime, devinfo
409 410
411 - def getWinServices(self):
412 """ 413 Return a list of (devname, user, passwd, {'EvtSys':0,'Exchange':0}) 414 """ 415 svcinfo = [] 416 allsvcs = {} 417 for s in self.getSubComponents("WinService"): 418 svcs=allsvcs.setdefault(s.hostname(),{}) 419 name = s.name() 420 if isinstance(name, unicode): 421 name = name.encode(s.zCollectorDecoding) 422 svcs[name] = (s.getStatus(), s.getAqProperty('zFailSeverity')) 423 for dev in self.getSubDevices(): 424 if not dev.monitorDevice(): continue 425 if dev.getProperty( 'zWmiMonitorIgnore', False): continue 426 svcs = allsvcs.get(dev.getId(), {}) 427 if not svcs and not dev.zWinEventlog: continue 428 user = dev.getProperty('zWinUser','') 429 passwd = dev.getProperty( 'zWinPassword', '') 430 svcinfo.append((dev.id, str(user), str(passwd), svcs)) 431 return svcinfo
432 433 434 security.declareProtected('View', 'searchDeviceSummary')
435 - def searchDeviceSummary(self, query):
436 """ 437 Search device summary index and return device objects 438 """ 439 if not query: return [] 440 zcatalog = self._getCatalog() 441 if not zcatalog: return [] 442 results = zcatalog({'summary':query}) 443 return self._convertResultsToObj(results)
444 445 446 security.declareProtected('View', 'searchInterfaces')
447 - def searchInterfaces(self, query):
448 """ 449 Search interfaces index and return interface objects 450 """ 451 if not query: return [] 452 zcatalog = getattr(self, 'interfaceSearch', None) 453 if not zcatalog: return [] 454 results = zcatalog(query) 455 return self._convertResultsToObj(results)
456 457
458 - def _convertResultsToObj(self, results):
459 devices = [] 460 for brain in results: 461 try: 462 devobj = self.getObjByPath(brain.getPrimaryId) 463 devices.append(devobj) 464 except KeyError: 465 log.warn("bad path '%s' in index" % brain.getPrimaryId) 466 467 return devices
468
469 - def _findDevice(self, devicename, useTitle=True):
470 """ 471 Returns all devices whose ip/id/title match devicename. 472 ip/id matches are at the front of the list. 473 474 @rtype: list of brains 475 """ 476 idIpQuery = Or( MatchGlob('id', devicename), 477 Eq('getDeviceIp', devicename) ) 478 if useTitle: 479 titleOrIdQuery = MatchGlob('titleOrId', devicename) 480 query = Or( idIpQuery, titleOrIdQuery ) 481 rankSort = RankByQueries_Max( ( idIpQuery, 16 ), 482 ( titleOrIdQuery, 8 ) ) 483 devices = self._getCatalog().evalAdvancedQuery(query, (rankSort,)) 484 else: 485 devices = self._getCatalog().evalAdvancedQuery(idIpQuery) 486 return devices
487
488 - def findDevicePath(self, devicename):
489 """ 490 Look up a device and return its path 491 """ 492 ret = self._findDevice(devicename) 493 if not ret: return "" 494 return ret[0].getPrimaryId
495
496 - def findDevice(self, devicename):
497 """ 498 Returns the first device whose ip/id matches devicename. If 499 there is no ip/id match, return the first device whose title 500 matches devicename. 501 """ 502 ret = self._findDevice(devicename) 503 if ret: return ret[0].getObject()
504
505 - def findDeviceByIdOrIp(self, devicename):
506 """ 507 Returns the first device that has an ip/id that matches devicename 508 """ 509 ret = self._findDevice( devicename, False ) 510 if ret: return ret[0].getObject()
511
512 - def findDeviceByIdExact(self, devicename):
513 """ 514 Look up device in catalog and return it. devicename 515 must match device id exactly 516 """ 517 for brains in self._getCatalog()(id=devicename): 518 dev = brains.getObject() 519 if dev.id == devicename: 520 return dev
521
522 - def findDevicePingStatus(self, devicename):
523 """ 524 look up device in catalog and return its pingStatus 525 """ 526 dev = self.findDevice(devicename) 527 if dev: return dev.getPingStatusNumber()
528 529
530 - def getSubComponents(self, meta_type="", monitored=True):
531 """ 532 Return generator of components, by meta_type if specified 533 """ 534 zcat = self.componentSearch 535 res = zcat({'meta_type': meta_type, 'monitored': monitored}) 536 for b in res: 537 try: 538 c = self.getObjByPath(b.getPrimaryId) 539 if self.checkRemotePerm("View", c): 540 yield c 541 except KeyError: 542 log.warn("bad path '%s' in index 'componentSearch'", 543 b.getPrimaryId)
544 545 546 security.declareProtected("ZenCommon", "getMonitoredComponents")
547 - def getMonitoredComponents(self):
548 """ 549 Return monitored components for devices within this DeviceDeviceClass 550 """ 551 return self.getSubComponents()
552 553 554 security.declareProtected('View', 'getRRDTemplates')
555 - def getRRDTemplates(self, context=None):
556 """ 557 Return the actual RRDTemplate instances. 558 """ 559 templates = {} 560 if not context: context = self 561 mychain = aq_chain(context) 562 mychain.reverse() 563 for obj in mychain: 564 try: 565 templates.update(dict((t.id, t) for t in obj.rrdTemplates())) 566 except AttributeError: 567 pass 568 return templates.values()
569 570
571 - def getAvailableTemplates(self):
572 """ 573 Returns all available templates 574 """ 575 def cmpTemplates(a, b): 576 return cmp(a.id.lower(), b.id.lower())
577 templates = self.getRRDTemplates() 578 templates.sort(cmpTemplates) 579 pdc = self.getPythonDeviceClass() 580 return [ t for t in templates 581 if issubclass(pdc, t.getTargetPythonClass()) ] 582 583
584 - def bindTemplates(self, ids=(), REQUEST=None):
585 """ 586 This will bind available templates to the zDeviceTemplates 587 """ 588 return self.setZenProperty('zDeviceTemplates', ids, REQUEST)
589
590 - def removeZDeviceTemplates(self, REQUEST=None):
591 """ 592 Deletes the local zProperty, zDeviceTemplates 593 """ 594 if self.getPrimaryPath()[-2:] == ('dmd', 'Devices'): 595 self.setZenProperty('zDeviceTemplates', ['Device']) 596 else: 597 self.deleteZenProperty('zDeviceTemplates') 598 messaging.IMessageSender(self).sendToBrowser( 599 'Bindings Reset', 600 'Template bindings for this class were reset.' 601 ) 602 return self.callZenScreen(REQUEST)
603 604
605 - def getAllRRDTemplates(self, rrdts=None):
606 """ 607 Return all RRDTemplates at this level and below in the object tree. 608 If rrdts is provided then it must be a list of RRDTemplates which 609 will be extended with the templates from here and returned. 610 611 The original getAllRRDTemplates() method has been renamed 612 getAllRRDTemplatesPainfully(). It walks the object tree looking 613 for templates which is a very slow way of going about things. 614 The newer RRDTemplate.YieldAllRRDTemplate() method uses the 615 searchRRDTemplates catalog to speed things up dramatically. 616 YieldAllRRDTemplates is smart enough to revert to 617 getAllRRDTemplatesPainfully if the catalog is not present. 618 619 The searchRRDTemplates catalog was added in 2.2 620 """ 621 if rrdts is None: 622 rrdts = [] 623 rrdts.extend(RRDTemplate.YieldAllRRDTemplates(self)) 624 return rrdts
625 626
627 - def getAllRRDTemplatesPainfully(self, rrdts=None):
628 """ 629 RRDTemplate.YieldAllRRDTemplates() is probably what you want. 630 It takes advantage of the searchRRDTemplates catalog to get 631 much better performance. This method iterates over objects looking 632 for templates which is a slow, painful process. 633 """ 634 if rrdts is None: rrdts = [] 635 rrdts.extend(self.rrdTemplates()) 636 for dev in self.devices(): 637 rrdts += dev.objectValues('RRDTemplate') 638 for comps in dev.getDeviceComponents(): 639 rrdts += comps.objectValues('RRDTemplate') 640 for child in self.children(): 641 child.getAllRRDTemplatesPainfully(rrdts) 642 return rrdts
643 644 645 security.declareProtected('Add DMD Objects', 'manage_addRRDTemplate')
646 - def manage_addRRDTemplate(self, id, REQUEST=None):
647 """ 648 Add an RRDTemplate to this DeviceClass. 649 """ 650 if not id: return self.callZenScreen(REQUEST) 651 id = self.prepId(id) 652 org = RRDTemplate.RRDTemplate(id) 653 self.rrdTemplates._setObject(org.id, org) 654 if REQUEST: 655 messaging.IMessageSender(self).sendToBrowser( 656 'Template Added', 657 'The "%s" template has been created.' % id 658 ) 659 return self.callZenScreen(REQUEST)
660 661 662 security.declareProtected(ZEN_EDIT_LOCAL_TEMPLATES, 663 'manage_copyRRDTemplates')
664 - def manage_copyRRDTemplates(self, ids=(), REQUEST=None):
665 """ 666 Put a reference to the objects named in ids in the clip board 667 """ 668 if not ids: return self.callZenScreen(REQUEST) 669 ids = [ id for id in ids if self.rrdTemplates._getOb(id, None) is not None] 670 if not ids: return self.callZenScreen(REQUEST) 671 cp = self.rrdTemplates.manage_copyObjects(ids) 672 if REQUEST: 673 resp=REQUEST['RESPONSE'] 674 resp.setCookie('__cp', cp, path='/zport/dmd') 675 REQUEST['__cp'] = cp 676 messaging.IMessageSender(self).sendToBrowser( 677 'Templates Copied', 678 'Templates have been copied: %s' % ', '.join(ids) 679 ) 680 return self.callZenScreen(REQUEST) 681 return cp
682 683 684 security.declareProtected(ZEN_EDIT_LOCAL_TEMPLATES, 685 'manage_pasteRRDTemplates')
686 - def manage_pasteRRDTemplates(self, moveTarget=None, cb_copy_data=None, REQUEST=None):
687 """ 688 Paste RRDTemplates that have been copied before. 689 """ 690 cp = None 691 if cb_copy_data: cp = cb_copy_data 692 elif REQUEST: 693 cp = REQUEST.get("__cp",None) 694 695 if cp: 696 if moveTarget: 697 target = self.getDmdRoot(self.dmdRootName).getOrganizer(moveTarget) 698 else: 699 target = self 700 target.rrdTemplates.manage_pasteObjects(cp) 701 else: 702 target = None 703 704 if REQUEST: 705 REQUEST['RESPONSE'].setCookie('__cp', 'deleted', path='/zport/dmd', 706 expires='Wed, 31-Dec-97 23:59:59 GMT') 707 REQUEST['__cp'] = None 708 if target: 709 message = "Template(s) copied to %s" % moveTarget 710 else: 711 message = None 712 messaging.IMessageSender(self).sendToBrowser( 713 'Template(s) Copied', 714 message 715 ) 716 if not isinstance(REQUEST, FakeRequest): 717 url = target.getPrimaryUrlPath() + '/perfConfig' 718 if message: 719 url += '?message=%s' % message 720 REQUEST['RESPONSE'].redirect(url) 721 else: 722 return self.callZenScreen(REQUEST)
723 724 725 security.declareProtected(ZEN_EDIT_LOCAL_TEMPLATES, 726 'manage_copyAndPasteRRDTemplates')
727 - def manage_copyAndPasteRRDTemplates(self, ids=(), copyTarget=None, REQUEST=None):
728 """ 729 Copy the selected templates into the specified device class. 730 """ 731 if not ids: 732 messaging.IMessageSender(self).sendToBrowser( 733 'Invalid', 734 'No templates were selected.', 735 priority=messaging.WARNING 736 ) 737 return self.callZenScreen(REQUEST) 738 if copyTarget is None: 739 messaging.IMessageSender(self).sendToBrowser( 740 'Invalid', 741 'No target was selected.', 742 priority=messaging.WARNING 743 ) 744 return self.callZenScreen(REQUEST) 745 cp = self.manage_copyRRDTemplates(ids) 746 return self.manage_pasteRRDTemplates(copyTarget, cp, REQUEST)
747 748 749 security.declareProtected(ZEN_EDIT_LOCAL_TEMPLATES, 750 'manage_deleteRRDTemplates')
751 - def manage_deleteRRDTemplates(self, ids=(), paths=(), REQUEST=None):
752 """ 753 Delete RRDTemplates from this DeviceClass 754 (skips ones in other Classes) 755 """ 756 if not ids and not paths: 757 return self.callZenScreen(REQUEST) 758 for id in ids: 759 if (getattr(aq_base(self), 'rrdTemplates', False) 760 and getattr(aq_base(self.rrdTemplates),id,False)): 761 self.rrdTemplates._delObject(id) 762 for path in paths: 763 temp = self.dmd.getObjByPath(path) 764 if temp.deviceClass(): 765 temp.deviceClass().rrdTemplates._delObject(temp.id) 766 else: 767 temp.device()._delObject(temp.id) 768 if REQUEST: 769 messaging.IMessageSender(self).sendToBrowser( 770 'Templates Deleted', 771 'Templates were deleted: %s' % ", ".join(ids) 772 ) 773 return self.callZenScreen(REQUEST)
774 775
776 - def createCatalog(self):
777 """ 778 Make the catalog for device searching 779 """ 780 from Products.ZCatalog.ZCatalog import manage_addZCatalog 781 782 # Make catalog for Devices 783 manage_addZCatalog(self, self.default_catalog, 784 self.default_catalog) 785 zcat = self._getOb(self.default_catalog) 786 cat = zcat._catalog 787 for idxname in ['id', 788 'getDeviceIp','getDeviceClassPath','getProdState','titleOrId']: 789 cat.addIndex(idxname, makeCaseInsensitiveFieldIndex(idxname)) 790 cat.addIndex('getPhysicalPath', makePathIndex('getPhysicalPath')) 791 cat.addIndex('path', makeMultiPathIndex('path')) 792 zcat.addColumn('getPrimaryId') 793 zcat.addColumn('id') 794 zcat.addColumn('path') 795 zcat.addColumn('details') 796 797 # add extra fields to the catalog 798 fieldIndexes = ['getHWSerialNumber', 'getHWTag', 799 'getHWManufacturerName', 'getHWProductClass', 800 'getOSProductName', 'getOSManufacturerName', 801 'getPerformanceServerName', 'ipAddressAsInt', 802 'getProductionStateString', 'getPriorityString', 803 'getLocationName'] 804 keywordIndexes = ['getSystemNames', 'getDeviceGroupNames'] 805 806 # field indexes 807 for indexName in fieldIndexes: 808 cat.addIndex(indexName, makeCaseInsensitiveFieldIndex(indexName)) 809 810 # keyword indexes 811 for indexName in keywordIndexes: 812 cat.addIndex(indexName, makeCaseInsensitiveKeywordIndex(indexName)) 813 814 # permissions 815 cat.addIndex('allowedRolesAndUsers', makeCaseSensitiveKeywordIndex('allowedRolesAndUsers')) 816 817 # make catalog for device components 818 manage_addZCatalog(self, "componentSearch", "componentSearch") 819 zcat = self._getOb("componentSearch") 820 cat = zcat._catalog 821 cat.addIndex('meta_type', makeCaseInsensitiveFieldIndex('meta_type')) 822 cat.addIndex('getParentDeviceName', 823 makeCaseInsensitiveFieldIndex('getParentDeviceName')) 824 cat.addIndex('getCollectors', 825 makeCaseInsensitiveKeywordIndex('getCollectors')) 826 # XXX still using regular FieldIndex here for now, since this contains 827 # binary information 828 zcat.addIndex('monitored', 'FieldIndex') 829 zcat.addColumn('getPrimaryId') 830 zcat.addColumn('meta_type')
831 832
833 - def reIndex(self):
834 """ 835 Go through all devices in this tree and reindex them. 836 """ 837 zcat = getToolByName(self, self.default_catalog) 838 zcat.manage_catalogClear() 839 self.componentSearch.manage_catalogClear() 840 for dev in self.getSubDevicesGen_recursive(): 841 dev.index_object() 842 notify(IndexingEvent(dev)) 843 for comp in dev.getDeviceComponentsNoIndexGen(): 844 comp.index_object() 845 notify(IndexingEvent(comp))
846 847
848 - def buildDeviceTreeProperties(self):
849 """ 850 Create a new device tree with a default configuration 851 """ 852 devs = self.getDmdRoot("Devices") 853 for id, value, type in Z_PROPERTIES: 854 if not devs.hasProperty(id): 855 devs._setProperty(id, value, type)
856
857 - def zenPropertyOptions(self, propname):
858 """ 859 Provide a set of default options for a zProperty 860 861 @param propname: zProperty name 862 @type propname: string 863 @return: list of zProperty options 864 @rtype: list 865 """ 866 if propname == 'zCollectorPlugins': 867 from Products.DataCollector.Plugins import loadPlugins 868 names = [ldr.pluginName for ldr in loadPlugins(self.dmd)] 869 names.sort() 870 return names 871 if propname == 'zCommandProtocol': 872 return ['ssh', 'telnet'] 873 if propname == 'zSnmpVer': 874 return ['v1', 'v2c', 'v3'] 875 if propname == 'zSnmpAuthType': 876 return ['', 'MD5', 'SHA'] 877 if propname == 'zSnmpPrivType': 878 return ['', 'DES', 'AES'] 879 return DeviceOrganizer.zenPropertyOptions(self, propname)
880 881
882 - def pushConfig(self, REQUEST=None):
883 """ 884 This will result in a push of all the devices to live collectors 885 886 @param REQUEST: Zope REQUEST object 887 @type REQUEST: Zope REQUEST object 888 """ 889 self._p_changed = True 890 if REQUEST: 891 messaging.IMessageSender(self).sendToBrowser( 892 'Pushed Changes', 893 'Changes to %s were pushed to collectors.' % self.id 894 ) 895 return self.callZenScreen(REQUEST)
896 897 898 security.declareProtected('Change Device', 'setLastChange')
899 - def setLastChange(self, value=None):
900 """ 901 Set the changed datetime for this device. 902 903 @param value: changed datetime. Default is now. 904 @type value: number 905 """ 906 if value is None: 907 value = time.time() 908 self._lastChange = float(value)
909
910 - def register_devtype(self, description, protocol):
911 """ 912 Define this class in terms of a description of the devices it should 913 contain and the protocol by which they would normally be monitored. 914 """ 915 t = (description, protocol) 916 if not self.isLocal('devtypes'): 917 self._setProperty('devtypes', [], 'lines') 918 if t not in self.devtypes: 919 self.devtypes.append(t) 920 self._p_changed = True
921
922 - def unregister_devtype(self, description, protocol):
923 t = (description, protocol) 924 if hasattr(self, 'devtypes'): 925 if t in self.devtypes: 926 self.devtypes.remove(t) 927 self._p_changed = True
928 929 930 InitializeClass(DeviceClass) 931