Package ZenUtils :: Module Utils
[hide private]
[frames] | no frames]

Source Code for Module ZenUtils.Utils

  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__="""Utils 
 15   
 16  General Utility function module 
 17   
 18  $Id: Utils.py,v 1.15 2004/04/04 02:22:38 edahl Exp $""" 
 19   
 20  __version__ = "$Revision: 1.15 $"[11:-2] 
 21   
 22  import sys 
 23  import os 
 24  import types 
 25  import struct 
 26  import logging 
 27  import re 
 28  import socket 
 29  from sets import Set 
 30  log = logging.getLogger("zen.Utils") 
 31   
 32  from Acquisition import aq_base 
 33  from zExceptions import NotFound 
 34  from AccessControl import getSecurityManager 
 35  from AccessControl import Unauthorized 
 36  from AccessControl.ZopeGuards import guarded_getattr 
 37  from ZODB.POSException import ConflictError 
 38  from Acquisition import Acquired, aq_inner, aq_parent, aq_base 
 39   
 40  from Products.ZenUtils.Exceptions import ZenPathError 
 41   
42 -class HtmlFormatter(logging.Formatter):
43
44 - def __init__(self):
45 logging.Formatter.__init__(self, 46 """<tr class="loggingRow"> 47 <td>%(asctime)s</td><td>%(levelname)s</td> 48 <td>%(name)s</td><td>%(message)s</td> 49 </tr> 50 """, 51 "%Y-%m-%d %H:%M:%S")
52
53 - def formatException(self, exc_info):
54 exc = logging.Formatter.formatException(self,exc_info) 55 return """<tr class="tablevalues"><td colspan="4">%s</td></tr>""" % exc
56 57
58 -def setWebLoggingStream(stream):
59 """Setup logging to log to a browser using a request object.""" 60 handler = logging.StreamHandler(stream) 61 handler.setFormatter(HtmlFormatter()) 62 rlog = logging.getLogger() 63 rlog.addHandler(handler) 64 rlog.setLevel(logging.ERROR) 65 zlog = logging.getLogger("zen") 66 zlog.setLevel(logging.INFO) 67 return handler
68 69
70 -def clearWebLoggingStream(handler):
71 """Clear our web logger.""" 72 rlog = logging.getLogger() 73 rlog.removeHandler(handler)
74 75
76 -def convToUnits(numb, divby=1024.0):
77 """Convert a number to its human readable form. ie: 4GB, 4MB, etc. 78 """ 79 units = ('B','KB','MB','GB','TB','PB') 80 numb = float(numb) 81 sign = 1 82 if numb < 0: 83 numb = abs(numb) 84 sign = -1 85 for unit in units: 86 if numb < divby: break 87 numb /= divby 88 return "%.1f%s" % (numb * sign, unit)
89 90
91 -def travAndColl(obj, toonerel, collect, collectname):
92 """walk a series of to one rels collecting collectname into collect""" 93 #from Acquisition import aq_base 94 value = getattr(aq_base(obj), collectname, None) 95 if value: 96 collect.append(value) 97 rel = getattr(aq_base(obj), toonerel, None) 98 if callable(rel): 99 nobj = rel() 100 if nobj: 101 return travAndColl(nobj, toonerel, collect, collectname) 102 return collect
103 104
105 -def getObjByPath(base, path, restricted=0):
106 """Get a Zope object by its path (e.g. '/Devices/Server/Linux'). 107 Mostly a stripdown of unrestrictedTraverse method from Zope 2.8.8. 108 """ 109 if not path: 110 return base 111 112 _getattr = getattr 113 _none = None 114 marker = object() 115 116 if isinstance(path, str): 117 # Unicode paths are not allowed 118 path = path.split('/') 119 else: 120 path = list(path) 121 122 REQUEST = {'TraversalRequestNameStack': path} 123 path.reverse() 124 path_pop=path.pop 125 126 if len(path) > 1 and not path[0]: 127 # Remove trailing slash 128 path.pop(0) 129 130 if restricted: 131 securityManager = getSecurityManager() 132 else: 133 securityManager = _none 134 135 if not path[-1]: 136 # If the path starts with an empty string, go to the root first. 137 path_pop() 138 base = base.getPhysicalRoot() 139 if (restricted 140 and not securityManager.validate(None, None, None, base)): 141 raise Unauthorized, base 142 143 obj = base 144 while path: 145 name = path_pop() 146 __traceback_info__ = path, name 147 148 if name[0] == '_': 149 # Never allowed in a URL. 150 raise NotFound, name 151 152 if name == '..': 153 next = aq_parent(obj) 154 if next is not _none: 155 if restricted and not securityManager.validate( 156 obj, obj,name, next): 157 raise Unauthorized, name 158 obj = next 159 continue 160 161 bobo_traverse = _getattr(obj, '__bobo_traverse__', _none) 162 if bobo_traverse is not _none: 163 next = bobo_traverse(REQUEST, name) 164 if restricted: 165 if aq_base(next) is not next: 166 # The object is wrapped, so the acquisition 167 # context is the container. 168 container = aq_parent(aq_inner(next)) 169 elif _getattr(next, 'im_self', _none) is not _none: 170 # Bound method, the bound instance 171 # is the container 172 container = next.im_self 173 elif _getattr(aq_base(obj), name, marker) == next: 174 # Unwrapped direct attribute of the object so 175 # object is the container 176 container = obj 177 else: 178 # Can't determine container 179 container = _none 180 try: 181 validated = securityManager.validate( 182 obj, container, name, next) 183 except Unauthorized: 184 # If next is a simple unwrapped property, it's 185 # parentage is indeterminate, but it may have been 186 # acquired safely. In this case validate will 187 # raise an error, and we can explicitly check that 188 # our value was acquired safely. 189 validated = 0 190 if container is _none and \ 191 guarded_getattr(obj, name, marker) is next: 192 validated = 1 193 if not validated: 194 raise Unauthorized, name 195 else: 196 if restricted: 197 next = guarded_getattr(obj, name, marker) 198 else: 199 next = _getattr(obj, name, marker) 200 ## Below this is a change from the standard traverse from zope 201 ## it allows a path to use acquisition which is not what 202 ## we want. Our version will fail if one element of the 203 ## path doesn't exist. -EAD 204 #if hasattr(aq_base(obj), name): 205 # next = _getattr(obj, name, marker) 206 #else: 207 # raise NotFound, name 208 if next is marker: 209 try: 210 next=obj[name] 211 except AttributeError: 212 # Raise NotFound for easier debugging 213 # instead of AttributeError: __getitem__ 214 raise NotFound, name 215 if restricted and not securityManager.validate( 216 obj, obj, _none, next): 217 raise Unauthorized, name 218 obj = next 219 return obj
220 221 222
223 -def checkClass(myclass, className):
224 """perform issubclass using class name as string""" 225 if myclass.__name__ == className: 226 return 1 227 for mycl in myclass.__bases__: 228 if checkClass(mycl, className): 229 return 1
230 231
232 -def lookupClass(productName, classname=None):
233 """look in sys.modules for our class""" 234 import sys 235 if sys.modules.has_key(productName): 236 mod = sys.modules[productName] 237 elif sys.modules.has_key("Products."+productName): 238 mod = sys.modules["Products."+productName] 239 else: 240 return None 241 if not classname: 242 classname = productName.split('.')[-1] 243 return getattr(mod,classname)
244 245
246 -def importClass(modulePath, classname=""):
247 """Import a class from the module given. 248 """ 249 try: 250 if not classname: classname = modulePath.split(".")[-1] 251 mod = __import__(modulePath, globals(), locals(), classname) 252 return getattr(mod, classname) 253 except AttributeError: 254 raise ImportError("failed importing class %s from module %s" % ( 255 classname, modulePath))
256 257
258 -def cleanstring(value):
259 """take the trailing \x00 off the end of a string""" 260 if type(value) in types.StringTypes: 261 value = value.split('\0')[0] 262 return value
263 264
265 -def getSubObjects(base, filter=None, decend=None, retobjs=None):
266 """do a depth first search looking for objects that the function filter 267 returns as true. If decend is passed it will check to see if we 268 should keep going down or not""" 269 if not retobjs: retobjs = [] 270 for obj in base.objectValues(): 271 if not filter or filter(obj): 272 retobjs.append(obj) 273 if not decend or decend(obj): 274 retobjs = getSubObjects(obj, filter, decend, retobjs) 275 return retobjs
276 277
278 -def getSubObjectsMemo(base, filter=None, decend=None, memo={}):
279 """do a depth first search looking for objects that the function filter 280 returns as true. If decend is passed it will check to see if we 281 should keep going down or not""" 282 from Products.ZenRelations.RelationshipManager \ 283 import RelationshipManager 284 if base.meta_type == "To One Relationship": 285 objs = [base.obj] 286 else: 287 objs = base.objectValues() 288 for obj in objs: 289 if (isinstance(obj, RelationshipManager) and 290 not obj.getPrimaryDmdId().startswith(base.getPrimaryDmdId())): 291 continue 292 if not filter or filter(obj): 293 yield obj 294 if not decend or decend(obj): 295 for x in getSubObjectsMemo(obj, filter, decend, memo): 296 yield x
297 298
299 -def getAllConfmonObjects(base):
300 """get all ZenModelRM objects in database""" 301 from Products.ZenModel.ZenModelRM import ZenModelRM 302 from Products.ZenModel.ZenModelBase import ZenModelBase 303 from Products.ZenRelations.ToManyContRelationship \ 304 import ToManyContRelationship 305 from Products.ZenRelations.ToManyRelationship \ 306 import ToManyRelationship 307 from Products.ZenRelations.ToOneRelationship \ 308 import ToOneRelationship 309 def decend(obj): 310 return ( 311 isinstance(obj, ZenModelBase) or 312 isinstance(obj, ToManyContRelationship) or 313 isinstance(obj, ToManyRelationship) or 314 isinstance(obj, ToOneRelationship))
315 def filter(obj): 316 return isinstance(obj, ZenModelRM) and obj.id != "dmd" 317 return getSubObjectsMemo(base, filter=filter, decend=decend) 318
319 -def zenpathsplit(pathstring):
320 """split a zen path and clean up any blanks or bogus spaces in it""" 321 path = pathstring.split("/") 322 path = filter(lambda x: x, path) 323 path = map(lambda x: x.strip(), path) 324 return path
325
326 -def zenpathjoin(pathar):
327 """build a zenpath in its string form""" 328 return "/" + "/".join(pathar)
329
330 -def OLDgetHierarchyObj(root, name, factory, lastfactory=None, 331 relpath=None, lastrelpath=None, llog=None):
332 """build and return the path to an object 333 based on a hierarchical name (ex /Mail/Mta) relative 334 to the root passed in. If lastfactory is passed the leaf object 335 will be created with it instead of factory. 336 relpath is the relationship within which we will recurse as 337 objects are created. Having the relationship in the path passed 338 is optional.""" 339 path = zenpathsplit(name) 340 for id in path: 341 if id == relpath: continue 342 if getattr(aq_base(root), id, False): 343 nextroot = getattr(root, id) 344 else: 345 if id == path[-1]: 346 if lastrelpath: relpath = lastrelpath 347 if lastfactory: factory = lastfactory 348 if relpath and getattr(aq_base(root), relpath, False): 349 relobj = getattr(root, relpath) 350 if not getattr(aq_base(relobj), id, False): 351 log.debug("creating object with id %s in relation %s", 352 id, relobj.getId()) 353 factory(relobj, id) 354 nextroot = relobj._getOb(id) 355 else: 356 log.debug("creating object with id %s", id) 357 factory(root, id) 358 nextroot = root._getOb(id) 359 root = nextroot 360 return root
361 362
363 -def createHierarchyObj(root, name, factory, relpath="", llog=None):
364 """ 365 Create a hierarchy object from its path we use relpath to skip down 366 any missing relations in the path and factory is the constructor for 367 this object. 368 """ 369 rootName = root.id 370 for id in zenpathsplit(name): 371 if id == rootName: continue 372 if id == relpath or getattr(aq_base(root), relpath, False): 373 root = getattr(root, relpath) 374 if not getattr(aq_base(root), id, False): 375 if id == relpath: 376 raise AttributeError("relpath %s not found" % relpath) 377 log.debug("Creating object with id %s in object %s",id,root.getId()) 378 newobj = factory(id) 379 root._setObject(id, newobj) 380 root = getattr(root, id) 381 return root
382 383
384 -def getHierarchyObj(root, name, relpath=None):
385 """Return an object using its path relations are optional in the path.""" 386 for id in zenpathsplit(name): 387 if id == relpath or getattr(aq_base(root), relpath, False): 388 root = getattr(root, relpath) 389 if not getattr(root, id, False): 390 raise ZenPathError("Path %s id %s not found on object %s" % 391 (name, id, root.getPrimaryId())) 392 root = getattr(root, id, None) 393 return root
394 395 396
397 -def basicAuthUrl(username, password, url):
398 """add the username and password to a url in the form 399 http://username:password@host/path""" 400 urlar = url.split('/') 401 if not username or not password or urlar[2].find('@') > -1: 402 return url 403 urlar[2] = "%s:%s@%s" % (username, password, urlar[2]) 404 return "/".join(urlar)
405 406 407
408 -def prepId(id, subchar='_'):
409 """Make an id with valid url characters. Subs [^a-zA-Z0-9-_,.$\(\) ] 410 with subchar. If id then starts with subchar it is removed. 411 """ 412 _prepId = re.compile(r'[^a-zA-Z0-9-_,.$\(\) ]').sub 413 _cleanend = re.compile(r"%s+$" % subchar).sub 414 if id is None: 415 raise ValueError('Ids can not be None') 416 if type(id) not in types.StringTypes: 417 id = str(id) 418 id = _prepId(subchar, id) 419 while id.startswith(subchar): 420 if len(id) > 1: id = id[1:] 421 else: id = "-" 422 id = _cleanend("",id) 423 return str(id)
424
425 -def sendEmail(emsg, host, port=25, usetls=0, usr='', pwd=''):
426 ''' Send an email. Return a tuple: 427 (sucess, message) where sucess is True or False. 428 ''' 429 import smtplib 430 fromaddr = emsg['From'] 431 toaddr = emsg['To'].split(', ') 432 try: 433 server = smtplib.SMTP(host, port) 434 if usetls: 435 server.ehlo() 436 server.starttls() 437 server.ehlo() 438 if len(usr): server.login(usr, pwd) 439 server.sendmail(fromaddr, toaddr, emsg.as_string()) 440 # Need to catch the quit because some servers using TLS throw an 441 # EOF error on quit, so the email gets sent over and over 442 try: server.quit() 443 except: pass 444 except (smtplib.SMTPException, socket.error): 445 result = (False, '%s - %s' % tuple(sys.exc_info()[:2])) 446 else: 447 result = (True, '') 448 return result
449 450
451 -def sendPage(recipient, msg, snppHost, snppPort):
452 ''' Send a page. Return a tuple: (success, message) where 453 sucess is True or False. 454 ''' 455 import Pager 456 try: 457 rcpt = Pager.Recipient((recipient or '').strip()) 458 pmsg = Pager.Message(msg) 459 page = Pager.Pager((rcpt,), pmsg, snppHost, snppPort) 460 page.send() 461 except (Pager.SNPPException, Pager.PagerException, socket.error): 462 result = (False, '%s - %s' % tuple(sys.exc_info()[:2])) 463 else: 464 result = (True, '') 465 return result
466 467
468 -def zdecode(context, value):
469 if type(value) == type(''): 470 decoding = getattr(context, 'zCollectorDecoding', 'latin-1') 471 value = value.decode(decoding) 472 return value
473 474
475 -def localIpCheck(context, ip):
476 """Test to see if ip it should not be included in the network map.""" 477 return re.search(getattr(context, 'zLocalIpAddresses', '^$'), ip)
478
479 -def localInterfaceCheck(context, intname):
480 """Test to see if ips on an in should not be included in the network map.""" 481 return re.search(getattr(context, 'zLocalInterfaceNames', '^$'), intname)
482 483
484 -def cmpClassNames(obj, classnames):
485 """ Check to see if any of an object's base classes 486 are in a list of class names. Like isinstance(), 487 but without requiring a class to compare against. 488 """ 489 finalnames = Set() 490 x = [obj.__class__] 491 while x: 492 thisclass = x.pop() 493 x.extend(thisclass.__bases__) 494 finalnames.add(thisclass.__name__) 495 return bool( Set(classnames).intersection(finalnames) )
496
497 -def resequence(context, objects, seqmap, origseq, REQUEST):
498 if seqmap and origseq: 499 try: 500 origseq = tuple([long(s) for s in origseq]) 501 seqmap = tuple([float(s) for s in seqmap]) 502 except ValueError: 503 origseq = () 504 seqmap = () 505 orig = dict([(o.sequence, o) for o in objects]) 506 if origseq: 507 for oldSeq, newSeq in zip(origseq, seqmap): 508 orig[oldSeq].sequence = newSeq 509 def sort(x): 510 x = list(x) 511 x.sort(lambda a, b: cmp(a.sequence, b.sequence)) 512 return x
513 for i, obj in enumerate(sort(objects)): 514 obj.sequence = i 515 if REQUEST: 516 return context.callZenScreen(REQUEST) 517
518 -def cleanupSkins(dmd):
519 ps = dmd.getPhysicalRoot().zport.portal_skins 520 layers = ps._objects 521 layers = filter(lambda x:getattr(ps, x['id'], False), layers) 522 ps._objects = tuple(layers)
523
524 -def edgesToXML(edges, start=()):
525 nodet = '<Node id="%s" prop="%s" icon="%s" color="%s"/>' 526 edget = '<Edge fromID="%s" toID="%s"/>' 527 xmlels = ['<Start name="%s" url="%s"/>' % start] 528 nodeels = [] 529 edgeels = [] 530 for a, b in edges: 531 node1 = nodet % (a[0], a[0], a[1], a[2]) 532 node2 = nodet % (b[0], b[0], b[1], b[2]) 533 edge1 = edget % (a[0], b[0]) 534 if node1 not in nodeels: nodeels.append(node1) 535 if node2 not in nodeels: nodeels.append(node2) 536 if edge1 not in edgeels: edgeels.append(edge1) 537 xmlels.extend(nodeels) 538 xmlels.extend(edgeels) 539 xmldoc = "<graph>%s</graph>" % ''.join(list(xmlels)) 540 return xmldoc
541
542 -def zenPath(*args):
543 args = [a.strip('/') for a in args] 544 return os.path.join(os.environ['ZENHOME'], *args)
545
546 -def extractPostContent(REQUEST):
547 """ 548 IE puts the POST content in one place in the REQUEST object, and Firefox in 549 another. Thus we need to try both. 550 """ 551 try: 552 try: 553 # Firefox 554 result = REQUEST._file.read() 555 except: 556 # IE 557 result = REQUEST.form.keys()[0] 558 except: result = '' 559 return result
560