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