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

Source Code for Module Products.ZenModel.DataRoot

  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__="""DataRoot 
 12   
 13  DataRoot is the object manager which contains all confmon 
 14  data objects.  It can be used as a global acquisition 
 15  name space. 
 16  """ 
 17   
 18  import re 
 19  from zope.interface import implements 
 20  from AccessControl import ClassSecurityInfo 
 21  from AccessControl import getSecurityManager 
 22  from OFS.OrderedFolder import OrderedFolder 
 23  from Globals import DTMLFile 
 24  from Globals import InitializeClass 
 25  from Globals import DevelopmentMode 
 26  from Products.ZenModel.SiteError import SiteError 
 27  from Products.ZenModel.ZenModelBase import ZenModelBase 
 28  from Products.ZenModel.ZenMenuable import ZenMenuable 
 29  from Products.ZenRelations.RelSchema import * 
 30  from Products.ZenUtils.IpUtil import IpAddressError 
 31  from Products.ZenWidgets import messaging 
 32  from Products.ZenUtils.Security import activateSessionBasedAuthentication, activateCookieBasedAuthentication 
 33  from Commandable import Commandable 
 34  import socket 
 35  import os 
 36  import sys 
 37  import string 
 38  from Products.ZenMessaging.audit import audit 
 39  from Products.ZenUtils.Utils import zenPath, binPath 
 40  from Products.ZenUtils.Utils import extractPostContent 
 41  from Products.ZenUtils.jsonutils import json 
 42   
 43  from Products.ZenEvents.Exceptions import * 
 44   
 45  from ZenModelRM import ZenModelRM 
 46  from ZenossSecurity import ZEN_COMMON, ZEN_MANAGE_DMD, ZEN_VIEW 
 47  from interfaces import IDataRoot 
48 49 -def manage_addDataRoot(context, id, title = None, REQUEST = None):
50 """make a device""" 51 dr = DataRoot(id, title) 52 context._setObject(id, dr) 53 54 if REQUEST is not None: 55 REQUEST['RESPONSE'].redirect(context.absolute_url() + '/manage_main')
56 57 58 addDataRoot = DTMLFile('dtml/addDataRoot',globals()) 59 60 __pychecker__='no-override'
61 62 -class DataRoot(ZenModelRM, OrderedFolder, Commandable, ZenMenuable):
63 implements(IDataRoot) 64 65 meta_type = portal_type = 'DataRoot' 66 67 manage_main = OrderedFolder.manage_main 68 69 manage_options = OrderedFolder.manage_options 70 71 #setTitle = DTMLFile('dtml/setTitle',globals()) 72 73 _rq = True 74 uuid = None 75 availableVersion = None 76 lastVersionCheck = 0 77 lastVersionCheckAttempt = 0 78 versionCheckOptIn = True 79 reportMetricsOptIn = True 80 acceptedTerms = True 81 instanceIdentifier = 'Zenoss' 82 smtpHost = 'localhost' 83 pageCommand = '$ZENHOME/bin/zensnpp localhost 444 $RECIPIENT' 84 smtpPort = 25 85 smtpUser = '' 86 smtpPass = '' 87 smtpUseTLS = 0 88 emailFrom = '' 89 iconMap = {} 90 geomapapikey = '' 91 geocache = '' 92 version = "" 93 # how we should store our user credentials 94 AUTH_TYPE_SESSION = "session" 95 AUTH_TYPE_COOKIE = "cookie" 96 userAuthType = AUTH_TYPE_SESSION 97 pauseHubNotifications = False 98 99 _properties=( 100 {'id':'title', 'type': 'string', 'mode':'w'}, 101 {'id':'prodStateDashboardThresh','type':'int','mode':'w'}, 102 {'id':'prodStateConversions','type':'lines','mode':'w'}, 103 {'id':'priorityConversions','type':'lines','mode':'w'}, 104 {'id':'priorityDashboardThresh','type':'int','mode':'w'}, 105 {'id':'statusConversions','type':'lines','mode':'w'}, 106 {'id':'interfaceStateConversions','type':'lines','mode':'w'}, 107 {'id':'administrativeRoles','type':'lines','mode':'w'}, 108 {'id':'uuid', 'type': 'string', 'mode':'w'}, 109 {'id':'availableVersion', 'type': 'string', 'mode':'w'}, 110 {'id':'lastVersionCheck', 'type': 'long', 'mode':'w'}, 111 {'id':'lastVersionCheckAttempt', 'type': 'long', 'mode':'w'}, 112 {'id':'versionCheckOptIn', 'type': 'boolean', 'mode':'w'}, 113 {'id':'reportMetricsOptIn', 'type': 'boolean', 'mode':'w'}, 114 {'id':'instanceIdentifier', 'type': 'string', 'mode':'w'}, 115 {'id':'smtpHost', 'type': 'string', 'mode':'w'}, 116 {'id':'smtpPort', 'type': 'int', 'mode':'w'}, 117 {'id':'pageCommand', 'type': 'string', 'mode':'w'}, 118 {'id':'smtpUser', 'type': 'string', 'mode':'w'}, 119 {'id':'smtpPass', 'type': 'string', 'mode':'w'}, 120 {'id':'smtpUseTLS', 'type': 'int', 'mode':'w'}, 121 {'id':'emailFrom', 'type': 'string', 'mode':'w'}, 122 {'id':'geomapapikey', 'type': 'string', 'mode':'w'}, 123 {'id':'userAuthType', 'type': 'string', 'mode':'w'}, 124 {'id':'geocache', 'type': 'string', 'mode':'w'}, 125 {'id':'pauseHubNotifications', 'type': 'boolean', 'mode':'w'}, 126 ) 127 128 _relations = ( 129 ('userCommands', ToManyCont(ToOne, 'Products.ZenModel.UserCommand', 'commandable')), 130 # packs is depracated. Has been moved to dmd.ZenPackManager.packs 131 # Should be removed post Zenoss 2.2 132 # TODO 133 ('packs', ToManyCont(ToOne, 'Products.ZenModel.ZenPack', 'root')), 134 ('zenMenus', ToManyCont( 135 ToOne, 'Products.ZenModel.ZenMenu', 'menuable')), 136 ) 137 138 # Screen action bindings (and tab definitions) 139 factory_type_information = ( 140 { 141 'id' : 'DataRoot', 142 'meta_type' : 'DataRoot', 143 'description' : """Arbitrary device grouping class""", 144 'icon' : 'DataRoot_icon.gif', 145 'product' : 'ZenModel', 146 'factory' : 'manage_addStatusMonitorconf', 147 'immediate_view' : 'Dashboard', 148 'actions' : 149 ( 150 { 'id' : 'settings' 151 , 'name' : 'Settings' 152 , 'action' : 'editSettings' 153 , 'permissions' : ( "Manage DMD", ) 154 }, 155 { 'id' : 'manage' 156 , 'name' : 'Commands' 157 , 'action' : 'dataRootManage' 158 , 'permissions' : ('Manage DMD',) 159 }, 160 { 'id' : 'users' 161 , 'name' : 'Users' 162 , 'action' : 'ZenUsers/manageUserFolder' 163 , 'permissions' : ( 'Manage DMD', ) 164 }, 165 { 'id' : 'packs' 166 , 'name' : 'ZenPacks' 167 , 'action' : 'ZenPackManager/viewZenPacks' 168 , 'permissions' : ( "Manage DMD", ) 169 }, 170 { 'id' : 'portlets' 171 , 'name' : 'Portlets' 172 , 'action' : 'editPortletPerms' 173 , 'permissions' : ( "Manage DMD", ) 174 }, 175 { 'id' : 'daemons' 176 , 'name' : 'Daemons' 177 , 'action' : '../About/zenossInfo' 178 , 'permissions' : ( "Manage DMD", ) 179 }, 180 { 'id' : 'versions' 181 , 'name' : 'Versions' 182 , 'action' : '../About/zenossVersions' 183 , 'permissions' : ( "Manage DMD", ) 184 }, 185 { 'id' : 'backups' 186 , 'name' : 'Backups' 187 , 'action' : 'backupInfo' 188 , 'permissions' : ( "Manage DMD", ) 189 }, 190 { 'id' : 'eventConfig' 191 , 'name' : 'Events' 192 , 'action' : 'eventConfig' 193 , 'permissions' : ( "Manage DMD", ) 194 }, 195 { 'id' : 'userInterfaceConfig' 196 , 'name' : 'User Interface' 197 , 'action' : 'userInterfaceConfig' 198 , 'permissions' : ( "Manage DMD", ) 199 }, 200 ) 201 }, 202 ) 203 204 security = ClassSecurityInfo() 205 206 # production state threshold at which devices show on dashboard 207 prodStateDashboardThresh = 1000 208 209 # priority threshold at which devices show on dashboard 210 priorityDashboardThresh = 2 211 212 prodStateConversions = [ 213 'Production:1000', 214 'Pre-Production:500', 215 'Test:400', 216 'Maintenance:300', 217 'Decommissioned:-1', 218 ] 219 220 priorityConversions = [ 221 'Highest:5', 222 'High:4', 223 'Normal:3', 224 'Low:2', 225 'Lowest:1', 226 'Trivial:0', 227 ] 228 229 statusConversions = [ 230 'Up:0', 231 'None:-1', 232 'No DNS:-2', 233 ] 234 235 interfaceStateConversions = [ 236 'up:1', 237 'down:2', 238 'testing:3', 239 'unknown:4', 240 'dormant:5', 241 'notPresent:6', 242 'lowerLayerDown:7', 243 ] 244 245 administrativeRoles = ( 246 "Administrator", 247 "Analyst", 248 "Engineer", 249 "Tester", 250 ) 251 252 defaultDateRange = 129600 253 performanceDateRanges = [ 254 ('Hourly',129600,), 255 ('Daily',864000,), 256 ('Weekly',3628800,), 257 ('Monthly',41472000,), 258 ('Yearly',62208000,) 259 ] 260 261 262 # when calculating the primary path this will be its root 263 zPrimaryBasePath = ("", "zport") 264 265
266 - def __init__(self, id, title=None):
267 ZenModelRM.__init__(self, id, title) 268 from ZVersion import VERSION 269 self.version = "Zenoss " + VERSION
270
271 - def index_html(self):
272 """ 273 Override to force redirection to quickstart. 274 """ 275 if not self._rq: 276 return self.unrestrictedTraverse('quickstart')() 277 return self()
278
279 - def getEventCount(self, **kwargs):
280 """Return the current event list for this managed entity. 281 """ 282 return self.ZenEventManager.getEventCount(**kwargs)
283 284 security.declareProtected(ZEN_COMMON, 'getEventClassNames')
285 - def getEventClassNames(self):
286 """ 287 Get a list of all event class names within the permission scope. 288 """ 289 return self.Events.getOrganizerNames()
290 291
292 - def getDmdRoots(self):
293 return filter(lambda o: o.isInTree, self.objectValues())
294 295
296 - def exportXmlHook(self,ofile, ignorerels):
297 map(lambda x: x.exportXml(ofile, ignorerels), self.getDmdRoots())
298 299 300 security.declareProtected(ZEN_COMMON, 'getProdStateConversions')
301 - def getProdStateConversions(self):
302 """getProdStateConversions() -> return a list of tuples 303 for prodstat select edit box""" 304 return self.getConversions(self.prodStateConversions)
305 306 307 security.declareProtected(ZEN_COMMON, 'convertProdState')
308 - def convertProdState(self, prodState):
309 '''convert a numeric production state to a 310 textual representation using the prodStateConversions 311 map''' 312 return self.convertAttribute(prodState, self.prodStateConversions)
313 314 315 security.declareProtected(ZEN_COMMON, 'getStatusConversions')
316 - def getStatusConversions(self):
317 """get text strings for status field""" 318 return self.getConversions(self.statusConversions)
319 320 321 security.declareProtected(ZEN_COMMON, 'convertStatus')
322 - def convertStatus(self, status):
323 """get text strings for status field""" 324 return self.convertAttribute(status, self.statusConversions)
325 326 security.declareProtected(ZEN_COMMON, 'getPriorityConversions')
327 - def getPriorityConversions(self):
328 return self.getConversions(self.priorityConversions)
329 330 security.declareProtected(ZEN_COMMON, 'convertPriority')
331 - def convertPriority(self, priority):
333 334 security.declareProtected(ZEN_COMMON, 'getInterfaceStateConversions')
336 """get text strings for interface status""" 337 if hasattr(self, 'interfaceStateConversions'): 338 return self.getConversions(self.interfaceStateConversions)
339 340 341 security.declareProtected(ZEN_COMMON, 'convertAttribute')
342 - def convertAttribute(self, numbValue, conversions):
343 '''convert a numeric production state to a 344 textual representation using the prodStateConversions 345 map''' 346 numbValue = int(numbValue) 347 for line in conversions: 348 line = line.rstrip() 349 (name, number) = line.split(':') 350 if int(number) == numbValue: 351 return name 352 return numbValue
353 354 security.declareProtected(ZEN_COMMON, 'convertStatusToDot')
355 - def convertStatusToDot(self, status):
356 colors = ['green', 'yellow', 'orange', 'red'] 357 try: 358 return colors[status] 359 except IndexError: 360 return 'grey'
361 362 security.declareProtected(ZEN_COMMON, 'getConversions')
363 - def getConversions(self, attribute):
364 """get the text list of itmes that convert to ints""" 365 convs = [] 366 for item in attribute: 367 tup = item.split(':') 368 try: 369 tup[1] = int(tup[1]) 370 except (IndexError, ValueError): 371 continue 372 convs.append(tup) 373 return convs
374 375 security.declarePublic('filterObjectsRegex')
376 - def filterObjectsRegex(self, filter, objects, 377 filteratt='id', negatefilter=0):
378 """filter a list of objects based on a regex""" 379 filter = re.compile(filter).search 380 filteredObjects = [] 381 for obj in objects: 382 value = getattr(obj, filteratt, None) 383 if callable(value): 384 value = value() 385 fvalue = filter(value) 386 if (fvalue and not negatefilter) or (not fvalue and negatefilter): 387 filteredObjects.append(obj) 388 return filteredObjects
389 390 391 security.declareProtected('View', 'myUserGroups')
392 - def myUserGroups(self):
393 user = self.REQUEST.get('AUTHENTICATED_USER') 394 if hasattr(user, 'getGroups'): 395 return user.getGroups() 396 else: 397 return ()
398 399 400 security.declareProtected('View', 'getAllUserGroups')
401 - def getAllUserGroups(self):
402 return self.acl_users.getGroups()
403 404 405 security.declareProtected(ZEN_VIEW, 'zenoss_error_message')
406 - def zenoss_error_message(self,error_type,error_value, 407 error_traceback,error_message):
408 """Return an error page that is more friendly then the standard stack 409 trace + feedback page for ConflictErrors and MySQL errors (we need to 410 add out of disk space errors). If one of these is not found we return 411 the old stacktrace page 412 """ 413 from ZODB.POSException import ConflictError 414 from Products.ZenEvents.Exceptions import MySQLConnectionError 415 416 from zope.component import getUtility 417 from Products.ZenUtils.ZodbFactory import IZodbFactoryLookup 418 connectionFactory = getUtility(IZodbFactoryLookup).get() 419 420 if isinstance(error_value, ConflictError): 421 return self.zenoss_conflict_error_message() 422 elif isinstance(error_value, MySQLConnectionError) \ 423 or isinstance(error_value, connectionFactory.exceptions.Error): 424 return self.zenoss_mysql_error_message(error_value=error_value) 425 426 from traceback import format_exception 427 error_formatted = ''.join(format_exception(error_type, error_value, error_traceback)) 428 return self.zenoss_feedback_error_message(error_type=error_type, 429 error_value=error_value, 430 error_traceback=error_traceback, 431 error_formatted=error_formatted)
432 433
434 - def reportError(self):
435 ''' send an email to the zenoss error email address 436 then send user to a thankyou page or an email error page. 437 ''' 438 if self.smtpHost: host = self.smtpHost 439 else: host = None 440 port = self.smtpPort and self.smtpPort or 25 441 usetls = self.smtpUseTLS 442 usr = self.smtpUser 443 pwd = self.smtpPass 444 445 mailSent = SiteError.sendErrorEmail( 446 self.REQUEST.errorType, 447 self.REQUEST.errorValue, 448 self.REQUEST.errorTrace, 449 self.REQUEST.errorUrl, 450 self.About.getZenossRevision(), 451 self.About.getZenossVersionShort(), 452 self.REQUEST.contactName, 453 self.REQUEST.contactEmail, 454 self.REQUEST.comments, 455 host, port, usetls, usr, pwd) 456 if not mailSent: 457 body = SiteError.createReport( 458 self.REQUEST.errorType, 459 self.REQUEST.errorValue, 460 self.REQUEST.errorTrace, 461 self.REQUEST.errorUrl, 462 self.About.getZenossRevision(), 463 self.About.getZenossVersionShort(), 464 True, 465 self.REQUEST.contactName, 466 self.REQUEST.contactEmail, 467 self.REQUEST.comments) 468 return self.errorEmailFailure(toAddress=SiteError.ERRORS_ADDRESS, 469 body=body) 470 return self.errorEmailThankYou()
471 472 473 #security.declareProtected('View', 'writeExportRows')
474 - def writeExportRows(self, fieldsAndLabels, objects, out=None):
475 '''Write out csv rows with the given objects and fields. 476 If out is not None then call out.write() with the result and return None 477 otherwise return the result. 478 Each item in fieldsAndLabels is either a string representing a 479 field/key/index (see getDataField) or it is a tuple of (field, label) 480 where label is the string to be used in the first row as label 481 for that column. 482 Objects can be either dicts, lists/tuples or other objects. Field 483 is interpreted as a key, index or attribute depending on what 484 object is. 485 Method names can be passed instead of attribute/key/indices as field. 486 In this case the method is called and the return value is used in 487 the export. 488 ''' 489 import csv 490 import StringIO 491 if out: 492 buffer = out 493 else: 494 buffer = StringIO.StringIO() 495 fields = [] 496 labels = [] 497 if not fieldsAndLabels: 498 fieldsAndLabels = [] 499 if not objects: 500 objects = [] 501 for p in fieldsAndLabels: 502 if isinstance(p, tuple): 503 fields.append(p[0]) 504 labels.append(p[1]) 505 else: 506 fields.append(p) 507 labels.append(p) 508 writer = csv.writer(buffer) 509 writer.writerow(labels) 510 def getDataField(thing, field): 511 if isinstance(thing, dict): 512 value = thing.get(field, '') 513 elif isinstance(thing, list) or isinstance(thing, tuple): 514 value = thing[int(field)] 515 else: 516 value = getattr(thing, field, '') 517 if isinstance(value, ZenModelBase): 518 value = value.id 519 elif callable(value): 520 value = value() 521 if value == None: 522 value = '' 523 return str(value)
524 for o in objects: 525 writer.writerow([getDataField(o,f) for f in fields]) 526 if out: 527 result = None 528 else: 529 result = buffer.getvalue() 530 return result
531 532
533 - def getUserCommandTargets(self):
534 ''' Called by Commandable.doCommand() to ascertain objects on which 535 a UserCommand should be executed. 536 ''' 537 raise NotImplemented
538 539
540 - def getUrlForUserCommands(self):
541 return self.getPrimaryUrlPath() + '/dataRootManage'
542 543
544 - def getDefaultEmailFrom(self):
545 return 'zenossuser_%s@%s' % (getSecurityManager().getUser().getId(), socket.getfqdn())
546 547
548 - def getEmailFrom(self):
549 ''' Return self.emailFrom or a suitable default 550 ''' 551 return self.emailFrom or self.getDefaultEmailFrom()
552 553
554 - def checkValidId(self, id, prep_id = False):
555 """Checks a valid id 556 """ 557 if len(id) > 128: 558 return 'Command definition names can not be longer than 128 characters.' 559 allowed = set(string.ascii_letters + string.digits + '_') 560 attempted = set(id) 561 if not attempted.issubset(allowed): 562 return 'Only letters, digits and underscores are allowed' + \ 563 ' in command definition names.' 564 return ZenModelRM.checkValidId(self, id, prep_id)
565 566
567 - def setGeocodeCache(self, REQUEST=None):
568 """ Store a JSON representation of 569 the Google Maps geocode cache 570 """ 571 cache = extractPostContent(REQUEST) 572 try: cache = cache.decode('utf-8') 573 except: pass 574 self.geocache = cache 575 return True
576
577 - def clearGeocodeCache(self, REQUEST=None):
578 """ 579 Clear the Google Maps cache. 580 """ 581 self.geocache = ''
582 583 security.declareProtected(ZEN_COMMON, 'getGeoCache') 584 @json
585 - def getGeoCache(self):
586 cachestr = self.geocache 587 for char in ('\\r', '\\n'): 588 cachestr = cachestr.replace(char, ' ') 589 return cachestr
590
591 - def goToStatusPage(self, objid, REQUEST=None):
592 """ Find a device or network and redirect 593 to its status page. 594 """ 595 import urllib 596 objid = urllib.unquote(objid) 597 try: 598 devid = objid 599 if not devid.endswith('*'): devid += '*' 600 obj = self.Devices.findDevice(devid) 601 except: 602 obj=None 603 if not obj: 604 try: 605 obj = self.Networks.getNet(objid) 606 except IpAddressError: 607 return None 608 if not obj: return None 609 if REQUEST is not None: 610 REQUEST['RESPONSE'].redirect(obj.getPrimaryUrlPath())
611 612
613 - def getXMLEdges(self, objid, depth=1, filter="/"):
614 """ Get the XML representation of network nodes 615 and edges using the obj with objid as a root 616 """ 617 import urllib 618 objid = urllib.unquote(objid) 619 try: 620 devid = objid 621 if not devid.endswith('*'): devid += '*' 622 obj = self.Networks.getNet(objid) 623 except: obj=None 624 if not obj: 625 obj = self.Devices.findDevice(devid) 626 if not obj: 627 return '<graph><Start name="%s"/></graph>' % objid 628 return obj.getXMLEdges(int(depth), filter, 629 start=(obj.id,obj.getPrimaryUrlPath()))
630 631 632 security.declareProtected(ZEN_MANAGE_DMD, 'getBackupFilesInfo')
633 - def getBackupFilesInfo(self):
634 """ 635 Retrieve a list of dictionaries describing the files in 636 $ZENHOME/backups. 637 """ 638 import stat 639 import datetime 640 import operator 641 642 def FmtFileSize(size): 643 for power, units in ((3, 'GB'), (2, 'MB'), (1, 'KB')): 644 if size > pow(1024, power): 645 fmt = '%.2f %s' % ((size * 1.0)/pow(1024, power), units) 646 break 647 else: 648 fmt = '%s bytes' % size 649 return fmt
650 651 backupsDir = zenPath('backups') 652 fileInfo = [] 653 if os.path.isdir(backupsDir): 654 for dirPath, dirNames, fileNames in os.walk(backupsDir): 655 dirNames[:] = [] 656 for fileName in fileNames: 657 filePath = os.path.join(backupsDir, fileName) 658 info = os.stat(filePath) 659 fileInfo.append({ 660 'fileName': fileName, 661 'size': info[stat.ST_SIZE], 662 'sizeFormatted': FmtFileSize(info[stat.ST_SIZE]), 663 'modDate': info[stat.ST_MTIME], 664 'modDateFormatted': datetime.datetime.fromtimestamp( 665 info[stat.ST_MTIME]).strftime( 666 '%c'), 667 }) 668 fileInfo.sort(key=operator.itemgetter('modDate')) 669 return fileInfo 670 671 672 security.declareProtected(ZEN_MANAGE_DMD, 'manage_createBackup')
673 - def manage_createBackup(self, includeEvents=None, includeMysqlLogin=None, 674 timeout=120, REQUEST=None, writeMethod=None):
675 """ 676 Create a new backup file using zenbackup and the options specified 677 in the request. 678 679 This method makes use of the fact that DataRoot is a Commandable 680 in order to use Commandable.write 681 """ 682 import popen2 683 import fcntl 684 import time 685 import select 686 687 def write(s): 688 if writeMethod: 689 writeMethod(s) 690 elif REQUEST: 691 self.write(REQUEST.RESPONSE, s)
692 693 footer = None 694 if REQUEST and not writeMethod: 695 header, footer = self.commandOutputTemplate().split('OUTPUT_TOKEN') 696 REQUEST.RESPONSE.write(str(header)) 697 write('') 698 try: 699 cmd = binPath('zenbackup') + ' -v10' 700 if not includeEvents: 701 cmd += ' --no-eventsdb' 702 if not includeMysqlLogin: 703 cmd += ' --no-save-mysql-access' 704 try: 705 timeout = int(timeout) 706 except ValueError: 707 timeout = 120 708 timeout = max(timeout, 1) 709 child = popen2.Popen4(cmd) 710 flags = fcntl.fcntl(child.fromchild, fcntl.F_GETFL) 711 fcntl.fcntl(child.fromchild, fcntl.F_SETFL, flags | os.O_NDELAY) 712 endtime = time.time() + timeout 713 write('%s' % cmd) 714 write('') 715 pollPeriod = 1 716 firstPass = True 717 while time.time() < endtime and (firstPass or child.poll() == -1): 718 firstPass = False 719 r, w, e = select.select([child.fromchild], [], [], pollPeriod) 720 if r: 721 t = child.fromchild.read() 722 # We are sometimes getting to this point without any data 723 # from child.fromchild. I don't think that should happen 724 # but the conditional below seems to be necessary. 725 if t: 726 write(t) 727 728 if child.poll() == -1: 729 write('Backup timed out after %s seconds.' % timeout) 730 import signal 731 os.kill(child.pid, signal.SIGKILL) 732 733 write('DONE') 734 except Exception: 735 write('Exception while performing backup.') 736 write('type: %s value: %s' % tuple(sys.exc_info()[:2])) 737 else: 738 if REQUEST or writeMethod: 739 audit('UI.Backup.Create') 740 write('') 741 if REQUEST and footer: 742 REQUEST.RESPONSE.write(footer) 743 744 745 security.declareProtected(ZEN_MANAGE_DMD, 'manage_deleteBackups')
746 - def manage_deleteBackups(self, fileNames=(), REQUEST=None):
747 """ 748 Delete the specified files from $ZENHOME/backups 749 """ 750 backupsDir = zenPath('backups') 751 removed = [] 752 if os.path.isdir(backupsDir): 753 for dirPath, dirNames, dirFileNames in os.walk(backupsDir): 754 dirNames[:] = [] 755 for fileName in fileNames: 756 if fileName in dirFileNames: 757 toRemove = os.path.join(dirPath, fileName) 758 res = os.remove(toRemove) 759 if not res: 760 removed.append(toRemove) 761 if REQUEST: 762 audit('UI.Backup.Delete', files=removed) 763 messaging.IMessageSender(self).sendToBrowser( 764 'Backups Deleted', 765 '%s backup files have been deleted.' % len(removed) 766 ) 767 else: 768 if REQUEST: 769 messaging.IMessageSender(self).sendToBrowser( 770 'Backup Directory Missing', 771 'Unable to find $ZENHOME/backups.', 772 messaging.WARNING 773 ) 774 if REQUEST: 775 return self.callZenScreen(REQUEST)
776 777
778 - def getProductName(self):
779 """ 780 Return a string that represents the Zenoss product that is installed. 781 Currently this is something like 'core' or 'enterprise'. This is 782 used in the version check code to retrieve the available version 783 for the correct product. 784 """ 785 return getattr(self, 'productName', 'core')
786 787
788 - def error_handler(self, error=None):
789 """ 790 Returns pretty messages when errors are raised in templates. 791 792 Access this method from a template like so: 793 <div tal:content="..." 794 ... 795 tal:on-error="structure python:here.dmd.error_handler(error)"> 796 797 @param error: A TALES.ErrorInfo instance with attributes type, value 798 and traceback. 799 @return: HTML fragment with an error message 800 """ 801 if error.type==MySQLConnectionError: 802 msg = "Unable to connect to the MySQL server." 803 804 elif error.type in [ pythonThresholdException, rpnThresholdException ]: 805 msg= error.value 806 807 else: 808 raise 809 810 return '<b class="errormsg">%s</b>' % msg
811 812 @json
813 - def isDebugMode(self):
814 """ 815 Whether we're in debug mode, so that javascript will behave accordingly 816 """ 817 return DevelopmentMode
818
819 - def versionId(self):
820 """ 821 Get a string representative of the code version, to override JS 822 caching. 823 """ 824 return self.About.getZenossVersion().full().replace( 825 'Zenoss','').replace(' ','').replace('.','')
826
827 - def _updateEmailNotifications(self, REQUEST):
828 """update email notifications that use system-wide settings""" 829 830 # translates dmd property to notification content key 831 email_props = dict(smtpHost="host", 832 smtpPort="port", 833 smtpUser="user", 834 smtpPass="password", 835 smtpUseTLS="useTls", 836 emailFrom="email_from") 837 838 # did the system-wide email properties change? 839 email_props_changed = False 840 for prop in email_props: 841 if self.getProperty(prop) != REQUEST.get(prop): 842 email_props_changed = True 843 break 844 845 # if so, find all email notifications that use the system-wide 846 # settings and update them 847 if email_props_changed: 848 for notif in self.NotificationSubscriptions.objectValues(): 849 if notif.action == "email": 850 851 notif_uses_system_props = True 852 for prop, content_key in email_props.iteritems(): 853 if prop == "emailFrom": 854 if notif.content[content_key] != self.getEmailFrom(): 855 notif_uses_system_props = False 856 break 857 if prop == "smtpPort": 858 if int(notif.content[content_key]) != self.getProperty(prop): 859 notif_uses_system_props = False 860 break 861 elif notif.content[content_key] != self.getProperty(prop): 862 notif_uses_system_props = False 863 break 864 865 if notif_uses_system_props: 866 notif._p_changed = True 867 for prop, content_key in email_props.iteritems(): 868 notif.content[content_key] = REQUEST.get(prop) 869 if not notif.content["email_from"]: 870 notif.content["email_from"] = self.getDefaultEmailFrom()
871 872 security.declareProtected('Manage DMD', 'zmanage_editProperties')
873 - def zmanage_editProperties(self, REQUEST=None, redirect=False):
874 """Handle our authentication mechanism 875 """ 876 if REQUEST: 877 app = self.unrestrictedTraverse('/') 878 if REQUEST.get('userAuthType') == self.AUTH_TYPE_SESSION: 879 activateSessionBasedAuthentication(self.zport) 880 activateSessionBasedAuthentication(app) # for admin 881 elif REQUEST.get('userAuthType') == self.AUTH_TYPE_COOKIE: 882 activateCookieBasedAuthentication(self.zport) 883 activateCookieBasedAuthentication(app) # for admin 884 self._updateEmailNotifications(REQUEST) 885 return super(DataRoot, self).zmanage_editProperties(REQUEST, redirect)
886 887 888 InitializeClass(DataRoot) 889