CedarBackup2.actions.validate

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