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

Source Code for Module CedarBackup3.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,2015 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 3 (>= 3.4) 
 29  # Project  : Cedar Backup, release 3 
 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 CedarBackup3.util import getUidGid, getFunctionReference 
 55  from CedarBackup3.actions.util import createWriter 
 56   
 57   
 58  ######################################################################## 
 59  # Module-wide constants and variables 
 60  ######################################################################## 
 61   
 62  logger = logging.getLogger("CedarBackup3.log.actions.validate") 
 63   
 64   
 65  ######################################################################## 
 66  # Public functions 
 67  ######################################################################## 
 68   
 69  ############################# 
 70  # executeValidate() function 
 71  ############################# 
 72   
73 -def executeValidate(configPath, options, config):
74 """ 75 Executes the validate action. 76 77 This action validates each of the individual sections in the config file. 78 This is a "runtime" validation. The config file itself is already valid in 79 a structural sense, so what we check here that is that we can actually use 80 the configuration without any problems. 81 82 There's a separate validation function for each of the configuration 83 sections. Each validation function returns a true/false indication for 84 whether configuration was valid, and then logs any configuration problems it 85 finds. This way, one pass over configuration indicates most or all of the 86 obvious problems, rather than finding just one problem at a time. 87 88 Any reported problems will be logged at the ERROR level normally, or at the 89 INFO level if the quiet flag is enabled. 90 91 @param configPath: Path to configuration file on disk. 92 @type configPath: String representing a path on disk. 93 94 @param options: Program command-line options. 95 @type options: Options object. 96 97 @param config: Program configuration. 98 @type config: Config object. 99 100 @raise ValueError: If some configuration value is invalid. 101 """ 102 logger.debug("Executing the 'validate' action.") 103 if options.quiet: 104 logfunc = logger.info # info so it goes to the log 105 else: 106 logfunc = logger.error # error so it goes to the screen 107 valid = True 108 valid &= _validateReference(config, logfunc) 109 valid &= _validateOptions(config, logfunc) 110 valid &= _validateCollect(config, logfunc) 111 valid &= _validateStage(config, logfunc) 112 valid &= _validateStore(config, logfunc) 113 valid &= _validatePurge(config, logfunc) 114 valid &= _validateExtensions(config, logfunc) 115 if valid: 116 logfunc("Configuration is valid.") 117 else: 118 logfunc("Configuration is not valid.")
119 120 121 ######################################################################## 122 # Private utility functions 123 ######################################################################## 124 125 ####################### 126 # _checkDir() function 127 ####################### 128
129 -def _checkDir(path, writable, logfunc, prefix):
130 """ 131 Checks that the indicated directory is OK. 132 133 The path must exist, must be a directory, must be readable and executable, 134 and must optionally be writable. 135 136 @param path: Path to check. 137 @param writable: Check that path is writable. 138 @param logfunc: Function to use for logging errors. 139 @param prefix: Prefix to use on logged errors. 140 141 @return: True if the directory is OK, False otherwise. 142 """ 143 if not os.path.exists(path): 144 logfunc("%s [%s] does not exist." % (prefix, path)) 145 return False 146 if not os.path.isdir(path): 147 logfunc("%s [%s] is not a directory." % (prefix, path)) 148 return False 149 if not os.access(path, os.R_OK): 150 logfunc("%s [%s] is not readable." % (prefix, path)) 151 return False 152 if not os.access(path, os.X_OK): 153 logfunc("%s [%s] is not executable." % (prefix, path)) 154 return False 155 if writable and not os.access(path, os.W_OK): 156 logfunc("%s [%s] is not writable." % (prefix, path)) 157 return False 158 return True
159 160 161 ################################ 162 # _validateReference() function 163 ################################ 164
165 -def _validateReference(config, logfunc):
166 """ 167 Execute runtime validations on reference configuration. 168 169 We only validate that reference configuration exists at all. 170 171 @param config: Program configuration. 172 @param logfunc: Function to use for logging errors 173 174 @return: True if configuration is valid, false otherwise. 175 """ 176 valid = True 177 if config.reference is None: 178 logfunc("Required reference configuration does not exist.") 179 valid = False 180 return valid
181 182 183 ############################## 184 # _validateOptions() function 185 ############################## 186
187 -def _validateOptions(config, logfunc):
188 """ 189 Execute runtime validations on options configuration. 190 191 The following validations are enforced: 192 193 - The options section must exist 194 - The working directory must exist and must be writable 195 - The backup user and backup group must exist 196 197 @param config: Program configuration. 198 @param logfunc: Function to use for logging errors 199 200 @return: True if configuration is valid, false otherwise. 201 """ 202 valid = True 203 if config.options is None: 204 logfunc("Required options configuration does not exist.") 205 valid = False 206 else: 207 valid &= _checkDir(config.options.workingDir, True, logfunc, "Working directory") 208 try: 209 getUidGid(config.options.backupUser, config.options.backupGroup) 210 except ValueError: 211 logfunc("Backup user:group [%s:%s] invalid." % (config.options.backupUser, config.options.backupGroup)) 212 valid = False 213 return valid
214 215 216 ############################## 217 # _validateCollect() function 218 ############################## 219
220 -def _validateCollect(config, logfunc):
221 """ 222 Execute runtime validations on collect configuration. 223 224 The following validations are enforced: 225 226 - The target directory must exist and must be writable 227 - Each of the individual collect directories must exist and must be readable 228 229 @param config: Program configuration. 230 @param logfunc: Function to use for logging errors 231 232 @return: True if configuration is valid, false otherwise. 233 """ 234 valid = True 235 if config.collect is not None: 236 valid &= _checkDir(config.collect.targetDir, True, logfunc, "Collect target directory") 237 if config.collect.collectDirs is not None: 238 for collectDir in config.collect.collectDirs: 239 valid &= _checkDir(collectDir.absolutePath, False, logfunc, "Collect directory") 240 return valid
241 242 243 ############################ 244 # _validateStage() function 245 ############################ 246
247 -def _validateStage(config, logfunc):
248 """ 249 Execute runtime validations on stage configuration. 250 251 The following validations are enforced: 252 253 - The target directory must exist and must be writable 254 - Each local peer's collect directory must exist and must be readable 255 256 @note: We currently do not validate anything having to do with remote peers, 257 since we don't have a straightforward way of doing it. It would require 258 adding an rsh command rather than just an rcp command to configuration, and 259 that just doesn't seem worth it right now. 260 261 @param config: Program configuration. 262 @param logfunc: Function to use for logging errors 263 264 @return: True if configuration is valid, False otherwise. 265 """ 266 valid = True 267 if config.stage is not None: 268 valid &= _checkDir(config.stage.targetDir, True, logfunc, "Stage target dir ") 269 if config.stage.localPeers is not None: 270 for peer in config.stage.localPeers: 271 valid &= _checkDir(peer.collectDir, False, logfunc, "Local peer collect dir ") 272 return valid
273 274 275 ############################ 276 # _validateStore() function 277 ############################ 278
279 -def _validateStore(config, logfunc):
280 """ 281 Execute runtime validations on store configuration. 282 283 The following validations are enforced: 284 285 - The source directory must exist and must be readable 286 - The backup device (path and SCSI device) must be valid 287 288 @param config: Program configuration. 289 @param logfunc: Function to use for logging errors 290 291 @return: True if configuration is valid, False otherwise. 292 """ 293 valid = True 294 if config.store is not None: 295 valid &= _checkDir(config.store.sourceDir, False, logfunc, "Store source directory") 296 try: 297 createWriter(config) 298 except ValueError: 299 logfunc("Backup device [%s] [%s] is not valid." % (config.store.devicePath, config.store.deviceScsiId)) 300 valid = False 301 return valid
302 303 304 ############################ 305 # _validatePurge() function 306 ############################ 307
308 -def _validatePurge(config, logfunc):
309 """ 310 Execute runtime validations on purge configuration. 311 312 The following validations are enforced: 313 314 - Each purge directory must exist and must be writable 315 316 @param config: Program configuration. 317 @param logfunc: Function to use for logging errors 318 319 @return: True if configuration is valid, False otherwise. 320 """ 321 valid = True 322 if config.purge is not None: 323 if config.purge.purgeDirs is not None: 324 for purgeDir in config.purge.purgeDirs: 325 valid &= _checkDir(purgeDir.absolutePath, True, logfunc, "Purge directory") 326 return valid
327 328 329 ################################# 330 # _validateExtensions() function 331 ################################# 332
333 -def _validateExtensions(config, logfunc):
334 """ 335 Execute runtime validations on extensions configuration. 336 337 The following validations are enforced: 338 339 - Each indicated extension function must exist. 340 341 @param config: Program configuration. 342 @param logfunc: Function to use for logging errors 343 344 @return: True if configuration is valid, False otherwise. 345 """ 346 valid = True 347 if config.extensions is not None: 348 if config.extensions.actions is not None: 349 for action in config.extensions.actions: 350 try: 351 getFunctionReference(action.module, action.function) 352 except ImportError: 353 logfunc("Unable to find function [%s.%s]." % (action.module, action.function)) 354 valid = False 355 except ValueError: 356 logfunc("Function [%s.%s] is not callable." % (action.module, action.function)) 357 valid = False 358 return valid
359