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

Source Code for Module ZenModel.ZenModelBase

  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__="""ZenModelBase 
 15   
 16  $Id: ZenModelBase.py,v 1.17 2004/04/23 19:11:58 edahl Exp $""" 
 17   
 18  __version__ = "$Revision: 1.17 $"[11:-2] 
 19   
 20  import copy 
 21  import re 
 22  import time 
 23   
 24  import sys  
 25  from urllib import unquote 
 26  from OFS.ObjectManager import checkValidId as globalCheckValidId 
 27   
 28  from AccessControl import ClassSecurityInfo, getSecurityManager, Unauthorized 
 29  from Globals import InitializeClass 
 30  from Acquisition import aq_base, aq_chain 
 31   
 32  from Products.CMFCore.utils import _verifyActionPermissions 
 33   
 34  from Products.ZenUtils.Utils import zenpathsplit, zenpathjoin 
 35  from Products.ZenUtils.Utils import createHierarchyObj, getHierarchyObj 
 36  from Products.ZenUtils.Utils import getObjByPath 
 37   
 38  from Products.ZenUtils.Utils import prepId as globalPrepId 
 39   
 40  from ZenossSecurity import * 
 41   
 42   
 43  # Custom device properties start with c 
 44  iscustprop = re.compile("^c[A-Z]").search 
 45   
46 -class ZenModelBase(object):
47 """ 48 All ZenModel Persistent classes inherit from this class. It provides some 49 screen management functionality, and general utility methods. 50 """ 51 sub_meta_types = () 52 #prodStateThreshold = 500 53 54 security = ClassSecurityInfo() 55
56 - def __call__(self):
57 """ 58 Invokes the default view. 59 """ 60 view = "view" 61 if hasattr(self, "factory_type_information"): 62 view = self.factory_type_information[0]['immediate_view'] 63 else: 64 raise 'Not Found', ('Cannot find default view for "%s"' % 65 '/'.join(self.getPhysicalPath())) 66 return self.restrictedTraverse(view)()
67 68 index_html = None # This special value informs ZPublisher to use __call__ 69 70 71 security.declareProtected(ZEN_VIEW, 'view')
72 - def view(self):
73 ''' 74 Returns the default view even if index_html is overridden. 75 76 @permission: ZEN_VIEW 77 ''' 78 return self()
79 80
81 - def __hash__(self):
82 return hash(self.id)
83
84 - def prepId(self, id, subchar='_'):
85 """ 86 Clean out an id of illegal characters. 87 88 @type id: string 89 @param subchar: Character to be substituted with illegal characters 90 @type subchar: string 91 @rtype: string 92 93 >>> dmd.Devices.prepId('ab^*cd') 94 'ab__cd' 95 >>> dmd.Devices.prepId('ab^*cd', subchar='Z') 96 'abZZcd' 97 >>> dmd.Devices.prepId('/boot') 98 'boot' 99 >>> dmd.Devices.prepId('/') 100 '-' 101 """ 102 return globalPrepId(id, subchar)
103
104 - def checkValidId(self, id, prep_id = False):
105 """ 106 Checks that an id is a valid Zope id. Looks for invalid characters and 107 checks that the id doesn't already exist in this context. 108 109 @type id: string 110 @type prep_id: boolean 111 @rtype: boolean 112 113 >>> dmd.Devices.checkValidId('^*') 114 'The id "^*" contains characters illegal in URLs.' 115 >>> dmd.Devices.checkValidId('Server') 116 'The id "Server" is invalid - it is already in use.' 117 >>> dmd.Devices.checkValidId('ZenTestId') 118 True 119 """ 120 new_id = unquote(id) 121 if prep_id: new_id = self.prepId(id) 122 try: 123 globalCheckValidId(self, new_id) 124 return True 125 except: 126 return str(sys.exc_info()[1])
127 128
129 - def getUnusedId(self, relName, baseKey, extensionIter=None):
130 """ 131 Return a new id that is not already in use in the relationship. If 132 baseKey is not already in use, return that. Otherwise append values 133 from extensionIter to baseKey until an used key is found. The default 134 extensionIter appends integers starting with 2 and counting up. 135 136 @type relName: string 137 @type baseKey: string 138 @type extensionIter: iterator 139 @rtype: string 140 141 >>> id1 = dmd.Devices.getUnusedId('devices', 'dev') 142 >>> id1 143 'dev' 144 >>> dmd.Devices.createInstance(id1) 145 <Device at /zport/dmd/Devices/devices/dev> 146 >>> id2 = dmd.Devices.getUnusedId('devices', 'dev') 147 >>> id2 148 'dev2' 149 """ 150 import itertools 151 if extensionIter is None: 152 extensionIter = itertools.count(2) 153 rel = getattr(self, relName) 154 candidate = baseKey 155 while candidate in rel.objectIds(): 156 candidate = self.prepId('%s%s' % (baseKey, extensionIter.next())) 157 return candidate
158 159 171 172
173 - def callZenScreen(self, REQUEST, redirect=False):
174 """ 175 Call and return screen specified by zenScreenName value of REQUEST. 176 If zenScreenName is not present call the default screen. This is used 177 in functions that are called from forms to get back to the correct 178 screen with the correct context. 179 """ 180 if REQUEST is None or getattr(REQUEST, 'dontRender', False): 181 # EventView uses a FakeRequest class to avoid the overhead 182 # of rendering pages as result of ajax calls. 183 return '' 184 screenName = REQUEST.get("zenScreenName", "") 185 if redirect: 186 nurl = "%s/%s" % (self.getPrimaryUrlPath(), screenName) 187 REQUEST['RESPONSE'].redirect(nurl) 188 else: 189 REQUEST['URL'] = "%s/%s" % (self.absolute_url_path(), screenName) 190 screen = getattr(self, screenName, False) 191 if not screen: return self() 192 return screen()
193 194
195 - def zenScreenUrl(self):
196 """ 197 Return the url for the current screen as defined by zenScreenName. 198 If zenScreenName is not found in the request the request url is used. 199 200 @return: An url to this object 201 @rtype: string 202 """ 203 screenName = self.REQUEST.get("zenScreenName", "") 204 if not screenName: return self.REQUEST.URL 205 return self.getPrimaryUrlPath() + "/" + screenName
206 207 232 233
234 - def getBreadCrumbUrlPath(self):
235 """ 236 Return the url to be used in breadcrumbs for this object. normally 237 this is equal to getPrimaryUrlPath. It can be used as a hook to modify 238 the url so that it points towards a different tab then the default. 239 240 @return: A url to this object 241 @rtype: string 242 243 >>> dmd.Devices.getBreadCrumbUrlPath() 244 '/zport/dmd/Devices' 245 >>> rc = dmd.Reports._getOb('Graph Reports') 246 >>> rc.manage_addGraphReport('test').getBreadCrumbUrlPath() 247 '/zport/dmd/Reports/Graph%20Reports/test/editGraphReport' 248 """ 249 return self.getPrimaryUrlPath()
250 251
252 - def breadCrumbs(self, terminator='dmd'):
253 """ 254 Return the data to create the breadcrumb links for this object. 255 256 This is a list of tuples where the first value is the URL of the bread 257 crumb and the second is the lable. 258 259 @return: List of tuples to create a bread crumbs 260 @rtype: list 261 262 >>> dmd.Devices.Server.breadCrumbs() 263 [('/zport/dmd/Devices', 'Devices'), 264 ('/zport/dmd/Devices/Server', 'Server')] 265 """ 266 links = [] 267 curDir = self.primaryAq() 268 while curDir.id != terminator: 269 if curDir.meta_type == 'ToManyContRelationship': 270 curDir = curDir.getPrimaryParent() 271 continue 272 if not getattr(aq_base(curDir),"getBreadCrumbUrlPath", False): 273 break 274 url = "" 275 if self.checkRemotePerm("View", curDir): 276 url = curDir.getBreadCrumbUrlPath() 277 links.append((url, curDir.id)) 278 curDir = curDir.aq_parent 279 links.reverse() 280 return links
281 282 283 security.declareProtected(ZEN_VIEW, 'getZ')
284 - def getZ(self, zpropname):
285 """ 286 Return the value of a zProperty on this object. This method is used to 287 lookup zProperties for a user with a role that doesn't have direct 288 access to an attribute further up the acquisition path. 289 290 @param zpropname: Name of zProperty 291 @type zpropname: string 292 @return: Value of zProperty 293 @permission: ZEN_VIEW 294 295 >>> dmd.Devices.getZ('zSnmpPort') 296 161 297 """ 298 return getattr(self, zpropname)
299 300 301 security.declareProtected(ZEN_COMMON, 'checkRemotePerm')
302 - def checkRemotePerm(self, permission, robject):
303 """ 304 Look to see if the current user has permission on remote object. 305 306 @param permission: Zope permission to be tested. ie "View" 307 @param robject: remote objecct on which test is run. Will test on 308 primary acquisition path. 309 @rtype: boolean 310 @permission: ZEN_COMMON 311 """ 312 user = getSecurityManager().getUser() 313 return user.has_permission(permission, robject.primaryAq())
314 315 316 317 security.declareProtected(ZEN_VIEW, 'zentinelTabs')
318 - def zentinelTabs(self, templateName):
319 """ 320 Return a list of hashes that define the screen tabs for this object. 321 322 Keys in the hash are: 323 - action = the name of the page template for this tab 324 - name = the label used on the tab 325 - permissions = a tuple of permissions to view this template 326 327 @permission: ZEN_VIEW 328 329 >>> dmd.Devices.zentinelTabs('deviceOrganizerStatus') 330 [{'action': 'deviceOrganizerStatus', 'selected': True, 331 'name': 'Classes', 'permissions': ('View',)}, 332 {'action': 'viewEvents', 'name': 'Events', 'permissions': ('View',)}, 333 {'action': 'viewHistoryEvents', 'name': 'History', 334 'permissions': ('View',)}, 335 {'action': 'zPropertyEdit', 'name': 'zProperties', 336 'permissions': ('View',)}, 337 {'action': 'perfConfig', 'name': 'Templates', 338 'permissions': ('Manage DMD',)}] 339 """ 340 tabs = [] 341 user = getSecurityManager().getUser() 342 actions = self.factory_type_information[0]['actions'] 343 for a in actions: 344 def permfilter(p): return user.has_permission(p,self) 345 permok = filter(permfilter, a['permissions']) 346 if not a.get('visible', True) or not permok: 347 continue 348 a = a.copy() 349 if a['action'] == templateName: a['selected'] = True 350 tabs.append(a) 351 return tabs
352 353 354 security.declareProtected(ZEN_MANAGE_DMD, 'zmanage_editProperties')
355 - def zmanage_editProperties(self, REQUEST=None, redirect=False):
356 """ 357 Edit a ZenModel object and return its proper page template. 358 Object will be reindexed if nessesary. 359 360 @permission: ZEN_MANAGE_DMD 361 """ 362 self.manage_changeProperties(**REQUEST.form) 363 index_object = getattr(self, 'index_object', lambda self: None) 364 index_object() 365 if REQUEST: 366 from Products.ZenUtils.Time import SaveMessage 367 REQUEST['message'] = SaveMessage() 368 return self.callZenScreen(REQUEST, redirect=redirect)
369 370 371 security.declareProtected(ZEN_VIEW, 'getPrimaryDmdId')
372 - def getPrimaryDmdId(self, rootName="dmd", subrel=""):
373 """ 374 Return the full dmd id of this object for instance /Devices/Server. 375 Everything before dmd is removed. A different rootName can be passed 376 to stop at a different object in the path. If subrel is passed any 377 relationship name in the path to the object will be removed. 378 379 @param rootName: Name of root 380 @type rootName: string 381 @param subrel: Name of relation 382 @type subrel: string 383 @return: Path to object 384 @rtype: string 385 @permission: ZEN_VIEW 386 387 >>> d = dmd.Devices.Server.createInstance('test') 388 >>> d.getPrimaryDmdId() 389 '/Devices/Server/devices/test' 390 >>> d.getPrimaryDmdId('Devices') 391 '/Server/devices/test' 392 >>> d.getPrimaryDmdId('Devices','devices') 393 '/Server/test' 394 """ 395 path = list(self.getPrimaryPath()) 396 path = path[path.index(rootName)+1:] 397 if subrel: path = filter(lambda x: x != subrel, path) 398 return '/'+'/'.join(path)
399 400
401 - def zenpathjoin(self, path):
402 """ 403 DEPRECATED Build a Zenoss path based on a list or tuple. 404 405 @type path: list or tuple 406 407 >>> dmd.zenpathjoin(('zport', 'dmd', 'Devices', 'Server')) 408 '/zport/dmd/Devices/Server' 409 """ 410 return zenpathjoin(path)
411 412
413 - def zenpathsplit(self, path):
414 """ 415 DEPRECATED Split a path on its '/'. 416 """ 417 return zenpathsplit(path)
418 419
420 - def createHierarchyObj(self, root, name, factory, relpath="", log=None):
421 """ 422 DEPRECATED this is only seems to be used in Organizer.createOrganizer - 423 Create an object from its path we use relpath to skip down any missing 424 relations in the path and factory is the constructor for this object. 425 """ 426 return createHierarchyObj(root, name, factory, relpath, log)
427 428
429 - def getHierarchyObj(self, root, name, relpath):
430 """ 431 DEPRECATED this doesn't seem to be used anywere don't use it!!! 432 """ 433 return getHierarchyObj(root, name, relpath)
434 435
436 - def getDmd(self):
437 """ 438 DEPRECATED Return the dmd root object with unwraped acquisition path. 439 440 >>> dmd.Devices.Server.getDmd() 441 <DataRoot at /zport/dmd> 442 """ 443 for obj in aq_chain(self): 444 if obj.id == 'dmd': return obj
445 446
447 - def getDmdRoot(self, name):
448 """ 449 Return a dmd root organizer such as "Systems". The acquisition path 450 will be cleaned so that it points directly to the root. 451 452 >>> dmd.Devices.Server.getDmdRoot("Systems") 453 <System at /zport/dmd/Systems> 454 """ 455 dmd = self.getDmd() 456 return dmd._getOb(name)
457 458
459 - def getDmdObj(self, path):
460 """ 461 DEPRECATED Return an object from path that starts at dmd. 462 463 >>> dmd.getDmdObj('/Devices/Server') 464 <DeviceClass at /zport/dmd/Devices/Server> 465 """ 466 if path.startswith("/"): path = path[1:] 467 return self.getDmd().getObjByPath(path)
468 469
470 - def getZopeObj(self, path):
471 """ 472 DEPRECATED Return an object from path tat starts at zope root. 473 474 >>> dmd.getZopeObj('/zport/dmd/Devices/Server') 475 <DeviceClass at /zport/dmd/Devices/Server> 476 """ 477 return self.getObjByPath(path)
478 479
480 - def getNowString(self):
481 """ 482 Return the current time as a string in the format '2007/09/27 14:09:53'. 483 484 @rtype: string 485 """ 486 return time.strftime("%Y/%m/%d %H:%M:%S", time.localtime())
487 488
489 - def todayDate(self):
490 """ 491 Return today's date as a string in the format 'mm/dd/yyyy'. 492 493 @rtype: string 494 """ 495 return time.strftime("%m/%d/%Y", time.localtime())
496 497
498 - def yesterdayDate(self):
499 """ 500 Return yesterday's date as a string in the format 'mm/dd/yyyy'. 501 502 @rtype: string 503 """ 504 yesterday = time.time() - 24*3600 505 return time.strftime("%m/%d/%Y", time.localtime(yesterday))
506 507
508 - def all_meta_types(self, interfaces=None):
509 """ 510 DEPRECATED Override the ObjectManager method that is used to control 511 the items available in the add drop down in the ZMI. It uses the 512 attribute sub_menu_items to create the data structures. This is a list 513 of meta_types for the available classes. This functionality is rarely 514 used in Zenoss because the ZMI is not the perfered management 515 interface. 516 """ 517 mts = super(ZenModelBase,self).all_meta_types(interfaces) 518 if self.sub_meta_types: 519 mts = filter(lambda mt: mt['name'] in self.sub_meta_types, mts) 520 return mts
521 522 523 security.declareProtected('Delete objects', 'manage_deleteObjects')
524 - def manage_deleteObjects(self, ids=(), REQUEST=None):
525 """ 526 Delete objects by id from this object and return to the current 527 template as defined by callZenScreen. Uses ObjectManager._delObject to 528 remove the object. 529 530 @permission: ZEN_VIEW 531 """ 532 for id in ids: self._delObject(id) 533 if REQUEST: 534 return self.callZenScreen(REQUEST)
535 536
537 - def custPropertyIds(self):
538 """ 539 List custom properties that are defined at root node. Custom properties 540 start with a lower "c" followed by a uppercase character. 541 """ 542 return self.zenPropertyIds(pfilt=iscustprop)
543 544
545 - def custPropertyMap(self):
546 """ 547 Return custom property definitions. 548 549 @rtype: [{'id':'cName','label':'Name', 'type':'string'},] 550 """ 551 return self.zenPropertyMap(pfilt=iscustprop)
552 553
554 - def visibleCustPropertyMap(self):
555 """ 556 List custom property definitions that are visible using 557 custPropertyMap:: 558 559 @rtype: [{'id':'cName','label':'Name', 'type':'string'},] 560 """ 561 return [ p for p in self.zenPropertyMap(pfilt=iscustprop) \ 562 if p.get('visible', True) ]
563 564 565 security.declareProtected(ZEN_MANAGE_DMD, 'saveCustProperties')
566 - def saveCustProperties(self, REQUEST):
567 """ 568 Save custom properties from REQUEST.form. 569 570 @permission: ZEN_MANAGE_DMD 571 """ 572 return self.saveZenProperties(iscustprop, REQUEST)
573 574
575 - def getObjByPath(self, path):
576 """ 577 Lookup and object by its path. Basically does a Zope unrestricted 578 traverse on the path given. 579 580 @type path: list or string /zport/dmd/Devices 581 582 >>> dmd.getObjByPath(('zport','dmd','Devices')) 583 <DeviceClass at /zport/dmd/Devices> 584 >>> dmd.getObjByPath(('Devices','Server')) 585 <DeviceClass at /zport/dmd/Devices/Server> 586 >>> dmd.getObjByPath('/zport/dmd/Devices/Server') 587 <DeviceClass at /zport/dmd/Devices/Server> 588 >>> dmd.getObjByPath('Devices/Server') 589 <DeviceClass at /zport/dmd/Devices/Server> 590 """ 591 return getObjByPath(self, path)
592 593
594 - def isLocalName(self, name):
595 """ 596 Check to see if a name is local to our current context or if it comes 597 from our acquisition chain. 598 599 @rtype: boolean 600 601 >>> dmd.isLocalName('Devices') 602 True 603 >>> dmd.Devices.Server.isLocalName('Devices') 604 False 605 """ 606 v = getattr(aq_base(self), name, '__ZENMARKER__') 607 return v != '__ZENMARKER__'
608 609 security.declareProtected(ZEN_VIEW, 'helpLink') 638 639 640 security.declareProtected(ZEN_VIEW, 'getIconPath')
641 - def getIconPath(self):
642 """ 643 Return the icon associated with this object. The icon path is defined 644 in the zPropoerty zIcon. 645 646 @return: Path to icon 647 @rtype: string 648 @permission: ZEN_VIEW 649 650 >>> d = dmd.Devices.Server.createInstance('test') 651 >>> d.getIconPath() 652 '/zport/dmd/img/icons/server.png' 653 """ 654 return self.dmd.getIconPath(self)
655 656 657 InitializeClass(ZenModelBase) 658