1
2
3
4
5
6
7
8
9
10
11
12
13
14 import re
15
16 from OFS.PropertyManager import PropertyManager
17 from zExceptions import BadRequest
18 from Globals import DTMLFile
19 from Globals import InitializeClass
20 from Acquisition import aq_base, aq_chain
21 from ZPublisher.Converters import type_converters
22 from Products.ZenModel.ZenossSecurity import *
23 from AccessControl import ClassSecurityInfo
24 from Exceptions import zenmarker
25 iszprop = re.compile("^z[A-Z]").search
26
27 from Products.ZenUtils.Utils import unused
28
29
30
31
32 Z_PROPERTIES = [
33
34
35
36 ('zPythonClass', '', 'string'),
37
38
39
40 ('zProdStateThreshold', 300, 'int'),
41
42
43
44 ('zIfDescription', False, 'boolean'),
45
46
47 ('zSnmpCommunities', ['public', 'private'], 'lines'),
48 ('zSnmpCommunity', 'public', 'string'),
49 ('zSnmpPort', 161, 'int'),
50 ('zSnmpVer', 'v1', 'string'),
51 ('zSnmpTries', 2, 'int'),
52 ('zSnmpTimeout', 2.5, 'float'),
53 ('zSnmpSecurityName', '', 'string'),
54 ('zSnmpAuthPassword', '', 'password'),
55 ('zSnmpPrivPassword', '', 'password'),
56 ('zSnmpAuthType', '', 'string'),
57 ('zSnmpPrivType', '', 'string'),
58 ('zRouteMapCollectOnlyLocal', False, 'boolean'),
59 ('zRouteMapCollectOnlyIndirect', False, 'boolean'),
60 ('zRouteMapMaxRoutes', 500, 'int'),
61 ('zInterfaceMapIgnoreTypes', '', 'string'),
62 ('zInterfaceMapIgnoreNames', '', 'string'),
63 ('zFileSystemMapIgnoreTypes', [], 'lines'),
64 ('zFileSystemMapIgnoreNames', '', 'string'),
65 ('zFileSystemSizeOffset', 1.0, 'float'),
66 ('zHardDiskMapMatch', '', 'string'),
67 ('zSysedgeDiskMapIgnoreNames', '', 'string'),
68 ('zIpServiceMapMaxPort', 1024, 'int'),
69 ('zDeviceTemplates', ['Device'], 'lines'),
70 ('zLocalIpAddresses', '^127|^0\\.0|^169\\.254|^224', 'string'),
71 ('zLocalInterfaceNames', '^lo|^vmnet', 'string'),
72
73
74 ('zSnmpMonitorIgnore', False, 'boolean'),
75 ('zPingMonitorIgnore', False, 'boolean'),
76 ('zWmiMonitorIgnore', True, 'boolean'),
77 ('zStatusConnectTimeout', 15.0, 'float'),
78
79
80 ('zCollectorPlugins', [], 'lines'),
81 ('zCollectorClientTimeout', 180, 'int'),
82 ('zCollectorDecoding', 'latin-1', 'string'),
83 ('zCommandUsername', '', 'string'),
84 ('zCommandPassword', '', 'password'),
85 ('zCommandProtocol', 'ssh', 'string'),
86 ('zCommandPort', 22, 'int'),
87 ('zCommandLoginTries', 1, 'int'),
88 ('zCommandLoginTimeout', 10.0, 'float'),
89 ('zCommandCommandTimeout', 10.0, 'float'),
90 ('zCommandSearchPath', [], 'lines'),
91 ('zCommandExistanceTest', 'test -f %s', 'string'),
92 ('zCommandPath', '/usr/local/zenoss/libexec', 'string'),
93 ('zTelnetLoginRegex', 'ogin:.$', 'string'),
94 ('zTelnetPasswordRegex', 'assword:', 'string'),
95 ('zTelnetSuccessRegexList', ['\\$.$', '\\#.$'], 'lines'),
96 ('zTelnetEnable', False, 'boolean'),
97 ('zTelnetEnableRegex', 'assword:', 'string'),
98 ('zTelnetTermLength', True, 'boolean'),
99 ('zTelnetPromptTimeout', 10.0, 'float'),
100 ('zKeyPath', '~/.ssh/id_dsa', 'string'),
101 ('zMaxOIDPerRequest', 40, 'int'),
102
103
104 ('zLinks', '', 'string'),
105
106
107 ('zWinUser', '', 'string'),
108 ('zWinPassword', '', 'password'),
109 ('zWinEventlogMinSeverity', 2, 'int'),
110 ('zWinEventlog', False, 'boolean'),
111
112
113 ('zIcon', '/zport/dmd/img/icons/noicon.png', 'string'),
114 ]
115
117 """
118 Transforms the property value based on its type.
119
120 Follows the Descriptor protocol defined at
121 http://docs.python.org/reference/datamodel.html#descriptors
122 """
123
124 - def __init__(self, id, type, transformer):
125 self.id = id
126 self.type = type
127 self.transformer = transformer
128
129 - def __get__(self, instance, owner):
130 """
131 Returns self for class attribute access. Returns the transformed
132 value for instance attribute access.
133 """
134 try:
135 if instance is None:
136 retval = self
137 else:
138 self._migrate(instance)
139 value = instance._propertyValues[self.id]
140 retval = self._transform(instance, value, 'transformForGet')
141 return retval
142 except:
143 raise AttributeError
144
145 - def __set__(self, instance, value):
151
158
160 """
161 If the id is in __dict__ then move the value to the _propertyValues
162 dictionary. Check to make sure that the type of this descriptor class
163 and the type in the Zope OFS PropertyManager metadata are the same.
164 """
165 if not hasattr(instance, '_propertyValues'):
166 instance._propertyValues = {}
167 if self.id in vars(instance):
168 self._set(instance, vars(instance)[self.id])
169 del instance.__dict__[self.id]
170 instance._p_changed = True
171 for dct in instance._properties:
172 if dct['id'] == self.id:
173 if dct['type'] != self.type:
174 dct['type'] = self.type
175 instance._p_changed = True
176 break
177
178 - def _set(self, instance, value):
179 """
180 Transform and set the value in the _propertyValues dictionary.
181 """
182 valueToSet = self._transform(instance, value, 'transformForSet')
183 instance._propertyValues[self.id] = valueToSet
184
192
194 """
195 ZenPropertyManager adds keyedselection type to PropertyManager.
196 A keyedselection displayes a different name in the popup then
197 the actual value the popup will have.
198
199 It also has management for zenProperties which are properties that can be
200 inherited long the acquision chain. All properties are for a branch are
201 defined on a "root node" specified by the function which must be returned
202 by the function getZenRootNode that should be over ridden in a sub class.
203 Prperties can then be added further "down" the aq_chain by calling
204 setZenProperty on any contained node.
205
206 ZenProperties all have the same prefix which is defined by iszprop
207 this can be overridden in a subclass.
208
209 ZenPropertyManager overrides getProperty and getPropertyType from
210 PropertyManager to support acquisition. If you want to query an object
211 about a property, but do not want it to search the acquistion chain then
212 use the super classes method or aq_base. Example:
213
214 # acquires property from dmd.Devices
215 dmd.Devices.Server.getProperty('zCollectorPlugins')
216
217 # does not acquire property from dmd.Devices
218 PropertyManager.getProperty(dmd.Devices.Server, 'zCollectorPlugins')
219
220 # also does not acquire property from dmd.Devices
221 aq_base(dmd.Devices.Server).getProperty('zSnmpCommunity')
222
223 The properties are stored as attributes which is convenient, but can be
224 confusing. Attribute access always uses acquistion. Setting an
225 attribute, will not add it to the list of properties, so subsquent calls
226 to hasProperty or getProperty won't return it.
227
228 Property Transformers are stored at dmd.propertyTransformers and transform
229 the property based on type during calls to the _setProperty,
230 _updateProperty, and getProperty methods. Adding a property using
231 _setProperty applies the appropriate transformer and adds its value as an
232 attribute, but when you access it as an attribute the property transformer
233 is again applied, but this time using its transformForGet method.
234 """
235 __pychecker__='no-override'
236
237 security = ClassSecurityInfo()
238
239 manage_propertiesForm=DTMLFile('dtml/properties', globals(),
240 property_extensible_schema__=1)
241
243 """override from PerpertyManager to handle checks and ip creation"""
244 self._wrapperCheck(value)
245 propType = self.getPropertyType(id)
246 if propType == 'keyedselection':
247 value = int(value)
248 if not getattr(self,'_v_propdict',False):
249 self._v_propdict = self.propdict()
250 if self._v_propdict.has_key('setter'):
251 settername = self._v_propdict['setter']
252 setter = getattr(aq_base(self), settername, None)
253 if not setter:
254 raise ValueError("setter %s for property %s doesn't exist"
255 % (settername, id))
256 if not callable(setter):
257 raise TypeError("setter %s for property %s not callable"
258 % (settername, id))
259 setter(value)
260 else:
261 setattr(self, id, value)
262
263
264 - def _setProperty(self, id, value, type='string', label=None,
265 visible=True, setter=None):
266 """for selection and multiple selection properties
267 the value argument indicates the select variable
268 of the property
269 """
270 self._wrapperCheck(value)
271 if not self.valid_property_id(id):
272 raise BadRequest, 'Id %s is invalid or duplicate' % id
273
274 def setprops(**pschema):
275 self._properties=self._properties+(pschema,)
276 if setter: pschema['setter'] = setter
277 if label: pschema['label'] = label
278
279 if type in ('selection', 'multiple selection'):
280 if not hasattr(self, value):
281 raise BadRequest, 'No select variable %s' % value
282 setprops(id=id,type=type, visible=visible,
283 select_variable=value)
284 if type=='selection':
285 self._setPropValue(id, '')
286 else:
287 self._setPropValue(id, [])
288 else:
289 setprops(id=id, type=type, visible=visible)
290 self._setPropValue(id, value)
291
310
311
312 _onlystars = re.compile("^\*+$").search
313 security.declareProtected(ZEN_ZPROPERTIES_EDIT, 'manage_editProperties')
315 """
316 Edit object properties via the web.
317 The purpose of this method is to change all property values,
318 even those not listed in REQUEST; otherwise checkboxes that
319 get turned off will be ignored. Use manage_changeProperties()
320 instead for most situations.
321 """
322 for prop in self._propertyMap():
323 name=prop['id']
324 if 'w' in prop.get('mode', 'wd'):
325 value=REQUEST.get(name, '')
326 if self.zenPropIsPassword(name) and self._onlystars(value):
327 continue
328 self._updateProperty(name, value)
329 if getattr(self, "index_object", False):
330 self.index_object()
331 if REQUEST:
332 message="Saved changes."
333 return self.manage_propertiesForm(self,REQUEST,
334 manage_tabs_message=message)
335
336
338 """sub class must implement to use zenProperties."""
339 raise NotImplementedError
340
341 security.declareProtected(ZEN_ZPROPERTIES_VIEW, 'zenPropertyIds')
343 """
344 Return list of device tree property names.
345 If all use list from property root node.
346 """
347 if all:
348 rootnode = self.getZenRootNode()
349 else:
350 if self.id == self.dmdRootName: return []
351 rootnode = aq_base(self)
352 props = []
353 for prop in rootnode.propertyIds():
354 if not pfilt(prop): continue
355 props.append(prop)
356 props.sort()
357 return props
358
359 security.declareProtected(ZEN_ZPROPERTIES_VIEW, 'zenPropertyItems')
361 """Return list of (id, value) tuples of zenProperties.
362 """
363 return map(lambda x: (x, getattr(self, x)), self.zenPropertyIds())
364
365 security.declareProtected(ZEN_ZPROPERTIES_VIEW, 'zenPropertyMap')
367 """Return property mapping of device tree properties."""
368 rootnode = self.getZenRootNode()
369 pmap = []
370 for pdict in rootnode.propertyMap():
371 if pfilt(pdict['id']): pmap.append(pdict)
372 pmap.sort(lambda x, y: cmp(x['id'], y['id']))
373 return pmap
374
375 security.declareProtected(ZEN_ZPROPERTIES_VIEW, 'zenPropertyString')
377 """Return the value of a device tree property as a string"""
378 def displayLines(lines):
379 return '\n'.join([str(line) for line in lines])
380 def displayPassword(password):
381 return '*' * len(password)
382 def displayOthers(other):
383 return other
384 displayFunctions = {'lines': displayLines,
385 'password': displayPassword}
386 display = displayFunctions.get(self.getPropertyType(id),
387 displayOthers)
388 return display(self.getProperty(id, ''))
389
390 security.declareProtected(ZEN_ZPROPERTIES_VIEW, 'zenPropIsPassword')
392 """Is this field a password field.
393 """
394 return self.getPropertyType(id) == 'password'
395
396 security.declareProtected(ZEN_ZPROPERTIES_VIEW, 'zenPropertyPath')
405
406 security.declareProtected(ZEN_ZPROPERTIES_EDIT, 'setZenProperty')
408 """
409 Add or set the propvalue of the property propname on this node of
410 the device Class tree.
411 """
412 ptype = self.getPropertyType(propname)
413 if ptype == 'lines':
414 dedupedList = []
415 for x in propvalue:
416 if x not in dedupedList:
417 dedupedList.append(x)
418 propvalue = dedupedList
419 if getattr(aq_base(self), propname, zenmarker) != zenmarker:
420 self._updateProperty(propname, propvalue)
421 else:
422 if ptype in ("selection", 'multiple selection'): ptype="string"
423 if type_converters.has_key(ptype):
424 propvalue=type_converters[ptype](propvalue)
425 if getattr(self, propname, None) != propvalue:
426 self._setProperty(propname, propvalue, type=ptype)
427 if REQUEST: return self.callZenScreen(REQUEST)
428
429 security.declareProtected(ZEN_ZPROPERTIES_EDIT, 'saveZenProperties')
444
445 security.declareProtected(ZEN_ZPROPERTIES_EDIT, 'deleteZenProperty')
447 """
448 Delete device tree properties from the this DeviceClass object.
449 """
450 if propname:
451 try:
452 self._delProperty(propname)
453 except AttributeError:
454
455
456
457 newProps = [x for x in self._properties if x['id'] != propname]
458 self._properties=tuple(newProps)
459 if REQUEST: return self.callZenScreen(REQUEST)
460
461 security.declareProtected(ZEN_ZPROPERTIES_VIEW, 'zenPropertyOptions')
463 "Provide a set of default options for a ZProperty"
464 unused(propname)
465 return []
466
467 security.declareProtected(ZEN_ZPROPERTIES_VIEW, 'isLocal')
469 """Check to see if a name is local to our current context.
470 """
471 v = getattr(aq_base(self), propname, zenmarker)
472 return v != zenmarker
473
474 security.declareProtected(ZEN_ZPROPERTIES_VIEW, 'getOverriddenObjects')
493
495 """
496 Returns self or the first acquisition parent that has a property with
497 the id. Returns None if no parent had the id.
498 """
499 for ob in aq_chain(self):
500 if isinstance(ob, ZenPropertyManager) and ob.hasProperty(id):
501 parentWithProperty = ob
502 break
503 else:
504 parentWithProperty = None
505 return parentWithProperty
506
508 """
509 Override method in PropertyManager to support acquisition.
510 """
511 if useAcquisition:
512 hasProp = self._findParentWithProperty(id) is not None
513 else:
514 hasProp = PropertyManager.hasProperty(self, id)
515 return hasProp
516
518 """
519 Get property value and apply transformer. Overrides method in Zope's
520 PropertyManager class. Acquire values from aquisiton parents if
521 needed.
522 """
523 ob = self._findParentWithProperty(id)
524 if ob is None:
525 value = d
526 else:
527 value = PropertyManager.getProperty(ob, id, d)
528 return value
529
530 security.declareProtected(ZEN_ZPROPERTIES_VIEW, 'getPropertyType')
541
542 security.declareProtected(ZEN_ZPROPERTIES_VIEW, 'getZ')
543 - def getZ(self, id):
544 """
545 Return the value of a zProperty on this object. This method is used to
546 lookup zProperties for a user with a role that doesn't have direct
547 access to an attribute further up the acquisition path. If the
548 requested property is a password, then None is returned.
549
550 @param id: id of zProperty
551 @type id: string
552 @return: Value of zProperty
553 @permission: ZEN_ZPROPERTIES_VIEW
554
555 >>> dmd.Devices.getZ('zSnmpPort')
556 161
557 >>> dmd.Devices.getZ('zWinPassword')
558 >>>
559 """
560 if self.hasProperty(id, useAcquisition=True) \
561 and not self.zenPropIsPassword(id):
562 returnValue = self.getProperty(id)
563 else:
564 returnValue = None
565 return returnValue
566
567 InitializeClass(ZenPropertyManager)
568
577
587
589 """
590 Set the property descriptors on the ZenPropertyManager class. The
591 transformerFactories parameter is a dictionary that maps a property type
592 to a callable factory that produces instances with transformForGet and
593 transformForSet methods.
594 """
595
596 zprops = Z_PROPERTIES[:]
597
598
599 from Products.ZenUtils.PkgResources import pkg_resources
600 for zpkg in pkg_resources.iter_entry_points('zenoss.zenpacks'):
601
602 fromlist = zpkg.module_name.split('.')[:-1]
603 module = __import__(zpkg.module_name, globals(), locals(), fromlist)
604 if hasattr(module, 'ZenPack'):
605 zprops.extend(module.ZenPack.packZProperties)
606
607 monkeypatchDescriptors(zprops, transformerFactories)
608
618