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