Package Products :: Package ZenRelations :: Module ZenPropertyManager
[hide private]
[frames] | no frames]

Source Code for Module Products.ZenRelations.ZenPropertyManager

  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  import re 
 15  import logging 
 16  import exceptions 
 17   
 18  from OFS.PropertyManager import PropertyManager 
 19  from zExceptions import BadRequest 
 20  from Globals import DTMLFile 
 21  from Globals import InitializeClass 
 22  from Acquisition import aq_base, aq_chain 
 23  from ZPublisher.Converters import type_converters 
 24  from Products.ZenModel.ZenossSecurity import * 
 25  from AccessControl import ClassSecurityInfo 
 26  from Exceptions import zenmarker 
 27  from Products.ZenWidgets.interfaces import IMessageSender 
 28  from Products.ZenRelations.zPropertyCategory import getzPropertyCategory 
 29  iszprop = re.compile("^z[A-Z]").search 
 30   
 31  from Products.ZenUtils.Utils import unused 
 32   
 33  log = logging.getLogger('zen.PropertyManager') 
 34   
 35  # Z_PROPERTIES is a list of (id, type, value) pairs that define all the 
 36  # zProperties.  The values are set on dmd.Devices in the 
 37  # buildDeviceTreeProperties of DeviceClass 
 38  Z_PROPERTIES = [ 
 39   
 40      # zPythonClass maps device class to python classs (separate from device 
 41      # class name) 
 42      ('zPythonClass', '', 'string'), 
 43   
 44      # zProdStateThreshold is the production state threshold at which to start 
 45      # monitoring boxes 
 46      ('zProdStateThreshold', 300, 'int'), 
 47   
 48      # zIfDescription determines whether or not the ifdescripion field is 
 49      # displayed 
 50      ('zIfDescription', False, 'boolean'), 
 51   
 52      # Snmp collection properties 
 53      ('zSnmpCommunities', ['public', 'private'], 'lines'), 
 54      ('zSnmpCommunity', 'public', 'string'), 
 55      ('zSnmpPort', 161, 'int'), 
 56      ('zSnmpVer', 'v1', 'string'), 
 57      ('zSnmpTries', 2, 'int'), 
 58      ('zSnmpTimeout', 2.5, 'float'), 
 59      ('zSnmpEngineId', '', 'string'), 
 60      ('zSnmpSecurityName', '', 'string'), 
 61      ('zSnmpAuthPassword', '', 'password'), 
 62      ('zSnmpPrivPassword', '', 'password'), 
 63      ('zSnmpAuthType', '', 'string'), 
 64      ('zSnmpPrivType', '', 'string'), 
 65      ('zSnmpCollectionInterval', 300, 'int'), 
 66      ('zRouteMapCollectOnlyLocal', False, 'boolean'), 
 67      ('zRouteMapCollectOnlyIndirect', False, 'boolean'), 
 68      ('zRouteMapMaxRoutes', 500, 'int'), 
 69      ('zInterfaceMapIgnoreTypes', '', 'string'), 
 70      ('zInterfaceMapIgnoreNames', '', 'string'), 
 71      ('zFileSystemMapIgnoreTypes', [], 'lines'), 
 72      ('zFileSystemMapIgnoreNames', '', 'string'), 
 73      ('zFileSystemSizeOffset', 1.0, 'float'), 
 74      ('zHardDiskMapMatch', '', 'string'), 
 75      ('zSysedgeDiskMapIgnoreNames', '', 'string'), 
 76      ('zIpServiceMapMaxPort', 1024, 'int'), 
 77      ('zDeviceTemplates', ['Device'], 'lines'), 
 78      ('zLocalIpAddresses', '^127|^0\\.0|^169\\.254|^224', 'string'), 
 79      ('zLocalInterfaceNames', '^lo|^vmnet', 'string'), 
 80   
 81      # Status monitor properties 
 82      ('zSnmpMonitorIgnore', False, 'boolean'), 
 83      ('zPingMonitorIgnore', False, 'boolean'), 
 84      ('zWmiMonitorIgnore', True, 'boolean'), 
 85      ('zStatusConnectTimeout', 15.0, 'float'), 
 86   
 87      # DataCollector properties 
 88      ('zCollectorPlugins', [], 'lines'), 
 89      ('zCollectorClientTimeout', 180, 'int'), 
 90      ('zCollectorDecoding', 'latin-1', 'string'), 
 91      ('zCommandUsername', '', 'string'), 
 92      ('zCommandPassword', '', 'password'), 
 93      ('zCommandProtocol', 'ssh', 'string'), 
 94      ('zCommandPort', 22, 'int'), 
 95      ('zCommandLoginTries', 1, 'int'), 
 96      ('zCommandLoginTimeout', 10.0, 'float'), 
 97      ('zCommandCommandTimeout', 10.0, 'float'), 
 98      ('zCommandSearchPath', [], 'lines'), 
 99      ('zCommandExistanceTest', 'test -f %s', 'string'), 
100      ('zCommandPath', '/usr/local/zenoss/libexec', 'string'), 
101      ('zTelnetLoginRegex', 'ogin:.$', 'string'), 
102      ('zTelnetPasswordRegex', 'assword:', 'string'), 
103      ('zTelnetSuccessRegexList', ['\\$.$', '\\#.$'], 'lines'), 
104      ('zTelnetEnable', False, 'boolean'), 
105      ('zTelnetEnableRegex', 'assword:', 'string'), 
106      ('zTelnetTermLength', True, 'boolean'), 
107      ('zTelnetPromptTimeout', 10.0, 'float'), 
108      ('zKeyPath', '~/.ssh/id_dsa', 'string'), 
109      ('zMaxOIDPerRequest', 40, 'int'), 
110   
111      # Extra stuff for users 
112      ('zLinks', '', 'string'), 
113   
114      # Windows WMI collector properties 
115      ('zWinUser', '', 'string'), 
116      ('zWinPassword', '', 'password'), 
117      ('zWinEventlogMinSeverity', 2, 'int'), 
118      ('zWinEventlog', False, 'boolean'), 
119   
120      # zIcon is the icon path 
121      ('zIcon', '/zport/dmd/img/icons/noicon.png', 'string'), 
122      ] 
123   
124 -class PropertyDescriptor(object):
125 """ 126 Transforms the property value based on its type. 127 128 Follows the Descriptor protocol defined at 129 http://docs.python.org/reference/datamodel.html#descriptors 130 """ 131
132 - def __init__(self, id, type, transformer):
133 self.id = id 134 self.type = type 135 self.transformer = transformer
136
137 - def __get__(self, instance, owner):
138 """ 139 Returns self for class attribute access. Returns the transformed 140 value for instance attribute access. 141 """ 142 try: 143 if instance is None: 144 retval = self 145 else: 146 self._migrate(instance) 147 value = instance._propertyValues[self.id] 148 retval = self._transform(instance, value, 'transformForGet') 149 return retval 150 except: 151 raise AttributeError
152
153 - def __set__(self, instance, value):
154 """ 155 Transforms the value and sets it. 156 """ 157 self._migrate(instance) 158 self._set(instance, value)
159
160 - def __delete__(self, instance):
161 """ 162 Delete the property. 163 """ 164 self._migrate(instance) 165 del instance._propertyValues[self.id]
166
167 - def _migrate(self, instance):
168 """ 169 If the id is in __dict__ then move the value to the _propertyValues 170 dictionary. Check to make sure that the type of this descriptor class 171 and the type in the Zope OFS PropertyManager metadata are the same. 172 """ 173 if not hasattr(instance, '_propertyValues'): 174 instance._propertyValues = {} 175 if self.id in vars(instance): 176 self._set(instance, vars(instance)[self.id]) 177 del instance.__dict__[self.id] 178 instance._p_changed = True 179 for dct in instance._properties: 180 if dct['id'] == self.id: 181 if dct['type'] != self.type: 182 dct['type'] = self.type 183 instance._p_changed = True 184 break
185
186 - def _set(self, instance, value):
187 """ 188 Transform and set the value in the _propertyValues dictionary. 189 """ 190 valueToSet = self._transform(instance, value, 'transformForSet') 191 instance._propertyValues[self.id] = valueToSet
192
193 - def _transform(self, instance, value, method):
194 """ 195 Lookup the transformer for the type and transform the value. The 196 method parameter can be 'transformForGet' or 'transformForSet' and 197 determines the transformer method that is called. 198 """ 199 return getattr(self.transformer, method)(value)
200
201 -class ZenPropertyDoesNotExist(exceptions.ValueError):
202 pass
203
204 -class ZenPropertyManager(object, PropertyManager):
205 """ 206 207 ZenPropertyManager adds keyedselection type to PropertyManager. 208 A keyedselection displayes a different name in the popup then 209 the actual value the popup will have. 210 211 It also has management for zenProperties which are properties that can be 212 inherited long the acquision chain. All properties are for a branch are 213 defined on a "root node" specified by the function which must be returned 214 by the function getZenRootNode that should be over ridden in a sub class. 215 Prperties can then be added further "down" the aq_chain by calling 216 setZenProperty on any contained node. 217 218 ZenProperties all have the same prefix which is defined by iszprop 219 this can be overridden in a subclass. 220 221 ZenPropertyManager overrides getProperty and getPropertyType from 222 PropertyManager to support acquisition. If you want to query an object 223 about a property, but do not want it to search the acquistion chain then 224 use the super classes method or aq_base. Example: 225 226 # acquires property from dmd.Devices 227 dmd.Devices.Server.getProperty('zCollectorPlugins') 228 229 # does not acquire property from dmd.Devices 230 PropertyManager.getProperty(dmd.Devices.Server, 'zCollectorPlugins') 231 232 # also does not acquire property from dmd.Devices 233 aq_base(dmd.Devices.Server).getProperty('zSnmpCommunity') 234 235 The properties are stored as attributes which is convenient, but can be 236 confusing. Attribute access always uses acquistion. Setting an 237 attribute, will not add it to the list of properties, so subsquent calls 238 to hasProperty or getProperty won't return it. 239 240 Property Transformers are stored at dmd.propertyTransformers and transform 241 the property based on type during calls to the _setProperty, 242 _updateProperty, and getProperty methods. Adding a property using 243 _setProperty applies the appropriate transformer and adds its value as an 244 attribute, but when you access it as an attribute the property transformer 245 is again applied, but this time using its transformForGet method. 246 """ 247 __pychecker__='no-override' 248 249 security = ClassSecurityInfo() 250 251 manage_propertiesForm=DTMLFile('dtml/properties', globals(), 252 property_extensible_schema__=1) 253
254 - def _setPropValue(self, id, value):
255 """override from PerpertyManager to handle checks and ip creation""" 256 self._wrapperCheck(value) 257 propType = self.getPropertyType(id) 258 if propType == 'keyedselection': 259 value = int(value) 260 if not getattr(self,'_v_propdict',False): 261 self._v_propdict = self.propdict() 262 if 'setter' in self._v_propdict: 263 settername = self._v_propdict['setter'] 264 setter = getattr(aq_base(self), settername, None) 265 if not setter: 266 raise ValueError("setter %s for property %s doesn't exist" 267 % (settername, id)) 268 if not callable(setter): 269 raise TypeError("setter %s for property %s not callable" 270 % (settername, id)) 271 setter(value) 272 else: 273 setattr(self, id, value)
274 275
276 - def _setProperty(self, id, value, type='string', label=None, 277 visible=True, setter=None):
278 """for selection and multiple selection properties 279 the value argument indicates the select variable 280 of the property 281 """ 282 self._wrapperCheck(value) 283 if not self.valid_property_id(id): 284 raise BadRequest, 'Id %s is invalid or duplicate' % id 285 286 def setprops(**pschema): 287 self._properties=self._properties+(pschema,) 288 if setter: pschema['setter'] = setter 289 if label: pschema['label'] = label
290 291 if type in ('selection', 'multiple selection'): 292 if not hasattr(self, value): 293 raise BadRequest, 'No select variable %s' % value 294 setprops(id=id,type=type, visible=visible, 295 select_variable=value) 296 if type=='selection': 297 self._setPropValue(id, '') 298 else: 299 self._setPropValue(id, []) 300 else: 301 setprops(id=id, type=type, visible=visible) 302 self._setPropValue(id, value)
303
304 - def _updateProperty(self, id, value):
305 """ This method sets a property on a zope object. It overrides the 306 method in PropertyManager. If Zope is upgraded you will need to check 307 that this method has not changed! It is overridden so that we can catch 308 the ValueError returned from the field2* converters in the class 309 Converters.py 310 """ 311 try: 312 super(ZenPropertyManager, self)._updateProperty(id, value) 313 except ValueError: 314 msg = "Error Saving Property '%s'. New value '%s' is of invalid " 315 msg += "type. It should be type '%s'." 316 proptype = self.getPropertyType(id) 317 args = (id, value, proptype) 318 log.error(msg % args)
319 320 321 _onlystars = re.compile("^\*+$").search 322 security.declareProtected(ZEN_ZPROPERTIES_EDIT, 'manage_editProperties')
323 - def manage_editProperties(self, REQUEST):
324 """ 325 Edit object properties via the web. 326 The purpose of this method is to change all property values, 327 even those not listed in REQUEST; otherwise checkboxes that 328 get turned off will be ignored. Use manage_changeProperties() 329 instead for most situations. 330 """ 331 for prop in self._propertyMap(): 332 name=prop['id'] 333 if 'w' in prop.get('mode', 'wd'): 334 value=REQUEST.get(name, '') 335 if self.zenPropIsPassword(name) and self._onlystars(value): 336 continue 337 self._updateProperty(name, value) 338 if getattr(self, "index_object", False): 339 self.index_object() 340 if REQUEST: 341 message="Saved changes." 342 return self.manage_propertiesForm(self,REQUEST, 343 manage_tabs_message=message)
344 345
346 - def getZenRootNode(self):
347 """sub class must implement to use zenProperties.""" 348 raise NotImplementedError
349 350 security.declareProtected(ZEN_ZPROPERTIES_VIEW, 'zenPropertyIds')
351 - def zenPropertyIds(self, all=True, pfilt=iszprop):
352 """ 353 Return list of device tree property names. 354 If all use list from property root node. 355 """ 356 if all: 357 rootnode = self.getZenRootNode() 358 else: 359 if self.id == self.dmdRootName: return [] 360 rootnode = aq_base(self) 361 props = [] 362 for prop in rootnode.propertyIds(): 363 if not pfilt(prop): continue 364 props.append(prop) 365 props.sort() 366 return props
367 368 security.declareProtected(ZEN_ZPROPERTIES_VIEW, 'zenPropertyItems')
369 - def zenPropertyItems(self):
370 """Return list of (id, value) tuples of zenProperties. 371 """ 372 return map(lambda x: (x, getattr(self, x)), self.zenPropertyIds())
373 374 security.declareProtected(ZEN_ZPROPERTIES_VIEW, 'zenPropertyMap')
375 - def zenPropertyMap(self, pfilt=iszprop):
376 """Return property mapping of device tree properties.""" 377 rootnode = self.getZenRootNode() 378 pmap = [] 379 for pdict in rootnode.propertyMap(): 380 if pfilt(pdict['id']): pmap.append(pdict) 381 pmap.sort(lambda x, y: cmp(x['id'], y['id'])) 382 return pmap
383 384 security.declareProtected(ZEN_ZPROPERTIES_VIEW, 'zenPropertyString')
385 - def zenPropertyString(self, id):
386 """Return the value of a device tree property as a string""" 387 def displayLines(lines): 388 return '\n'.join(str(line) for line in lines)
389 def displayPassword(password): 390 return '*' * len(password) 391 def displayOthers(other): 392 return other 393 displayFunctions = {'lines': displayLines, 394 'password': displayPassword} 395 display = displayFunctions.get(self.getPropertyType(id), 396 displayOthers) 397 return display(self.getProperty(id, '')) 398 399 security.declareProtected(ZEN_ZPROPERTIES_VIEW, 'zenPropIsPassword')
400 - def zenPropIsPassword(self, id):
401 """Is this field a password field. 402 """ 403 return self.getPropertyType(id) == 'password'
404 405 security.declareProtected(ZEN_ZPROPERTIES_VIEW, 'zenPropertyPath')
406 - def zenPropertyPath(self, id):
407 """Return the primaryId of where a device tree property is found.""" 408 ob = self._findParentWithProperty(id) 409 if ob is None: 410 path = None 411 else: 412 path = ob.getPrimaryId(self.getZenRootNode().getId()) 413 return path
414 415 security.declareProtected(ZEN_ZPROPERTIES_EDIT, 'setZenProperty')
416 - def setZenProperty(self, propname, propvalue, REQUEST=None):
417 """ 418 Add or set the propvalue of the property propname on this node of 419 the device Class tree. 420 """ 421 ptype = self.getPropertyType(propname) 422 if ptype == 'lines': 423 dedupedList = [] 424 for x in propvalue: 425 if x not in dedupedList: 426 dedupedList.append(x) 427 propvalue = dedupedList 428 if getattr(aq_base(self), propname, zenmarker) != zenmarker: 429 self._updateProperty(propname, propvalue) 430 else: 431 if ptype in ("selection", 'multiple selection'): ptype="string" 432 if ptype in type_converters: 433 propvalue=type_converters[ptype](propvalue) 434 if getattr(self, propname, None) != propvalue: 435 self._setProperty(propname, propvalue, type=ptype) 436 if REQUEST: return self.callZenScreen(REQUEST)
437 438 security.declareProtected(ZEN_ZPROPERTIES_EDIT, 'saveZenProperties')
439 - def saveZenProperties(self, pfilt=iszprop, REQUEST=None):
440 """Save all ZenProperties found in the REQUEST.form object. 441 """ 442 for name, value in REQUEST.form.items(): 443 if pfilt(name): 444 if self.zenPropIsPassword(name) and self._onlystars(value): 445 continue 446 if name == 'zCollectorPlugins': 447 if tuple(getattr(self, name, ())) != tuple(value): 448 self.setZenProperty(name, value) 449 else: 450 self.setZenProperty(name, value) 451 452 if REQUEST: 453 IMessageSender(self).sendToBrowser( 454 'Configuration Propeties Updated', 455 'Configuration properties have been updated.' 456 ) 457 458 return self.callZenScreen(REQUEST)
459 460 security.declareProtected(ZEN_ZPROPERTIES_EDIT, 'deleteZenProperty')
461 - def deleteZenProperty(self, propname=None, REQUEST=None):
462 """ 463 Delete device tree properties from the this DeviceClass object. 464 """ 465 if propname: 466 try: 467 self._delProperty(propname) 468 except AttributeError: 469 #occasional object corruption where the propName is in 470 #_properties but not set as an attribute. filter out the prop 471 #and create a new _properties tuple 472 newProps = [x for x in self._properties if x['id'] != propname] 473 self._properties=tuple(newProps) 474 except exceptions.ValueError: 475 raise ZenPropertyDoesNotExist() 476 if REQUEST: return self.callZenScreen(REQUEST)
477 478 security.declareProtected(ZEN_ZPROPERTIES_VIEW, 'zenPropertyOptions')
479 - def zenPropertyOptions(self, propname):
480 "Provide a set of default options for a ZProperty" 481 unused(propname) 482 return []
483 484 security.declareProtected(ZEN_ZPROPERTIES_VIEW, 'isLocal')
485 - def isLocal(self, propname):
486 """Check to see if a name is local to our current context. 487 """ 488 v = getattr(aq_base(self), propname, zenmarker) 489 return v != zenmarker
490 491 security.declareProtected(ZEN_ZPROPERTIES_VIEW, 'getOverriddenObjects')
492 - def getOverriddenObjects(self, propname, showDevices=False):
493 """ Get the objects that override a property somewhere below in the tree 494 """ 495 if showDevices: 496 objects = [] 497 for inst in self.getSubInstances('devices'): 498 if inst.isLocal(propname) and inst not in objects: 499 objects.append(inst) 500 for suborg in self.children(): 501 if suborg.isLocal(propname): 502 objects.append(suborg) 503 for inst in suborg.getOverriddenObjects(propname, showDevices): 504 if inst not in objects: 505 objects.append(inst) 506 return objects 507 508 return [ org for org in self.getSubOrganizers() 509 if org.isLocal(propname) ]
510
511 - def _findParentWithProperty(self, id):
512 """ 513 Returns self or the first acquisition parent that has a property with 514 the id. Returns None if no parent had the id. 515 """ 516 for ob in aq_chain(self): 517 if isinstance(ob, ZenPropertyManager) and ob.hasProperty(id): 518 parentWithProperty = ob 519 break 520 else: 521 parentWithProperty = None 522 return parentWithProperty
523
524 - def hasProperty(self, id, useAcquisition=False):
525 """ 526 Override method in PropertyManager to support acquisition. 527 """ 528 if useAcquisition: 529 hasProp = self._findParentWithProperty(id) is not None 530 else: 531 hasProp = PropertyManager.hasProperty(self, id) 532 return hasProp
533
534 - def getProperty(self, id, d=None):
535 """ 536 Get property value and apply transformer. Overrides method in Zope's 537 PropertyManager class. Acquire values from aquisiton parents if 538 needed. 539 """ 540 ob = self._findParentWithProperty(id) 541 if ob is None: 542 value = d 543 else: 544 value = PropertyManager.getProperty(ob, id, d) 545 return value
546 547 security.declareProtected(ZEN_ZPROPERTIES_VIEW, 'getPropertyType')
548 - def getPropertyType(self, id):
549 """ 550 Overrides methods from PropertyManager to support acquistion. 551 """ 552 ob = self._findParentWithProperty(id) 553 if ob is None: 554 type = None 555 else: 556 type = PropertyManager.getPropertyType(ob, id) 557 return type
558 559 security.declareProtected(ZEN_ZPROPERTIES_VIEW, 'getZ')
560 - def getZ(self, id):
561 """ 562 Return the value of a zProperty on this object. This method is used to 563 lookup zProperties for a user with a role that doesn't have direct 564 access to an attribute further up the acquisition path. If the 565 requested property is a password, then None is returned. 566 567 @param id: id of zProperty 568 @type id: string 569 @return: Value of zProperty 570 @permission: ZEN_ZPROPERTIES_VIEW 571 572 >>> dmd.Devices.getZ('zSnmpPort') 573 161 574 >>> dmd.Devices.getZ('zWinPassword') 575 >>> 576 """ 577 if self.hasProperty(id, useAcquisition=True) \ 578 and not self.zenPropIsPassword(id): 579 returnValue = self.getProperty(id) 580 else: 581 returnValue = None 582 return returnValue
583
584 - def exportZProperties(self):
585 """ 586 For this manager will return the following about each zProperty 587 Will return the following about each Zen Property 588 - id - identifier 589 - islocal - if this object has a local definition 590 - value - value for this object 591 - valueAsString - string representation of the property 592 - type - int string lines etc 593 - path - where it is defined 594 - options - acceptable values of this zProperty 595 """ 596 props = [] 597 for zId in self.zenPropertyIds(): 598 prop = dict( 599 id=zId, 600 islocal=self.hasProperty(zId), 601 type=self.getPropertyType(zId), 602 path=self.zenPropertyPath(zId), 603 options=self.zenPropertyOptions(zId), 604 category=getzPropertyCategory(zId), 605 value=None, 606 valueAsString=self.zenPropertyString(zId) 607 ) 608 if not self.zenPropIsPassword(zId): 609 prop['value'] = self.getZ(zId) 610 else: 611 prop['value'] = self.zenPropertyString(zId) 612 props.append(prop) 613 return props
614 615 InitializeClass(ZenPropertyManager) 616
617 -class IdentityTransformer(object):
618 "A do-nothing transformer to use as the default" 619
620 - def transformForGet(self, value):
621 return value
622
623 - def transformForSet(self, value):
624 return value
625
626 -def monkeypatchDescriptors(zprops, transformerFactories):
627 """ 628 monkeypatch ZenPropertyManager adding an instance of the descriptor class 629 for each of the zProperties 630 """ 631 for id, value, type in zprops: 632 factory = transformerFactories.get(type, IdentityTransformer) 633 descriptor = PropertyDescriptor(id, type, factory()) 634 setattr(ZenPropertyManager, id, descriptor)
635
636 -def setDescriptors(transformerFactories):
637 """ 638 Set the property descriptors on the ZenPropertyManager class. The 639 transformerFactories parameter is a dictionary that maps a property type 640 to a callable factory that produces instances with transformForGet and 641 transformForSet methods. 642 """ 643 # copy the core zProps 644 zprops = Z_PROPERTIES[:] 645 646 # add zProps from zenpacks 647 from Products.ZenUtils.PkgResources import pkg_resources 648 for zpkg in pkg_resources.iter_entry_points('zenoss.zenpacks'): 649 # fromlist is typically ZenPacks.zenoss 650 fromlist = zpkg.module_name.split('.')[:-1] 651 module = __import__(zpkg.module_name, globals(), locals(), fromlist) 652 if hasattr(module, 'ZenPack'): 653 zprops.extend(module.ZenPack.packZProperties) 654 655 monkeypatchDescriptors(zprops, transformerFactories)
656
657 -def updateDescriptors(type, transformer):
658 """ 659 Update all descriptors with the specified type to use the specified 660 transformer. 661 """ 662 for var in vars(ZenPropertyManager): 663 attr = getattr(ZenPropertyManager, var) 664 if isinstance(attr, PropertyDescriptor) and attr.type == type: 665 attr.transformer = transformer
666