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

Source Code for Module ZenModel.ZenModelRM

  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 as published by 
  8  # the Free Software Foundation. 
  9  # 
 10  # For complete information please visit: http://www.zenoss.com/oss/ 
 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  #from Products.ZCatalog.CatalogAwareness import CatalogAware 
 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 #should this class show in left nav tree 49 50 security = ClassSecurityInfo() 51
52 - def __init__(self, id, title=None, buildRelations=True):
53 self.createdTime = DateTime(time.time()) 54 RelationshipManager.__init__(self, id, title, buildRelations)
55 56 security.declareProtected('Manage DMD', 'rename')
57 - def rename(self, newId, REQUEST=None):
58 """Delete device from the DMD""" 59 renamed = False 60 if newId and newId != self.getId(): 61 parent = self.getPrimaryParent() 62 oldId = self.getId() 63 parent.manage_renameObject(oldId, newId) 64 renamed = True 65 if REQUEST: 66 if renamed: 67 messaging.IMessageSender(self).sendToBrowser( 68 'Object Renamed', 69 "Object %s was renamed to %s." % (oldId, newId) 70 ) 71 return self.callZenScreen(REQUEST, renamed) 72 return renamed
73 74 75 security.declareProtected('Manage DMD', 'zmanage_editProperties')
76 - def zmanage_editProperties(self, REQUEST=None, redirect=False):
77 """Edit a ZenModel object and return its proper page template 78 """ 79 redirect = False 80 if REQUEST.form.has_key("newId"): 81 redirect = self.rename(REQUEST.form["newId"]) 82 return ZenModelBase.zmanage_editProperties(self, REQUEST, redirect)
83 84
85 - def zmanage_addProperty(self, id, value, type, label, visible, 86 prefix='c', REQUEST=None):
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
122 - def zmanage_exportObject(self, context=None, REQUEST=None):
123 """Export objects to specific locations. 124 """ 125 if not context: 126 context = self 127 redirect = False 128 dest = 'filesystem' 129 if REQUEST: 130 dest = REQUEST.form.get('dest') 131 fileBase = '%s_%s.xml' % (context.getNodeName(), context.id) 132 if dest == 'filesystem': 133 filename = zenPath('export', fileBase) 134 msg = "Item has been exported to: %s at " % filename 135 elif dest == 'zenossdotnet': 136 # create temp file 137 filename = '' 138 # get https URL for user space at Zenoss.net 139 url = 'https://%s:%[email protected]/' 140 # build XML-RPC proxy object for publishing to Zenoss.net 141 import xmlrpclib 142 server = xmlrpclib.ProxyServer(url) 143 msg = "Item has been exported to: %s. Note that you will need to " 144 msg += "login at Zenoss.net and publish this template in order to " 145 msg += "share it with others. Exported at " 146 msg %= url 147 # open file 148 exportFile = open(filename, 'w+') 149 # export object to file 150 context.exportXml(exportFile) 151 # cleanup 152 exportFile.close() 153 if dest == 'zenossdotnet': 154 # get data 155 exportFile = open(filename) 156 dataToSend = exportFile.read() 157 exportFile.close() 158 # push data up to Zenoss.net 159 server.postUserTemplate(dataToSend) 160 if REQUEST: 161 messaging.IMessageSender(self).sendToBrowser( 162 'Export Object', msg) 163 return self.callZenScreen(REQUEST, redirect)
164 165
166 - def zmanage_importObjects(self, context=None, REQUEST=None):
167 """Import an XML file as the Zenoss objects and properties it 168 represents. 169 """ 170 # XXX 171 # for right now, we're only using this through the web, so a REQUEST is 172 # always define; when we have a use-case for imports via command line, 173 # we will add that code here 174 if not context: 175 context = self.getPhysicalRoot() 176 # get the submitted data 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 # load the objects into Zenoss 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
199 - def zmanage_importObject(self, REQUEST=None):
200 """Import objects into Zenoss. 201 """ 202 pass
203
204 - def zmanage_delProperties(self, ids=(), REQUEST=None):
205 """Delete properties from an object. 206 """ 207 for id in ids: 208 self._delProperty(id) 209 if REQUEST: 210 messaging.IMessageSender(self).sendToBrowser( 211 'Properties Deleted', 212 'Properties %s have been deleted' % (', '.join(ids)) 213 ) 214 return self.callZenScreen(REQUEST)
215 216
217 - def zmanage_delObjects(self, ids=(), relation="", REQUEST=None):
218 """Delete objects from this object or one of its relations. 219 """ 220 target = self 221 if relation: target = self._getOb(relation) 222 for id in ids: 223 target._delObject(id) 224 if REQUEST: 225 messaging.IMessageSender(self).sendToBrowser( 226 'Objects Deleted', 227 'Objects %s have been deleted' % (', '.join(ids)) 228 ) 229 return self.callZenScreen(REQUEST)
230 231 232 security.declareProtected('View', 'getDmdKey')
233 - def getDmdKey(self):
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')
247 - def primarySortKey(self):
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')
261 - def viewName(self):
262 return self.getId()
263 264 265 #actions?
266 - def getTreeItems(self):
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):
275 return getSubObjects(self, filter, decend, retobjs)
276 277
278 - def getCreatedTimeString(self):
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
288 - def changePythonClass(self, newPythonClass, container):
289 """change the python class of a persistent object""" 290 id = self.id 291 nobj = newPythonClass(id) #make new instance from new class 292 nobj = nobj.__of__(container) #make aq_chain same as self 293 nobj.oldid = self.id 294 nobj.setPrimaryPath() #set up the primarypath for the copy 295 #move all sub objects to new object 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 # confuse pychecker: 301 setObject = RelationshipManager._setObject 302 setObject(nobj, sobj.id, sobj) 303 nobj.buildRelations() #build out any missing relations 304 # copy properties to new object 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
314 - def getZenRootNode(self):
315 """Return the root node for our zProperties.""" 316 return self.getDmdRoot(self.dmdRootName)
317 318
319 - def editableDeviceList(self):
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
327 - def creator(self):
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
341 - def index_object(self):
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
348 - def unindex_object(self):
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
355 - def reindex_all(self, obj=None):
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
368 - def findChild(self, path):
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