1
2
3
4
5
6
7
8
9
10
11
12
13
14 __doc__="""ZenModelRM
15
16 $Id: ZenModelRM.py,v 1.50 2004/05/10 20:49:09 edahl Exp $"""
17
18 __version__ = "$Revision: 1.50 $"[11:-2]
19
20 import os
21 import time
22
23 from DateTime import DateTime
24 from OFS.History import Historical
25 from Acquisition import aq_base
26 from AccessControl import ClassSecurityInfo
27 from ZPublisher.Converters import type_converters
28
29
30 from ZenModelBase import ZenModelBase, iscustprop
31 from ZenPacker import ZenPacker
32 from Products.ZenWidgets import messaging
33 from Products.ZenUtils.Utils import getSubObjects, zenPath
34 from Products.ZenRelations.ImportRM import ImportRM
35 from Products.ZenRelations.RelationshipManager import RelationshipManager
36
37 -class ZenModelRM(ZenModelBase, RelationshipManager, Historical, ZenPacker):
38 """
39 Base class for all Persistent classes that have relationships.
40 Provides RelationshipManagement, Customized PropertyManagement,
41 Catalog Indexing, and Historical change tracking.
42 """
43
44 meta_type = 'ZenModelRM'
45
46 default_catalog = ''
47
48 isInTree = 0
49
50 security = ClassSecurityInfo()
51
52 - def __init__(self, id, title=None, buildRelations=True):
55
56 security.declareProtected('Manage DMD', 'rename')
57 - def rename(self, newId, REQUEST=None):
73
74
75 security.declareProtected('Manage DMD', 'zmanage_editProperties')
83
84
87 """Add a new property via the web.
88 Sets a new property with the given id, type, and value.
89 Id must start with a 'c' for custom attributes added via the
90 Custom Schema tab.
91 """
92 if type_converters.has_key(type) and value:
93 value=type_converters[type](value)
94 id = id.strip()
95 if prefix and not id.startswith(prefix):
96 id = prefix + id
97 if not iscustprop(id):
98 if REQUEST:
99 messaging.IMessageSender(self).sendToBrowser(
100 'Error',
101 "Custom property name should be in this format: cProperty",
102 priority=messaging.WARNING
103 )
104 return self.callZenScreen(REQUEST)
105 elif self.hasProperty(id):
106 if REQUEST:
107 messaging.IMessageSender(self).sendToBrowser(
108 'Error',
109 "Custom property: %s already exists" % id,
110 priority=messaging.WARNING
111 )
112 return self.callZenScreen(REQUEST)
113 else:
114 self._setProperty(id, value, type, label, visible)
115 if REQUEST:
116 messaging.IMessageSender(self).sendToBrowser(
117 'Property Added',
118 "Custom property: %s added" % id
119 )
120 return self.callZenScreen(REQUEST)
121
164
165
167 """Import an XML file as the Zenoss objects and properties it
168 represents.
169 """
170
171
172
173
174 if not context:
175 context = self.getPhysicalRoot()
176
177 filenames = REQUEST.form.get('filenames')
178 urlnames = REQUEST.form.get('urlnames')
179 doDelete = REQUEST.form.get('dodelete')
180 xmlfiles = []
181 for collection in [filenames, urlnames]:
182 if collection:
183 if isinstance(collection, list):
184 xmlfiles.extend(collection)
185 else:
186 xmlfiles.append(collection)
187
188 im = ImportRM(noopts=True, app=self.getPhysicalRoot())
189 for xmlfile in xmlfiles:
190 im.loadObjectFromXML(context, xmlfile)
191 if doDelete and xmlfile in filenames:
192 os.unlink(xmlfile)
193 if REQUEST:
194 messaging.IMessageSender(self).sendToBrowser(
195 'Import Objects', 'Objects imported')
196 return self.callZenScreen(REQUEST)
197
198
200 """Import objects into Zenoss.
201 """
202 pass
203
215
216
230
231
232 security.declareProtected('View', 'getDmdKey')
234 """
235 Hook to get the name of an object. Usually its self.getId() but is
236 overridden by Organizer to be getOrganizerName.
237
238 >>> dmd.Manufacturers.createManufacturer('Cisco').getDmdKey()
239 'Cisco'
240 >>> dmd.Devices.Server.getDmdKey()
241 '/Server'
242 """
243 return self.getId()
244
245
246 security.declareProtected('View', 'primarySortKey')
248 """
249 Hook for the value used to sort this object. Defaults to self.getId().
250 IpNetwork for instance overrides to allow it to sort by the IP numeric
251 value not its string value.
252
253 >>> n = dmd.Networks.createNet('1.2.3.0', 24)
254 >>> n.primarySortKey()
255 16909056L
256 """
257 return self.getId()
258
259
260 security.declareProtected('View', 'viewName')
263
264
265
267 nodes = []
268 for item in self.objectValues():
269 if hasattr(aq_base(item), "isInTree") and item.isInTree:
270 nodes.append(item)
271 return nodes
272
273
274 - def getSubObjects(self, filter=None, decend=None, retobjs=None):
276
277
279 """return the creation time as a string"""
280 return self.createdTime.strftime('%Y/%m/%d %H:%M:%S')
281
282
284 """return the modification time as a string"""
285 return self.bobobase_modification_time().strftime('%Y/%m/%d %H:%M:%S')
286
287
289 """change the python class of a persistent object"""
290 id = self.id
291 nobj = newPythonClass(id)
292 nobj = nobj.__of__(container)
293 nobj.oldid = self.id
294 nobj.setPrimaryPath()
295
296 nrelations = self.ZenSchemaManager.getRelations(nobj).keys()
297 for sobj in self.objectValues():
298 RelationshipManager._delObject(self,sobj.getId())
299 if not hasattr(nobj, sobj.id) and sobj.id in nrelations:
300
301 setObject = RelationshipManager._setObject
302 setObject(nobj, sobj.id, sobj)
303 nobj.buildRelations()
304
305 noprop = getattr(nobj, 'zNoPropertiesCopy', [])
306 for name in nobj.getPropertyNames():
307 if (getattr(self, name, None) and name not in noprop and
308 hasattr(nobj, "_updateProperty")):
309 val = getattr(self, name)
310 nobj._updateProperty(name, val)
311 return aq_base(nobj)
312
313
317
318
320 """
321 Return true if user has Manager role and self has a deviceList.
322 """
323 return self.isManager() and \
324 getattr(aq_base(self), "deviceMoveTargets", False)
325
326
328 """
329 Method needed for CatalogAwarnessInterface. Implemented here so that
330 Subclasses (who would have the same implementation) don't need to.
331 Other methods (except reindex_all) are implemented on the concreate
332 class.
333 """
334 users=[]
335 for user, roles in self.get_local_roles():
336 if 'Owner' in roles:
337 users.append(user)
338 return ', '.join(users)
339
340
342 """A common method to allow Findables to index themselves."""
343 cat = getattr(self, self.default_catalog, None)
344 if cat != None:
345 cat.catalog_object(self, self.getPrimaryId())
346
347
349 """A common method to allow Findables to unindex themselves."""
350 cat = getattr(self, self.default_catalog, None)
351 if cat != None:
352 cat.uncatalog_object(self.getPrimaryId())
353
354
356 """
357 Called for in the CataLogAwarenessInterface not sure this is needed.
358 """
359 if obj is None: obj=self
360 if hasattr(aq_base(obj), 'index_object'):
361 obj.index_object()
362 if hasattr(aq_base(obj), 'objectValues'):
363 sub=obj.objectValues()
364 for item in sub:
365 self.reindex_all(item)
366 return 'done!'
367
369 """
370 Find child using the ids found in path. Path separator is '/'. This
371 is similar to using attributes, but doesn't use acquisition. For
372 example, if 'Devices/Server/Linux' exists, but
373 'Devices/Server/SSH/Linux' does not, then the two methods will behave
374 differently. dmd.Devices.Server.SSH.Linux will return
375 'Devices/Server/Linux', whereas this method will throw an exception.
376 """
377 child = self
378 for id in path.split('/'):
379 child = dict(child.objectItems())[id]
380 return child
381