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

Source Code for Module Products.ZenModel.ZenModelRM

  1  ############################################################################## 
  2  #  
  3  # Copyright (C) Zenoss, Inc. 2007, all rights reserved. 
  4  #  
  5  # This content is made available according to terms specified in 
  6  # License.zenoss under the directory where your Zenoss product is installed. 
  7  #  
  8  ############################################################################## 
  9   
 10   
 11  __doc__="""ZenModelRM 
 12   
 13  $Id: ZenModelRM.py,v 1.50 2004/05/10 20:49:09 edahl Exp $""" 
 14   
 15  __version__ = "$Revision: 1.50 $"[11:-2] 
 16   
 17  import os 
 18  import time 
 19   
 20  from DateTime import DateTime 
 21  from OFS.History import Historical 
 22  from Acquisition import aq_base 
 23  from AccessControl import ClassSecurityInfo 
 24  from ZPublisher.Converters import type_converters 
 25  from zope.interface import implements 
 26  from OFS.interfaces import IItem 
 27   
 28  from ZenModelBase import ZenModelBase, iscustprop 
 29  from ZenPacker import ZenPacker 
 30  from Products.ZenWidgets import messaging 
 31  from Products.ZenUtils.Utils import getSubObjects, zenPath 
 32  from Products.ZenRelations.ImportRM import ImportRM 
 33  from Products.ZenRelations.RelationshipManager import RelationshipManager 
 34  from Products.ZenModel.ZenossSecurity import * 
 35   
36 -class ZenModelRM(ZenModelBase, RelationshipManager, Historical, ZenPacker):
37 """ 38 Base class for all Persistent classes that have relationships. 39 Provides RelationshipManagement, Customized PropertyManagement, 40 Catalog Indexing, and Historical change tracking. 41 """ 42 implements(IItem) 43 meta_type = 'ZenModelRM' 44 45 default_catalog = '' 46 47 isInTree = 0 #should this class show in left nav tree 48 49 security = ClassSecurityInfo() 50
51 - def __init__(self, id, title=None, buildRelations=True):
52 self.createdTime = DateTime(time.time()) 53 RelationshipManager.__init__(self, id, title, buildRelations)
54
55 - def setTitle(self, title):
56 self.title = title 57 from Products.Zuul.interfaces import ICatalogTool 58 ICatalogTool(self).update(self)
59 60 security.declareProtected('Manage DMD', 'rename')
61 - def rename(self, newId, REQUEST=None):
62 """Delete device from the DMD""" 63 renamed = False 64 if newId and newId != self.getId(): 65 parent = self.getPrimaryParent() 66 oldId = self.getId() 67 parent.manage_renameObject(oldId, newId) 68 renamed = True 69 if REQUEST: 70 if renamed: 71 messaging.IMessageSender(self).sendToBrowser( 72 'Object Renamed', 73 "Object %s was renamed to %s." % (oldId, newId) 74 ) 75 return self.callZenScreen(REQUEST, renamed) 76 return renamed
77 78 79 security.declareProtected('Manage DMD', 'zmanage_editProperties')
80 - def zmanage_editProperties(self, REQUEST=None, redirect=False, audit=True):
81 """Edit a ZenModel object and return its proper page template 82 """ 83 redirect = False 84 if REQUEST.form.has_key("newId"): 85 redirect = self.rename(REQUEST.form["newId"]) 86 return ZenModelBase.zmanage_editProperties(self, REQUEST, redirect, audit)
87 88
89 - def zmanage_addProperty(self, id, value, type, label, visible, 90 prefix='c', REQUEST=None):
91 """Add a new property via the web. 92 Sets a new property with the given id, type, and value. 93 Id must start with a 'c' for custom attributes added via the 94 Custom Schema tab. 95 """ 96 if type in type_converters and value: 97 value=type_converters[type](value) 98 id = id.strip() 99 if prefix and not id.startswith(prefix): 100 id = prefix + id 101 if not iscustprop(id): 102 if REQUEST: 103 messaging.IMessageSender(self).sendToBrowser( 104 'Error', 105 "Custom property name should be in this format: cProperty", 106 priority=messaging.WARNING 107 ) 108 return self.callZenScreen(REQUEST) 109 elif self.hasProperty(id): 110 if REQUEST: 111 messaging.IMessageSender(self).sendToBrowser( 112 'Error', 113 "Custom property: %s already exists" % id, 114 priority=messaging.WARNING 115 ) 116 return self.callZenScreen(REQUEST) 117 else: 118 self._setProperty(id, value, type, label, visible) 119 if REQUEST: 120 messaging.IMessageSender(self).sendToBrowser( 121 'Property Added', 122 "Custom property: %s added" % id 123 ) 124 return self.callZenScreen(REQUEST)
125
126 - def zmanage_exportObject(self, context=None, REQUEST=None):
127 """Export objects to specific locations. 128 """ 129 if not context: 130 context = self 131 redirect = False 132 dest = 'filesystem' 133 if REQUEST: 134 dest = REQUEST.form.get('dest') 135 fileBase = '%s_%s.xml' % (context.getNodeName(), context.id) 136 if dest == 'filesystem': 137 filename = zenPath('export', fileBase) 138 msg = "Item has been exported to: %s at " % filename 139 elif dest == 'zenossdotnet': 140 # create temp file 141 filename = '' 142 # get https URL for user space at Zenoss.net 143 url = 'https://%s:%[email protected]/' 144 # build XML-RPC proxy object for publishing to Zenoss.net 145 import xmlrpclib 146 server = xmlrpclib.ProxyServer(url) 147 msg = "Item has been exported to: %s. Note that you will need to " 148 msg += "login at Zenoss.net and publish this template in order to " 149 msg += "share it with others. Exported at " 150 msg %= url 151 # open file 152 exportFile = open(filename, 'w+') 153 # export object to file 154 context.exportXml(exportFile) 155 # cleanup 156 exportFile.close() 157 if dest == 'zenossdotnet': 158 # get data 159 exportFile = open(filename) 160 dataToSend = exportFile.read() 161 exportFile.close() 162 # push data up to Zenoss.net 163 server.postUserTemplate(dataToSend) 164 if REQUEST: 165 messaging.IMessageSender(self).sendToBrowser( 166 'Export Object', msg) 167 return self.callZenScreen(REQUEST, redirect)
168 169
170 - def zmanage_importObjects(self, context=None, REQUEST=None):
171 """Import an XML file as the Zenoss objects and properties it 172 represents. 173 """ 174 # XXX 175 # for right now, we're only using this through the web, so a REQUEST is 176 # always define; when we have a use-case for imports via command line, 177 # we will add that code here 178 if not context: 179 context = self.getPhysicalRoot() 180 # get the submitted data 181 filenames = REQUEST.form.get('filenames') 182 urlnames = REQUEST.form.get('urlnames') 183 doDelete = REQUEST.form.get('dodelete') 184 xmlfiles = [] 185 for collection in [filenames, urlnames]: 186 if collection: 187 if isinstance(collection, list): 188 xmlfiles.extend(collection) 189 else: 190 xmlfiles.append(collection) 191 # load the objects into Zenoss 192 im = ImportRM(noopts=True, app=self.getPhysicalRoot()) 193 for xmlfile in xmlfiles: 194 im.loadObjectFromXML(context, xmlfile) 195 if doDelete and xmlfile in filenames: 196 os.unlink(xmlfile) 197 if REQUEST: 198 messaging.IMessageSender(self).sendToBrowser( 199 'Import Objects', 'Objects imported') 200 return self.callZenScreen(REQUEST)
201 202
203 - def zmanage_importObject(self, REQUEST=None):
204 """Import objects into Zenoss. 205 """ 206 pass
207
208 - def zmanage_delProperties(self, ids=(), REQUEST=None):
209 """Delete properties from an object. 210 """ 211 for id in ids: 212 self._delProperty(id) 213 if REQUEST: 214 messaging.IMessageSender(self).sendToBrowser( 215 'Properties Deleted', 216 'Properties %s have been deleted' % (', '.join(ids)) 217 ) 218 return self.callZenScreen(REQUEST)
219 220
221 - def zmanage_delObjects(self, ids=(), relation="", REQUEST=None):
222 """Delete objects from this object or one of its relations. 223 """ 224 target = self 225 if relation: target = self._getOb(relation) 226 for id in ids: 227 target._delObject(id) 228 if REQUEST: 229 messaging.IMessageSender(self).sendToBrowser( 230 'Objects Deleted', 231 'Objects %s have been deleted' % (', '.join(ids)) 232 ) 233 return self.callZenScreen(REQUEST)
234 235 236 security.declareProtected('View', 'getDmdKey')
237 - def getDmdKey(self):
238 """ 239 Hook to get the name of an object. Usually its self.getId() but is 240 overridden by Organizer to be getOrganizerName. 241 242 >>> dmd.Manufacturers.createManufacturer('Cisco').getDmdKey() 243 'Cisco' 244 >>> dmd.Devices.Server.getDmdKey() 245 '/Server' 246 """ 247 return self.getId()
248 249 250 security.declareProtected('View', 'primarySortKey')
251 - def primarySortKey(self):
252 """ 253 Hook for the value used to sort this object. Defaults to self.getId(). 254 """ 255 return self.titleOrId()
256 257 258 security.declareProtected('View', 'viewName')
259 - def viewName(self):
260 return self.titleOrId()
261 262 263 #actions?
264 - def getTreeItems(self):
265 nodes = [] 266 for item in self.objectValues(): 267 if hasattr(aq_base(item), "isInTree") and item.isInTree: 268 nodes.append(item) 269 return nodes
270 271
272 - def getSubObjects(self, filter=None, decend=None, retobjs=None):
273 return getSubObjects(self, filter, decend, retobjs)
274 275
276 - def getCreatedTimeString(self):
277 """return the creation time as a string""" 278 return self.createdTime.strftime('%Y/%m/%d %H:%M:%S')
279 280
282 """return the modification time as a string""" 283 return self.bobobase_modification_time().strftime('%Y/%m/%d %H:%M:%S')
284 285
286 - def changePythonClass(self, newPythonClass, container):
287 """change the python class of a persistent object""" 288 id = self.id 289 nobj = newPythonClass(id) #make new instance from new class 290 nobj = nobj.__of__(container) #make aq_chain same as self 291 nobj.oldid = self.id 292 nobj.setPrimaryPath() #set up the primarypath for the copy 293 #move all sub objects to new object 294 nrelations = self.ZenSchemaManager.getRelations(nobj).keys() 295 for sobj in self.objectValues(): 296 RelationshipManager._delObject(self,sobj.getId()) 297 if not hasattr(nobj, sobj.id) and sobj.id in nrelations: 298 # confuse pychecker: 299 setObject = RelationshipManager._setObject 300 setObject(nobj, sobj.id, sobj) 301 nobj.buildRelations() #build out any missing relations 302 # copy properties to new object 303 noprop = getattr(nobj, 'zNoPropertiesCopy', []) 304 for name in nobj.getPropertyNames(): 305 if (getattr(self, name, None) and name not in noprop and 306 hasattr(nobj, "_updateProperty")): 307 val = getattr(self, name) 308 nobj._updateProperty(name, val) 309 return aq_base(nobj)
310 311
312 - def getZenRootNode(self):
313 """Return the root node for our zProperties.""" 314 return self.getDmdRoot(self.dmdRootName)
315 316
317 - def editableDeviceList(self):
318 """ 319 Return true if user has Manager role and self has a deviceList. 320 """ 321 if not getattr(aq_base(self), "deviceMoveTargets", False): 322 return False 323 324 if self.isManager() or \ 325 self.checkRemotePerm(ZEN_CHANGE_DEVICE_PRODSTATE, self): 326 return True 327 328 return False
329 330
331 - def creator(self):
332 """ 333 Method needed for CatalogAwarnessInterface. Implemented here so that 334 Subclasses (who would have the same implementation) don't need to. 335 Other methods (except reindex_all) are implemented on the concreate 336 class. 337 """ 338 users=[] 339 for user, roles in self.get_local_roles(): 340 if 'Owner' in roles: 341 users.append(user) 342 return ', '.join(users)
343 344
345 - def index_object(self, idxs=None):
346 """A common method to allow Findables to index themselves.""" 347 cat = getattr(self, self.default_catalog, None) 348 if cat != None: 349 cat.catalog_object(self, self.getPrimaryId(), idxs=idxs)
350 351 352
353 - def unindex_object(self):
354 """A common method to allow Findables to unindex themselves.""" 355 cat = getattr(self, self.default_catalog, None) 356 if cat != None: 357 cat.uncatalog_object(self.getPrimaryId())
358 359
360 - def reindex_all(self, obj=None):
361 """ 362 Called for in the CataLogAwarenessInterface not sure this is needed. 363 """ 364 if obj is None: obj=self 365 if hasattr(aq_base(obj), 'index_object'): 366 obj.index_object() 367 if hasattr(aq_base(obj), 'objectValues'): 368 sub=obj.objectValues() 369 for item in sub: 370 self.reindex_all(item) 371 return 'done!'
372
373 - def findChild(self, path):
374 """ 375 Find child using the ids found in path. Path separator is '/'. This 376 is similar to using attributes, but doesn't use acquisition. For 377 example, if 'Devices/Server/Linux' exists, but 378 'Devices/Server/SSH/Linux' does not, then the two methods will behave 379 differently. dmd.Devices.Server.SSH.Linux will return 380 'Devices/Server/Linux', whereas this method will throw an exception. 381 """ 382 child = self 383 for id in path.split('/'): 384 child = child._getOb(id) 385 return child
386