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

Source Code for Module ZenModel.DataRoot

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