CedarBackup3.actions.validate

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