Package CedarBackup2 :: Package actions :: Module validate
[hide private]
[frames] | no frames]

Source Code for Module CedarBackup2.actions.validate

  1  # -*- coding: iso-8859-1 -*- 
  2  # vim: set ft=python ts=3 sw=3 expandtab: 
  3  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 
  4  # 
  5  #              C E D A R 
  6  #          S O L U T I O N S       "Software done right." 
  7  #           S O F T W A R E 
  8  # 
  9  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 
 10  # 
 11  # Copyright (c) 2004-2007,2010 Kenneth J. Pronovici. 
 12  # All rights reserved. 
 13  # 
 14  # This program is free software; you can redistribute it and/or 
 15  # modify it under the terms of the GNU General Public License, 
 16  # Version 2, as published by the Free Software Foundation. 
 17  # 
 18  # This program is distributed in the hope that it will be useful, 
 19  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 20  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
 21  # 
 22  # Copies of the GNU General Public License are available from 
 23  # the Free Software Foundation website, http://www.gnu.org/. 
 24  # 
 25  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 
 26  # 
 27  # Author   : Kenneth J. Pronovici <pronovic@ieee.org> 
 28  # Language : Python 2 (>= 2.7) 
 29  # Project  : Cedar Backup, release 2 
 30  # Purpose  : Implements the standard 'validate' action. 
 31  # 
 32  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 
 33   
 34  ######################################################################## 
 35  # Module documentation 
 36  ######################################################################## 
 37   
 38  """ 
 39  Implements the standard 'validate' action. 
 40  @sort: executeValidate 
 41  @author: Kenneth J. Pronovici <pronovic@ieee.org> 
 42  """ 
 43   
 44   
 45  ######################################################################## 
 46  # Imported modules 
 47  ######################################################################## 
 48   
 49  # System modules 
 50  import os 
 51  import logging 
 52   
 53  # Cedar Backup modules 
 54  from CedarBackup2.util import getUidGid, getFunctionReference 
 55  from CedarBackup2.actions.util import createWriter 
 56   
 57   
 58  ######################################################################## 
 59  # Module-wide constants and variables 
 60  ######################################################################## 
 61   
 62  logger = logging.getLogger("CedarBackup2.log.actions.validate") 
 63   
 64   
 65  ######################################################################## 
 66  # Public functions 
 67  ######################################################################## 
 68   
 69  ############################# 
 70  # executeValidate() function 
 71  ############################# 
 72   
 73  # pylint: disable=W0613 
74 -def executeValidate(configPath, options, config):
75 """ 76 Executes the validate action. 77 78 This action validates each of the individual sections in the config file. 79 This is a "runtime" validation. The config file itself is already valid in 80 a structural sense, so what we check here that is that we can actually use 81 the configuration without any problems. 82 83 There's a separate validation function for each of the configuration 84 sections. Each validation function returns a true/false indication for 85 whether configuration was valid, and then logs any configuration problems it 86 finds. This way, one pass over configuration indicates most or all of the 87 obvious problems, rather than finding just one problem at a time. 88 89 Any reported problems will be logged at the ERROR level normally, or at the 90 INFO level if the quiet flag is enabled. 91 92 @param configPath: Path to configuration file on disk. 93 @type configPath: String representing a path on disk. 94 95 @param options: Program command-line options. 96 @type options: Options object. 97 98 @param config: Program configuration. 99 @type config: Config object. 100 101 @raise ValueError: If some configuration value is invalid. 102 """ 103 logger.debug("Executing the 'validate' action.") 104 if options.quiet: 105 logfunc = logger.info # info so it goes to the log 106 else: 107 logfunc = logger.error # error so it goes to the screen 108 valid = True 109 valid &= _validateReference(config, logfunc) 110 valid &= _validateOptions(config, logfunc) 111 valid &= _validateCollect(config, logfunc) 112 valid &= _validateStage(config, logfunc) 113 valid &= _validateStore(config, logfunc) 114 valid &= _validatePurge(config, logfunc) 115 valid &= _validateExtensions(config, logfunc) 116 if valid: 117 logfunc("Configuration is valid.") 118 else: 119 logfunc("Configuration is not valid.")
120 121 122 ######################################################################## 123 # Private utility functions 124 ######################################################################## 125 126 ####################### 127 # _checkDir() function 128 ####################### 129
130 -def _checkDir(path, writable, logfunc, prefix):
131 """ 132 Checks that the indicated directory is OK. 133 134 The path must exist, must be a directory, must be readable and executable, 135 and must optionally be writable. 136 137 @param path: Path to check. 138 @param writable: Check that path is writable. 139 @param logfunc: Function to use for logging errors. 140 @param prefix: Prefix to use on logged errors. 141 142 @return: True if the directory is OK, False otherwise. 143 """ 144 if not os.path.exists(path): 145 logfunc("%s [%s] does not exist." % (prefix, path)) 146 return False 147 if not os.path.isdir(path): 148 logfunc("%s [%s] is not a directory." % (prefix, path)) 149 return False 150 if not os.access(path, os.R_OK): 151 logfunc("%s [%s] is not readable." % (prefix, path)) 152 return False 153 if not os.access(path, os.X_OK): 154 logfunc("%s [%s] is not executable." % (prefix, path)) 155 return False 156 if writable and not os.access(path, os.W_OK): 157 logfunc("%s [%s] is not writable." % (prefix, path)) 158 return False 159 return True
160 161 162 ################################ 163 # _validateReference() function 164 ################################ 165
166 -def _validateReference(config, logfunc):
167 """ 168 Execute runtime validations on reference configuration. 169 170 We only validate that reference configuration exists at all. 171 172 @param config: Program configuration. 173 @param logfunc: Function to use for logging errors 174 175 @return: True if configuration is valid, false otherwise. 176 """ 177 valid = True 178 if config.reference is None: 179 logfunc("Required reference configuration does not exist.") 180 valid = False 181 return valid
182 183 184 ############################## 185 # _validateOptions() function 186 ############################## 187
188 -def _validateOptions(config, logfunc):
189 """ 190 Execute runtime validations on options configuration. 191 192 The following validations are enforced: 193 194 - The options section must exist 195 - The working directory must exist and must be writable 196 - The backup user and backup group must exist 197 198 @param config: Program configuration. 199 @param logfunc: Function to use for logging errors 200 201 @return: True if configuration is valid, false otherwise. 202 """ 203 valid = True 204 if config.options is None: 205 logfunc("Required options configuration does not exist.") 206 valid = False 207 else: 208 valid &= _checkDir(config.options.workingDir, True, logfunc, "Working directory") 209 try: 210 getUidGid(config.options.backupUser, config.options.backupGroup) 211 except ValueError: 212 logfunc("Backup user:group [%s:%s] invalid." % (config.options.backupUser, config.options.backupGroup)) 213 valid = False 214 return valid
215 216 217 ############################## 218 # _validateCollect() function 219 ############################## 220
221 -def _validateCollect(config, logfunc):
222 """ 223 Execute runtime validations on collect configuration. 224 225 The following validations are enforced: 226 227 - The target directory must exist and must be writable 228 - Each of the individual collect directories must exist and must be readable 229 230 @param config: Program configuration. 231 @param logfunc: Function to use for logging errors 232 233 @return: True if configuration is valid, false otherwise. 234 """ 235 valid = True 236 if config.collect is not None: 237 valid &= _checkDir(config.collect.targetDir, True, logfunc, "Collect target directory") 238 if config.collect.collectDirs is not None: 239 for collectDir in config.collect.collectDirs: 240 valid &= _checkDir(collectDir.absolutePath, False, logfunc, "Collect directory") 241 return valid
242 243 244 ############################ 245 # _validateStage() function 246 ############################ 247
248 -def _validateStage(config, logfunc):
249 """ 250 Execute runtime validations on stage configuration. 251 252 The following validations are enforced: 253 254 - The target directory must exist and must be writable 255 - Each local peer's collect directory must exist and must be readable 256 257 @note: We currently do not validate anything having to do with remote peers, 258 since we don't have a straightforward way of doing it. It would require 259 adding an rsh command rather than just an rcp command to configuration, and 260 that just doesn't seem worth it right now. 261 262 @param config: Program configuration. 263 @param logfunc: Function to use for logging errors 264 265 @return: True if configuration is valid, False otherwise. 266 """ 267 valid = True 268 if config.stage is not None: 269 valid &= _checkDir(config.stage.targetDir, True, logfunc, "Stage target dir ") 270 if config.stage.localPeers is not None: 271 for peer in config.stage.localPeers: 272 valid &= _checkDir(peer.collectDir, False, logfunc, "Local peer collect dir ") 273 return valid
274 275 276 ############################ 277 # _validateStore() function 278 ############################ 279
280 -def _validateStore(config, logfunc):
281 """ 282 Execute runtime validations on store configuration. 283 284 The following validations are enforced: 285 286 - The source directory must exist and must be readable 287 - The backup device (path and SCSI device) must be valid 288 289 @param config: Program configuration. 290 @param logfunc: Function to use for logging errors 291 292 @return: True if configuration is valid, False otherwise. 293 """ 294 valid = True 295 if config.store is not None: 296 valid &= _checkDir(config.store.sourceDir, False, logfunc, "Store source directory") 297 try: 298 createWriter(config) 299 except ValueError: 300 logfunc("Backup device [%s] [%s] is not valid." % (config.store.devicePath, config.store.deviceScsiId)) 301 valid = False 302 return valid
303 304 305 ############################ 306 # _validatePurge() function 307 ############################ 308
309 -def _validatePurge(config, logfunc):
310 """ 311 Execute runtime validations on purge configuration. 312 313 The following validations are enforced: 314 315 - Each purge directory must exist and must be writable 316 317 @param config: Program configuration. 318 @param logfunc: Function to use for logging errors 319 320 @return: True if configuration is valid, False otherwise. 321 """ 322 valid = True 323 if config.purge is not None: 324 if config.purge.purgeDirs is not None: 325 for purgeDir in config.purge.purgeDirs: 326 valid &= _checkDir(purgeDir.absolutePath, True, logfunc, "Purge directory") 327 return valid
328 329 330 ################################# 331 # _validateExtensions() function 332 ################################# 333
334 -def _validateExtensions(config, logfunc):
335 """ 336 Execute runtime validations on extensions configuration. 337 338 The following validations are enforced: 339 340 - Each indicated extension function must exist. 341 342 @param config: Program configuration. 343 @param logfunc: Function to use for logging errors 344 345 @return: True if configuration is valid, False otherwise. 346 """ 347 valid = True 348 if config.extensions is not None: 349 if config.extensions.actions is not None: 350 for action in config.extensions.actions: 351 try: 352 getFunctionReference(action.module, action.function) 353 except ImportError: 354 logfunc("Unable to find function [%s.%s]." % (action.module, action.function)) 355 valid = False 356 except ValueError: 357 logfunc("Function [%s.%s] is not callable." % (action.module, action.function)) 358 valid = False 359 return valid
360