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 """
40 Provides configuration-related objects.
41
42 Summary
43 =======
44
45 Cedar Backup stores all of its configuration in an XML document typically
46 called C{cback.conf}. The standard location for this document is in
47 C{/etc}, but users can specify a different location if they want to.
48
49 The C{Config} class is a Python object representation of a Cedar Backup XML
50 configuration file. The representation is two-way: XML data can be used to
51 create a C{Config} object, and then changes to the object can be propogated
52 back to disk. A C{Config} object can even be used to create a configuration
53 file from scratch programmatically.
54
55 The C{Config} class is intended to be the only Python-language interface to
56 Cedar Backup configuration on disk. Cedar Backup will use the class as its
57 internal representation of configuration, and applications external to Cedar
58 Backup itself (such as a hypothetical third-party configuration tool written
59 in Python or a third party extension module) should also use the class when
60 they need to read and write configuration files.
61
62 Backwards Compatibility
63 =======================
64
65 The configuration file format has changed between Cedar Backup 1.x and Cedar
66 Backup 2.x. Any Cedar Backup 1.x configuration file is also a valid Cedar
67 Backup 2.x configuration file. However, it doesn't work to go the other
68 direction, as the 2.x configuration files may contain additional fields that
69 are not accepted by older versions of the software.
70
71 XML Configuration Structure
72 ===========================
73
74 A C{Config} object can either be created "empty", or can be created based on
75 XML input (either in the form of a string or read in from a file on disk).
76 Generally speaking, the XML input I{must} result in a C{Config} object which
77 passes the validations laid out below in the I{Validation} section.
78
79 An XML configuration file is composed of seven sections:
80
81 - I{reference}: specifies reference information about the file (author, revision, etc)
82 - I{extensions}: specifies mappings to Cedar Backup extensions (external code)
83 - I{options}: specifies global configuration options
84 - I{collect}: specifies configuration related to the collect action
85 - I{stage}: specifies configuration related to the stage action
86 - I{store}: specifies configuration related to the store action
87 - I{purge}: specifies configuration related to the purge action
88
89 Each section is represented by an class in this module, and then the overall
90 C{Config} class is a composition of the various other classes.
91
92 Any configuration section that is missing in the XML document (or has not
93 been filled into an "empty" document) will just be set to C{None} in the
94 object representation. The same goes for individual fields within each
95 configuration section. Keep in mind that the document might not be
96 completely valid if some sections or fields aren't filled in - but that
97 won't matter until validation takes place (see the I{Validation} section
98 below).
99
100 Unicode vs. String Data
101 =======================
102
103 By default, all string data that comes out of XML documents in Python is
104 unicode data (i.e. C{u"whatever"}). This is fine for many things, but when
105 it comes to filesystem paths, it can cause us some problems. We really want
106 strings to be encoded in the filesystem encoding rather than being unicode.
107 So, most elements in configuration which represent filesystem paths are
108 coverted to plain strings using L{util.encodePath}. The main exception is
109 the various C{absoluteExcludePath} and C{relativeExcludePath} lists. These
110 are I{not} converted, because they are generally only used for filtering,
111 not for filesystem operations.
112
113 Validation
114 ==========
115
116 There are two main levels of validation in the C{Config} class and its
117 children. The first is field-level validation. Field-level validation
118 comes into play when a given field in an object is assigned to or updated.
119 We use Python's C{property} functionality to enforce specific validations on
120 field values, and in some places we even use customized list classes to
121 enforce validations on list members. You should expect to catch a
122 C{ValueError} exception when making assignments to configuration class
123 fields.
124
125 The second level of validation is post-completion validation. Certain
126 validations don't make sense until a document is fully "complete". We don't
127 want these validations to apply all of the time, because it would make
128 building up a document from scratch a real pain. For instance, we might
129 have to do things in the right order to keep from throwing exceptions, etc.
130
131 All of these post-completion validations are encapsulated in the
132 L{Config.validate} method. This method can be called at any time by a
133 client, and will always be called immediately after creating a C{Config}
134 object from XML data and before exporting a C{Config} object to XML. This
135 way, we get decent ease-of-use but we also don't accept or emit invalid
136 configuration files.
137
138 The L{Config.validate} implementation actually takes two passes to
139 completely validate a configuration document. The first pass at validation
140 is to ensure that the proper sections are filled into the document. There
141 are default requirements, but the caller has the opportunity to override
142 these defaults.
143
144 The second pass at validation ensures that any filled-in section contains
145 valid data. Any section which is not set to C{None} is validated according
146 to the rules for that section (see below).
147
148 I{Reference Validations}
149
150 No validations.
151
152 I{Extensions Validations}
153
154 The list of actions may be either C{None} or an empty list C{[]} if desired.
155 Each extended action must include a name, a module and a function. Then, an
156 extended action must include either an index or dependency information.
157 Which one is required depends on which order mode is configured.
158
159 I{Options Validations}
160
161 All fields must be filled in. The rcp command is used as a default value
162 for all remote peers in the staging section. Remote peers can also rely on
163 the backup user as the default remote user name if they choose.
164
165 I{Collect Validations}
166
167 The target directory must be filled in. The collect mode, archive mode and
168 ignore file are all optional. The list of absolute paths to exclude and
169 patterns to exclude may be either C{None} or an empty list C{[]} if desired.
170
171 Each collect directory entry must contain an absolute path to collect, and
172 then must either be able to take collect mode, archive mode and ignore file
173 configuration from the parent C{CollectConfig} object, or must set each
174 value on its own. The list of absolute paths to exclude, relative paths to
175 exclude and patterns to exclude may be either C{None} or an empty list C{[]}
176 if desired. Any list of absolute paths to exclude or patterns to exclude
177 will be combined with the same list in the C{CollectConfig} object to make
178 the complete list for a given directory.
179
180 I{Stage Validations}
181
182 The target directory must be filled in. There must be at least one peer
183 (remote or local) between the two lists of peers. A list with no entries
184 can be either C{None} or an empty list C{[]} if desired.
185
186 Local peers must be completely filled in, including both name and collect
187 directory. Remote peers must also fill in the name and collect directory,
188 but can leave the remote user and rcp command unset. In this case, the
189 remote user is assumed to match the backup user from the options section and
190 rcp command is taken directly from the options section.
191
192 I{Store Validations}
193
194 The device type and drive speed are optional, and all other values are
195 required (missing booleans will be set to defaults, which is OK).
196
197 The image writer functionality in the C{writer} module is supposed to be
198 able to handle a device speed of C{None}. Any caller which needs a "real"
199 (non-C{None}) value for the device type can use C{DEFAULT_DEVICE_TYPE},
200 which is guaranteed to be sensible.
201
202 I{Purge Validations}
203
204 The list of purge directories may be either C{None} or an empty list C{[]}
205 if desired. All purge directories must contain a path and a retain days
206 value.
207
208 @sort: ActionDependencies, ActionHook, PreActionHook, PostActionHook,
209 ExtendedAction, CommandOverride, CollectFile, CollectDir, PurgeDir, LocalPeer,
210 RemotePeer, ReferenceConfig, ExtensionsConfig, OptionsConfig,
211 CollectConfig, StageConfig, StoreConfig, PurgeConfig, Config,
212 DEFAULT_DEVICE_TYPE, DEFAULT_MEDIA_TYPE,
213 VALID_DEVICE_TYPES, VALID_MEDIA_TYPES,
214 VALID_COLLECT_MODES, VALID_ARCHIVE_MODES,
215 VALID_ORDER_MODES
216
217 @var DEFAULT_DEVICE_TYPE: The default device type.
218 @var DEFAULT_MEDIA_TYPE: The default media type.
219 @var VALID_DEVICE_TYPES: List of valid device types.
220 @var VALID_MEDIA_TYPES: List of valid media types.
221 @var VALID_COLLECT_MODES: List of valid collect modes.
222 @var VALID_COMPRESS_MODES: List of valid compress modes.
223 @var VALID_ARCHIVE_MODES: List of valid archive modes.
224 @var VALID_ORDER_MODES: List of valid extension order modes.
225
226 @author: Kenneth J. Pronovici <pronovic@ieee.org>
227 """
228
229
230
231
232
233
234 import os
235 import re
236 import logging
237
238
239 from CedarBackup2.writers.util import validateScsiId, validateDriveSpeed
240 from CedarBackup2.util import UnorderedList, AbsolutePathList, ObjectTypeList
241 from CedarBackup2.util import RegexMatchList, RegexList, encodePath
242 from CedarBackup2.xmlutil import isElement, readChildren, readFirstChild
243 from CedarBackup2.xmlutil import readStringList, readString, readInteger, readBoolean
244 from CedarBackup2.xmlutil import addContainerNode, addStringNode, addIntegerNode, addBooleanNode
245 from CedarBackup2.xmlutil import createInputDom, createOutputDom, serializeDom
246
247
248
249
250
251
252 logger = logging.getLogger("CedarBackup2.log.config")
253
254 DEFAULT_DEVICE_TYPE = "cdwriter"
255 DEFAULT_MEDIA_TYPE = "cdrw-74"
256
257 VALID_DEVICE_TYPES = [ "cdwriter", "dvdwriter", ]
258 VALID_CD_MEDIA_TYPES = [ "cdr-74", "cdrw-74", "cdr-80", "cdrw-80", ]
259 VALID_DVD_MEDIA_TYPES = [ "dvd+r", "dvd+rw", ]
260 VALID_MEDIA_TYPES = VALID_CD_MEDIA_TYPES + VALID_DVD_MEDIA_TYPES
261 VALID_COLLECT_MODES = [ "daily", "weekly", "incr", ]
262 VALID_ARCHIVE_MODES = [ "tar", "targz", "tarbz2", ]
263 VALID_COMPRESS_MODES = [ "none", "gzip", "bzip2", ]
264 VALID_ORDER_MODES = [ "index", "dependency", ]
265 VALID_BLANK_MODES = [ "daily", "weekly", ]
266
267 REWRITABLE_MEDIA_TYPES = [ "cdrw-74", "cdrw-80", "dvd+rw", ]
268
269 ACTION_NAME_REGEX = r"^[a-z0-9]*$"
270
271
272
273
274
275
277
278 """
279 Class representing dependencies associated with an extended action.
280
281 Execution ordering for extended actions is done in one of two ways: either by using
282 index values (lower index gets run first) or by having the extended action specify
283 dependencies in terms of other named actions. This class encapsulates the dependency
284 information for an extended action.
285
286 As with all of the other classes that represent configuration sections, all
287 of these values are optional. It is up to some higher-level construct to
288 decide whether everything they need is filled in. Some validation is done
289 on non-C{None} assignments through the use of the Python C{property()}
290 construct.
291
292 The following restrictions exist on data in this class:
293
294 - Any action name must be a non-empty string matching C{ACTION_NAME_REGEX}
295
296 @sort: __init__, __repr__, __str__, __cmp__, action, command, before, after
297 """
298
299 - def __init__(self, beforeList=None, afterList=None):
300 """
301 Constructor for the C{ActionDependencies} class.
302
303 @param beforeList: List of named actions that this action must be run before
304 @param afterList: List of named actions that this action must be run after
305
306 @raise ValueError: If one of the values is invalid.
307 """
308 self._beforeList = None
309 self._afterList = None
310 self.beforeList = beforeList
311 self.afterList = afterList
312
314 """
315 Official string representation for class instance.
316 """
317 return "ActionDependencies(%s, %s)" % (self.beforeList, self.afterList)
318
320 """
321 Informal string representation for class instance.
322 """
323 return self.__repr__()
324
326 """
327 Definition of equals operator for this class.
328 @param other: Other object to compare to.
329 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
330 """
331 if other is None:
332 return 1
333 if self._beforeList != other._beforeList:
334 if self._beforeList < other._beforeList:
335 return -1
336 else:
337 return 1
338 if self._afterList != other._afterList:
339 if self._afterList < other._afterList:
340 return -1
341 else:
342 return 1
343 return 0
344
346 """
347 Property target used to set the "run before" list.
348 Either the value must be C{None} or each element must be a string matching ACTION_NAME_REGEX.
349 @raise ValueError: If the value does not match the regular expression.
350 """
351 if value is None:
352 self._beforeList = None
353 else:
354 try:
355 saved = self._beforeList
356 self._beforeList = RegexMatchList(ACTION_NAME_REGEX, emptyAllowed=False, prefix="Action name")
357 self._beforeList.extend(value)
358 except Exception, e:
359 self._beforeList = saved
360 raise e
361
363 """
364 Property target used to get the "run before" list.
365 """
366 return self._beforeList
367
369 """
370 Property target used to set the "run after" list.
371 Either the value must be C{None} or each element must be a string matching ACTION_NAME_REGEX.
372 @raise ValueError: If the value does not match the regular expression.
373 """
374 if value is None:
375 self._afterList = None
376 else:
377 try:
378 saved = self._afterList
379 self._afterList = RegexMatchList(ACTION_NAME_REGEX, emptyAllowed=False, prefix="Action name")
380 self._afterList.extend(value)
381 except Exception, e:
382 self._afterList = saved
383 raise e
384
386 """
387 Property target used to get the "run after" list.
388 """
389 return self._afterList
390
391 beforeList = property(_getBeforeList, _setBeforeList, None, "List of named actions that this action must be run before.")
392 afterList = property(_getAfterList, _setAfterList, None, "List of named actions that this action must be run after.")
393
394
395
396
397
398
400
401 """
402 Class representing a hook associated with an action.
403
404 A hook associated with an action is a shell command to be executed either
405 before or after a named action is executed.
406
407 As with all of the other classes that represent configuration sections, all
408 of these values are optional. It is up to some higher-level construct to
409 decide whether everything they need is filled in. Some validation is done
410 on non-C{None} assignments through the use of the Python C{property()}
411 construct.
412
413 The following restrictions exist on data in this class:
414
415 - The action name must be a non-empty string matching C{ACTION_NAME_REGEX}
416 - The shell command must be a non-empty string.
417
418 The internal C{before} and C{after} instance variables are always set to
419 False in this parent class.
420
421 @sort: __init__, __repr__, __str__, __cmp__, action, command, before, after
422 """
423
424 - def __init__(self, action=None, command=None):
425 """
426 Constructor for the C{ActionHook} class.
427
428 @param action: Action this hook is associated with
429 @param command: Shell command to execute
430
431 @raise ValueError: If one of the values is invalid.
432 """
433 self._action = None
434 self._command = None
435 self._before = False
436 self._after = False
437 self.action = action
438 self.command = command
439
441 """
442 Official string representation for class instance.
443 """
444 return "ActionHook(%s, %s, %s, %s)" % (self.action, self.command, self.before, self.after)
445
447 """
448 Informal string representation for class instance.
449 """
450 return self.__repr__()
451
453 """
454 Definition of equals operator for this class.
455 @param other: Other object to compare to.
456 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
457 """
458 if other is None:
459 return 1
460 if self._action != other._action:
461 if self._action < other._action:
462 return -1
463 else:
464 return 1
465 if self._command != other._command:
466 if self._command < other._command:
467 return -1
468 else:
469 return 1
470 if self._before != other._before:
471 if self._before < other._before:
472 return -1
473 else:
474 return 1
475 if self._after != other._after:
476 if self._after < other._after:
477 return -1
478 else:
479 return 1
480 return 0
481
483 """
484 Property target used to set the action name.
485 The value must be a non-empty string if it is not C{None}.
486 It must also consist only of lower-case letters and digits.
487 @raise ValueError: If the value is an empty string.
488 """
489 pattern = re.compile(ACTION_NAME_REGEX)
490 if value is not None:
491 if len(value) < 1:
492 raise ValueError("The action name must be a non-empty string.")
493 if not pattern.search(value):
494 raise ValueError("The action name must consist of only lower-case letters and digits.")
495 self._action = value
496
498 """
499 Property target used to get the action name.
500 """
501 return self._action
502
504 """
505 Property target used to set the command.
506 The value must be a non-empty string if it is not C{None}.
507 @raise ValueError: If the value is an empty string.
508 """
509 if value is not None:
510 if len(value) < 1:
511 raise ValueError("The command must be a non-empty string.")
512 self._command = value
513
515 """
516 Property target used to get the command.
517 """
518 return self._command
519
521 """
522 Property target used to get the before flag.
523 """
524 return self._before
525
527 """
528 Property target used to get the after flag.
529 """
530 return self._after
531
532 action = property(_getAction, _setAction, None, "Action this hook is associated with.")
533 command = property(_getCommand, _setCommand, None, "Shell command to execute.")
534 before = property(_getBefore, None, None, "Indicates whether command should be executed before action.")
535 after = property(_getAfter, None, None, "Indicates whether command should be executed after action.")
536
538
539 """
540 Class representing a pre-action hook associated with an action.
541
542 A hook associated with an action is a shell command to be executed either
543 before or after a named action is executed. In this case, a pre-action hook
544 is executed before the named action.
545
546 As with all of the other classes that represent configuration sections, all
547 of these values are optional. It is up to some higher-level construct to
548 decide whether everything they need is filled in. Some validation is done
549 on non-C{None} assignments through the use of the Python C{property()}
550 construct.
551
552 The following restrictions exist on data in this class:
553
554 - The action name must be a non-empty string consisting of lower-case letters and digits.
555 - The shell command must be a non-empty string.
556
557 The internal C{before} instance variable is always set to True in this
558 class.
559
560 @sort: __init__, __repr__, __str__, __cmp__, action, command, before, after
561 """
562
563 - def __init__(self, action=None, command=None):
564 """
565 Constructor for the C{PreActionHook} class.
566
567 @param action: Action this hook is associated with
568 @param command: Shell command to execute
569
570 @raise ValueError: If one of the values is invalid.
571 """
572 ActionHook.__init__(self, action, command)
573 self._before = True
574
576 """
577 Official string representation for class instance.
578 """
579 return "PreActionHook(%s, %s, %s, %s)" % (self.action, self.command, self.before, self.after)
580
581 -class PostActionHook(ActionHook):
582
583 """
584 Class representing a pre-action hook associated with an action.
585
586 A hook associated with an action is a shell command to be executed either
587 before or after a named action is executed. In this case, a post-action hook
588 is executed after the named action.
589
590 As with all of the other classes that represent configuration sections, all
591 of these values are optional. It is up to some higher-level construct to
592 decide whether everything they need is filled in. Some validation is done
593 on non-C{None} assignments through the use of the Python C{property()}
594 construct.
595
596 The following restrictions exist on data in this class:
597
598 - The action name must be a non-empty string consisting of lower-case letters and digits.
599 - The shell command must be a non-empty string.
600
601 The internal C{before} instance variable is always set to True in this
602 class.
603
604 @sort: __init__, __repr__, __str__, __cmp__, action, command, before, after
605 """
606
607 - def __init__(self, action=None, command=None):
608 """
609 Constructor for the C{PostActionHook} class.
610
611 @param action: Action this hook is associated with
612 @param command: Shell command to execute
613
614 @raise ValueError: If one of the values is invalid.
615 """
616 ActionHook.__init__(self, action, command)
617 self._after = True
618
619 - def __repr__(self):
620 """
621 Official string representation for class instance.
622 """
623 return "PostActionHook(%s, %s, %s, %s)" % (self.action, self.command, self.before, self.after)
624
625
626
627
628
629
631
632 """
633 Class representing optimized store-action media blanking behavior.
634
635 As with all of the other classes that represent configuration sections, all
636 of these values are optional. It is up to some higher-level construct to
637 decide whether everything they need is filled in. Some validation is done
638 on non-C{None} assignments through the use of the Python C{property()}
639 construct.
640
641 The following restrictions exist on data in this class:
642
643 - The blanking mode must be a one of the values in L{VALID_BLANK_MODES}
644 - The blanking factor must be a positive floating point number
645
646 @sort: __init__, __repr__, __str__, __cmp__, blankMode, blankFactor
647 """
648
649 - def __init__(self, blankMode=None, blankFactor=None):
650 """
651 Constructor for the C{BlankBehavior} class.
652
653 @param blankMode: Blanking mode
654 @param blankFactor: Blanking factor
655
656 @raise ValueError: If one of the values is invalid.
657 """
658 self._blankMode = None
659 self._blankFactor = None
660 self.blankMode = blankMode
661 self.blankFactor = blankFactor
662
664 """
665 Official string representation for class instance.
666 """
667 return "BlankBehavior(%s, %s)" % (self.blankMode, self.blankFactor)
668
670 """
671 Informal string representation for class instance.
672 """
673 return self.__repr__()
674
676 """
677 Definition of equals operator for this class.
678 @param other: Other object to compare to.
679 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
680 """
681 if other is None:
682 return 1
683 if self._blankMode != other._blankMode:
684 if self._blankMode < other._blankMode:
685 return -1
686 else:
687 return 1
688 if self._blankFactor != other._blankFactor:
689 if self._blankFactor < other._blankFactor:
690 return -1
691 else:
692 return 1
693 return 0
694
696 """
697 Property target used to set the blanking mode.
698 The value must be one of L{VALID_BLANK_MODES}.
699 @raise ValueError: If the value is not valid.
700 """
701 if value is not None:
702 if value not in VALID_BLANK_MODES:
703 raise ValueError("Blanking mode must be one of %s." % VALID_BLANK_MODES)
704 self._blankMode = value
705
707 """
708 Property target used to get the blanking mode.
709 """
710 return self._blankMode
711
713 """
714 Property target used to set the blanking factor.
715 The value must be a non-empty string if it is not C{None}.
716 @raise ValueError: If the value is an empty string.
717 @raise ValueError: If the value is not a valid floating point number
718 @raise ValueError: If the value is less than zero
719 """
720 if value is not None:
721 if len(value) < 1:
722 raise ValueError("Blanking factor must be a non-empty string.")
723 floatValue = float(value)
724 if floatValue < 0.0:
725 raise ValueError("Blanking factor cannot be negative.")
726 self._blankFactor = value
727
729 """
730 Property target used to get the blanking factor.
731 """
732 return self._blankFactor
733
734 blankMode = property(_getBlankMode, _setBlankMode, None, "Blanking mode")
735 blankFactor = property(_getBlankFactor, _setBlankFactor, None, "Blanking factor")
736
737
738
739
740
741
743
744 """
745 Class representing an extended action.
746
747 As with all of the other classes that represent configuration sections, all
748 of these values are optional. It is up to some higher-level construct to
749 decide whether everything they need is filled in. Some validation is done
750 on non-C{None} assignments through the use of the Python C{property()}
751 construct.
752
753 Essentially, an extended action needs to allow the following to happen::
754
755 exec("from %s import %s" % (module, function))
756 exec("%s(action, configPath")" % function)
757
758 The following restrictions exist on data in this class:
759
760 - The action name must be a non-empty string consisting of lower-case letters and digits.
761 - The module must be a non-empty string and a valid Python identifier.
762 - The function must be an on-empty string and a valid Python identifier.
763 - If set, the index must be a positive integer.
764 - If set, the dependencies attribute must be an C{ActionDependencies} object.
765
766 @sort: __init__, __repr__, __str__, __cmp__, name, module, function, index, dependencies
767 """
768
769 - def __init__(self, name=None, module=None, function=None, index=None, dependencies=None):
770 """
771 Constructor for the C{ExtendedAction} class.
772
773 @param name: Name of the extended action
774 @param module: Name of the module containing the extended action function
775 @param function: Name of the extended action function
776 @param index: Index of action, used for execution ordering
777 @param dependencies: Dependencies for action, used for execution ordering
778
779 @raise ValueError: If one of the values is invalid.
780 """
781 self._name = None
782 self._module = None
783 self._function = None
784 self._index = None
785 self._dependencies = None
786 self.name = name
787 self.module = module
788 self.function = function
789 self.index = index
790 self.dependencies = dependencies
791
793 """
794 Official string representation for class instance.
795 """
796 return "ExtendedAction(%s, %s, %s, %s, %s)" % (self.name, self.module, self.function, self.index, self.dependencies)
797
799 """
800 Informal string representation for class instance.
801 """
802 return self.__repr__()
803
805 """
806 Definition of equals operator for this class.
807 @param other: Other object to compare to.
808 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
809 """
810 if other is None:
811 return 1
812 if self._name != other._name:
813 if self._name < other._name:
814 return -1
815 else:
816 return 1
817 if self._module != other._module:
818 if self._module < other._module:
819 return -1
820 else:
821 return 1
822 if self._function != other._function:
823 if self._function < other._function:
824 return -1
825 else:
826 return 1
827 if self._index != other._index:
828 if self._index < other._index:
829 return -1
830 else:
831 return 1
832 if self._dependencies != other._dependencies:
833 if self._dependencies < other._dependencies:
834 return -1
835 else:
836 return 1
837 return 0
838
840 """
841 Property target used to set the action name.
842 The value must be a non-empty string if it is not C{None}.
843 It must also consist only of lower-case letters and digits.
844 @raise ValueError: If the value is an empty string.
845 """
846 pattern = re.compile(ACTION_NAME_REGEX)
847 if value is not None:
848 if len(value) < 1:
849 raise ValueError("The action name must be a non-empty string.")
850 if not pattern.search(value):
851 raise ValueError("The action name must consist of only lower-case letters and digits.")
852 self._name = value
853
855 """
856 Property target used to get the action name.
857 """
858 return self._name
859
861 """
862 Property target used to set the module name.
863 The value must be a non-empty string if it is not C{None}.
864 It must also be a valid Python identifier.
865 @raise ValueError: If the value is an empty string.
866 """
867 pattern = re.compile(r"^([A-Za-z_][A-Za-z0-9_]*)(\.[A-Za-z_][A-Za-z0-9_]*)*$")
868 if value is not None:
869 if len(value) < 1:
870 raise ValueError("The module name must be a non-empty string.")
871 if not pattern.search(value):
872 raise ValueError("The module name must be a valid Python identifier.")
873 self._module = value
874
876 """
877 Property target used to get the module name.
878 """
879 return self._module
880
882 """
883 Property target used to set the function name.
884 The value must be a non-empty string if it is not C{None}.
885 It must also be a valid Python identifier.
886 @raise ValueError: If the value is an empty string.
887 """
888 pattern = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*$")
889 if value is not None:
890 if len(value) < 1:
891 raise ValueError("The function name must be a non-empty string.")
892 if not pattern.search(value):
893 raise ValueError("The function name must be a valid Python identifier.")
894 self._function = value
895
897 """
898 Property target used to get the function name.
899 """
900 return self._function
901
903 """
904 Property target used to set the action index.
905 The value must be an integer >= 0.
906 @raise ValueError: If the value is not valid.
907 """
908 if value is None:
909 self._index = None
910 else:
911 try:
912 value = int(value)
913 except TypeError:
914 raise ValueError("Action index value must be an integer >= 0.")
915 if value < 0:
916 raise ValueError("Action index value must be an integer >= 0.")
917 self._index = value
918
920 """
921 Property target used to get the action index.
922 """
923 return self._index
924
926 """
927 Property target used to set the action dependencies information.
928 If not C{None}, the value must be a C{ActionDependecies} object.
929 @raise ValueError: If the value is not a C{ActionDependencies} object.
930 """
931 if value is None:
932 self._dependencies = None
933 else:
934 if not isinstance(value, ActionDependencies):
935 raise ValueError("Value must be a C{ActionDependencies} object.")
936 self._dependencies = value
937
939 """
940 Property target used to get action dependencies information.
941 """
942 return self._dependencies
943
944 name = property(_getName, _setName, None, "Name of the extended action.")
945 module = property(_getModule, _setModule, None, "Name of the module containing the extended action function.")
946 function = property(_getFunction, _setFunction, None, "Name of the extended action function.")
947 index = property(_getIndex, _setIndex, None, "Index of action, used for execution ordering.")
948 dependencies = property(_getDependencies, _setDependencies, None, "Dependencies for action, used for execution ordering.")
949
950
951
952
953
954
956
957 """
958 Class representing a piece of Cedar Backup command override configuration.
959
960 As with all of the other classes that represent configuration sections, all
961 of these values are optional. It is up to some higher-level construct to
962 decide whether everything they need is filled in. Some validation is done
963 on non-C{None} assignments through the use of the Python C{property()}
964 construct.
965
966 The following restrictions exist on data in this class:
967
968 - The absolute path must be absolute
969
970 @note: Lists within this class are "unordered" for equality comparisons.
971
972 @sort: __init__, __repr__, __str__, __cmp__, command, absolutePath
973 """
974
975 - def __init__(self, command=None, absolutePath=None):
976 """
977 Constructor for the C{CommandOverride} class.
978
979 @param command: Name of command to be overridden.
980 @param absolutePath: Absolute path of the overrridden command.
981
982 @raise ValueError: If one of the values is invalid.
983 """
984 self._command = None
985 self._absolutePath = None
986 self.command = command
987 self.absolutePath = absolutePath
988
990 """
991 Official string representation for class instance.
992 """
993 return "CommandOverride(%s, %s)" % (self.command, self.absolutePath)
994
996 """
997 Informal string representation for class instance.
998 """
999 return self.__repr__()
1000
1002 """
1003 Definition of equals operator for this class.
1004 @param other: Other object to compare to.
1005 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
1006 """
1007 if other is None:
1008 return 1
1009 if self._command != other._command:
1010 if self._command < other.command:
1011 return -1
1012 else:
1013 return 1
1014 if self._absolutePath != other._absolutePath:
1015 if self._absolutePath < other.absolutePath:
1016 return -1
1017 else:
1018 return 1
1019 return 0
1020
1022 """
1023 Property target used to set the command.
1024 The value must be a non-empty string if it is not C{None}.
1025 @raise ValueError: If the value is an empty string.
1026 """
1027 if value is not None:
1028 if len(value) < 1:
1029 raise ValueError("The command must be a non-empty string.")
1030 self._command = value
1031
1033 """
1034 Property target used to get the command.
1035 """
1036 return self._command
1037
1039 """
1040 Property target used to set the absolute path.
1041 The value must be an absolute path if it is not C{None}.
1042 It does not have to exist on disk at the time of assignment.
1043 @raise ValueError: If the value is not an absolute path.
1044 @raise ValueError: If the value cannot be encoded properly.
1045 """
1046 if value is not None:
1047 if not os.path.isabs(value):
1048 raise ValueError("Not an absolute path: [%s]" % value)
1049 self._absolutePath = encodePath(value)
1050
1052 """
1053 Property target used to get the absolute path.
1054 """
1055 return self._absolutePath
1056
1057 command = property(_getCommand, _setCommand, None, doc="Name of command to be overridden.")
1058 absolutePath = property(_getAbsolutePath, _setAbsolutePath, None, doc="Absolute path of the overrridden command.")
1059
1060
1061
1062
1063
1064
1066
1067 """
1068 Class representing a Cedar Backup collect file.
1069
1070 As with all of the other classes that represent configuration sections, all
1071 of these values are optional. It is up to some higher-level construct to
1072 decide whether everything they need is filled in. Some validation is done
1073 on non-C{None} assignments through the use of the Python C{property()}
1074 construct.
1075
1076 The following restrictions exist on data in this class:
1077
1078 - Absolute paths must be absolute
1079 - The collect mode must be one of the values in L{VALID_COLLECT_MODES}.
1080 - The archive mode must be one of the values in L{VALID_ARCHIVE_MODES}.
1081
1082 @sort: __init__, __repr__, __str__, __cmp__, absolutePath, collectMode, archiveMode
1083 """
1084
1085 - def __init__(self, absolutePath=None, collectMode=None, archiveMode=None):
1086 """
1087 Constructor for the C{CollectFile} class.
1088
1089 @param absolutePath: Absolute path of the file to collect.
1090 @param collectMode: Overridden collect mode for this file.
1091 @param archiveMode: Overridden archive mode for this file.
1092
1093 @raise ValueError: If one of the values is invalid.
1094 """
1095 self._absolutePath = None
1096 self._collectMode = None
1097 self._archiveMode = None
1098 self.absolutePath = absolutePath
1099 self.collectMode = collectMode
1100 self.archiveMode = archiveMode
1101
1107
1109 """
1110 Informal string representation for class instance.
1111 """
1112 return self.__repr__()
1113
1115 """
1116 Definition of equals operator for this class.
1117 @param other: Other object to compare to.
1118 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
1119 """
1120 if other is None:
1121 return 1
1122 if self._absolutePath != other._absolutePath:
1123 if self._absolutePath < other.absolutePath:
1124 return -1
1125 else:
1126 return 1
1127 if self._collectMode != other._collectMode:
1128 if self._collectMode < other._collectMode:
1129 return -1
1130 else:
1131 return 1
1132 if self._archiveMode != other._archiveMode:
1133 if self._archiveMode < other._archiveMode:
1134 return -1
1135 else:
1136 return 1
1137 return 0
1138
1140 """
1141 Property target used to set the absolute path.
1142 The value must be an absolute path if it is not C{None}.
1143 It does not have to exist on disk at the time of assignment.
1144 @raise ValueError: If the value is not an absolute path.
1145 @raise ValueError: If the value cannot be encoded properly.
1146 """
1147 if value is not None:
1148 if not os.path.isabs(value):
1149 raise ValueError("Not an absolute path: [%s]" % value)
1150 self._absolutePath = encodePath(value)
1151
1153 """
1154 Property target used to get the absolute path.
1155 """
1156 return self._absolutePath
1157
1159 """
1160 Property target used to set the collect mode.
1161 If not C{None}, the mode must be one of the values in L{VALID_COLLECT_MODES}.
1162 @raise ValueError: If the value is not valid.
1163 """
1164 if value is not None:
1165 if value not in VALID_COLLECT_MODES:
1166 raise ValueError("Collect mode must be one of %s." % VALID_COLLECT_MODES)
1167 self._collectMode = value
1168
1170 """
1171 Property target used to get the collect mode.
1172 """
1173 return self._collectMode
1174
1176 """
1177 Property target used to set the archive mode.
1178 If not C{None}, the mode must be one of the values in L{VALID_ARCHIVE_MODES}.
1179 @raise ValueError: If the value is not valid.
1180 """
1181 if value is not None:
1182 if value not in VALID_ARCHIVE_MODES:
1183 raise ValueError("Archive mode must be one of %s." % VALID_ARCHIVE_MODES)
1184 self._archiveMode = value
1185
1187 """
1188 Property target used to get the archive mode.
1189 """
1190 return self._archiveMode
1191
1192 absolutePath = property(_getAbsolutePath, _setAbsolutePath, None, doc="Absolute path of the file to collect.")
1193 collectMode = property(_getCollectMode, _setCollectMode, None, doc="Overridden collect mode for this file.")
1194 archiveMode = property(_getArchiveMode, _setArchiveMode, None, doc="Overridden archive mode for this file.")
1195
1196
1197
1198
1199
1200
1202
1203 """
1204 Class representing a Cedar Backup collect directory.
1205
1206 As with all of the other classes that represent configuration sections, all
1207 of these values are optional. It is up to some higher-level construct to
1208 decide whether everything they need is filled in. Some validation is done
1209 on non-C{None} assignments through the use of the Python C{property()}
1210 construct.
1211
1212 The following restrictions exist on data in this class:
1213
1214 - Absolute paths must be absolute
1215 - The collect mode must be one of the values in L{VALID_COLLECT_MODES}.
1216 - The archive mode must be one of the values in L{VALID_ARCHIVE_MODES}.
1217 - The ignore file must be a non-empty string.
1218
1219 For the C{absoluteExcludePaths} list, validation is accomplished through the
1220 L{util.AbsolutePathList} list implementation that overrides common list
1221 methods and transparently does the absolute path validation for us.
1222
1223 @note: Lists within this class are "unordered" for equality comparisons.
1224
1225 @sort: __init__, __repr__, __str__, __cmp__, absolutePath, collectMode,
1226 archiveMode, ignoreFile, absoluteExcludePaths, relativeExcludePaths,
1227 excludePatterns
1228 """
1229
1230 - def __init__(self, absolutePath=None, collectMode=None, archiveMode=None, ignoreFile=None,
1231 absoluteExcludePaths=None, relativeExcludePaths=None, excludePatterns=None):
1232 """
1233 Constructor for the C{CollectDir} class.
1234
1235 @param absolutePath: Absolute path of the directory to collect.
1236 @param collectMode: Overridden collect mode for this directory.
1237 @param archiveMode: Overridden archive mode for this directory.
1238 @param ignoreFile: Overidden ignore file name for this directory.
1239 @param absoluteExcludePaths: List of absolute paths to exclude.
1240 @param relativeExcludePaths: List of relative paths to exclude.
1241 @param excludePatterns: List of regular expression patterns to exclude.
1242
1243 @raise ValueError: If one of the values is invalid.
1244 """
1245 self._absolutePath = None
1246 self._collectMode = None
1247 self._archiveMode = None
1248 self._ignoreFile = None
1249 self._absoluteExcludePaths = None
1250 self._relativeExcludePaths = None
1251 self._excludePatterns = None
1252 self.absolutePath = absolutePath
1253 self.collectMode = collectMode
1254 self.archiveMode = archiveMode
1255 self.ignoreFile = ignoreFile
1256 self.absoluteExcludePaths = absoluteExcludePaths
1257 self.relativeExcludePaths = relativeExcludePaths
1258 self.excludePatterns = excludePatterns
1259
1261 """
1262 Official string representation for class instance.
1263 """
1264 return "CollectDir(%s, %s, %s, %s, %s, %s, %s)" % (self.absolutePath, self.collectMode,
1265 self.archiveMode, self.ignoreFile,
1266 self.absoluteExcludePaths,
1267 self.relativeExcludePaths,
1268 self.excludePatterns)
1269
1271 """
1272 Informal string representation for class instance.
1273 """
1274 return self.__repr__()
1275
1277 """
1278 Definition of equals operator for this class.
1279 Lists within this class are "unordered" for equality comparisons.
1280 @param other: Other object to compare to.
1281 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
1282 """
1283 if other is None:
1284 return 1
1285 if self._absolutePath != other._absolutePath:
1286 if self._absolutePath < other.absolutePath:
1287 return -1
1288 else:
1289 return 1
1290 if self._collectMode != other._collectMode:
1291 if self._collectMode < other._collectMode:
1292 return -1
1293 else:
1294 return 1
1295 if self._archiveMode != other._archiveMode:
1296 if self._archiveMode < other._archiveMode:
1297 return -1
1298 else:
1299 return 1
1300 if self._ignoreFile != other._ignoreFile:
1301 if self._ignoreFile < other._ignoreFile:
1302 return -1
1303 else:
1304 return 1
1305 if self._absoluteExcludePaths != other._absoluteExcludePaths:
1306 if self._absoluteExcludePaths < other._absoluteExcludePaths:
1307 return -1
1308 else:
1309 return 1
1310 if self._relativeExcludePaths != other._relativeExcludePaths:
1311 if self._relativeExcludePaths < other._relativeExcludePaths:
1312 return -1
1313 else:
1314 return 1
1315 if self._excludePatterns != other._excludePatterns:
1316 if self._excludePatterns < other._excludePatterns:
1317 return -1
1318 else:
1319 return 1
1320 return 0
1321
1323 """
1324 Property target used to set the absolute path.
1325 The value must be an absolute path if it is not C{None}.
1326 It does not have to exist on disk at the time of assignment.
1327 @raise ValueError: If the value is not an absolute path.
1328 @raise ValueError: If the value cannot be encoded properly.
1329 """
1330 if value is not None:
1331 if not os.path.isabs(value):
1332 raise ValueError("Not an absolute path: [%s]" % value)
1333 self._absolutePath = encodePath(value)
1334
1336 """
1337 Property target used to get the absolute path.
1338 """
1339 return self._absolutePath
1340
1342 """
1343 Property target used to set the collect mode.
1344 If not C{None}, the mode must be one of the values in L{VALID_COLLECT_MODES}.
1345 @raise ValueError: If the value is not valid.
1346 """
1347 if value is not None:
1348 if value not in VALID_COLLECT_MODES:
1349 raise ValueError("Collect mode must be one of %s." % VALID_COLLECT_MODES)
1350 self._collectMode = value
1351
1353 """
1354 Property target used to get the collect mode.
1355 """
1356 return self._collectMode
1357
1359 """
1360 Property target used to set the archive mode.
1361 If not C{None}, the mode must be one of the values in L{VALID_ARCHIVE_MODES}.
1362 @raise ValueError: If the value is not valid.
1363 """
1364 if value is not None:
1365 if value not in VALID_ARCHIVE_MODES:
1366 raise ValueError("Archive mode must be one of %s." % VALID_ARCHIVE_MODES)
1367 self._archiveMode = value
1368
1370 """
1371 Property target used to get the archive mode.
1372 """
1373 return self._archiveMode
1374
1376 """
1377 Property target used to set the ignore file.
1378 The value must be a non-empty string if it is not C{None}.
1379 @raise ValueError: If the value is an empty string.
1380 """
1381 if value is not None:
1382 if len(value) < 1:
1383 raise ValueError("The ignore file must be a non-empty string.")
1384 self._ignoreFile = value
1385
1387 """
1388 Property target used to get the ignore file.
1389 """
1390 return self._ignoreFile
1391
1393 """
1394 Property target used to set the absolute exclude paths list.
1395 Either the value must be C{None} or each element must be an absolute path.
1396 Elements do not have to exist on disk at the time of assignment.
1397 @raise ValueError: If the value is not an absolute path.
1398 """
1399 if value is None:
1400 self._absoluteExcludePaths = None
1401 else:
1402 try:
1403 saved = self._absoluteExcludePaths
1404 self._absoluteExcludePaths = AbsolutePathList()
1405 self._absoluteExcludePaths.extend(value)
1406 except Exception, e:
1407 self._absoluteExcludePaths = saved
1408 raise e
1409
1411 """
1412 Property target used to get the absolute exclude paths list.
1413 """
1414 return self._absoluteExcludePaths
1415
1417 """
1418 Property target used to set the relative exclude paths list.
1419 Elements do not have to exist on disk at the time of assignment.
1420 """
1421 if value is None:
1422 self._relativeExcludePaths = None
1423 else:
1424 try:
1425 saved = self._relativeExcludePaths
1426 self._relativeExcludePaths = UnorderedList()
1427 self._relativeExcludePaths.extend(value)
1428 except Exception, e:
1429 self._relativeExcludePaths = saved
1430 raise e
1431
1433 """
1434 Property target used to get the relative exclude paths list.
1435 """
1436 return self._relativeExcludePaths
1437
1439 """
1440 Property target used to set the exclude patterns list.
1441 """
1442 if value is None:
1443 self._excludePatterns = None
1444 else:
1445 try:
1446 saved = self._excludePatterns
1447 self._excludePatterns = RegexList()
1448 self._excludePatterns.extend(value)
1449 except Exception, e:
1450 self._excludePatterns = saved
1451 raise e
1452
1454 """
1455 Property target used to get the exclude patterns list.
1456 """
1457 return self._excludePatterns
1458
1459 absolutePath = property(_getAbsolutePath, _setAbsolutePath, None, doc="Absolute path of the directory to collect.")
1460 collectMode = property(_getCollectMode, _setCollectMode, None, doc="Overridden collect mode for this directory.")
1461 archiveMode = property(_getArchiveMode, _setArchiveMode, None, doc="Overridden archive mode for this directory.")
1462 ignoreFile = property(_getIgnoreFile, _setIgnoreFile, None, doc="Overridden ignore file name for this directory.")
1463 absoluteExcludePaths = property(_getAbsoluteExcludePaths, _setAbsoluteExcludePaths, None, "List of absolute paths to exclude.")
1464 relativeExcludePaths = property(_getRelativeExcludePaths, _setRelativeExcludePaths, None, "List of relative paths to exclude.")
1465 excludePatterns = property(_getExcludePatterns, _setExcludePatterns, None, "List of regular expression patterns to exclude.")
1466
1467
1468
1469
1470
1471
1473
1474 """
1475 Class representing a Cedar Backup purge directory.
1476
1477 As with all of the other classes that represent configuration sections, all
1478 of these values are optional. It is up to some higher-level construct to
1479 decide whether everything they need is filled in. Some validation is done
1480 on non-C{None} assignments through the use of the Python C{property()}
1481 construct.
1482
1483 The following restrictions exist on data in this class:
1484
1485 - The absolute path must be an absolute path
1486 - The retain days value must be an integer >= 0.
1487
1488 @sort: __init__, __repr__, __str__, __cmp__, absolutePath, retainDays
1489 """
1490
1491 - def __init__(self, absolutePath=None, retainDays=None):
1492 """
1493 Constructor for the C{PurgeDir} class.
1494
1495 @param absolutePath: Absolute path of the directory to be purged.
1496 @param retainDays: Number of days content within directory should be retained.
1497
1498 @raise ValueError: If one of the values is invalid.
1499 """
1500 self._absolutePath = None
1501 self._retainDays = None
1502 self.absolutePath = absolutePath
1503 self.retainDays = retainDays
1504
1506 """
1507 Official string representation for class instance.
1508 """
1509 return "PurgeDir(%s, %s)" % (self.absolutePath, self.retainDays)
1510
1512 """
1513 Informal string representation for class instance.
1514 """
1515 return self.__repr__()
1516
1518 """
1519 Definition of equals operator for this class.
1520 @param other: Other object to compare to.
1521 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
1522 """
1523 if other is None:
1524 return 1
1525 if self._absolutePath != other._absolutePath:
1526 if self._absolutePath < other._absolutePath:
1527 return -1
1528 else:
1529 return 1
1530 if self._retainDays != other._retainDays:
1531 if self._retainDays < other._retainDays:
1532 return -1
1533 else:
1534 return 1
1535 return 0
1536
1538 """
1539 Property target used to set the absolute path.
1540 The value must be an absolute path if it is not C{None}.
1541 It does not have to exist on disk at the time of assignment.
1542 @raise ValueError: If the value is not an absolute path.
1543 @raise ValueError: If the value cannot be encoded properly.
1544 """
1545 if value is not None:
1546 if not os.path.isabs(value):
1547 raise ValueError("Absolute path must, er, be an absolute path.")
1548 self._absolutePath = encodePath(value)
1549
1551 """
1552 Property target used to get the absolute path.
1553 """
1554 return self._absolutePath
1555
1557 """
1558 Property target used to set the retain days value.
1559 The value must be an integer >= 0.
1560 @raise ValueError: If the value is not valid.
1561 """
1562 if value is None:
1563 self._retainDays = None
1564 else:
1565 try:
1566 value = int(value)
1567 except TypeError:
1568 raise ValueError("Retain days value must be an integer >= 0.")
1569 if value < 0:
1570 raise ValueError("Retain days value must be an integer >= 0.")
1571 self._retainDays = value
1572
1574 """
1575 Property target used to get the absolute path.
1576 """
1577 return self._retainDays
1578
1579 absolutePath = property(_getAbsolutePath, _setAbsolutePath, None, "Absolute path of directory to purge.")
1580 retainDays = property(_getRetainDays, _setRetainDays, None, "Number of days content within directory should be retained.")
1581
1582
1583
1584
1585
1586
1588
1589 """
1590 Class representing a Cedar Backup peer.
1591
1592 As with all of the other classes that represent configuration sections, all
1593 of these values are optional. It is up to some higher-level construct to
1594 decide whether everything they need is filled in. Some validation is done
1595 on non-C{None} assignments through the use of the Python C{property()}
1596 construct.
1597
1598 The following restrictions exist on data in this class:
1599
1600 - The peer name must be a non-empty string.
1601 - The collect directory must be an absolute path.
1602
1603 @sort: __init__, __repr__, __str__, __cmp__, name, collectDir
1604 """
1605
1606 - def __init__(self, name=None, collectDir=None):
1607 """
1608 Constructor for the C{LocalPeer} class.
1609
1610 @param name: Name of the peer, typically a valid hostname.
1611 @param collectDir: Collect directory to stage files from on peer.
1612
1613 @raise ValueError: If one of the values is invalid.
1614 """
1615 self._name = None
1616 self._collectDir = None
1617 self.name = name
1618 self.collectDir = collectDir
1619
1621 """
1622 Official string representation for class instance.
1623 """
1624 return "LocalPeer(%s, %s)" % (self.name, self.collectDir)
1625
1627 """
1628 Informal string representation for class instance.
1629 """
1630 return self.__repr__()
1631
1633 """
1634 Definition of equals operator for this class.
1635 @param other: Other object to compare to.
1636 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
1637 """
1638 if other is None:
1639 return 1
1640 if self._name != other._name:
1641 if self._name < other._name:
1642 return -1
1643 else:
1644 return 1
1645 if self._collectDir != other._collectDir:
1646 if self._collectDir < other._collectDir:
1647 return -1
1648 else:
1649 return 1
1650 return 0
1651
1653 """
1654 Property target used to set the peer name.
1655 The value must be a non-empty string if it is not C{None}.
1656 @raise ValueError: If the value is an empty string.
1657 """
1658 if value is not None:
1659 if len(value) < 1:
1660 raise ValueError("The peer name must be a non-empty string.")
1661 self._name = value
1662
1664 """
1665 Property target used to get the peer name.
1666 """
1667 return self._name
1668
1670 """
1671 Property target used to set the collect directory.
1672 The value must be an absolute path if it is not C{None}.
1673 It does not have to exist on disk at the time of assignment.
1674 @raise ValueError: If the value is not an absolute path.
1675 @raise ValueError: If the value cannot be encoded properly.
1676 """
1677 if value is not None:
1678 if not os.path.isabs(value):
1679 raise ValueError("Collect directory must be an absolute path.")
1680 self._collectDir = encodePath(value)
1681
1683 """
1684 Property target used to get the collect directory.
1685 """
1686 return self._collectDir
1687
1688 name = property(_getName, _setName, None, "Name of the peer, typically a valid hostname.")
1689 collectDir = property(_getCollectDir, _setCollectDir, None, "Collect directory to stage files from on peer.")
1690
1691
1692
1693
1694
1695
1697
1698 """
1699 Class representing a Cedar Backup peer.
1700
1701 As with all of the other classes that represent configuration sections, all
1702 of these values are optional. It is up to some higher-level construct to
1703 decide whether everything they need is filled in. Some validation is done
1704 on non-C{None} assignments through the use of the Python C{property()}
1705 construct.
1706
1707 The following restrictions exist on data in this class:
1708
1709 - The peer name must be a non-empty string.
1710 - The collect directory must be an absolute path.
1711 - The remote user must be a non-empty string.
1712 - The rcp command must be a non-empty string.
1713
1714 @sort: __init__, __repr__, __str__, __cmp__, name, collectDir, remoteUser, rcpCommand
1715 """
1716
1717 - def __init__(self, name=None, collectDir=None, remoteUser=None, rcpCommand=None):
1718 """
1719 Constructor for the C{RemotePeer} class.
1720
1721 @param name: Name of the peer, must be a valid hostname.
1722 @param collectDir: Collect directory to stage files from on peer.
1723 @param remoteUser: Name of backup user on remote peer.
1724 @param rcpCommand: Overridden rcp-compatible copy command for peer.
1725
1726 @raise ValueError: If one of the values is invalid.
1727 """
1728 self._name = None
1729 self._collectDir = None
1730 self._remoteUser = None
1731 self._rcpCommand = None
1732 self.name = name
1733 self.collectDir = collectDir
1734 self.remoteUser = remoteUser
1735 self.rcpCommand = rcpCommand
1736
1738 """
1739 Official string representation for class instance.
1740 """
1741 return "RemotePeer(%s, %s, %s, %s)" % (self.name, self.collectDir, self.remoteUser, self.rcpCommand)
1742
1744 """
1745 Informal string representation for class instance.
1746 """
1747 return self.__repr__()
1748
1750 """
1751 Definition of equals operator for this class.
1752 @param other: Other object to compare to.
1753 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
1754 """
1755 if other is None:
1756 return 1
1757 if self._name != other._name:
1758 if self._name < other._name:
1759 return -1
1760 else:
1761 return 1
1762 if self._collectDir != other._collectDir:
1763 if self._collectDir < other._collectDir:
1764 return -1
1765 else:
1766 return 1
1767 if self._remoteUser != other._remoteUser:
1768 if self._remoteUser < other._remoteUser:
1769 return -1
1770 else:
1771 return 1
1772 if self._rcpCommand != other._rcpCommand:
1773 if self._rcpCommand < other._rcpCommand:
1774 return -1
1775 else:
1776 return 1
1777 return 0
1778
1780 """
1781 Property target used to set the peer name.
1782 The value must be a non-empty string if it is not C{None}.
1783 @raise ValueError: If the value is an empty string.
1784 """
1785 if value is not None:
1786 if len(value) < 1:
1787 raise ValueError("The peer name must be a non-empty string.")
1788 self._name = value
1789
1791 """
1792 Property target used to get the peer name.
1793 """
1794 return self._name
1795
1797 """
1798 Property target used to set the collect directory.
1799 The value must be an absolute path if it is not C{None}.
1800 It does not have to exist on disk at the time of assignment.
1801 @raise ValueError: If the value is not an absolute path.
1802 @raise ValueError: If the value cannot be encoded properly.
1803 """
1804 if value is not None:
1805 if not os.path.isabs(value):
1806 raise ValueError("Collect directory must be an absolute path.")
1807 self._collectDir = encodePath(value)
1808
1810 """
1811 Property target used to get the collect directory.
1812 """
1813 return self._collectDir
1814
1816 """
1817 Property target used to set the remote user.
1818 The value must be a non-empty string if it is not C{None}.
1819 @raise ValueError: If the value is an empty string.
1820 """
1821 if value is not None:
1822 if len(value) < 1:
1823 raise ValueError("The remote user must be a non-empty string.")
1824 self._remoteUser = value
1825
1827 """
1828 Property target used to get the remote user.
1829 """
1830 return self._remoteUser
1831
1833 """
1834 Property target used to set the rcp command.
1835 The value must be a non-empty string if it is not C{None}.
1836 @raise ValueError: If the value is an empty string.
1837 """
1838 if value is not None:
1839 if len(value) < 1:
1840 raise ValueError("The remote user must be a non-empty string.")
1841 self._rcpCommand = value
1842
1844 """
1845 Property target used to get the rcp command.
1846 """
1847 return self._rcpCommand
1848
1849 name = property(_getName, _setName, None, "Name of the peer, must be a valid hostname.")
1850 collectDir = property(_getCollectDir, _setCollectDir, None, "Collect directory to stage files from on peer.")
1851 remoteUser = property(_getRemoteUser, _setRemoteUser, None, "Name of backup user on remote peer.")
1852 rcpCommand = property(_getRcpCommand, _setRcpCommand, None, "Overridden rcp-compatible copy command for peer.")
1853
1854
1855
1856
1857
1858
1860
1861 """
1862 Class representing a Cedar Backup reference configuration.
1863
1864 The reference information is just used for saving off metadata about
1865 configuration and exists mostly for backwards-compatibility with Cedar
1866 Backup 1.x.
1867
1868 As with all of the other classes that represent configuration sections, all
1869 of these values are optional. It is up to some higher-level construct to
1870 decide whether everything they need is filled in. We don't do any
1871 validation on the contents of any of the fields, although we generally
1872 expect them to be strings.
1873
1874 @sort: __init__, __repr__, __str__, __cmp__, author, revision, description, generator
1875 """
1876
1877 - def __init__(self, author=None, revision=None, description=None, generator=None):
1878 """
1879 Constructor for the C{ReferenceConfig} class.
1880
1881 @param author: Author of the configuration file.
1882 @param revision: Revision of the configuration file.
1883 @param description: Description of the configuration file.
1884 @param generator: Tool that generated the configuration file.
1885 """
1886 self._author = None
1887 self._revision = None
1888 self._description = None
1889 self._generator = None
1890 self.author = author
1891 self.revision = revision
1892 self.description = description
1893 self.generator = generator
1894
1896 """
1897 Official string representation for class instance.
1898 """
1899 return "ReferenceConfig(%s, %s, %s, %s)" % (self.author, self.revision, self.description, self.generator)
1900
1902 """
1903 Informal string representation for class instance.
1904 """
1905 return self.__repr__()
1906
1908 """
1909 Definition of equals operator for this class.
1910 @param other: Other object to compare to.
1911 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
1912 """
1913 if other is None:
1914 return 1
1915 if self._author != other._author:
1916 if self._author < other._author:
1917 return -1
1918 else:
1919 return 1
1920 if self._revision != other._revision:
1921 if self._revision < other._revision:
1922 return -1
1923 else:
1924 return 1
1925 if self._description != other._description:
1926 if self._description < other._description:
1927 return -1
1928 else:
1929 return 1
1930 if self._generator != other._generator:
1931 if self._generator < other._generator:
1932 return -1
1933 else:
1934 return 1
1935 return 0
1936
1938 """
1939 Property target used to set the author value.
1940 No validations.
1941 """
1942 self._author = value
1943
1945 """
1946 Property target used to get the author value.
1947 """
1948 return self._author
1949
1951 """
1952 Property target used to set the revision value.
1953 No validations.
1954 """
1955 self._revision = value
1956
1958 """
1959 Property target used to get the revision value.
1960 """
1961 return self._revision
1962
1964 """
1965 Property target used to set the description value.
1966 No validations.
1967 """
1968 self._description = value
1969
1971 """
1972 Property target used to get the description value.
1973 """
1974 return self._description
1975
1977 """
1978 Property target used to set the generator value.
1979 No validations.
1980 """
1981 self._generator = value
1982
1984 """
1985 Property target used to get the generator value.
1986 """
1987 return self._generator
1988
1989 author = property(_getAuthor, _setAuthor, None, "Author of the configuration file.")
1990 revision = property(_getRevision, _setRevision, None, "Revision of the configuration file.")
1991 description = property(_getDescription, _setDescription, None, "Description of the configuration file.")
1992 generator = property(_getGenerator, _setGenerator, None, "Tool that generated the configuration file.")
1993
1994
1995
1996
1997
1998
2000
2001 """
2002 Class representing Cedar Backup extensions configuration.
2003
2004 Extensions configuration is used to specify "extended actions" implemented
2005 by code external to Cedar Backup. For instance, a hypothetical third party
2006 might write extension code to collect database repository data. If they
2007 write a properly-formatted extension function, they can use the extension
2008 configuration to map a command-line Cedar Backup action (i.e. "database")
2009 to their function.
2010
2011 As with all of the other classes that represent configuration sections, all
2012 of these values are optional. It is up to some higher-level construct to
2013 decide whether everything they need is filled in. Some validation is done
2014 on non-C{None} assignments through the use of the Python C{property()}
2015 construct.
2016
2017 The following restrictions exist on data in this class:
2018
2019 - If set, the order mode must be one of the values in C{VALID_ORDER_MODES}
2020 - The actions list must be a list of C{ExtendedAction} objects.
2021
2022 @sort: __init__, __repr__, __str__, __cmp__, orderMode, actions
2023 """
2024
2025 - def __init__(self, actions=None, orderMode=None):
2026 """
2027 Constructor for the C{ExtensionsConfig} class.
2028 @param actions: List of extended actions
2029 """
2030 self._orderMode = None
2031 self._actions = None
2032 self.orderMode = orderMode
2033 self.actions = actions
2034
2036 """
2037 Official string representation for class instance.
2038 """
2039 return "ExtensionsConfig(%s, %s)" % (self.orderMode, self.actions)
2040
2042 """
2043 Informal string representation for class instance.
2044 """
2045 return self.__repr__()
2046
2048 """
2049 Definition of equals operator for this class.
2050 @param other: Other object to compare to.
2051 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
2052 """
2053 if other is None:
2054 return 1
2055 if self._orderMode != other._orderMode:
2056 if self._orderMode < other._orderMode:
2057 return -1
2058 else:
2059 return 1
2060 if self._actions != other._actions:
2061 if self._actions < other._actions:
2062 return -1
2063 else:
2064 return 1
2065 return 0
2066
2068 """
2069 Property target used to set the order mode.
2070 The value must be one of L{VALID_ORDER_MODES}.
2071 @raise ValueError: If the value is not valid.
2072 """
2073 if value is not None:
2074 if value not in VALID_ORDER_MODES:
2075 raise ValueError("Order mode must be one of %s." % VALID_ORDER_MODES)
2076 self._orderMode = value
2077
2079 """
2080 Property target used to get the order mode.
2081 """
2082 return self._orderMode
2083
2085 """
2086 Property target used to set the actions list.
2087 Either the value must be C{None} or each element must be an C{ExtendedAction}.
2088 @raise ValueError: If the value is not a C{ExtendedAction}
2089 """
2090 if value is None:
2091 self._actions = None
2092 else:
2093 try:
2094 saved = self._actions
2095 self._actions = ObjectTypeList(ExtendedAction, "ExtendedAction")
2096 self._actions.extend(value)
2097 except Exception, e:
2098 self._actions = saved
2099 raise e
2100
2102 """
2103 Property target used to get the actions list.
2104 """
2105 return self._actions
2106
2107 orderMode = property(_getOrderMode, _setOrderMode, None, "Order mode for extensions, to control execution ordering.")
2108 actions = property(_getActions, _setActions, None, "List of extended actions.")
2109
2110
2111
2112
2113
2114
2116
2117 """
2118 Class representing a Cedar Backup global options configuration.
2119
2120 The options section is used to store global configuration options and
2121 defaults that can be applied to other sections.
2122
2123 As with all of the other classes that represent configuration sections, all
2124 of these values are optional. It is up to some higher-level construct to
2125 decide whether everything they need is filled in. Some validation is done
2126 on non-C{None} assignments through the use of the Python C{property()}
2127 construct.
2128
2129 The following restrictions exist on data in this class:
2130
2131 - The working directory must be an absolute path.
2132 - The starting day must be a day of the week in English, i.e. C{"monday"}, C{"tuesday"}, etc.
2133 - All of the other values must be non-empty strings if they are set to something other than C{None}.
2134 - The overrides list must be a list of C{CommandOverride} objects.
2135 - The hooks list must be a list of C{ActionHook} objects.
2136
2137 @sort: __init__, __repr__, __str__, __cmp__, startingDay, workingDir,
2138 backupUser, backupGroup, rcpCommand, overrides
2139 """
2140
2141 - def __init__(self, startingDay=None, workingDir=None, backupUser=None,
2142 backupGroup=None, rcpCommand=None, overrides=None, hooks=None):
2143 """
2144 Constructor for the C{OptionsConfig} class.
2145
2146 @param startingDay: Day that starts the week.
2147 @param workingDir: Working (temporary) directory to use for backups.
2148 @param backupUser: Effective user that backups should run as.
2149 @param backupGroup: Effective group that backups should run as.
2150 @param rcpCommand: Default rcp-compatible copy command for staging.
2151 @param overrides: List of configured command path overrides, if any.
2152 @param hooks: List of configured pre- and post-action hooks.
2153
2154 @raise ValueError: If one of the values is invalid.
2155 """
2156 self._startingDay = None
2157 self._workingDir = None
2158 self._backupUser = None
2159 self._backupGroup = None
2160 self._rcpCommand = None
2161 self._overrides = None
2162 self._hooks = None
2163 self.startingDay = startingDay
2164 self.workingDir = workingDir
2165 self.backupUser = backupUser
2166 self.backupGroup = backupGroup
2167 self.rcpCommand = rcpCommand
2168 self.overrides = overrides
2169 self.hooks = hooks
2170
2172 """
2173 Official string representation for class instance.
2174 """
2175 return "OptionsConfig(%s, %s, %s, %s, %s, %s, %s)" % (self.startingDay, self.workingDir,
2176 self.backupUser, self.backupGroup,
2177 self.rcpCommand, self.overrides,
2178 self.hooks)
2179
2181 """
2182 Informal string representation for class instance.
2183 """
2184 return self.__repr__()
2185
2187 """
2188 Definition of equals operator for this class.
2189 @param other: Other object to compare to.
2190 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
2191 """
2192 if other is None:
2193 return 1
2194 if self._startingDay != other._startingDay:
2195 if self._startingDay < other._startingDay:
2196 return -1
2197 else:
2198 return 1
2199 if self._workingDir != other._workingDir:
2200 if self._workingDir < other._workingDir:
2201 return -1
2202 else:
2203 return 1
2204 if self._backupUser != other._backupUser:
2205 if self._backupUser < other._backupUser:
2206 return -1
2207 else:
2208 return 1
2209 if self._backupGroup != other._backupGroup:
2210 if self._backupGroup < other._backupGroup:
2211 return -1
2212 else:
2213 return 1
2214 if self._rcpCommand != other._rcpCommand:
2215 if self._rcpCommand < other._rcpCommand:
2216 return -1
2217 else:
2218 return 1
2219 if self._overrides != other._overrides:
2220 if self._overrides < other._overrides:
2221 return -1
2222 else:
2223 return 1
2224 if self._hooks != other._hooks:
2225 if self._hooks < other._hooks:
2226 return -1
2227 else:
2228 return 1
2229 return 0
2230
2232 """
2233 Property target used to set the starting day.
2234 If it is not C{None}, the value must be a valid English day of the week,
2235 one of C{"monday"}, C{"tuesday"}, C{"wednesday"}, etc.
2236 @raise ValueError: If the value is not a valid day of the week.
2237 """
2238 if value is not None:
2239 if value not in ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday", ]:
2240 raise ValueError("Starting day must be an English day of the week, i.e. \"monday\".")
2241 self._startingDay = value
2242
2244 """
2245 Property target used to get the starting day.
2246 """
2247 return self._startingDay
2248
2250 """
2251 Property target used to set the working directory.
2252 The value must be an absolute path if it is not C{None}.
2253 It does not have to exist on disk at the time of assignment.
2254 @raise ValueError: If the value is not an absolute path.
2255 @raise ValueError: If the value cannot be encoded properly.
2256 """
2257 if value is not None:
2258 if not os.path.isabs(value):
2259 raise ValueError("Working directory must be an absolute path.")
2260 self._workingDir = encodePath(value)
2261
2263 """
2264 Property target used to get the working directory.
2265 """
2266 return self._workingDir
2267
2269 """
2270 Property target used to set the backup user.
2271 The value must be a non-empty string if it is not C{None}.
2272 @raise ValueError: If the value is an empty string.
2273 """
2274 if value is not None:
2275 if len(value) < 1:
2276 raise ValueError("Backup user must be a non-empty string.")
2277 self._backupUser = value
2278
2280 """
2281 Property target used to get the backup user.
2282 """
2283 return self._backupUser
2284
2286 """
2287 Property target used to set the backup group.
2288 The value must be a non-empty string if it is not C{None}.
2289 @raise ValueError: If the value is an empty string.
2290 """
2291 if value is not None:
2292 if len(value) < 1:
2293 raise ValueError("Backup group must be a non-empty string.")
2294 self._backupGroup = value
2295
2297 """
2298 Property target used to get the backup group.
2299 """
2300 return self._backupGroup
2301
2303 """
2304 Property target used to set the rcp command.
2305 The value must be a non-empty string if it is not C{None}.
2306 @raise ValueError: If the value is an empty string.
2307 """
2308 if value is not None:
2309 if len(value) < 1:
2310 raise ValueError("The rcp command must be a non-empty string.")
2311 self._rcpCommand = value
2312
2314 """
2315 Property target used to get the rcp command.
2316 """
2317 return self._rcpCommand
2318
2320 """
2321 Property target used to set the command path overrides list.
2322 Either the value must be C{None} or each element must be a C{CommandOverride}.
2323 @raise ValueError: If the value is not a C{CommandOverride}
2324 """
2325 if value is None:
2326 self._overrides = None
2327 else:
2328 try:
2329 saved = self._overrides
2330 self._overrides = ObjectTypeList(CommandOverride, "CommandOverride")
2331 self._overrides.extend(value)
2332 except Exception, e:
2333 self._overrides = saved
2334 raise e
2335
2337 """
2338 Property target used to get the command path overrides list.
2339 """
2340 return self._overrides
2341
2343 """
2344 Property target used to set the pre- and post-action hooks list.
2345 Either the value must be C{None} or each element must be an C{ActionHook}.
2346 @raise ValueError: If the value is not a C{CommandOverride}
2347 """
2348 if value is None:
2349 self._hooks = None
2350 else:
2351 try:
2352 saved = self._hooks
2353 self._hooks = ObjectTypeList(ActionHook, "ActionHook")
2354 self._hooks.extend(value)
2355 except Exception, e:
2356 self._hooks = saved
2357 raise e
2358
2360 """
2361 Property target used to get the command path hooks list.
2362 """
2363 return self._hooks
2364
2365 startingDay = property(_getStartingDay, _setStartingDay, None, "Day that starts the week.")
2366 workingDir = property(_getWorkingDir, _setWorkingDir, None, "Working (temporary) directory to use for backups.")
2367 backupUser = property(_getBackupUser, _setBackupUser, None, "Effective user that backups should run as.")
2368 backupGroup = property(_getBackupGroup, _setBackupGroup, None, "Effective group that backups should run as.")
2369 rcpCommand = property(_getRcpCommand, _setRcpCommand, None, "Default rcp-compatible copy command for staging.")
2370 overrides = property(_getOverrides, _setOverrides, None, "List of configured command path overrides, if any.")
2371 hooks = property(_getHooks, _setHooks, None, "List of configured pre- and post-action hooks.")
2372
2373
2374
2375
2376
2377
2379
2380 """
2381 Class representing a Cedar Backup collect configuration.
2382
2383 As with all of the other classes that represent configuration sections, all
2384 of these values are optional. It is up to some higher-level construct to
2385 decide whether everything they need is filled in. Some validation is done
2386 on non-C{None} assignments through the use of the Python C{property()}
2387 construct.
2388
2389 The following restrictions exist on data in this class:
2390
2391 - The target directory must be an absolute path.
2392 - The collect mode must be one of the values in L{VALID_COLLECT_MODES}.
2393 - The archive mode must be one of the values in L{VALID_ARCHIVE_MODES}.
2394 - The ignore file must be a non-empty string.
2395 - Each of the paths in C{absoluteExcludePaths} must be an absolute path
2396 - The collect file list must be a list of C{CollectFile} objects.
2397 - The collect directory list must be a list of C{CollectDir} objects.
2398
2399 For the C{absoluteExcludePaths} list, validation is accomplished through the
2400 L{util.AbsolutePathList} list implementation that overrides common list
2401 methods and transparently does the absolute path validation for us.
2402
2403 For the C{collectFiles} and C{collectDirs} list, validation is accomplished
2404 through the L{util.ObjectTypeList} list implementation that overrides common
2405 list methods and transparently ensures that each element has an appropriate
2406 type.
2407
2408 @note: Lists within this class are "unordered" for equality comparisons.
2409
2410 @sort: __init__, __repr__, __str__, __cmp__, targetDir,
2411 collectMode, archiveMode, ignoreFile, absoluteExcludePaths,
2412 excludePatterns, collectFiles, collectDirs
2413 """
2414
2415 - def __init__(self, targetDir=None, collectMode=None, archiveMode=None, ignoreFile=None,
2416 absoluteExcludePaths=None, excludePatterns=None, collectFiles=None, collectDirs=None):
2417 """
2418 Constructor for the C{CollectConfig} class.
2419
2420 @param targetDir: Directory to collect files into.
2421 @param collectMode: Default collect mode.
2422 @param archiveMode: Default archive mode for collect files.
2423 @param ignoreFile: Default ignore file name.
2424 @param absoluteExcludePaths: List of absolute paths to exclude.
2425 @param excludePatterns: List of regular expression patterns to exclude.
2426 @param collectFiles: List of collect files.
2427 @param collectDirs: List of collect directories.
2428
2429 @raise ValueError: If one of the values is invalid.
2430 """
2431 self._targetDir = None
2432 self._collectMode = None
2433 self._archiveMode = None
2434 self._ignoreFile = None
2435 self._absoluteExcludePaths = None
2436 self._excludePatterns = None
2437 self._collectFiles = None
2438 self._collectDirs = None
2439 self.targetDir = targetDir
2440 self.collectMode = collectMode
2441 self.archiveMode = archiveMode
2442 self.ignoreFile = ignoreFile
2443 self.absoluteExcludePaths = absoluteExcludePaths
2444 self.excludePatterns = excludePatterns
2445 self.collectFiles = collectFiles
2446 self.collectDirs = collectDirs
2447
2449 """
2450 Official string representation for class instance.
2451 """
2452 return "CollectConfig(%s, %s, %s, %s, %s, %s, %s, %s)" % (self.targetDir, self.collectMode, self.archiveMode,
2453 self.ignoreFile, self.absoluteExcludePaths,
2454 self.excludePatterns, self.collectFiles, self.collectDirs)
2455
2457 """
2458 Informal string representation for class instance.
2459 """
2460 return self.__repr__()
2461
2463 """
2464 Definition of equals operator for this class.
2465 Lists within this class are "unordered" for equality comparisons.
2466 @param other: Other object to compare to.
2467 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
2468 """
2469 if other is None:
2470 return 1
2471 if self._targetDir != other._targetDir:
2472 if self._targetDir < other._targetDir:
2473 return -1
2474 else:
2475 return 1
2476 if self._collectMode != other._collectMode:
2477 if self._collectMode < other._collectMode:
2478 return -1
2479 else:
2480 return 1
2481 if self._archiveMode != other._archiveMode:
2482 if self._archiveMode < other._archiveMode:
2483 return -1
2484 else:
2485 return 1
2486 if self._ignoreFile != other._ignoreFile:
2487 if self._ignoreFile < other._ignoreFile:
2488 return -1
2489 else:
2490 return 1
2491 if self._absoluteExcludePaths != other._absoluteExcludePaths:
2492 if self._absoluteExcludePaths < other._absoluteExcludePaths:
2493 return -1
2494 else:
2495 return 1
2496 if self._excludePatterns != other._excludePatterns:
2497 if self._excludePatterns < other._excludePatterns:
2498 return -1
2499 else:
2500 return 1
2501 if self._collectFiles != other._collectFiles:
2502 if self._collectFiles < other._collectFiles:
2503 return -1
2504 else:
2505 return 1
2506 if self._collectDirs != other._collectDirs:
2507 if self._collectDirs < other._collectDirs:
2508 return -1
2509 else:
2510 return 1
2511 return 0
2512
2514 """
2515 Property target used to set the target directory.
2516 The value must be an absolute path if it is not C{None}.
2517 It does not have to exist on disk at the time of assignment.
2518 @raise ValueError: If the value is not an absolute path.
2519 @raise ValueError: If the value cannot be encoded properly.
2520 """
2521 if value is not None:
2522 if not os.path.isabs(value):
2523 raise ValueError("Target directory must be an absolute path.")
2524 self._targetDir = encodePath(value)
2525
2527 """
2528 Property target used to get the target directory.
2529 """
2530 return self._targetDir
2531
2533 """
2534 Property target used to set the collect mode.
2535 If not C{None}, the mode must be one of L{VALID_COLLECT_MODES}.
2536 @raise ValueError: If the value is not valid.
2537 """
2538 if value is not None:
2539 if value not in VALID_COLLECT_MODES:
2540 raise ValueError("Collect mode must be one of %s." % VALID_COLLECT_MODES)
2541 self._collectMode = value
2542
2544 """
2545 Property target used to get the collect mode.
2546 """
2547 return self._collectMode
2548
2550 """
2551 Property target used to set the archive mode.
2552 If not C{None}, the mode must be one of L{VALID_ARCHIVE_MODES}.
2553 @raise ValueError: If the value is not valid.
2554 """
2555 if value is not None:
2556 if value not in VALID_ARCHIVE_MODES:
2557 raise ValueError("Archive mode must be one of %s." % VALID_ARCHIVE_MODES)
2558 self._archiveMode = value
2559
2561 """
2562 Property target used to get the archive mode.
2563 """
2564 return self._archiveMode
2565
2567 """
2568 Property target used to set the ignore file.
2569 The value must be a non-empty string if it is not C{None}.
2570 @raise ValueError: If the value is an empty string.
2571 @raise ValueError: If the value cannot be encoded properly.
2572 """
2573 if value is not None:
2574 if len(value) < 1:
2575 raise ValueError("The ignore file must be a non-empty string.")
2576 self._ignoreFile = encodePath(value)
2577
2579 """
2580 Property target used to get the ignore file.
2581 """
2582 return self._ignoreFile
2583
2585 """
2586 Property target used to set the absolute exclude paths list.
2587 Either the value must be C{None} or each element must be an absolute path.
2588 Elements do not have to exist on disk at the time of assignment.
2589 @raise ValueError: If the value is not an absolute path.
2590 """
2591 if value is None:
2592 self._absoluteExcludePaths = None
2593 else:
2594 try:
2595 saved = self._absoluteExcludePaths
2596 self._absoluteExcludePaths = AbsolutePathList()
2597 self._absoluteExcludePaths.extend(value)
2598 except Exception, e:
2599 self._absoluteExcludePaths = saved
2600 raise e
2601
2603 """
2604 Property target used to get the absolute exclude paths list.
2605 """
2606 return self._absoluteExcludePaths
2607
2609 """
2610 Property target used to set the exclude patterns list.
2611 """
2612 if value is None:
2613 self._excludePatterns = None
2614 else:
2615 try:
2616 saved = self._excludePatterns
2617 self._excludePatterns = RegexList()
2618 self._excludePatterns.extend(value)
2619 except Exception, e:
2620 self._excludePatterns = saved
2621 raise e
2622
2624 """
2625 Property target used to get the exclude patterns list.
2626 """
2627 return self._excludePatterns
2628
2630 """
2631 Property target used to set the collect files list.
2632 Either the value must be C{None} or each element must be a C{CollectFile}.
2633 @raise ValueError: If the value is not a C{CollectFile}
2634 """
2635 if value is None:
2636 self._collectFiles = None
2637 else:
2638 try:
2639 saved = self._collectFiles
2640 self._collectFiles = ObjectTypeList(CollectFile, "CollectFile")
2641 self._collectFiles.extend(value)
2642 except Exception, e:
2643 self._collectFiles = saved
2644 raise e
2645
2647 """
2648 Property target used to get the collect files list.
2649 """
2650 return self._collectFiles
2651
2653 """
2654 Property target used to set the collect dirs list.
2655 Either the value must be C{None} or each element must be a C{CollectDir}.
2656 @raise ValueError: If the value is not a C{CollectDir}
2657 """
2658 if value is None:
2659 self._collectDirs = None
2660 else:
2661 try:
2662 saved = self._collectDirs
2663 self._collectDirs = ObjectTypeList(CollectDir, "CollectDir")
2664 self._collectDirs.extend(value)
2665 except Exception, e:
2666 self._collectDirs = saved
2667 raise e
2668
2670 """
2671 Property target used to get the collect dirs list.
2672 """
2673 return self._collectDirs
2674
2675 targetDir = property(_getTargetDir, _setTargetDir, None, "Directory to collect files into.")
2676 collectMode = property(_getCollectMode, _setCollectMode, None, "Default collect mode.")
2677 archiveMode = property(_getArchiveMode, _setArchiveMode, None, "Default archive mode for collect files.")
2678 ignoreFile = property(_getIgnoreFile, _setIgnoreFile, None, "Default ignore file name.")
2679 absoluteExcludePaths = property(_getAbsoluteExcludePaths, _setAbsoluteExcludePaths, None, "List of absolute paths to exclude.")
2680 excludePatterns = property(_getExcludePatterns, _setExcludePatterns, None, "List of regular expressions patterns to exclude.")
2681 collectFiles = property(_getCollectFiles, _setCollectFiles, None, "List of collect files.")
2682 collectDirs = property(_getCollectDirs, _setCollectDirs, None, "List of collect directories.")
2683
2684
2685
2686
2687
2688
2690
2691 """
2692 Class representing a Cedar Backup stage configuration.
2693
2694 As with all of the other classes that represent configuration sections, all
2695 of these values are optional. It is up to some higher-level construct to
2696 decide whether everything they need is filled in. Some validation is done
2697 on non-C{None} assignments through the use of the Python C{property()}
2698 construct.
2699
2700 The following restrictions exist on data in this class:
2701
2702 - The target directory must be an absolute path
2703 - The list of local peers must contain only C{LocalPeer} objects
2704 - The list of remote peers must contain only C{RemotePeer} objects
2705
2706 @note: Lists within this class are "unordered" for equality comparisons.
2707
2708 @sort: __init__, __repr__, __str__, __cmp__, targetDir, localPeers, remotePeers
2709 """
2710
2711 - def __init__(self, targetDir=None, localPeers=None, remotePeers=None):
2712 """
2713 Constructor for the C{StageConfig} class.
2714
2715 @param targetDir: Directory to stage files into, by peer name.
2716 @param localPeers: List of local peers.
2717 @param remotePeers: List of remote peers.
2718
2719 @raise ValueError: If one of the values is invalid.
2720 """
2721 self._targetDir = None
2722 self._localPeers = None
2723 self._remotePeers = None
2724 self.targetDir = targetDir
2725 self.localPeers = localPeers
2726 self.remotePeers = remotePeers
2727
2729 """
2730 Official string representation for class instance.
2731 """
2732 return "StageConfig(%s, %s, %s)" % (self.targetDir, self.localPeers, self.remotePeers)
2733
2735 """
2736 Informal string representation for class instance.
2737 """
2738 return self.__repr__()
2739
2741 """
2742 Definition of equals operator for this class.
2743 Lists within this class are "unordered" for equality comparisons.
2744 @param other: Other object to compare to.
2745 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
2746 """
2747 if other is None:
2748 return 1
2749 if self._targetDir != other._targetDir:
2750 if self._targetDir < other._targetDir:
2751 return -1
2752 else:
2753 return 1
2754 if self._localPeers != other._localPeers:
2755 if self._localPeers < other._localPeers:
2756 return -1
2757 else:
2758 return 1
2759 if self._remotePeers != other._remotePeers:
2760 if self._remotePeers < other._remotePeers:
2761 return -1
2762 else:
2763 return 1
2764 return 0
2765
2767 """
2768 Property target used to set the target directory.
2769 The value must be an absolute path if it is not C{None}.
2770 It does not have to exist on disk at the time of assignment.
2771 @raise ValueError: If the value is not an absolute path.
2772 @raise ValueError: If the value cannot be encoded properly.
2773 """
2774 if value is not None:
2775 if not os.path.isabs(value):
2776 raise ValueError("Target directory must be an absolute path.")
2777 self._targetDir = encodePath(value)
2778
2780 """
2781 Property target used to get the target directory.
2782 """
2783 return self._targetDir
2784
2786 """
2787 Property target used to set the local peers list.
2788 Either the value must be C{None} or each element must be a C{LocalPeer}.
2789 @raise ValueError: If the value is not an absolute path.
2790 """
2791 if value is None:
2792 self._localPeers = None
2793 else:
2794 try:
2795 saved = self._localPeers
2796 self._localPeers = ObjectTypeList(LocalPeer, "LocalPeer")
2797 self._localPeers.extend(value)
2798 except Exception, e:
2799 self._localPeers = saved
2800 raise e
2801
2803 """
2804 Property target used to get the local peers list.
2805 """
2806 return self._localPeers
2807
2809 """
2810 Property target used to set the remote peers list.
2811 Either the value must be C{None} or each element must be a C{RemotePeer}.
2812 @raise ValueError: If the value is not a C{RemotePeer}
2813 """
2814 if value is None:
2815 self._remotePeers = None
2816 else:
2817 try:
2818 saved = self._remotePeers
2819 self._remotePeers = ObjectTypeList(RemotePeer, "RemotePeer")
2820 self._remotePeers.extend(value)
2821 except Exception, e:
2822 self._remotePeers = saved
2823 raise e
2824
2826 """
2827 Property target used to get the remote peers list.
2828 """
2829 return self._remotePeers
2830
2831 targetDir = property(_getTargetDir, _setTargetDir, None, "Directory to stage files into, by peer name.")
2832 localPeers = property(_getLocalPeers, _setLocalPeers, None, "List of local peers.")
2833 remotePeers = property(_getRemotePeers, _setRemotePeers, None, "List of remote peers.")
2834
2835
2836
2837
2838
2839
2841
2842 """
2843 Class representing a Cedar Backup store configuration.
2844
2845 As with all of the other classes that represent configuration sections, all
2846 of these values are optional. It is up to some higher-level construct to
2847 decide whether everything they need is filled in. Some validation is done
2848 on non-C{None} assignments through the use of the Python C{property()}
2849 construct.
2850
2851 The following restrictions exist on data in this class:
2852
2853 - The source directory must be an absolute path.
2854 - The media type must be one of the values in L{VALID_MEDIA_TYPES}.
2855 - The device type must be one of the values in L{VALID_DEVICE_TYPES}.
2856 - The device path must be an absolute path.
2857 - The SCSI id, if provided, must be in the form specified by L{validateScsiId}.
2858 - The drive speed must be an integer >= 1
2859 - The blanking behavior must be a C{BlankBehavior} object
2860
2861 Note that although the blanking factor must be a positive floating point
2862 number, it is stored as a string. This is done so that we can losslessly go
2863 back and forth between XML and object representations of configuration.
2864
2865 @sort: __init__, __repr__, __str__, __cmp__, sourceDir,
2866 mediaType, deviceType, devicePath, deviceScsiId,
2867 driveSpeed, checkData, checkMedia, warnMidnite, noEject, blankBehavior
2868 """
2869
2870 - def __init__(self, sourceDir=None, mediaType=None, deviceType=None,
2871 devicePath=None, deviceScsiId=None, driveSpeed=None,
2872 checkData=False, warnMidnite=False, noEject=False,
2873 checkMedia=False, blankBehavior=None):
2874 """
2875 Constructor for the C{StoreConfig} class.
2876
2877 @param sourceDir: Directory whose contents should be written to media.
2878 @param mediaType: Type of the media (see notes above).
2879 @param deviceType: Type of the device (optional, see notes above).
2880 @param devicePath: Filesystem device name for writer device, i.e. C{/dev/cdrw}.
2881 @param deviceScsiId: SCSI id for writer device, i.e. C{[<method>:]scsibus,target,lun}.
2882 @param driveSpeed: Speed of the drive, i.e. C{2} for 2x drive, etc.
2883 @param checkData: Whether resulting image should be validated.
2884 @param checkMedia: Whether media should be checked before being written to.
2885 @param warnMidnite: Whether to generate warnings for crossing midnite.
2886 @param noEject: Indicates that the writer device should not be ejected.
2887 @param blankBehavior: Controls optimized blanking behavior.
2888
2889 @raise ValueError: If one of the values is invalid.
2890 """
2891 self._sourceDir = None
2892 self._mediaType = None
2893 self._deviceType = None
2894 self._devicePath = None
2895 self._deviceScsiId = None
2896 self._driveSpeed = None
2897 self._checkData = None
2898 self._checkMedia = None
2899 self._warnMidnite = None
2900 self._noEject = None
2901 self._blankBehavior = None
2902 self.sourceDir = sourceDir
2903 self.mediaType = mediaType
2904 self.deviceType = deviceType
2905 self.devicePath = devicePath
2906 self.deviceScsiId = deviceScsiId
2907 self.driveSpeed = driveSpeed
2908 self.checkData = checkData
2909 self.checkMedia = checkMedia
2910 self.warnMidnite = warnMidnite
2911 self.noEject = noEject
2912 self.blankBehavior = blankBehavior
2913
2915 """
2916 Official string representation for class instance.
2917 """
2918 return "StoreConfig(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)" % (self.sourceDir, self.mediaType, self.deviceType,
2919 self.devicePath, self.deviceScsiId, self.driveSpeed,
2920 self.checkData, self.warnMidnite, self.noEject,
2921 self.checkMedia, self.blankBehavior)
2922
2924 """
2925 Informal string representation for class instance.
2926 """
2927 return self.__repr__()
2928
2930 """
2931 Definition of equals operator for this class.
2932 @param other: Other object to compare to.
2933 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
2934 """
2935 if other is None:
2936 return 1
2937 if self._sourceDir != other._sourceDir:
2938 if self._sourceDir < other._sourceDir:
2939 return -1
2940 else:
2941 return 1
2942 if self._mediaType != other._mediaType:
2943 if self._mediaType < other._mediaType:
2944 return -1
2945 else:
2946 return 1
2947 if self._deviceType != other._deviceType:
2948 if self._deviceType < other._deviceType:
2949 return -1
2950 else:
2951 return 1
2952 if self._devicePath != other._devicePath:
2953 if self._devicePath < other._devicePath:
2954 return -1
2955 else:
2956 return 1
2957 if self._deviceScsiId != other._deviceScsiId:
2958 if self._deviceScsiId < other._deviceScsiId:
2959 return -1
2960 else:
2961 return 1
2962 if self._driveSpeed != other._driveSpeed:
2963 if self._driveSpeed < other._driveSpeed:
2964 return -1
2965 else:
2966 return 1
2967 if self._checkData != other._checkData:
2968 if self._checkData < other._checkData:
2969 return -1
2970 else:
2971 return 1
2972 if self._checkMedia != other._checkMedia:
2973 if self._checkMedia < other._checkMedia:
2974 return -1
2975 else:
2976 return 1
2977 if self._warnMidnite != other._warnMidnite:
2978 if self._warnMidnite < other._warnMidnite:
2979 return -1
2980 else:
2981 return 1
2982 if self._noEject != other._noEject:
2983 if self._noEject < other._noEject:
2984 return -1
2985 else:
2986 return 1
2987 if self._blankBehavior != other._blankBehavior:
2988 if self._blankBehavior < other._blankBehavior:
2989 return -1
2990 else:
2991 return 1
2992 return 0
2993
2995 """
2996 Property target used to set the source directory.
2997 The value must be an absolute path if it is not C{None}.
2998 It does not have to exist on disk at the time of assignment.
2999 @raise ValueError: If the value is not an absolute path.
3000 @raise ValueError: If the value cannot be encoded properly.
3001 """
3002 if value is not None:
3003 if not os.path.isabs(value):
3004 raise ValueError("Source directory must be an absolute path.")
3005 self._sourceDir = encodePath(value)
3006
3008 """
3009 Property target used to get the source directory.
3010 """
3011 return self._sourceDir
3012
3023
3029
3031 """
3032 Property target used to set the device type.
3033 The value must be one of L{VALID_DEVICE_TYPES}.
3034 @raise ValueError: If the value is not valid.
3035 """
3036 if value is not None:
3037 if value not in VALID_DEVICE_TYPES:
3038 raise ValueError("Device type must be one of %s." % VALID_DEVICE_TYPES)
3039 self._deviceType = value
3040
3042 """
3043 Property target used to get the device type.
3044 """
3045 return self._deviceType
3046
3048 """
3049 Property target used to set the device path.
3050 The value must be an absolute path if it is not C{None}.
3051 It does not have to exist on disk at the time of assignment.
3052 @raise ValueError: If the value is not an absolute path.
3053 @raise ValueError: If the value cannot be encoded properly.
3054 """
3055 if value is not None:
3056 if not os.path.isabs(value):
3057 raise ValueError("Device path must be an absolute path.")
3058 self._devicePath = encodePath(value)
3059
3061 """
3062 Property target used to get the device path.
3063 """
3064 return self._devicePath
3065
3067 """
3068 Property target used to set the SCSI id
3069 The SCSI id must be valid per L{validateScsiId}.
3070 @raise ValueError: If the value is not valid.
3071 """
3072 if value is None:
3073 self._deviceScsiId = None
3074 else:
3075 self._deviceScsiId = validateScsiId(value)
3076
3078 """
3079 Property target used to get the SCSI id.
3080 """
3081 return self._deviceScsiId
3082
3084 """
3085 Property target used to set the drive speed.
3086 The drive speed must be valid per L{validateDriveSpeed}.
3087 @raise ValueError: If the value is not valid.
3088 """
3089 self._driveSpeed = validateDriveSpeed(value)
3090
3092 """
3093 Property target used to get the drive speed.
3094 """
3095 return self._driveSpeed
3096
3098 """
3099 Property target used to set the check data flag.
3100 No validations, but we normalize the value to C{True} or C{False}.
3101 """
3102 if value:
3103 self._checkData = True
3104 else:
3105 self._checkData = False
3106
3108 """
3109 Property target used to get the check data flag.
3110 """
3111 return self._checkData
3112
3122
3128
3130 """
3131 Property target used to set the midnite warning flag.
3132 No validations, but we normalize the value to C{True} or C{False}.
3133 """
3134 if value:
3135 self._warnMidnite = True
3136 else:
3137 self._warnMidnite = False
3138
3140 """
3141 Property target used to get the midnite warning flag.
3142 """
3143 return self._warnMidnite
3144
3146 """
3147 Property target used to set the no-eject flag.
3148 No validations, but we normalize the value to C{True} or C{False}.
3149 """
3150 if value:
3151 self._noEject = True
3152 else:
3153 self._noEject = False
3154
3156 """
3157 Property target used to get the no-eject flag.
3158 """
3159 return self._noEject
3160
3162 """
3163 Property target used to set blanking behavior configuration.
3164 If not C{None}, the value must be a C{BlankBehavior} object.
3165 @raise ValueError: If the value is not a C{BlankBehavior}
3166 """
3167 if value is None:
3168 self._blankBehavior = None
3169 else:
3170 if not isinstance(value, BlankBehavior):
3171 raise ValueError("Value must be a C{BlankBehavior} object.")
3172 self._blankBehavior = value
3173
3175 """
3176 Property target used to get the blanking behavior configuration.
3177 """
3178 return self._blankBehavior
3179
3180 sourceDir = property(_getSourceDir, _setSourceDir, None, "Directory whose contents should be written to media.")
3181 mediaType = property(_getMediaType, _setMediaType, None, "Type of the media (see notes above).")
3182 deviceType = property(_getDeviceType, _setDeviceType, None, "Type of the device (optional, see notes above).")
3183 devicePath = property(_getDevicePath, _setDevicePath, None, "Filesystem device name for writer device.")
3184 deviceScsiId = property(_getDeviceScsiId, _setDeviceScsiId, None, "SCSI id for writer device (optional, see notes above).")
3185 driveSpeed = property(_getDriveSpeed, _setDriveSpeed, None, "Speed of the drive.")
3186 checkData = property(_getCheckData, _setCheckData, None, "Whether resulting image should be validated.")
3187 checkMedia = property(_getCheckMedia, _setCheckMedia, None, "Whether media should be checked before being written to.")
3188 warnMidnite = property(_getWarnMidnite, _setWarnMidnite, None, "Whether to generate warnings for crossing midnite.")
3189 noEject = property(_getNoEject, _setNoEject, None, "Indicates that the writer device should not be ejected.")
3190 blankBehavior = property(_getBlankBehavior, _setBlankBehavior, None, "Controls optimized blanking behavior.")
3191
3192
3193
3194
3195
3196
3198
3199 """
3200 Class representing a Cedar Backup purge configuration.
3201
3202 As with all of the other classes that represent configuration sections, all
3203 of these values are optional. It is up to some higher-level construct to
3204 decide whether everything they need is filled in. Some validation is done
3205 on non-C{None} assignments through the use of the Python C{property()}
3206 construct.
3207
3208 The following restrictions exist on data in this class:
3209
3210 - The purge directory list must be a list of C{PurgeDir} objects.
3211
3212 For the C{purgeDirs} list, validation is accomplished through the
3213 L{util.ObjectTypeList} list implementation that overrides common list
3214 methods and transparently ensures that each element is a C{PurgeDir}.
3215
3216 @note: Lists within this class are "unordered" for equality comparisons.
3217
3218 @sort: __init__, __repr__, __str__, __cmp__, purgeDirs
3219 """
3220
3222 """
3223 Constructor for the C{Purge} class.
3224 @param purgeDirs: List of purge directories.
3225 @raise ValueError: If one of the values is invalid.
3226 """
3227 self._purgeDirs = None
3228 self.purgeDirs = purgeDirs
3229
3231 """
3232 Official string representation for class instance.
3233 """
3234 return "PurgeConfig(%s)" % self.purgeDirs
3235
3237 """
3238 Informal string representation for class instance.
3239 """
3240 return self.__repr__()
3241
3243 """
3244 Definition of equals operator for this class.
3245 Lists within this class are "unordered" for equality comparisons.
3246 @param other: Other object to compare to.
3247 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
3248 """
3249 if other is None:
3250 return 1
3251 if self._purgeDirs != other._purgeDirs:
3252 if self._purgeDirs < other._purgeDirs:
3253 return -1
3254 else:
3255 return 1
3256 return 0
3257
3259 """
3260 Property target used to set the purge dirs list.
3261 Either the value must be C{None} or each element must be a C{PurgeDir}.
3262 @raise ValueError: If the value is not a C{PurgeDir}
3263 """
3264 if value is None:
3265 self._purgeDirs = None
3266 else:
3267 try:
3268 saved = self._purgeDirs
3269 self._purgeDirs = ObjectTypeList(PurgeDir, "PurgeDir")
3270 self._purgeDirs.extend(value)
3271 except Exception, e:
3272 self._purgeDirs = saved
3273 raise e
3274
3276 """
3277 Property target used to get the purge dirs list.
3278 """
3279 return self._purgeDirs
3280
3281 purgeDirs = property(_getPurgeDirs, _setPurgeDirs, None, "List of directories to purge.")
3282
3283
3284
3285
3286
3287
3289
3290
3291
3292
3293
3294 """
3295 Class representing a Cedar Backup XML configuration document.
3296
3297 The C{Config} class is a Python object representation of a Cedar Backup XML
3298 configuration file. It is intended to be the only Python-language interface
3299 to Cedar Backup configuration on disk for both Cedar Backup itself and for
3300 external applications.
3301
3302 The object representation is two-way: XML data can be used to create a
3303 C{Config} object, and then changes to the object can be propogated back to
3304 disk. A C{Config} object can even be used to create a configuration file
3305 from scratch programmatically.
3306
3307 This class and the classes it is composed from often use Python's
3308 C{property} construct to validate input and limit access to values. Some
3309 validations can only be done once a document is considered "complete"
3310 (see module notes for more details).
3311
3312 Assignments to the various instance variables must match the expected
3313 type, i.e. C{reference} must be a C{ReferenceConfig}. The internal check
3314 uses the built-in C{isinstance} function, so it should be OK to use
3315 subclasses if you want to.
3316
3317 If an instance variable is not set, its value will be C{None}. When an
3318 object is initialized without using an XML document, all of the values
3319 will be C{None}. Even when an object is initialized using XML, some of
3320 the values might be C{None} because not every section is required.
3321
3322 @note: Lists within this class are "unordered" for equality comparisons.
3323
3324 @sort: __init__, __repr__, __str__, __cmp__, extractXml, validate,
3325 reference, extensions, options, collect, stage, store, purge,
3326 _getReference, _setReference, _getExtensions, _setExtensions,
3327 _getOptions, _setOptions, _getCollect, _setCollect, _getStage,
3328 _setStage, _getStore, _setStore, _getPurge, _setPurge
3329 """
3330
3331
3332
3333
3334
3335 - def __init__(self, xmlData=None, xmlPath=None, validate=True):
3336 """
3337 Initializes a configuration object.
3338
3339 If you initialize the object without passing either C{xmlData} or
3340 C{xmlPath}, then configuration will be empty and will be invalid until it
3341 is filled in properly.
3342
3343 No reference to the original XML data or original path is saved off by
3344 this class. Once the data has been parsed (successfully or not) this
3345 original information is discarded.
3346
3347 Unless the C{validate} argument is C{False}, the L{Config.validate}
3348 method will be called (with its default arguments) against configuration
3349 after successfully parsing any passed-in XML. Keep in mind that even if
3350 C{validate} is C{False}, it might not be possible to parse the passed-in
3351 XML document if lower-level validations fail.
3352
3353 @note: It is strongly suggested that the C{validate} option always be set
3354 to C{True} (the default) unless there is a specific need to read in
3355 invalid configuration from disk.
3356
3357 @param xmlData: XML data representing configuration.
3358 @type xmlData: String data.
3359
3360 @param xmlPath: Path to an XML file on disk.
3361 @type xmlPath: Absolute path to a file on disk.
3362
3363 @param validate: Validate the document after parsing it.
3364 @type validate: Boolean true/false.
3365
3366 @raise ValueError: If both C{xmlData} and C{xmlPath} are passed-in.
3367 @raise ValueError: If the XML data in C{xmlData} or C{xmlPath} cannot be parsed.
3368 @raise ValueError: If the parsed configuration document is not valid.
3369 """
3370 self._reference = None
3371 self._extensions = None
3372 self._options = None
3373 self._collect = None
3374 self._stage = None
3375 self._store = None
3376 self._purge = None
3377 self.reference = None
3378 self.extensions = None
3379 self.options = None
3380 self.collect = None
3381 self.stage = None
3382 self.store = None
3383 self.purge = None
3384 if xmlData is not None and xmlPath is not None:
3385 raise ValueError("Use either xmlData or xmlPath, but not both.")
3386 if xmlData is not None:
3387 self._parseXmlData(xmlData)
3388 if validate:
3389 self.validate()
3390 elif xmlPath is not None:
3391 xmlData = open(xmlPath).read()
3392 self._parseXmlData(xmlData)
3393 if validate:
3394 self.validate()
3395
3396
3397
3398
3399
3400
3402 """
3403 Official string representation for class instance.
3404 """
3405 return "Config(%s, %s, %s, %s, %s, %s, %s)" % (self.reference, self.extensions, self.options,
3406 self.collect, self.stage, self.store, self.purge)
3407
3409 """
3410 Informal string representation for class instance.
3411 """
3412 return self.__repr__()
3413
3414
3415
3416
3417
3418
3420 """
3421 Definition of equals operator for this class.
3422 Lists within this class are "unordered" for equality comparisons.
3423 @param other: Other object to compare to.
3424 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
3425 """
3426 if other is None:
3427 return 1
3428 if self._reference != other._reference:
3429 if self._reference < other._reference:
3430 return -1
3431 else:
3432 return 1
3433 if self._extensions != other._extensions:
3434 if self._extensions < other._extensions:
3435 return -1
3436 else:
3437 return 1
3438 if self._options != other._options:
3439 if self._options < other._options:
3440 return -1
3441 else:
3442 return 1
3443 if self._collect != other._collect:
3444 if self._collect < other._collect:
3445 return -1
3446 else:
3447 return 1
3448 if self._stage != other._stage:
3449 if self._stage < other._stage:
3450 return -1
3451 else:
3452 return 1
3453 if self._store != other._store:
3454 if self._store < other._store:
3455 return -1
3456 else:
3457 return 1
3458 if self._purge != other._purge:
3459 if self._purge < other._purge:
3460 return -1
3461 else:
3462 return 1
3463 return 0
3464
3465
3466
3467
3468
3469
3471 """
3472 Property target used to set the reference configuration value.
3473 If not C{None}, the value must be a C{ReferenceConfig} object.
3474 @raise ValueError: If the value is not a C{ReferenceConfig}
3475 """
3476 if value is None:
3477 self._reference = None
3478 else:
3479 if not isinstance(value, ReferenceConfig):
3480 raise ValueError("Value must be a C{ReferenceConfig} object.")
3481 self._reference = value
3482
3484 """
3485 Property target used to get the reference configuration value.
3486 """
3487 return self._reference
3488
3489 - def _setExtensions(self, value):
3490 """
3491 Property target used to set the extensions configuration value.
3492 If not C{None}, the value must be a C{ExtensionsConfig} object.
3493 @raise ValueError: If the value is not a C{ExtensionsConfig}
3494 """
3495 if value is None:
3496 self._extensions = None
3497 else:
3498 if not isinstance(value, ExtensionsConfig):
3499 raise ValueError("Value must be a C{ExtensionsConfig} object.")
3500 self._extensions = value
3501
3502 - def _getExtensions(self):
3503 """
3504 Property target used to get the extensions configuration value.
3505 """
3506 return self._extensions
3507
3509 """
3510 Property target used to set the options configuration value.
3511 If not C{None}, the value must be an C{OptionsConfig} object.
3512 @raise ValueError: If the value is not a C{OptionsConfig}
3513 """
3514 if value is None:
3515 self._options = None
3516 else:
3517 if not isinstance(value, OptionsConfig):
3518 raise ValueError("Value must be a C{OptionsConfig} object.")
3519 self._options = value
3520
3522 """
3523 Property target used to get the options configuration value.
3524 """
3525 return self._options
3526
3528 """
3529 Property target used to set the collect configuration value.
3530 If not C{None}, the value must be a C{CollectConfig} object.
3531 @raise ValueError: If the value is not a C{CollectConfig}
3532 """
3533 if value is None:
3534 self._collect = None
3535 else:
3536 if not isinstance(value, CollectConfig):
3537 raise ValueError("Value must be a C{CollectConfig} object.")
3538 self._collect = value
3539
3541 """
3542 Property target used to get the collect configuration value.
3543 """
3544 return self._collect
3545
3547 """
3548 Property target used to set the stage configuration value.
3549 If not C{None}, the value must be a C{StageConfig} object.
3550 @raise ValueError: If the value is not a C{StageConfig}
3551 """
3552 if value is None:
3553 self._stage = None
3554 else:
3555 if not isinstance(value, StageConfig):
3556 raise ValueError("Value must be a C{StageConfig} object.")
3557 self._stage = value
3558
3560 """
3561 Property target used to get the stage configuration value.
3562 """
3563 return self._stage
3564
3566 """
3567 Property target used to set the store configuration value.
3568 If not C{None}, the value must be a C{StoreConfig} object.
3569 @raise ValueError: If the value is not a C{StoreConfig}
3570 """
3571 if value is None:
3572 self._store = None
3573 else:
3574 if not isinstance(value, StoreConfig):
3575 raise ValueError("Value must be a C{StoreConfig} object.")
3576 self._store = value
3577
3579 """
3580 Property target used to get the store configuration value.
3581 """
3582 return self._store
3583
3585 """
3586 Property target used to set the purge configuration value.
3587 If not C{None}, the value must be a C{PurgeConfig} object.
3588 @raise ValueError: If the value is not a C{PurgeConfig}
3589 """
3590 if value is None:
3591 self._purge = None
3592 else:
3593 if not isinstance(value, PurgeConfig):
3594 raise ValueError("Value must be a C{PurgeConfig} object.")
3595 self._purge = value
3596
3598 """
3599 Property target used to get the purge configuration value.
3600 """
3601 return self._purge
3602
3603 reference = property(_getReference, _setReference, None, "Reference configuration in terms of a C{ReferenceConfig} object.")
3604 extensions = property(_getExtensions, _setExtensions, None, "Extensions configuration in terms of a C{ExtensionsConfig} object.")
3605 options = property(_getOptions, _setOptions, None, "Options configuration in terms of a C{OptionsConfig} object.")
3606 collect = property(_getCollect, _setCollect, None, "Collect configuration in terms of a C{CollectConfig} object.")
3607 stage = property(_getStage, _setStage, None, "Stage configuration in terms of a C{StageConfig} object.")
3608 store = property(_getStore, _setStore, None, "Store configuration in terms of a C{StoreConfig} object.")
3609 purge = property(_getPurge, _setPurge, None, "Purge configuration in terms of a C{PurgeConfig} object.")
3610
3611
3612
3613
3614
3615
3617 """
3618 Extracts configuration into an XML document.
3619
3620 If C{xmlPath} is not provided, then the XML document will be returned as
3621 a string. If C{xmlPath} is provided, then the XML document will be written
3622 to the file and C{None} will be returned.
3623
3624 Unless the C{validate} parameter is C{False}, the L{Config.validate}
3625 method will be called (with its default arguments) against the
3626 configuration before extracting the XML. If configuration is not valid,
3627 then an XML document will not be extracted.
3628
3629 @note: It is strongly suggested that the C{validate} option always be set
3630 to C{True} (the default) unless there is a specific need to write an
3631 invalid configuration file to disk.
3632
3633 @param xmlPath: Path to an XML file to create on disk.
3634 @type xmlPath: Absolute path to a file.
3635
3636 @param validate: Validate the document before extracting it.
3637 @type validate: Boolean true/false.
3638
3639 @return: XML string data or C{None} as described above.
3640
3641 @raise ValueError: If configuration within the object is not valid.
3642 @raise IOError: If there is an error writing to the file.
3643 @raise OSError: If there is an error writing to the file.
3644 """
3645 if validate:
3646 self.validate()
3647 xmlData = self._extractXml()
3648 if xmlPath is not None:
3649 open(xmlPath, "w").write(xmlData)
3650 return None
3651 else:
3652 return xmlData
3653
3654 - def validate(self, requireOneAction=True, requireReference=False, requireExtensions=False, requireOptions=True,
3655 requireCollect=False, requireStage=False, requireStore=False, requirePurge=False):
3656 """
3657 Validates configuration represented by the object.
3658
3659 This method encapsulates all of the validations that should apply to a
3660 fully "complete" document but are not already taken care of by earlier
3661 validations. It also provides some extra convenience functionality which
3662 might be useful to some people. The process of validation is laid out in
3663 the I{Validation} section in the class notes (above).
3664
3665 @param requireOneAction: Require at least one of the collect, stage, store or purge sections.
3666 @param requireReference: Require the reference section.
3667 @param requireExtensions: Require the extensions section.
3668 @param requireOptions: Require the options section.
3669 @param requireCollect: Require the collect section.
3670 @param requireStage: Require the stage section.
3671 @param requireStore: Require the store section.
3672 @param requirePurge: Require the purge section.
3673
3674 @raise ValueError: If one of the validations fails.
3675 """
3676 if requireOneAction and (self.collect, self.stage, self.store, self.purge) == (None, None, None, None):
3677 raise ValueError("At least one of the collect, stage, store and purge sections is required.")
3678 if requireReference and self.reference is None:
3679 raise ValueError("The reference is section is required.")
3680 if requireExtensions and self.extensions is None:
3681 raise ValueError("The extensions is section is required.")
3682 if requireOptions and self.options is None:
3683 raise ValueError("The options is section is required.")
3684 if requireCollect and self.collect is None:
3685 raise ValueError("The collect is section is required.")
3686 if requireStage and self.stage is None:
3687 raise ValueError("The stage is section is required.")
3688 if requireStore and self.store is None:
3689 raise ValueError("The store is section is required.")
3690 if requirePurge and self.purge is None:
3691 raise ValueError("The purge is section is required.")
3692 self._validateContents()
3693
3694
3695
3696
3697
3698
3700 """
3701 Internal method to parse an XML string into the object.
3702
3703 This method parses the XML document into a DOM tree (C{xmlDom}) and then
3704 calls individual static methods to parse each of the individual
3705 configuration sections.
3706
3707 Most of the validation we do here has to do with whether the document can
3708 be parsed and whether any values which exist are valid. We don't do much
3709 validation as to whether required elements actually exist unless we have
3710 to to make sense of the document (instead, that's the job of the
3711 L{validate} method).
3712
3713 @param xmlData: XML data to be parsed
3714 @type xmlData: String data
3715
3716 @raise ValueError: If the XML cannot be successfully parsed.
3717 """
3718 (xmlDom, parentNode) = createInputDom(xmlData)
3719 self._reference = Config._parseReference(parentNode)
3720 self._extensions = Config._parseExtensions(parentNode)
3721 self._options = Config._parseOptions(parentNode)
3722 self._collect = Config._parseCollect(parentNode)
3723 self._stage = Config._parseStage(parentNode)
3724 self._store = Config._parseStore(parentNode)
3725 self._purge = Config._parsePurge(parentNode)
3726
3728 """
3729 Parses a reference configuration section.
3730
3731 We read the following fields::
3732
3733 author //cb_config/reference/author
3734 revision //cb_config/reference/revision
3735 description //cb_config/reference/description
3736 generator //cb_config/reference/generator
3737
3738 @param parentNode: Parent node to search beneath.
3739
3740 @return: C{ReferenceConfig} object or C{None} if the section does not exist.
3741 @raise ValueError: If some filled-in value is invalid.
3742 """
3743 reference = None
3744 sectionNode = readFirstChild(parentNode, "reference")
3745 if sectionNode is not None:
3746 reference = ReferenceConfig()
3747 reference.author = readString(sectionNode, "author")
3748 reference.revision = readString(sectionNode, "revision")
3749 reference.description = readString(sectionNode, "description")
3750 reference.generator = readString(sectionNode, "generator")
3751 return reference
3752 _parseReference = staticmethod(_parseReference)
3753
3755 """
3756 Parses an extensions configuration section.
3757
3758 We read the following fields::
3759
3760 orderMode //cb_config/extensions/order_mode
3761
3762 We also read groups of the following items, one list element per item::
3763
3764 name //cb_config/extensions/action/name
3765 module //cb_config/extensions/action/module
3766 function //cb_config/extensions/action/function
3767 index //cb_config/extensions/action/index
3768 dependencies //cb_config/extensions/action/depends
3769
3770 The extended actions are parsed by L{_parseExtendedActions}.
3771
3772 @param parentNode: Parent node to search beneath.
3773
3774 @return: C{ExtensionsConfig} object or C{None} if the section does not exist.
3775 @raise ValueError: If some filled-in value is invalid.
3776 """
3777 extensions = None
3778 sectionNode = readFirstChild(parentNode, "extensions")
3779 if sectionNode is not None:
3780 extensions = ExtensionsConfig()
3781 extensions.orderMode = readString(sectionNode, "order_mode")
3782 extensions.actions = Config._parseExtendedActions(sectionNode)
3783 return extensions
3784 _parseExtensions = staticmethod(_parseExtensions)
3785
3787 """
3788 Parses a options configuration section.
3789
3790 We read the following fields::
3791
3792 startingDay //cb_config/options/starting_day
3793 workingDir //cb_config/options/working_dir
3794 backupUser //cb_config/options/backup_user
3795 backupGroup //cb_config/options/backup_group
3796 rcpCommand //cb_config/options/rcp_command
3797
3798 We also read groups of the following items, one list element per
3799 item::
3800
3801 overrides //cb_config/options/override
3802
3803 The overrides are parsed by L{_parseOverrides}.
3804
3805 @param parentNode: Parent node to search beneath.
3806
3807 @return: C{OptionsConfig} object or C{None} if the section does not exist.
3808 @raise ValueError: If some filled-in value is invalid.
3809 """
3810 options = None
3811 sectionNode = readFirstChild(parentNode, "options")
3812 if sectionNode is not None:
3813 options = OptionsConfig()
3814 options.startingDay = readString(sectionNode, "starting_day")
3815 options.workingDir = readString(sectionNode, "working_dir")
3816 options.backupUser = readString(sectionNode, "backup_user")
3817 options.backupGroup = readString(sectionNode, "backup_group")
3818 options.rcpCommand = readString(sectionNode, "rcp_command")
3819 options.overrides = Config._parseOverrides(sectionNode)
3820 options.hooks = Config._parseHooks(sectionNode)
3821 return options
3822 _parseOptions = staticmethod(_parseOptions)
3823
3825 """
3826 Parses a collect configuration section.
3827
3828 We read the following individual fields::
3829
3830 targetDir //cb_config/collect/collect_dir
3831 collectMode //cb_config/collect/collect_mode
3832 archiveMode //cb_config/collect/archive_mode
3833 ignoreFile //cb_config/collect/ignore_file
3834
3835 We also read groups of the following items, one list element per
3836 item::
3837
3838 absoluteExcludePaths //cb_config/collect/exclude/abs_path
3839 excludePatterns //cb_config/collect/exclude/pattern
3840 collectFiles //cb_config/collect/file
3841 collectDirs //cb_config/collect/dir
3842
3843 The exclusions are parsed by L{_parseExclusions}, the collect files are
3844 parsed by L{_parseCollectFiles}, and the directories are parsed by
3845 L{_parseCollectDirs}.
3846
3847 @param parentNode: Parent node to search beneath.
3848
3849 @return: C{CollectConfig} object or C{None} if the section does not exist.
3850 @raise ValueError: If some filled-in value is invalid.
3851 """
3852 collect = None
3853 sectionNode = readFirstChild(parentNode, "collect")
3854 if sectionNode is not None:
3855 collect = CollectConfig()
3856 collect.targetDir = readString(sectionNode, "collect_dir")
3857 collect.collectMode = readString(sectionNode, "collect_mode")
3858 collect.archiveMode = readString(sectionNode, "archive_mode")
3859 collect.ignoreFile = readString(sectionNode, "ignore_file")
3860 (collect.absoluteExcludePaths, unused, collect.excludePatterns) = Config._parseExclusions(sectionNode)
3861 collect.collectFiles = Config._parseCollectFiles(sectionNode)
3862 collect.collectDirs = Config._parseCollectDirs(sectionNode)
3863 return collect
3864 _parseCollect = staticmethod(_parseCollect)
3865
3867 """
3868 Parses a stage configuration section.
3869
3870 We read the following individual fields::
3871
3872 targetDir //cb_config/stage/staging_dir
3873
3874 We also read groups of the following items, one list element per
3875 item::
3876
3877 localPeers //cb_config/stage/peer
3878 remotePeers //cb_config/stage/peer
3879
3880 The individual peer entries are parsed by L{_parsePeers}.
3881
3882 @param parentNode: Parent node to search beneath.
3883
3884 @return: C{StageConfig} object or C{None} if the section does not exist.
3885 @raise ValueError: If some filled-in value is invalid.
3886 """
3887 stage = None
3888 sectionNode = readFirstChild(parentNode, "stage")
3889 if sectionNode is not None:
3890 stage = StageConfig()
3891 stage.targetDir = readString(sectionNode, "staging_dir")
3892 (stage.localPeers, stage.remotePeers) = Config._parsePeers(sectionNode)
3893 return stage
3894 _parseStage = staticmethod(_parseStage)
3895
3897 """
3898 Parses a store configuration section.
3899
3900 We read the following fields::
3901
3902 sourceDir //cb_config/store/source_dir
3903 mediaType //cb_config/store/media_type
3904 deviceType //cb_config/store/device_type
3905 devicePath //cb_config/store/target_device
3906 deviceScsiId //cb_config/store/target_scsi_id
3907 driveSpeed //cb_config/store/drive_speed
3908 checkData //cb_config/store/check_data
3909 checkMedia //cb_config/store/check_media
3910 warnMidnite //cb_config/store/warn_midnite
3911 noEject //cb_config/store/no_eject
3912
3913 Blanking behavior configuration is parsed by the C{_parseBlankBehavior}
3914 method.
3915
3916 @param parentNode: Parent node to search beneath.
3917
3918 @return: C{StoreConfig} object or C{None} if the section does not exist.
3919 @raise ValueError: If some filled-in value is invalid.
3920 """
3921 store = None
3922 sectionNode = readFirstChild(parentNode, "store")
3923 if sectionNode is not None:
3924 store = StoreConfig()
3925 store.sourceDir = readString(sectionNode, "source_dir")
3926 store.mediaType = readString(sectionNode, "media_type")
3927 store.deviceType = readString(sectionNode, "device_type")
3928 store.devicePath = readString(sectionNode, "target_device")
3929 store.deviceScsiId = readString(sectionNode, "target_scsi_id")
3930 store.driveSpeed = readInteger(sectionNode, "drive_speed")
3931 store.checkData = readBoolean(sectionNode, "check_data")
3932 store.checkMedia = readBoolean(sectionNode, "check_media")
3933 store.warnMidnite = readBoolean(sectionNode, "warn_midnite")
3934 store.noEject = readBoolean(sectionNode, "no_eject")
3935 store.blankBehavior = Config._parseBlankBehavior(sectionNode)
3936 return store
3937 _parseStore = staticmethod(_parseStore)
3938
3940 """
3941 Parses a purge configuration section.
3942
3943 We read groups of the following items, one list element per
3944 item::
3945
3946 purgeDirs //cb_config/purge/dir
3947
3948 The individual directory entries are parsed by L{_parsePurgeDirs}.
3949
3950 @param parentNode: Parent node to search beneath.
3951
3952 @return: C{PurgeConfig} object or C{None} if the section does not exist.
3953 @raise ValueError: If some filled-in value is invalid.
3954 """
3955 purge = None
3956 sectionNode = readFirstChild(parentNode, "purge")
3957 if sectionNode is not None:
3958 purge = PurgeConfig()
3959 purge.purgeDirs = Config._parsePurgeDirs(sectionNode)
3960 return purge
3961 _parsePurge = staticmethod(_parsePurge)
3962
3964 """
3965 Reads extended actions data from immediately beneath the parent.
3966
3967 We read the following individual fields from each extended action::
3968
3969 name name
3970 module module
3971 function function
3972 index index
3973 dependencies depends
3974
3975 Dependency information is parsed by the C{_parseDependencies} method.
3976
3977 @param parentNode: Parent node to search beneath.
3978
3979 @return: List of extended actions.
3980 @raise ValueError: If the data at the location can't be read
3981 """
3982 lst = []
3983 for entry in readChildren(parentNode, "action"):
3984 if isElement(entry):
3985 action = ExtendedAction()
3986 action.name = readString(entry, "name")
3987 action.module = readString(entry, "module")
3988 action.function = readString(entry, "function")
3989 action.index = readInteger(entry, "index")
3990 action.dependencies = Config._parseDependencies(entry)
3991 lst.append(action);
3992 if lst == []:
3993 lst = None
3994 return lst
3995 _parseExtendedActions = staticmethod(_parseExtendedActions)
3996
3998 """
3999 Reads exclusions data from immediately beneath the parent.
4000
4001 We read groups of the following items, one list element per item::
4002
4003 absolute exclude/abs_path
4004 relative exclude/rel_path
4005 patterns exclude/pattern
4006
4007 If there are none of some pattern (i.e. no relative path items) then
4008 C{None} will be returned for that item in the tuple.
4009
4010 This method can be used to parse exclusions on both the collect
4011 configuration level and on the collect directory level within collect
4012 configuration.
4013
4014 @param parentNode: Parent node to search beneath.
4015
4016 @return: Tuple of (absolute, relative, patterns) exclusions.
4017 """
4018 sectionNode = readFirstChild(parentNode, "exclude")
4019 if sectionNode is None:
4020 return (None, None, None)
4021 else:
4022 absolute = readStringList(sectionNode, "abs_path")
4023 relative = readStringList(sectionNode, "rel_path")
4024 patterns = readStringList(sectionNode, "pattern")
4025 return (absolute, relative, patterns)
4026 _parseExclusions = staticmethod(_parseExclusions)
4027
4029 """
4030 Reads a list of C{CommandOverride} objects from immediately beneath the parent.
4031
4032 We read the following individual fields::
4033
4034 command command
4035 absolutePath abs_path
4036
4037 @param parentNode: Parent node to search beneath.
4038
4039 @return: List of C{CommandOverride} objects or C{None} if none are found.
4040 @raise ValueError: If some filled-in value is invalid.
4041 """
4042 lst = []
4043 for entry in readChildren(parentNode, "override"):
4044 if isElement(entry):
4045 override = CommandOverride()
4046 override.command = readString(entry, "command")
4047 override.absolutePath = readString(entry, "abs_path")
4048 lst.append(override)
4049 if lst == []:
4050 lst = None
4051 return lst
4052 _parseOverrides = staticmethod(_parseOverrides)
4053
4055 """
4056 Reads a list of C{ActionHook} objects from immediately beneath the parent.
4057
4058 We read the following individual fields::
4059
4060 action action
4061 command command
4062
4063 @param parentNode: Parent node to search beneath.
4064
4065 @return: List of C{ActionHook} objects or C{None} if none are found.
4066 @raise ValueError: If some filled-in value is invalid.
4067 """
4068 lst = []
4069 for entry in readChildren(parentNode, "pre_action_hook"):
4070 if isElement(entry):
4071 hook = PreActionHook()
4072 hook.action = readString(entry, "action")
4073 hook.command = readString(entry, "command")
4074 lst.append(hook)
4075 for entry in readChildren(parentNode, "post_action_hook"):
4076 if isElement(entry):
4077 hook = PostActionHook()
4078 hook.action = readString(entry, "action")
4079 hook.command = readString(entry, "command")
4080 lst.append(hook)
4081 if lst == []:
4082 lst = None
4083 return lst
4084 _parseHooks = staticmethod(_parseHooks)
4085
4087 """
4088 Reads a list of C{CollectFile} objects from immediately beneath the parent.
4089
4090 We read the following individual fields::
4091
4092 absolutePath abs_path
4093 collectMode mode I{or} collect_mode
4094 archiveMode archive_mode
4095
4096 The collect mode is a special case. Just a C{mode} tag is accepted, but
4097 we prefer C{collect_mode} for consistency with the rest of the config
4098 file and to avoid confusion with the archive mode. If both are provided,
4099 only C{mode} will be used.
4100
4101 @param parentNode: Parent node to search beneath.
4102
4103 @return: List of C{CollectFile} objects or C{None} if none are found.
4104 @raise ValueError: If some filled-in value is invalid.
4105 """
4106 lst = []
4107 for entry in readChildren(parentNode, "file"):
4108 if isElement(entry):
4109 cfile = CollectFile()
4110 cfile.absolutePath = readString(entry, "abs_path")
4111 cfile.collectMode = readString(entry, "mode")
4112 if cfile.collectMode is None:
4113 cfile.collectMode = readString(entry, "collect_mode")
4114 cfile.archiveMode = readString(entry, "archive_mode")
4115 lst.append(cfile)
4116 if lst == []:
4117 lst = None
4118 return lst
4119 _parseCollectFiles = staticmethod(_parseCollectFiles)
4120
4122 """
4123 Reads a list of C{CollectDir} objects from immediately beneath the parent.
4124
4125 We read the following individual fields::
4126
4127 absolutePath abs_path
4128 collectMode mode I{or} collect_mode
4129 archiveMode archive_mode
4130 ignoreFile ignore_file
4131
4132 The collect mode is a special case. Just a C{mode} tag is accepted for
4133 backwards compatibility, but we prefer C{collect_mode} for consistency
4134 with the rest of the config file and to avoid confusion with the archive
4135 mode. If both are provided, only C{mode} will be used.
4136
4137 We also read groups of the following items, one list element per
4138 item::
4139
4140 absoluteExcludePaths exclude/abs_path
4141 relativeExcludePaths exclude/rel_path
4142 excludePatterns exclude/pattern
4143
4144 The exclusions are parsed by L{_parseExclusions}.
4145
4146 @param parentNode: Parent node to search beneath.
4147
4148 @return: List of C{CollectDir} objects or C{None} if none are found.
4149 @raise ValueError: If some filled-in value is invalid.
4150 """
4151 lst = []
4152 for entry in readChildren(parentNode, "dir"):
4153 if isElement(entry):
4154 cdir = CollectDir()
4155 cdir.absolutePath = readString(entry, "abs_path")
4156 cdir.collectMode = readString(entry, "mode")
4157 if cdir.collectMode is None:
4158 cdir.collectMode = readString(entry, "collect_mode")
4159 cdir.archiveMode = readString(entry, "archive_mode")
4160 cdir.ignoreFile = readString(entry, "ignore_file")
4161 (cdir.absoluteExcludePaths, cdir.relativeExcludePaths, cdir.excludePatterns) = Config._parseExclusions(entry)
4162 lst.append(cdir)
4163 if lst == []:
4164 lst = None
4165 return lst
4166 _parseCollectDirs = staticmethod(_parseCollectDirs)
4167
4169 """
4170 Reads a list of C{PurgeDir} objects from immediately beneath the parent.
4171
4172 We read the following individual fields::
4173
4174 absolutePath <baseExpr>/abs_path
4175 retainDays <baseExpr>/retain_days
4176
4177 @param parentNode: Parent node to search beneath.
4178
4179 @return: List of C{PurgeDir} objects or C{None} if none are found.
4180 @raise ValueError: If the data at the location can't be read
4181 """
4182 lst = []
4183 for entry in readChildren(parentNode, "dir"):
4184 if isElement(entry):
4185 cdir = PurgeDir()
4186 cdir.absolutePath = readString(entry, "abs_path")
4187 cdir.retainDays = readInteger(entry, "retain_days")
4188 lst.append(cdir)
4189 if lst == []:
4190 lst = None
4191 return lst
4192 _parsePurgeDirs = staticmethod(_parsePurgeDirs)
4193
4195 """
4196 Reads remote and local peer data from immediately beneath the parent.
4197
4198 We read the following individual fields for both remote
4199 and local peers::
4200
4201 name name
4202 collectDir collect_dir
4203
4204 We also read the following individual fields for remote peers
4205 only::
4206
4207 remoteUser backup_user
4208 rcpCommand rcp_command
4209
4210 Additionally, the value in the C{type} field is used to determine whether
4211 this entry is a remote peer. If the type is C{"remote"}, it's a remote
4212 peer, and if the type is C{"local"}, it's a remote peer.
4213
4214 If there are none of one type of peer (i.e. no local peers) then C{None}
4215 will be returned for that item in the tuple.
4216
4217 @param parentNode: Parent node to search beneath.
4218
4219 @return: Tuple of (local, remote) peer lists.
4220 @raise ValueError: If the data at the location can't be read
4221 """
4222 localPeers = []
4223 remotePeers = []
4224 for entry in readChildren(parentNode, "peer"):
4225 if isElement(entry):
4226 peerType = readString(entry, "type")
4227 if peerType == "local":
4228 localPeer = LocalPeer()
4229 localPeer.name = readString(entry, "name")
4230 localPeer.collectDir = readString(entry, "collect_dir")
4231 localPeers.append(localPeer)
4232 elif peerType == "remote":
4233 remotePeer = RemotePeer()
4234 remotePeer.name = readString(entry, "name")
4235 remotePeer.collectDir = readString(entry, "collect_dir")
4236 remotePeer.remoteUser = readString(entry, "backup_user")
4237 remotePeer.rcpCommand = readString(entry, "rcp_command")
4238 remotePeers.append(remotePeer)
4239 if localPeers == []:
4240 localPeers = None
4241 if remotePeers == []:
4242 remotePeers = None
4243 return (localPeers, remotePeers)
4244 _parsePeers = staticmethod(_parsePeers)
4245
4247 """
4248 Reads extended action dependency information from a parent node.
4249
4250 We read the following individual fields::
4251
4252 runBefore depends/run_before
4253 runAfter depends/run_after
4254
4255 Each of these fields is a comma-separated list of action names.
4256
4257 The result is placed into an C{ActionDependencies} object.
4258
4259 If the dependencies parent node does not exist, C{None} will be returned.
4260 Otherwise, an C{ActionDependencies} object will always be created, even
4261 if it does not contain any actual dependencies in it.
4262
4263 @param parentNode: Parent node to search beneath.
4264
4265 @return: C{ActionDependencies} object or C{None}.
4266 @raise ValueError: If the data at the location can't be read
4267 """
4268 sectionNode = readFirstChild(parentNode, "depends")
4269 if sectionNode is None:
4270 return None
4271 else:
4272 runBefore = readString(sectionNode, "run_before")
4273 runAfter = readString(sectionNode, "run_after")
4274 beforeList = Config._parseCommaSeparatedString(runBefore)
4275 afterList = Config._parseCommaSeparatedString(runAfter)
4276 return ActionDependencies(beforeList, afterList)
4277 _parseDependencies = staticmethod(_parseDependencies)
4278
4280 """
4281 Parses a list of values out of a comma-separated string.
4282
4283 The items in the list are split by comma, and then have whitespace
4284 stripped. As a special case, if C{commaString} is C{None}, then C{None}
4285 will be returned.
4286
4287 @param commaString: List of values in comma-separated string format.
4288 @return: Values from commaString split into a list, or C{None}.
4289 """
4290 if commaString is None:
4291 return None
4292 else:
4293 pass1 = commaString.split(",")
4294 pass2 = []
4295 for item in pass1:
4296 item = item.strip()
4297 if len(item) > 0:
4298 pass2.append(item)
4299 return pass2
4300 _parseCommaSeparatedString = staticmethod(_parseCommaSeparatedString)
4301
4303 """
4304 Reads a single C{BlankBehavior} object from immediately beneath the parent.
4305
4306 We read the following individual fields::
4307
4308 blankMode blank_behavior/mode
4309 blankFactor blank_behavior/factor
4310
4311 @param parentNode: Parent node to search beneath.
4312
4313 @return: C{BlankBehavior} object or C{None} if none if the section is not found
4314 @raise ValueError: If some filled-in value is invalid.
4315 """
4316 blankBehavior = None
4317 sectionNode = readFirstChild(parentNode, "blank_behavior")
4318 if sectionNode is not None:
4319 blankBehavior = BlankBehavior()
4320 blankBehavior.blankMode = readString(sectionNode, "mode")
4321 blankBehavior.blankFactor = readString(sectionNode, "factor")
4322 return blankBehavior
4323 _parseBlankBehavior = staticmethod(_parseBlankBehavior)
4324
4325
4326
4327
4328
4329
4331 """
4332 Internal method to extract configuration into an XML string.
4333
4334 This method assumes that the internal L{validate} method has been called
4335 prior to extracting the XML, if the caller cares. No validation will be
4336 done internally.
4337
4338 As a general rule, fields that are set to C{None} will be extracted into
4339 the document as empty tags. The same goes for container tags that are
4340 filled based on lists - if the list is empty or C{None}, the container
4341 tag will be empty.
4342 """
4343 (xmlDom, parentNode) = createOutputDom()
4344 Config._addReference(xmlDom, parentNode, self.reference)
4345 Config._addExtensions(xmlDom, parentNode, self.extensions)
4346 Config._addOptions(xmlDom, parentNode, self.options)
4347 Config._addCollect(xmlDom, parentNode, self.collect)
4348 Config._addStage(xmlDom, parentNode, self.stage)
4349 Config._addStore(xmlDom, parentNode, self.store)
4350 Config._addPurge(xmlDom, parentNode, self.purge)
4351 xmlData = serializeDom(xmlDom)
4352 xmlDom.unlink()
4353 return xmlData
4354
4356 """
4357 Adds a <reference> configuration section as the next child of a parent.
4358
4359 We add the following fields to the document::
4360
4361 author //cb_config/reference/author
4362 revision //cb_config/reference/revision
4363 description //cb_config/reference/description
4364 generator //cb_config/reference/generator
4365
4366 If C{referenceConfig} is C{None}, then no container will be added.
4367
4368 @param xmlDom: DOM tree as from L{createOutputDom}.
4369 @param parentNode: Parent that the section should be appended to.
4370 @param referenceConfig: Reference configuration section to be added to the document.
4371 """
4372 if referenceConfig is not None:
4373 sectionNode = addContainerNode(xmlDom, parentNode, "reference")
4374 addStringNode(xmlDom, sectionNode, "author", referenceConfig.author)
4375 addStringNode(xmlDom, sectionNode, "revision", referenceConfig.revision)
4376 addStringNode(xmlDom, sectionNode, "description", referenceConfig.description)
4377 addStringNode(xmlDom, sectionNode, "generator", referenceConfig.generator)
4378 _addReference = staticmethod(_addReference)
4379
4381 """
4382 Adds an <extensions> configuration section as the next child of a parent.
4383
4384 We add the following fields to the document::
4385
4386 order_mode //cb_config/extensions/order_mode
4387
4388 We also add groups of the following items, one list element per item::
4389
4390 actions //cb_config/extensions/action
4391
4392 The extended action entries are added by L{_addExtendedAction}.
4393
4394 If C{extensionsConfig} is C{None}, then no container will be added.
4395
4396 @param xmlDom: DOM tree as from L{createOutputDom}.
4397 @param parentNode: Parent that the section should be appended to.
4398 @param extensionsConfig: Extensions configuration section to be added to the document.
4399 """
4400 if extensionsConfig is not None:
4401 sectionNode = addContainerNode(xmlDom, parentNode, "extensions")
4402 addStringNode(xmlDom, sectionNode, "order_mode", extensionsConfig.orderMode)
4403 if extensionsConfig.actions is not None:
4404 for action in extensionsConfig.actions:
4405 Config._addExtendedAction(xmlDom, sectionNode, action)
4406 _addExtensions = staticmethod(_addExtensions)
4407
4409 """
4410 Adds a <options> configuration section as the next child of a parent.
4411
4412 We add the following fields to the document::
4413
4414 startingDay //cb_config/options/starting_day
4415 workingDir //cb_config/options/working_dir
4416 backupUser //cb_config/options/backup_user
4417 backupGroup //cb_config/options/backup_group
4418 rcpCommand //cb_config/options/rcp_command
4419
4420 We also add groups of the following items, one list element per
4421 item::
4422
4423 overrides //cb_config/options/override
4424 hooks //cb_config/options/pre_action_hook
4425 hooks //cb_config/options/post_action_hook
4426
4427 The individual override items are added by L{_addOverride}. The
4428 individual hook items are added by L{_addHook}.
4429
4430 If C{optionsConfig} is C{None}, then no container will be added.
4431
4432 @param xmlDom: DOM tree as from L{createOutputDom}.
4433 @param parentNode: Parent that the section should be appended to.
4434 @param optionsConfig: Options configuration section to be added to the document.
4435 """
4436 if optionsConfig is not None:
4437 sectionNode = addContainerNode(xmlDom, parentNode, "options")
4438 addStringNode(xmlDom, sectionNode, "starting_day", optionsConfig.startingDay)
4439 addStringNode(xmlDom, sectionNode, "working_dir", optionsConfig.workingDir)
4440 addStringNode(xmlDom, sectionNode, "backup_user", optionsConfig.backupUser)
4441 addStringNode(xmlDom, sectionNode, "backup_group", optionsConfig.backupGroup)
4442 addStringNode(xmlDom, sectionNode, "rcp_command", optionsConfig.rcpCommand)
4443 if optionsConfig.overrides is not None:
4444 for override in optionsConfig.overrides:
4445 Config._addOverride(xmlDom, sectionNode, override)
4446 if optionsConfig.hooks is not None:
4447 for hook in optionsConfig.hooks:
4448 Config._addHook(xmlDom, sectionNode, hook)
4449 _addOptions = staticmethod(_addOptions)
4450
4452 """
4453 Adds a <collect> configuration section as the next child of a parent.
4454
4455 We add the following fields to the document::
4456
4457 targetDir //cb_config/collect/collect_dir
4458 collectMode //cb_config/collect/collect_mode
4459 archiveMode //cb_config/collect/archive_mode
4460 ignoreFile //cb_config/collect/ignore_file
4461
4462 We also add groups of the following items, one list element per
4463 item::
4464
4465 absoluteExcludePaths //cb_config/collect/exclude/abs_path
4466 excludePatterns //cb_config/collect/exclude/pattern
4467 collectFiles //cb_config/collect/file
4468 collectDirs //cb_config/collect/dir
4469
4470 The individual collect files are added by L{_addCollectFile} and
4471 individual collect directories are added by L{_addCollectDir}.
4472
4473 If C{collectConfig} is C{None}, then no container will be added.
4474
4475 @param xmlDom: DOM tree as from L{createOutputDom}.
4476 @param parentNode: Parent that the section should be appended to.
4477 @param collectConfig: Collect configuration section to be added to the document.
4478 """
4479 if collectConfig is not None:
4480 sectionNode = addContainerNode(xmlDom, parentNode, "collect")
4481 addStringNode(xmlDom, sectionNode, "collect_dir", collectConfig.targetDir)
4482 addStringNode(xmlDom, sectionNode, "collect_mode", collectConfig.collectMode)
4483 addStringNode(xmlDom, sectionNode, "archive_mode", collectConfig.archiveMode)
4484 addStringNode(xmlDom, sectionNode, "ignore_file", collectConfig.ignoreFile)
4485 if ((collectConfig.absoluteExcludePaths is not None and collectConfig.absoluteExcludePaths != []) or
4486 (collectConfig.excludePatterns is not None and collectConfig.excludePatterns != [])):
4487 excludeNode = addContainerNode(xmlDom, sectionNode, "exclude")
4488 if collectConfig.absoluteExcludePaths is not None:
4489 for absolutePath in collectConfig.absoluteExcludePaths:
4490 addStringNode(xmlDom, excludeNode, "abs_path", absolutePath)
4491 if collectConfig.excludePatterns is not None:
4492 for pattern in collectConfig.excludePatterns:
4493 addStringNode(xmlDom, excludeNode, "pattern", pattern)
4494 if collectConfig.collectFiles is not None:
4495 for collectFile in collectConfig.collectFiles:
4496 Config._addCollectFile(xmlDom, sectionNode, collectFile)
4497 if collectConfig.collectDirs is not None:
4498 for collectDir in collectConfig.collectDirs:
4499 Config._addCollectDir(xmlDom, sectionNode, collectDir)
4500 _addCollect = staticmethod(_addCollect)
4501
4502 - def _addStage(xmlDom, parentNode, stageConfig):
4503 """
4504 Adds a <stage> configuration section as the next child of a parent.
4505
4506 We add the following fields to the document::
4507
4508 targetDir //cb_config/stage/staging_dir
4509
4510 We also add groups of the following items, one list element per
4511 item::
4512
4513 localPeers //cb_config/stage/peer
4514 remotePeers //cb_config/stage/peer
4515
4516 The individual local and remote peer entries are added by
4517 L{_addLocalPeer} and L{_addRemotePeer}, respectively.
4518
4519 If C{stageConfig} is C{None}, then no container will be added.
4520
4521 @param xmlDom: DOM tree as from L{createOutputDom}.
4522 @param parentNode: Parent that the section should be appended to.
4523 @param stageConfig: Stage configuration section to be added to the document.
4524 """
4525 if stageConfig is not None:
4526 sectionNode = addContainerNode(xmlDom, parentNode, "stage")
4527 addStringNode(xmlDom, sectionNode, "staging_dir", stageConfig.targetDir)
4528 if stageConfig.localPeers is not None:
4529 for localPeer in stageConfig.localPeers:
4530 Config._addLocalPeer(xmlDom, sectionNode, localPeer)
4531 if stageConfig.remotePeers is not None:
4532 for remotePeer in stageConfig.remotePeers:
4533 Config._addRemotePeer(xmlDom, sectionNode, remotePeer)
4534 _addStage = staticmethod(_addStage)
4535
4536 - def _addStore(xmlDom, parentNode, storeConfig):
4537 """
4538 Adds a <store> configuration section as the next child of a parent.
4539
4540 We add the following fields to the document::
4541
4542 sourceDir //cb_config/store/source_dir
4543 mediaType //cb_config/store/media_type
4544 deviceType //cb_config/store/device_type
4545 devicePath //cb_config/store/target_device
4546 deviceScsiId //cb_config/store/target_scsi_id
4547 driveSpeed //cb_config/store/drive_speed
4548 checkData //cb_config/store/check_data
4549 checkMedia //cb_config/store/check_media
4550 warnMidnite //cb_config/store/warn_midnite
4551 noEject //cb_config/store/no_eject
4552
4553 Blanking behavior configuration is added by the L{_addBlankBehavior}
4554 method.
4555
4556 If C{storeConfig} is C{None}, then no container will be added.
4557
4558 @param xmlDom: DOM tree as from L{createOutputDom}.
4559 @param parentNode: Parent that the section should be appended to.
4560 @param storeConfig: Store configuration section to be added to the document.
4561 """
4562 if storeConfig is not None:
4563 sectionNode = addContainerNode(xmlDom, parentNode, "store")
4564 addStringNode(xmlDom, sectionNode, "source_dir", storeConfig.sourceDir)
4565 addStringNode(xmlDom, sectionNode, "media_type", storeConfig.mediaType)
4566 addStringNode(xmlDom, sectionNode, "device_type", storeConfig.deviceType)
4567 addStringNode(xmlDom, sectionNode, "target_device", storeConfig.devicePath)
4568 addStringNode(xmlDom, sectionNode, "target_scsi_id", storeConfig.deviceScsiId)
4569 addIntegerNode(xmlDom, sectionNode, "drive_speed", storeConfig.driveSpeed)
4570 addBooleanNode(xmlDom, sectionNode, "check_data", storeConfig.checkData)
4571 addBooleanNode(xmlDom, sectionNode, "check_media", storeConfig.checkMedia)
4572 addBooleanNode(xmlDom, sectionNode, "warn_midnite", storeConfig.warnMidnite)
4573 addBooleanNode(xmlDom, sectionNode, "no_eject", storeConfig.noEject)
4574 Config._addBlankBehavior(xmlDom, sectionNode, storeConfig.blankBehavior)
4575 _addStore = staticmethod(_addStore)
4576
4577 - def _addPurge(xmlDom, parentNode, purgeConfig):
4578 """
4579 Adds a <purge> configuration section as the next child of a parent.
4580
4581 We add the following fields to the document::
4582
4583 purgeDirs //cb_config/purge/dir
4584
4585 The individual directory entries are added by L{_addPurgeDir}.
4586
4587 If C{purgeConfig} is C{None}, then no container will be added.
4588
4589 @param xmlDom: DOM tree as from L{createOutputDom}.
4590 @param parentNode: Parent that the section should be appended to.
4591 @param purgeConfig: Purge configuration section to be added to the document.
4592 """
4593 if purgeConfig is not None:
4594 sectionNode = addContainerNode(xmlDom, parentNode, "purge")
4595 if purgeConfig.purgeDirs is not None:
4596 for purgeDir in purgeConfig.purgeDirs:
4597 Config._addPurgeDir(xmlDom, sectionNode, purgeDir)
4598 _addPurge = staticmethod(_addPurge)
4599
4601 """
4602 Adds an extended action container as the next child of a parent.
4603
4604 We add the following fields to the document::
4605
4606 name action/name
4607 module action/module
4608 function action/function
4609 index action/index
4610 dependencies action/depends
4611
4612 Dependencies are added by the L{_addDependencies} method.
4613
4614 The <action> node itself is created as the next child of the parent node.
4615 This method only adds one action node. The parent must loop for each action
4616 in the C{ExtensionsConfig} object.
4617
4618 If C{action} is C{None}, this method call will be a no-op.
4619
4620 @param xmlDom: DOM tree as from L{createOutputDom}.
4621 @param parentNode: Parent that the section should be appended to.
4622 @param action: Purge directory to be added to the document.
4623 """
4624 if action is not None:
4625 sectionNode = addContainerNode(xmlDom, parentNode, "action")
4626 addStringNode(xmlDom, sectionNode, "name", action.name)
4627 addStringNode(xmlDom, sectionNode, "module", action.module)
4628 addStringNode(xmlDom, sectionNode, "function", action.function)
4629 addIntegerNode(xmlDom, sectionNode, "index", action.index)
4630 Config._addDependencies(xmlDom, sectionNode, action.dependencies)
4631 _addExtendedAction = staticmethod(_addExtendedAction)
4632
4634 """
4635 Adds a command override container as the next child of a parent.
4636
4637 We add the following fields to the document::
4638
4639 command override/command
4640 absolutePath override/abs_path
4641
4642 The <override> node itself is created as the next child of the parent
4643 node. This method only adds one override node. The parent must loop for
4644 each override in the C{OptionsConfig} object.
4645
4646 If C{override} is C{None}, this method call will be a no-op.
4647
4648 @param xmlDom: DOM tree as from L{createOutputDom}.
4649 @param parentNode: Parent that the section should be appended to.
4650 @param override: Command override to be added to the document.
4651 """
4652 if override is not None:
4653 sectionNode = addContainerNode(xmlDom, parentNode, "override")
4654 addStringNode(xmlDom, sectionNode, "command", override.command)
4655 addStringNode(xmlDom, sectionNode, "abs_path", override.absolutePath)
4656 _addOverride = staticmethod(_addOverride)
4657
4658 - def _addHook(xmlDom, parentNode, hook):
4659 """
4660 Adds an action hook container as the next child of a parent.
4661
4662 The behavior varies depending on the value of the C{before} and C{after}
4663 flags on the hook. If the C{before} flag is set, it's a pre-action hook,
4664 and we'll add the following fields::
4665
4666 action pre_action_hook/action
4667 command pre_action_hook/command
4668
4669 If the C{after} flag is set, it's a post-action hook, and we'll add the
4670 following fields::
4671
4672 action post_action_hook/action
4673 command post_action_hook/command
4674
4675 The <pre_action_hook> or <post_action_hook> node itself is created as the
4676 next child of the parent node. This method only adds one hook node. The
4677 parent must loop for each hook in the C{OptionsConfig} object.
4678
4679 If C{hook} is C{None}, this method call will be a no-op.
4680
4681 @param xmlDom: DOM tree as from L{createOutputDom}.
4682 @param parentNode: Parent that the section should be appended to.
4683 @param hook: Command hook to be added to the document.
4684 """
4685 if hook is not None:
4686 if hook.before:
4687 sectionNode = addContainerNode(xmlDom, parentNode, "pre_action_hook")
4688 else:
4689 sectionNode = addContainerNode(xmlDom, parentNode, "post_action_hook")
4690 addStringNode(xmlDom, sectionNode, "action", hook.action)
4691 addStringNode(xmlDom, sectionNode, "command", hook.command)
4692 _addHook = staticmethod(_addHook)
4693
4695 """
4696 Adds a collect file container as the next child of a parent.
4697
4698 We add the following fields to the document::
4699
4700 absolutePath dir/abs_path
4701 collectMode dir/collect_mode
4702 archiveMode dir/archive_mode
4703
4704 Note that for consistency with collect directory handling we'll only emit
4705 the preferred C{collect_mode} tag.
4706
4707 The <file> node itself is created as the next child of the parent node.
4708 This method only adds one collect file node. The parent must loop
4709 for each collect file in the C{CollectConfig} object.
4710
4711 If C{collectFile} is C{None}, this method call will be a no-op.
4712
4713 @param xmlDom: DOM tree as from L{createOutputDom}.
4714 @param parentNode: Parent that the section should be appended to.
4715 @param collectFile: Collect file to be added to the document.
4716 """
4717 if collectFile is not None:
4718 sectionNode = addContainerNode(xmlDom, parentNode, "file")
4719 addStringNode(xmlDom, sectionNode, "abs_path", collectFile.absolutePath)
4720 addStringNode(xmlDom, sectionNode, "collect_mode", collectFile.collectMode)
4721 addStringNode(xmlDom, sectionNode, "archive_mode", collectFile.archiveMode)
4722 _addCollectFile = staticmethod(_addCollectFile)
4723
4725 """
4726 Adds a collect directory container as the next child of a parent.
4727
4728 We add the following fields to the document::
4729
4730 absolutePath dir/abs_path
4731 collectMode dir/collect_mode
4732 archiveMode dir/archive_mode
4733 ignoreFile dir/ignore_file
4734
4735 Note that an original XML document might have listed the collect mode
4736 using the C{mode} tag, since we accept both C{collect_mode} and C{mode}.
4737 However, here we'll only emit the preferred C{collect_mode} tag.
4738
4739 We also add groups of the following items, one list element per item::
4740
4741 absoluteExcludePaths dir/exclude/abs_path
4742 relativeExcludePaths dir/exclude/rel_path
4743 excludePatterns dir/exclude/pattern
4744
4745 The <dir> node itself is created as the next child of the parent node.
4746 This method only adds one collect directory node. The parent must loop
4747 for each collect directory in the C{CollectConfig} object.
4748
4749 If C{collectDir} is C{None}, this method call will be a no-op.
4750
4751 @param xmlDom: DOM tree as from L{createOutputDom}.
4752 @param parentNode: Parent that the section should be appended to.
4753 @param collectDir: Collect directory to be added to the document.
4754 """
4755 if collectDir is not None:
4756 sectionNode = addContainerNode(xmlDom, parentNode, "dir")
4757 addStringNode(xmlDom, sectionNode, "abs_path", collectDir.absolutePath)
4758 addStringNode(xmlDom, sectionNode, "collect_mode", collectDir.collectMode)
4759 addStringNode(xmlDom, sectionNode, "archive_mode", collectDir.archiveMode)
4760 addStringNode(xmlDom, sectionNode, "ignore_file", collectDir.ignoreFile)
4761 if ((collectDir.absoluteExcludePaths is not None and collectDir.absoluteExcludePaths != []) or
4762 (collectDir.relativeExcludePaths is not None and collectDir.relativeExcludePaths != []) or
4763 (collectDir.excludePatterns is not None and collectDir.excludePatterns != [])):
4764 excludeNode = addContainerNode(xmlDom, sectionNode, "exclude")
4765 if collectDir.absoluteExcludePaths is not None:
4766 for absolutePath in collectDir.absoluteExcludePaths:
4767 addStringNode(xmlDom, excludeNode, "abs_path", absolutePath)
4768 if collectDir.relativeExcludePaths is not None:
4769 for relativePath in collectDir.relativeExcludePaths:
4770 addStringNode(xmlDom, excludeNode, "rel_path", relativePath)
4771 if collectDir.excludePatterns is not None:
4772 for pattern in collectDir.excludePatterns:
4773 addStringNode(xmlDom, excludeNode, "pattern", pattern)
4774 _addCollectDir = staticmethod(_addCollectDir)
4775
4777 """
4778 Adds a local peer container as the next child of a parent.
4779
4780 We add the following fields to the document::
4781
4782 name peer/name
4783 collectDir peer/collect_dir
4784
4785 Additionally, C{peer/type} is filled in with C{"local"}, since this is a
4786 local peer.
4787
4788 The <peer> node itself is created as the next child of the parent node.
4789 This method only adds one peer node. The parent must loop for each peer
4790 in the C{StageConfig} object.
4791
4792 If C{localPeer} is C{None}, this method call will be a no-op.
4793
4794 @param xmlDom: DOM tree as from L{createOutputDom}.
4795 @param parentNode: Parent that the section should be appended to.
4796 @param localPeer: Purge directory to be added to the document.
4797 """
4798 if localPeer is not None:
4799 sectionNode = addContainerNode(xmlDom, parentNode, "peer")
4800 addStringNode(xmlDom, sectionNode, "name", localPeer.name)
4801 addStringNode(xmlDom, sectionNode, "type", "local")
4802 addStringNode(xmlDom, sectionNode, "collect_dir", localPeer.collectDir)
4803 _addLocalPeer = staticmethod(_addLocalPeer)
4804
4806 """
4807 Adds a remote peer container as the next child of a parent.
4808
4809 We add the following fields to the document::
4810
4811 name peer/name
4812 collectDir peer/collect_dir
4813 remoteUser peer/backup_user
4814 rcpCommand peer/rcp_command
4815
4816 Additionally, C{peer/type} is filled in with C{"remote"}, since this is a
4817 remote peer.
4818
4819 The <peer> node itself is created as the next child of the parent node.
4820 This method only adds one peer node. The parent must loop for each peer
4821 in the C{StageConfig} object.
4822
4823 If C{remotePeer} is C{None}, this method call will be a no-op.
4824
4825 @param xmlDom: DOM tree as from L{createOutputDom}.
4826 @param parentNode: Parent that the section should be appended to.
4827 @param remotePeer: Purge directory to be added to the document.
4828 """
4829 if remotePeer is not None:
4830 sectionNode = addContainerNode(xmlDom, parentNode, "peer")
4831 addStringNode(xmlDom, sectionNode, "name", remotePeer.name)
4832 addStringNode(xmlDom, sectionNode, "type", "remote")
4833 addStringNode(xmlDom, sectionNode, "collect_dir", remotePeer.collectDir)
4834 addStringNode(xmlDom, sectionNode, "backup_user", remotePeer.remoteUser)
4835 addStringNode(xmlDom, sectionNode, "rcp_command", remotePeer.rcpCommand)
4836 _addRemotePeer = staticmethod(_addRemotePeer)
4837
4839 """
4840 Adds a purge directory container as the next child of a parent.
4841
4842 We add the following fields to the document::
4843
4844 absolutePath dir/abs_path
4845 retainDays dir/retain_days
4846
4847 The <dir> node itself is created as the next child of the parent node.
4848 This method only adds one purge directory node. The parent must loop for
4849 each purge directory in the C{PurgeConfig} object.
4850
4851 If C{purgeDir} is C{None}, this method call will be a no-op.
4852
4853 @param xmlDom: DOM tree as from L{createOutputDom}.
4854 @param parentNode: Parent that the section should be appended to.
4855 @param purgeDir: Purge directory to be added to the document.
4856 """
4857 if purgeDir is not None:
4858 sectionNode = addContainerNode(xmlDom, parentNode, "dir")
4859 addStringNode(xmlDom, sectionNode, "abs_path", purgeDir.absolutePath)
4860 addIntegerNode(xmlDom, sectionNode, "retain_days", purgeDir.retainDays)
4861 _addPurgeDir = staticmethod(_addPurgeDir)
4862
4864 """
4865 Adds a extended action dependencies to parent node.
4866
4867 We add the following fields to the document::
4868
4869 runBefore depends/run_before
4870 runAfter depends/run_after
4871
4872 If C{dependencies} is C{None}, this method call will be a no-op.
4873
4874 @param xmlDom: DOM tree as from L{createOutputDom}.
4875 @param parentNode: Parent that the section should be appended to.
4876 @param dependencies: C{ActionDependencies} object to be added to the document
4877 """
4878 if dependencies is not None:
4879 sectionNode = addContainerNode(xmlDom, parentNode, "depends")
4880 runBefore = Config._buildCommaSeparatedString(dependencies.beforeList)
4881 runAfter = Config._buildCommaSeparatedString(dependencies.afterList)
4882 addStringNode(xmlDom, sectionNode, "run_before", runBefore)
4883 addStringNode(xmlDom, sectionNode, "run_after", runAfter)
4884 _addDependencies = staticmethod(_addDependencies)
4885
4887 """
4888 Creates a comma-separated string from a list of values.
4889
4890 As a special case, if C{valueList} is C{None}, then C{None} will be
4891 returned.
4892
4893 @param valueList: List of values to be placed into a string
4894
4895 @return: Values from valueList as a comma-separated string.
4896 """
4897 if valueList is None:
4898 return None
4899 return ",".join(valueList)
4900 _buildCommaSeparatedString = staticmethod(_buildCommaSeparatedString)
4901
4903 """
4904 Adds a blanking behavior container as the next child of a parent.
4905
4906 We add the following fields to the document::
4907
4908 blankMode blank_behavior/mode
4909 blankFactor blank_behavior/factor
4910
4911 The <blank_behavior> node itself is created as the next child of the
4912 parent node.
4913
4914 If C{blankBehavior} is C{None}, this method call will be a no-op.
4915
4916 @param xmlDom: DOM tree as from L{createOutputDom}.
4917 @param parentNode: Parent that the section should be appended to.
4918 @param blankBehavior: Blanking behavior to be added to the document.
4919 """
4920 if blankBehavior is not None:
4921 sectionNode = addContainerNode(xmlDom, parentNode, "blank_behavior")
4922 addStringNode(xmlDom, sectionNode, "mode", blankBehavior.blankMode)
4923 addStringNode(xmlDom, sectionNode, "factor", blankBehavior.blankFactor)
4924 _addBlankBehavior = staticmethod(_addBlankBehavior)
4925
4926
4927
4928
4929
4930
4932 """
4933 Validates configuration contents per rules discussed in module
4934 documentation.
4935
4936 This is the second pass at validation. It ensures that any filled-in
4937 section contains valid data. Any sections which is not set to C{None} is
4938 validated per the rules for that section, laid out in the module
4939 documentation (above).
4940
4941 @raise ValueError: If configuration is invalid.
4942 """
4943 self._validateReference()
4944 self._validateExtensions()
4945 self._validateOptions()
4946 self._validateCollect()
4947 self._validateStage()
4948 self._validateStore()
4949 self._validatePurge()
4950
4952 """
4953 Validates reference configuration.
4954 There are currently no reference-related validations.
4955 @raise ValueError: If reference configuration is invalid.
4956 """
4957 pass
4958
4960 """
4961 Validates extensions configuration.
4962
4963 The list of actions may be either C{None} or an empty list C{[]} if
4964 desired. Each extended action must include a name, a module, and a
4965 function.
4966
4967 Then, if the order mode is None or "index", an index is required; and if
4968 the order mode is "dependency", dependency information is required.
4969
4970 @raise ValueError: If reference configuration is invalid.
4971 """
4972 if self.extensions is not None:
4973 if self.extensions.actions is not None:
4974 names = []
4975 for action in self.extensions.actions:
4976 if action.name is None:
4977 raise ValueError("Each extended action must set a name.")
4978 names.append(action.name)
4979 if action.module is None:
4980 raise ValueError("Each extended action must set a module.")
4981 if action.function is None:
4982 raise ValueError("Each extended action must set a function.")
4983 if self.extensions.orderMode is None or self.extensions.orderMode == "index":
4984 if action.index is None:
4985 raise ValueError("Each extended action must set an index, based on order mode.")
4986 elif self.extensions.orderMode == "dependency":
4987 if action.dependencies is None:
4988 raise ValueError("Each extended action must set dependency information, based on order mode.")
4989 Config._checkUnique("Duplicate extension names exist:", names)
4990
4992 """
4993 Validates options configuration.
4994
4995 All fields must be filled in. The rcp command is used as a default value
4996 for all remote peers in the staging section. Remote peers can also rely
4997 on the backup user as the default remote user name if they choose.
4998
4999 @raise ValueError: If reference configuration is invalid.
5000 """
5001 if self.options is not None:
5002 if self.options.startingDay is None:
5003 raise ValueError("Options section starting day must be filled in.")
5004 if self.options.workingDir is None:
5005 raise ValueError("Options section working directory must be filled in.")
5006 if self.options.backupUser is None:
5007 raise ValueError("Options section backup user must be filled in.")
5008 if self.options.backupGroup is None:
5009 raise ValueError("Options section backup group must be filled in.")
5010 if self.options.rcpCommand is None:
5011 raise ValueError("Options section remote copy command must be filled in.")
5012
5014 """
5015 Validates collect configuration.
5016
5017 The target directory must be filled in. The collect mode, archive mode
5018 and ignore file are all optional. The list of absolute paths to exclude
5019 and patterns to exclude may be either C{None} or an empty list C{[]} if
5020 desired.
5021
5022 Each collect directory entry must contain an absolute path to collect,
5023 and then must either be able to take collect mode, archive mode and
5024 ignore file configuration from the parent C{CollectConfig} object, or
5025 must set each value on its own. The list of absolute paths to exclude,
5026 relative paths to exclude and patterns to exclude may be either C{None}
5027 or an empty list C{[]} if desired. Any list of absolute paths to exclude
5028 or patterns to exclude will be combined with the same list in the
5029 C{CollectConfig} object to make the complete list for a given directory.
5030
5031 @raise ValueError: If collect configuration is invalid.
5032 """
5033 if self.collect is not None:
5034 if self.collect.targetDir is None:
5035 raise ValueError("Collect section target directory must be filled in.")
5036 if self.collect.collectFiles is not None:
5037 for collectFile in self.collect.collectFiles:
5038 if collectFile.absolutePath is None:
5039 raise ValueError("Each collect file must set an absolute path.")
5040 if self.collect.collectMode is None and collectFile.collectMode is None:
5041 raise ValueError("Collect mode must either be set in parent collect section or individual collect file.")
5042 if self.collect.archiveMode is None and collectFile.archiveMode is None:
5043 raise ValueError("Archive mode must either be set in parent collect section or individual collect file.")
5044 if self.collect.collectDirs is not None:
5045 for collectDir in self.collect.collectDirs:
5046 if collectDir.absolutePath is None:
5047 raise ValueError("Each collect directory must set an absolute path.")
5048 if self.collect.collectMode is None and collectDir.collectMode is None:
5049 raise ValueError("Collect mode must either be set in parent collect section or individual collect directory.")
5050 if self.collect.archiveMode is None and collectDir.archiveMode is None:
5051 raise ValueError("Archive mode must either be set in parent collect section or individual collect directory.")
5052 if self.collect.ignoreFile is None and collectDir.ignoreFile is None:
5053 raise ValueError("Ignore file must either be set in parent collect section or individual collect directory.")
5054
5056 """
5057 Validates stage configuration.
5058
5059 The target directory must be filled in. There must be at least one peer
5060 (remote or local) between the two lists of peers. A list with no entries
5061 can be either C{None} or an empty list C{[]} if desired.
5062
5063 Local peers must be completely filled in, including both name and collect
5064 directory. Remote peers must also fill in the name and collect
5065 directory, but can leave the remote user and rcp command unset. In this
5066 case, the remote user is assumed to match the backup user from the
5067 options section and rcp command is taken directly from the options
5068 section.
5069
5070 @raise ValueError: If stage configuration is invalid.
5071 """
5072 if self.stage is not None:
5073 if self.stage.targetDir is None:
5074 raise ValueError("Stage section target directory must be filled in.")
5075 if self.stage.localPeers is None and self.stage.remotePeers is None:
5076 raise ValueError("Stage section must contain at least one backup peer.")
5077 if self.stage.localPeers is None and self.stage.remotePeers is not None:
5078 if len(self.stage.remotePeers) < 1:
5079 raise ValueError("Stage section must contain at least one backup peer.")
5080 elif self.stage.localPeers is not None and self.stage.remotePeers is None:
5081 if len(self.stage.localPeers) < 1:
5082 raise ValueError("Stage section must contain at least one backup peer.")
5083 elif self.stage.localPeers is not None and self.stage.remotePeers is not None:
5084 if len(self.stage.localPeers) + len(self.stage.remotePeers) < 1:
5085 raise ValueError("Stage section must contain at least one backup peer.")
5086 names = []
5087 if self.stage.localPeers is not None:
5088 for localPeer in self.stage.localPeers:
5089 if localPeer.name is None:
5090 raise ValueError("Local peers must set a name.")
5091 names.append(localPeer.name)
5092 if localPeer.collectDir is None:
5093 raise ValueError("Local peers must set a collect directory.")
5094 if self.stage.remotePeers is not None:
5095 for remotePeer in self.stage.remotePeers:
5096 if remotePeer.name is None:
5097 raise ValueError("Remote peers must set a name.")
5098 names.append(remotePeer.name)
5099 if remotePeer.collectDir is None:
5100 raise ValueError("Remote peers must set a collect directory.")
5101 if (self.options is None or self.options.backupUser is None) and remotePeer.remoteUser is None:
5102 raise ValueError("Remote user must either be set in options section or individual remote peer.")
5103 if (self.options is None or self.options.rcpCommand is None) and remotePeer.rcpCommand is None:
5104 raise ValueError("Remote copy command must either be set in options section or individual remote peer.")
5105 Config._checkUnique("Duplicate peer names exist:", names)
5106
5108 """
5109 Validates store configuration.
5110
5111 The device type, drive speed, and blanking behavior are optional. All
5112 other values are required. Missing booleans will be set to defaults.
5113
5114 If blanking behavior is provided, then both a blanking mode and a
5115 blanking factor are required.
5116
5117 The image writer functionality in the C{writer} module is supposed to be
5118 able to handle a device speed of C{None}.
5119
5120 Any caller which needs a "real" (non-C{None}) value for the device type
5121 can use C{DEFAULT_DEVICE_TYPE}, which is guaranteed to be sensible.
5122
5123 This is also where we make sure that the media type -- which is already a
5124 valid type -- matches up properly with the device type.
5125
5126 @raise ValueError: If store configuration is invalid.
5127 """
5128 if self.store is not None:
5129 if self.store.sourceDir is None:
5130 raise ValueError("Store section source directory must be filled in.")
5131 if self.store.mediaType is None:
5132 raise ValueError("Store section media type must be filled in.")
5133 if self.store.devicePath is None:
5134 raise ValueError("Store section device path must be filled in.")
5135 if self.store.deviceType == None or self.store.deviceType == "cdwriter":
5136 if self.store.mediaType not in VALID_CD_MEDIA_TYPES:
5137 raise ValueError("Media type must match device type.")
5138 elif self.store.deviceType == "dvdwriter":
5139 if self.store.mediaType not in VALID_DVD_MEDIA_TYPES:
5140 raise ValueError("Media type must match device type.")
5141 if self.store.blankBehavior is not None:
5142 if self.store.blankBehavior.blankMode is None and self.store.blankBehavior.blankFactor is None:
5143 raise ValueError("If blanking behavior is provided, all values must be filled in.")
5144
5146 """
5147 Validates purge configuration.
5148
5149 The list of purge directories may be either C{None} or an empty list
5150 C{[]} if desired. All purge directories must contain a path and a retain
5151 days value.
5152
5153 @raise ValueError: If purge configuration is invalid.
5154 """
5155 if self.purge is not None:
5156 if self.purge.purgeDirs is not None:
5157 for purgeDir in self.purge.purgeDirs:
5158 if purgeDir.absolutePath is None:
5159 raise ValueError("Each purge directory must set an absolute path.")
5160 if purgeDir.retainDays is None:
5161 raise ValueError("Each purge directory must set a retain days value.")
5162
5163
5164
5165
5166
5167
5169 """
5170 Checks that all values are unique.
5171
5172 The values list is checked for duplicate values. If there are
5173 duplicates, an exception is thrown. All duplicate values are listed in
5174 the exception.
5175
5176 @param prefix: Prefix to use in the thrown exception
5177 @param values: List of values to check
5178
5179 @raise ValueError: If there are duplicates in the list
5180 """
5181 values.sort()
5182 duplicates = []
5183 for i in range(1, len(values)):
5184 if values[i-1] == values[i]:
5185 duplicates.append(values[i])
5186 if duplicates:
5187 raise ValueError("%s %s" % (prefix, duplicates))
5188 _checkUnique = staticmethod(_checkUnique)
5189