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 Globals import DTMLFile
25 from Globals import InitializeClass
26 from OFS.History import Historical
27 from Acquisition import aq_base
28 from AccessControl import ClassSecurityInfo
29 from ZPublisher.Converters import type_converters
30
31
32 from ZenModelBase import ZenModelBase
33 from ZenPacker import ZenPacker
34 from Products.ZenUtils.Utils import getSubObjects, zenPath
35 from Products.ZenRelations.ImportRM import ImportRM
36 from Products.ZenRelations.RelationshipManager import RelationshipManager
37
38 -class ZenModelRM(ZenModelBase, RelationshipManager, Historical, ZenPacker):
39 """
40 Base class for all Persistent classes that have relationships.
41 Provides RelationshipManagement, Customized PropertyManagement,
42 Catalog Indexing, and Historical change tracking.
43 """
44
45 meta_type = 'ZenModelRM'
46
47 default_catalog = ''
48
49 isInTree = 0
50
51 security = ClassSecurityInfo()
52
56
57 security.declareProtected('Manage DMD', 'rename')
69
70
71 security.declareProtected('Manage DMD', 'zmanage_editProperties')
79
80
83 """Add a new property via the web.
84 Sets a new property with the given id, type, and value.
85 Id must start with a 'c' for custom attributes added via the
86 Custom Schema tab.
87 """
88 if type_converters.has_key(type):
89 value=type_converters[type](value)
90 if prefix and not id.startswith(prefix):
91 id = prefix + id
92 self._setProperty(id.strip(), value, type, label, visible)
93 if REQUEST:
94 REQUEST['message'] = "Property added"
95 return self.callZenScreen(REQUEST)
96
98 """Export objects to specific locations.
99 """
100 if not context:
101 context = self
102 redirect = False
103 dest = 'filesystem'
104 if REQUEST:
105 dest = REQUEST.form.get('dest')
106 fileBase = '%s_%s.xml' % (context.getNodeName(), context.id)
107 if dest == 'filesystem':
108 filename = zenPath('export', fileBase)
109 msg = "Item has been exported to: %s at " % filename
110 elif dest == 'zenossdotnet':
111
112 filename = ''
113
114 username = ''
115 password = ''
116
117 url = 'https://%s:%[email protected]/'
118
119 import xmlrpclib
120 server = xmlrpclib.ProxyServer(url)
121 msg = "Item has been exported to: %s. Note that you will need to "
122 msg += "login at Zenoss.net and publish this template in order to "
123 msg += "share it with others. Exported at "
124 msg %= url
125
126 exportFile = open(filename, 'w+')
127
128 context.exportXml(exportFile)
129
130 exportFile.close()
131 if dest == 'zenossdotnet':
132
133 exportFile = open(filename)
134 dataToSend = exportFile.read()
135 exportFile.close()
136
137 server.postUserTemplate(dataToSend)
138 if REQUEST:
139 REQUEST['message'] = msg
140 return self.callZenScreen(REQUEST, redirect)
141
142
144 """Import an XML file as the Zenoss objects and properties it
145 represents.
146 """
147
148
149
150
151 if not context:
152 context = self.getPhysicalRoot()
153
154 filenames = REQUEST.form.get('filenames')
155 urlnames = REQUEST.form.get('urlnames')
156 doDelete = REQUEST.form.get('dodelete')
157 xmlfiles = []
158 for collection in [filenames, urlnames]:
159 if collection:
160 if isinstance(collection, list):
161 xmlfiles.extend(collection)
162 else:
163 xmlfiles.append(collection)
164
165 im = ImportRM(noopts=True, app=self.getPhysicalRoot())
166 for xmlfile in xmlfiles:
167 im.loadObjectFromXML(context, xmlfile)
168 if doDelete and xmlfile in filenames:
169 os.unlink(xmlfile)
170 if REQUEST:
171 REQUEST['message'] = "Objects imported"
172 return self.callZenScreen(REQUEST)
173
174
176 """Import objects into Zenoss.
177 """
178 pass
179
181 """Delete properties from an object.
182 """
183 for id in ids:
184 self._delProperty(id)
185 if REQUEST:
186 REQUEST['message'] = "Properties deleted"
187 return self.callZenScreen(REQUEST)
188
189
200
201
202 security.declareProtected('View', 'getDmdKey')
204 """
205 Hook to get the name of an object. Usually its self.getId() but is
206 overridden by Organizer to be getOrganizerName.
207
208 >>> dmd.Manufacturers.Cisco.getDmdKey()
209 'Cisco'
210 >>> dmd.Devices.Server.getDmdKey()
211 '/Server'
212 """
213 return self.getId()
214
215
216 security.declareProtected('View', 'primarySortKey')
218 """
219 Hook for the value used to sort this object. Defaults to self.getId().
220 IpNetwork for instance overrides to allow it to sort by the IP numeric
221 value not its string value.
222
223 >>> n = dmd.Networks.createNet('1.2.3.0', 24)
224 >>> n.primarySortKey()
225 16909056L
226 """
227 return self.getId()
228
229
230 security.declareProtected('View', 'viewName')
233
234
235
242
243
246
247
249 """return the creation time as a string"""
250 return self.createdTime.strftime('%Y/%m/%d %H:%M:%S')
251
252
254 """return the modification time as a string"""
255 return self.bobobase_modification_time().strftime('%Y/%m/%d %H:%M:%S')
256
257
259 """change the python class of a persistent object"""
260 id = self.id
261 nobj = newPythonClass(id)
262 nobj = nobj.__of__(container)
263 nobj.oldid = self.id
264 nobj.setPrimaryPath()
265
266 nrelations = self.ZenSchemaManager.getRelations(nobj).keys()
267 for sobj in self.objectValues():
268 RelationshipManager._delObject(self,sobj.getId())
269 if not hasattr(nobj, sobj.id) and sobj.id in nrelations:
270 RelationshipManager._setObject(nobj, sobj.id, sobj)
271 nobj.buildRelations()
272
273 noprop = getattr(nobj, 'zNoPropertiesCopy', [])
274 for name in nobj.getPropertyNames():
275 if (getattr(self, name, None) and name not in noprop and
276 hasattr(nobj, "_updateProperty")):
277 val = getattr(self, name)
278 nobj._updateProperty(name, val)
279 return aq_base(nobj)
280
281
285
286
288 """
289 Return true if user has Manager role and self has a deviceList.
290 """
291 user = self.REQUEST.get('AUTHENTICATED_USER', None)
292 if user:
293 return "Manager" in user.getRoles() and \
294 getattr(aq_base(self), "deviceMoveTargets", False)
295
296
298 """
299 Method needed for CatalogAwarnessInterface. Implemented here so that
300 Subclasses (who would have the same implementation) don't need to.
301 Other methods (except reindex_all) are implemented on the concreate
302 class.
303 """
304 users=[]
305 for user, roles in self.get_local_roles():
306 if 'Owner' in roles:
307 users.append(user)
308 return ', '.join(users)
309
310
312 """A common method to allow Findables to index themselves."""
313 cat = getattr(self, self.default_catalog, None)
314 if cat != None:
315 cat.catalog_object(self, self.getPrimaryId())
316
317
319 """A common method to allow Findables to unindex themselves."""
320 cat = getattr(self, self.default_catalog, None)
321 if cat != None:
322 cat.uncatalog_object(self.getPrimaryId())
323
324
337