1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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
47
48
49
50 import os
51 import logging
52
53
54 from CedarBackup2.util import getUidGid, getFunctionReference
55 from CedarBackup2.actions.util import createWriter
56
57
58
59
60
61
62 logger = logging.getLogger("CedarBackup2.log.actions.validate")
63
64
65
66
67
68
69
70
71
72
73
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
106 else:
107 logfunc = logger.error
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
124
125
126
127
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
164
165
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
186
187
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
219
220
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
246
247
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
278
279
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
307
308
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
332
333
360