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, dereference, 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, dereference=False):
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 dereference: Whether to dereference links that are followed.
1378 @param absoluteExcludePaths: List of absolute paths to exclude.
1379 @param relativeExcludePaths: List of relative paths to exclude.
1380 @param excludePatterns: List of regular expression patterns to exclude.
1381
1382 @raise ValueError: If one of the values is invalid.
1383 """
1384 self._absolutePath = None
1385 self._collectMode = None
1386 self._archiveMode = None
1387 self._ignoreFile = None
1388 self._linkDepth = None
1389 self._deference = None
1390 self._absoluteExcludePaths = None
1391 self._relativeExcludePaths = None
1392 self._excludePatterns = None
1393 self.absolutePath = absolutePath
1394 self.collectMode = collectMode
1395 self.archiveMode = archiveMode
1396 self.ignoreFile = ignoreFile
1397 self.linkDepth = linkDepth
1398 self.dereference = dereference
1399 self.absoluteExcludePaths = absoluteExcludePaths
1400 self.relativeExcludePaths = relativeExcludePaths
1401 self.excludePatterns = excludePatterns
1402
1404 """
1405 Official string representation for class instance.
1406 """
1407 return "CollectDir(%s, %s, %s, %s, %s, %s, %s, %s, %s)" % (self.absolutePath, self.collectMode,
1408 self.archiveMode, self.ignoreFile,
1409 self.absoluteExcludePaths,
1410 self.relativeExcludePaths,
1411 self.excludePatterns,
1412 self.linkDepth, self.dereference)
1413
1415 """
1416 Informal string representation for class instance.
1417 """
1418 return self.__repr__()
1419
1421 """
1422 Definition of equals operator for this class.
1423 Lists within this class are "unordered" for equality comparisons.
1424 @param other: Other object to compare to.
1425 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
1426 """
1427 if other is None:
1428 return 1
1429 if self._absolutePath != other._absolutePath:
1430 if self._absolutePath < other.absolutePath:
1431 return -1
1432 else:
1433 return 1
1434 if self._collectMode != other._collectMode:
1435 if self._collectMode < other._collectMode:
1436 return -1
1437 else:
1438 return 1
1439 if self._archiveMode != other._archiveMode:
1440 if self._archiveMode < other._archiveMode:
1441 return -1
1442 else:
1443 return 1
1444 if self._ignoreFile != other._ignoreFile:
1445 if self._ignoreFile < other._ignoreFile:
1446 return -1
1447 else:
1448 return 1
1449 if self._linkDepth != other._linkDepth:
1450 if self._linkDepth < other._linkDepth:
1451 return -1
1452 else:
1453 return 1
1454 if self._dereference != other._dereference:
1455 if self._dereference < other._dereference:
1456 return -1
1457 else:
1458 return 1
1459 if self._absoluteExcludePaths != other._absoluteExcludePaths:
1460 if self._absoluteExcludePaths < other._absoluteExcludePaths:
1461 return -1
1462 else:
1463 return 1
1464 if self._relativeExcludePaths != other._relativeExcludePaths:
1465 if self._relativeExcludePaths < other._relativeExcludePaths:
1466 return -1
1467 else:
1468 return 1
1469 if self._excludePatterns != other._excludePatterns:
1470 if self._excludePatterns < other._excludePatterns:
1471 return -1
1472 else:
1473 return 1
1474 return 0
1475
1477 """
1478 Property target used to set the absolute path.
1479 The value must be an absolute path if it is not C{None}.
1480 It does not have to exist on disk at the time of assignment.
1481 @raise ValueError: If the value is not an absolute path.
1482 @raise ValueError: If the value cannot be encoded properly.
1483 """
1484 if value is not None:
1485 if not os.path.isabs(value):
1486 raise ValueError("Not an absolute path: [%s]" % value)
1487 self._absolutePath = encodePath(value)
1488
1490 """
1491 Property target used to get the absolute path.
1492 """
1493 return self._absolutePath
1494
1496 """
1497 Property target used to set the collect mode.
1498 If not C{None}, the mode must be one of the values in L{VALID_COLLECT_MODES}.
1499 @raise ValueError: If the value is not valid.
1500 """
1501 if value is not None:
1502 if value not in VALID_COLLECT_MODES:
1503 raise ValueError("Collect mode must be one of %s." % VALID_COLLECT_MODES)
1504 self._collectMode = value
1505
1507 """
1508 Property target used to get the collect mode.
1509 """
1510 return self._collectMode
1511
1513 """
1514 Property target used to set the archive mode.
1515 If not C{None}, the mode must be one of the values in L{VALID_ARCHIVE_MODES}.
1516 @raise ValueError: If the value is not valid.
1517 """
1518 if value is not None:
1519 if value not in VALID_ARCHIVE_MODES:
1520 raise ValueError("Archive mode must be one of %s." % VALID_ARCHIVE_MODES)
1521 self._archiveMode = value
1522
1524 """
1525 Property target used to get the archive mode.
1526 """
1527 return self._archiveMode
1528
1530 """
1531 Property target used to set the ignore file.
1532 The value must be a non-empty string if it is not C{None}.
1533 @raise ValueError: If the value is an empty string.
1534 """
1535 if value is not None:
1536 if len(value) < 1:
1537 raise ValueError("The ignore file must be a non-empty string.")
1538 self._ignoreFile = value
1539
1541 """
1542 Property target used to get the ignore file.
1543 """
1544 return self._ignoreFile
1545
1547 """
1548 Property target used to set the link depth.
1549 The value must be an integer >= 0.
1550 @raise ValueError: If the value is not valid.
1551 """
1552 if value is None:
1553 self._linkDepth = None
1554 else:
1555 try:
1556 value = int(value)
1557 except TypeError:
1558 raise ValueError("Link depth value must be an integer >= 0.")
1559 if value < 0:
1560 raise ValueError("Link depth value must be an integer >= 0.")
1561 self._linkDepth = value
1562
1564 """
1565 Property target used to get the action linkDepth.
1566 """
1567 return self._linkDepth
1568
1570 """
1571 Property target used to set the dereference flag.
1572 No validations, but we normalize the value to C{True} or C{False}.
1573 """
1574 if value:
1575 self._dereference = True
1576 else:
1577 self._dereference = False
1578
1580 """
1581 Property target used to get the dereference flag.
1582 """
1583 return self._dereference
1584
1586 """
1587 Property target used to set the absolute exclude paths list.
1588 Either the value must be C{None} or each element must be an absolute path.
1589 Elements do not have to exist on disk at the time of assignment.
1590 @raise ValueError: If the value is not an absolute path.
1591 """
1592 if value is None:
1593 self._absoluteExcludePaths = None
1594 else:
1595 try:
1596 saved = self._absoluteExcludePaths
1597 self._absoluteExcludePaths = AbsolutePathList()
1598 self._absoluteExcludePaths.extend(value)
1599 except Exception, e:
1600 self._absoluteExcludePaths = saved
1601 raise e
1602
1604 """
1605 Property target used to get the absolute exclude paths list.
1606 """
1607 return self._absoluteExcludePaths
1608
1610 """
1611 Property target used to set the relative exclude paths list.
1612 Elements do not have to exist on disk at the time of assignment.
1613 """
1614 if value is None:
1615 self._relativeExcludePaths = None
1616 else:
1617 try:
1618 saved = self._relativeExcludePaths
1619 self._relativeExcludePaths = UnorderedList()
1620 self._relativeExcludePaths.extend(value)
1621 except Exception, e:
1622 self._relativeExcludePaths = saved
1623 raise e
1624
1626 """
1627 Property target used to get the relative exclude paths list.
1628 """
1629 return self._relativeExcludePaths
1630
1632 """
1633 Property target used to set the exclude patterns list.
1634 """
1635 if value is None:
1636 self._excludePatterns = None
1637 else:
1638 try:
1639 saved = self._excludePatterns
1640 self._excludePatterns = RegexList()
1641 self._excludePatterns.extend(value)
1642 except Exception, e:
1643 self._excludePatterns = saved
1644 raise e
1645
1647 """
1648 Property target used to get the exclude patterns list.
1649 """
1650 return self._excludePatterns
1651
1652 absolutePath = property(_getAbsolutePath, _setAbsolutePath, None, doc="Absolute path of the directory to collect.")
1653 collectMode = property(_getCollectMode, _setCollectMode, None, doc="Overridden collect mode for this directory.")
1654 archiveMode = property(_getArchiveMode, _setArchiveMode, None, doc="Overridden archive mode for this directory.")
1655 ignoreFile = property(_getIgnoreFile, _setIgnoreFile, None, doc="Overridden ignore file name for this directory.")
1656 linkDepth = property(_getLinkDepth, _setLinkDepth, None, doc="Maximum at which soft links should be followed.")
1657 dereference = property(_getDereference, _setDereference, None, doc="Whether to dereference links that are followed.")
1658 absoluteExcludePaths = property(_getAbsoluteExcludePaths, _setAbsoluteExcludePaths, None, "List of absolute paths to exclude.")
1659 relativeExcludePaths = property(_getRelativeExcludePaths, _setRelativeExcludePaths, None, "List of relative paths to exclude.")
1660 excludePatterns = property(_getExcludePatterns, _setExcludePatterns, None, "List of regular expression patterns to exclude.")
1661
1662
1663
1664
1665
1666
1668
1669 """
1670 Class representing a Cedar Backup purge directory.
1671
1672 As with all of the other classes that represent configuration sections, all
1673 of these values are optional. It is up to some higher-level construct to
1674 decide whether everything they need is filled in. Some validation is done
1675 on non-C{None} assignments through the use of the Python C{property()}
1676 construct.
1677
1678 The following restrictions exist on data in this class:
1679
1680 - The absolute path must be an absolute path
1681 - The retain days value must be an integer >= 0.
1682
1683 @sort: __init__, __repr__, __str__, __cmp__, absolutePath, retainDays
1684 """
1685
1686 - def __init__(self, absolutePath=None, retainDays=None):
1687 """
1688 Constructor for the C{PurgeDir} class.
1689
1690 @param absolutePath: Absolute path of the directory to be purged.
1691 @param retainDays: Number of days content within directory should be retained.
1692
1693 @raise ValueError: If one of the values is invalid.
1694 """
1695 self._absolutePath = None
1696 self._retainDays = None
1697 self.absolutePath = absolutePath
1698 self.retainDays = retainDays
1699
1701 """
1702 Official string representation for class instance.
1703 """
1704 return "PurgeDir(%s, %s)" % (self.absolutePath, self.retainDays)
1705
1707 """
1708 Informal string representation for class instance.
1709 """
1710 return self.__repr__()
1711
1713 """
1714 Definition of equals operator for this class.
1715 @param other: Other object to compare to.
1716 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
1717 """
1718 if other is None:
1719 return 1
1720 if self._absolutePath != other._absolutePath:
1721 if self._absolutePath < other._absolutePath:
1722 return -1
1723 else:
1724 return 1
1725 if self._retainDays != other._retainDays:
1726 if self._retainDays < other._retainDays:
1727 return -1
1728 else:
1729 return 1
1730 return 0
1731
1733 """
1734 Property target used to set the absolute path.
1735 The value must be an absolute path if it is not C{None}.
1736 It does not have to exist on disk at the time of assignment.
1737 @raise ValueError: If the value is not an absolute path.
1738 @raise ValueError: If the value cannot be encoded properly.
1739 """
1740 if value is not None:
1741 if not os.path.isabs(value):
1742 raise ValueError("Absolute path must, er, be an absolute path.")
1743 self._absolutePath = encodePath(value)
1744
1746 """
1747 Property target used to get the absolute path.
1748 """
1749 return self._absolutePath
1750
1752 """
1753 Property target used to set the retain days value.
1754 The value must be an integer >= 0.
1755 @raise ValueError: If the value is not valid.
1756 """
1757 if value is None:
1758 self._retainDays = None
1759 else:
1760 try:
1761 value = int(value)
1762 except TypeError:
1763 raise ValueError("Retain days value must be an integer >= 0.")
1764 if value < 0:
1765 raise ValueError("Retain days value must be an integer >= 0.")
1766 self._retainDays = value
1767
1769 """
1770 Property target used to get the absolute path.
1771 """
1772 return self._retainDays
1773
1774 absolutePath = property(_getAbsolutePath, _setAbsolutePath, None, "Absolute path of directory to purge.")
1775 retainDays = property(_getRetainDays, _setRetainDays, None, "Number of days content within directory should be retained.")
1776
1777
1778
1779
1780
1781
1783
1784 """
1785 Class representing a Cedar Backup peer.
1786
1787 As with all of the other classes that represent configuration sections, all
1788 of these values are optional. It is up to some higher-level construct to
1789 decide whether everything they need is filled in. Some validation is done
1790 on non-C{None} assignments through the use of the Python C{property()}
1791 construct.
1792
1793 The following restrictions exist on data in this class:
1794
1795 - The peer name must be a non-empty string.
1796 - The collect directory must be an absolute path.
1797
1798 @sort: __init__, __repr__, __str__, __cmp__, name, collectDir
1799 """
1800
1801 - def __init__(self, name=None, collectDir=None):
1802 """
1803 Constructor for the C{LocalPeer} class.
1804
1805 @param name: Name of the peer, typically a valid hostname.
1806 @param collectDir: Collect directory to stage files from on peer.
1807
1808 @raise ValueError: If one of the values is invalid.
1809 """
1810 self._name = None
1811 self._collectDir = None
1812 self.name = name
1813 self.collectDir = collectDir
1814
1816 """
1817 Official string representation for class instance.
1818 """
1819 return "LocalPeer(%s, %s)" % (self.name, self.collectDir)
1820
1822 """
1823 Informal string representation for class instance.
1824 """
1825 return self.__repr__()
1826
1828 """
1829 Definition of equals operator for this class.
1830 @param other: Other object to compare to.
1831 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
1832 """
1833 if other is None:
1834 return 1
1835 if self._name != other._name:
1836 if self._name < other._name:
1837 return -1
1838 else:
1839 return 1
1840 if self._collectDir != other._collectDir:
1841 if self._collectDir < other._collectDir:
1842 return -1
1843 else:
1844 return 1
1845 return 0
1846
1848 """
1849 Property target used to set the peer name.
1850 The value must be a non-empty string if it is not C{None}.
1851 @raise ValueError: If the value is an empty string.
1852 """
1853 if value is not None:
1854 if len(value) < 1:
1855 raise ValueError("The peer name must be a non-empty string.")
1856 self._name = value
1857
1859 """
1860 Property target used to get the peer name.
1861 """
1862 return self._name
1863
1865 """
1866 Property target used to set the collect directory.
1867 The value must be an absolute path if it is not C{None}.
1868 It does not have to exist on disk at the time of assignment.
1869 @raise ValueError: If the value is not an absolute path.
1870 @raise ValueError: If the value cannot be encoded properly.
1871 """
1872 if value is not None:
1873 if not os.path.isabs(value):
1874 raise ValueError("Collect directory must be an absolute path.")
1875 self._collectDir = encodePath(value)
1876
1878 """
1879 Property target used to get the collect directory.
1880 """
1881 return self._collectDir
1882
1883 name = property(_getName, _setName, None, "Name of the peer, typically a valid hostname.")
1884 collectDir = property(_getCollectDir, _setCollectDir, None, "Collect directory to stage files from on peer.")
1885
1886
1887
1888
1889
1890
1892
1893 """
1894 Class representing a Cedar Backup peer.
1895
1896 As with all of the other classes that represent configuration sections, all
1897 of these values are optional. It is up to some higher-level construct to
1898 decide whether everything they need is filled in. Some validation is done
1899 on non-C{None} assignments through the use of the Python C{property()}
1900 construct.
1901
1902 The following restrictions exist on data in this class:
1903
1904 - The peer name must be a non-empty string.
1905 - The collect directory must be an absolute path.
1906 - The remote user must be a non-empty string.
1907 - The rcp command must be a non-empty string.
1908 - The rsh command must be a non-empty string.
1909 - The cback command must be a non-empty string.
1910 - Any managed action name must be a non-empty string matching C{ACTION_NAME_REGEX}
1911
1912 @sort: __init__, __repr__, __str__, __cmp__, name, collectDir, remoteUser, rcpCommand
1913 """
1914
1915 - def __init__(self, name=None, collectDir=None, remoteUser=None,
1916 rcpCommand=None, rshCommand=None, cbackCommand=None,
1917 managed=False, managedActions=None):
1918 """
1919 Constructor for the C{RemotePeer} class.
1920
1921 @param name: Name of the peer, must be a valid hostname.
1922 @param collectDir: Collect directory to stage files from on peer.
1923 @param remoteUser: Name of backup user on remote peer.
1924 @param rcpCommand: Overridden rcp-compatible copy command for peer.
1925 @param rshCommand: Overridden rsh-compatible remote shell command for peer.
1926 @param cbackCommand: Overridden cback-compatible command to use on remote peer.
1927 @param managed: Indicates whether this is a managed peer.
1928 @param managedActions: Overridden set of actions that are managed on the peer.
1929
1930 @raise ValueError: If one of the values is invalid.
1931 """
1932 self._name = None
1933 self._collectDir = None
1934 self._remoteUser = None
1935 self._rcpCommand = None
1936 self._rshCommand = None
1937 self._cbackCommand = None
1938 self._managed = None
1939 self._managedActions = None
1940 self.name = name
1941 self.collectDir = collectDir
1942 self.remoteUser = remoteUser
1943 self.rcpCommand = rcpCommand
1944 self.rshCommand = rshCommand
1945 self.cbackCommand = cbackCommand
1946 self.managed = managed
1947 self.managedActions = managedActions
1948
1950 """
1951 Official string representation for class instance.
1952 """
1953 return "RemotePeer(%s, %s, %s, %s, %s, %s, %s, %s)" % (self.name, self.collectDir, self.remoteUser,
1954 self.rcpCommand, self.rshCommand, self.cbackCommand,
1955 self.managed, self.managedActions)
1956
1958 """
1959 Informal string representation for class instance.
1960 """
1961 return self.__repr__()
1962
1964 """
1965 Definition of equals operator for this class.
1966 @param other: Other object to compare to.
1967 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
1968 """
1969 if other is None:
1970 return 1
1971 if self._name != other._name:
1972 if self._name < other._name:
1973 return -1
1974 else:
1975 return 1
1976 if self._collectDir != other._collectDir:
1977 if self._collectDir < other._collectDir:
1978 return -1
1979 else:
1980 return 1
1981 if self._remoteUser != other._remoteUser:
1982 if self._remoteUser < other._remoteUser:
1983 return -1
1984 else:
1985 return 1
1986 if self._rcpCommand != other._rcpCommand:
1987 if self._rcpCommand < other._rcpCommand:
1988 return -1
1989 else:
1990 return 1
1991 if self._rshCommand != other._rshCommand:
1992 if self._rshCommand < other._rshCommand:
1993 return -1
1994 else:
1995 return 1
1996 if self._cbackCommand != other._cbackCommand:
1997 if self._cbackCommand < other._cbackCommand:
1998 return -1
1999 else:
2000 return 1
2001 if self._managed != other._managed:
2002 if self._managed < other._managed:
2003 return -1
2004 else:
2005 return 1
2006 if self._managedActions != other._managedActions:
2007 if self._managedActions < other._managedActions:
2008 return -1
2009 else:
2010 return 1
2011 return 0
2012
2014 """
2015 Property target used to set the peer name.
2016 The value must be a non-empty string if it is not C{None}.
2017 @raise ValueError: If the value is an empty string.
2018 """
2019 if value is not None:
2020 if len(value) < 1:
2021 raise ValueError("The peer name must be a non-empty string.")
2022 self._name = value
2023
2025 """
2026 Property target used to get the peer name.
2027 """
2028 return self._name
2029
2031 """
2032 Property target used to set the collect directory.
2033 The value must be an absolute path if it is not C{None}.
2034 It does not have to exist on disk at the time of assignment.
2035 @raise ValueError: If the value is not an absolute path.
2036 @raise ValueError: If the value cannot be encoded properly.
2037 """
2038 if value is not None:
2039 if not os.path.isabs(value):
2040 raise ValueError("Collect directory must be an absolute path.")
2041 self._collectDir = encodePath(value)
2042
2044 """
2045 Property target used to get the collect directory.
2046 """
2047 return self._collectDir
2048
2050 """
2051 Property target used to set the remote user.
2052 The value must be a non-empty string if it is not C{None}.
2053 @raise ValueError: If the value is an empty string.
2054 """
2055 if value is not None:
2056 if len(value) < 1:
2057 raise ValueError("The remote user must be a non-empty string.")
2058 self._remoteUser = value
2059
2061 """
2062 Property target used to get the remote user.
2063 """
2064 return self._remoteUser
2065
2067 """
2068 Property target used to set the rcp command.
2069 The value must be a non-empty string if it is not C{None}.
2070 @raise ValueError: If the value is an empty string.
2071 """
2072 if value is not None:
2073 if len(value) < 1:
2074 raise ValueError("The rcp command must be a non-empty string.")
2075 self._rcpCommand = value
2076
2078 """
2079 Property target used to get the rcp command.
2080 """
2081 return self._rcpCommand
2082
2084 """
2085 Property target used to set the rsh command.
2086 The value must be a non-empty string if it is not C{None}.
2087 @raise ValueError: If the value is an empty string.
2088 """
2089 if value is not None:
2090 if len(value) < 1:
2091 raise ValueError("The rsh command must be a non-empty string.")
2092 self._rshCommand = value
2093
2095 """
2096 Property target used to get the rsh command.
2097 """
2098 return self._rshCommand
2099
2101 """
2102 Property target used to set the cback command.
2103 The value must be a non-empty string if it is not C{None}.
2104 @raise ValueError: If the value is an empty string.
2105 """
2106 if value is not None:
2107 if len(value) < 1:
2108 raise ValueError("The cback command must be a non-empty string.")
2109 self._cbackCommand = value
2110
2112 """
2113 Property target used to get the cback command.
2114 """
2115 return self._cbackCommand
2116
2118 """
2119 Property target used to set the managed flag.
2120 No validations, but we normalize the value to C{True} or C{False}.
2121 """
2122 if value:
2123 self._managed = True
2124 else:
2125 self._managed = False
2126
2128 """
2129 Property target used to get the managed flag.
2130 """
2131 return self._managed
2132
2134 """
2135 Property target used to set the managed actions list.
2136 Elements do not have to exist on disk at the time of assignment.
2137 """
2138 if value is None:
2139 self._managedActions = None
2140 else:
2141 try:
2142 saved = self._managedActions
2143 self._managedActions = RegexMatchList(ACTION_NAME_REGEX, emptyAllowed=False, prefix="Action name")
2144 self._managedActions.extend(value)
2145 except Exception, e:
2146 self._managedActions = saved
2147 raise e
2148
2150 """
2151 Property target used to get the managed actions list.
2152 """
2153 return self._managedActions
2154
2155 name = property(_getName, _setName, None, "Name of the peer, must be a valid hostname.")
2156 collectDir = property(_getCollectDir, _setCollectDir, None, "Collect directory to stage files from on peer.")
2157 remoteUser = property(_getRemoteUser, _setRemoteUser, None, "Name of backup user on remote peer.")
2158 rcpCommand = property(_getRcpCommand, _setRcpCommand, None, "Overridden rcp-compatible copy command for peer.")
2159 rshCommand = property(_getRshCommand, _setRshCommand, None, "Overridden rsh-compatible remote shell command for peer.")
2160 cbackCommand = property(_getCbackCommand, _setCbackCommand, None, "Overridden cback-compatible command to use on remote peer.")
2161 managed = property(_getManaged, _setManaged, None, "Indicates whether this is a managed peer.")
2162 managedActions = property(_getManagedActions, _setManagedActions, None, "Overridden set of actions that are managed on the peer.")
2163
2164
2165
2166
2167
2168
2170
2171 """
2172 Class representing a Cedar Backup reference configuration.
2173
2174 The reference information is just used for saving off metadata about
2175 configuration and exists mostly for backwards-compatibility with Cedar
2176 Backup 1.x.
2177
2178 As with all of the other classes that represent configuration sections, all
2179 of these values are optional. It is up to some higher-level construct to
2180 decide whether everything they need is filled in. We don't do any
2181 validation on the contents of any of the fields, although we generally
2182 expect them to be strings.
2183
2184 @sort: __init__, __repr__, __str__, __cmp__, author, revision, description, generator
2185 """
2186
2187 - def __init__(self, author=None, revision=None, description=None, generator=None):
2188 """
2189 Constructor for the C{ReferenceConfig} class.
2190
2191 @param author: Author of the configuration file.
2192 @param revision: Revision of the configuration file.
2193 @param description: Description of the configuration file.
2194 @param generator: Tool that generated the configuration file.
2195 """
2196 self._author = None
2197 self._revision = None
2198 self._description = None
2199 self._generator = None
2200 self.author = author
2201 self.revision = revision
2202 self.description = description
2203 self.generator = generator
2204
2206 """
2207 Official string representation for class instance.
2208 """
2209 return "ReferenceConfig(%s, %s, %s, %s)" % (self.author, self.revision, self.description, self.generator)
2210
2212 """
2213 Informal string representation for class instance.
2214 """
2215 return self.__repr__()
2216
2218 """
2219 Definition of equals operator for this class.
2220 @param other: Other object to compare to.
2221 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
2222 """
2223 if other is None:
2224 return 1
2225 if self._author != other._author:
2226 if self._author < other._author:
2227 return -1
2228 else:
2229 return 1
2230 if self._revision != other._revision:
2231 if self._revision < other._revision:
2232 return -1
2233 else:
2234 return 1
2235 if self._description != other._description:
2236 if self._description < other._description:
2237 return -1
2238 else:
2239 return 1
2240 if self._generator != other._generator:
2241 if self._generator < other._generator:
2242 return -1
2243 else:
2244 return 1
2245 return 0
2246
2248 """
2249 Property target used to set the author value.
2250 No validations.
2251 """
2252 self._author = value
2253
2255 """
2256 Property target used to get the author value.
2257 """
2258 return self._author
2259
2261 """
2262 Property target used to set the revision value.
2263 No validations.
2264 """
2265 self._revision = value
2266
2268 """
2269 Property target used to get the revision value.
2270 """
2271 return self._revision
2272
2274 """
2275 Property target used to set the description value.
2276 No validations.
2277 """
2278 self._description = value
2279
2281 """
2282 Property target used to get the description value.
2283 """
2284 return self._description
2285
2287 """
2288 Property target used to set the generator value.
2289 No validations.
2290 """
2291 self._generator = value
2292
2294 """
2295 Property target used to get the generator value.
2296 """
2297 return self._generator
2298
2299 author = property(_getAuthor, _setAuthor, None, "Author of the configuration file.")
2300 revision = property(_getRevision, _setRevision, None, "Revision of the configuration file.")
2301 description = property(_getDescription, _setDescription, None, "Description of the configuration file.")
2302 generator = property(_getGenerator, _setGenerator, None, "Tool that generated the configuration file.")
2303
2304
2305
2306
2307
2308
2310
2311 """
2312 Class representing Cedar Backup extensions configuration.
2313
2314 Extensions configuration is used to specify "extended actions" implemented
2315 by code external to Cedar Backup. For instance, a hypothetical third party
2316 might write extension code to collect database repository data. If they
2317 write a properly-formatted extension function, they can use the extension
2318 configuration to map a command-line Cedar Backup action (i.e. "database")
2319 to their function.
2320
2321 As with all of the other classes that represent configuration sections, all
2322 of these values are optional. It is up to some higher-level construct to
2323 decide whether everything they need is filled in. Some validation is done
2324 on non-C{None} assignments through the use of the Python C{property()}
2325 construct.
2326
2327 The following restrictions exist on data in this class:
2328
2329 - If set, the order mode must be one of the values in C{VALID_ORDER_MODES}
2330 - The actions list must be a list of C{ExtendedAction} objects.
2331
2332 @sort: __init__, __repr__, __str__, __cmp__, orderMode, actions
2333 """
2334
2335 - def __init__(self, actions=None, orderMode=None):
2336 """
2337 Constructor for the C{ExtensionsConfig} class.
2338 @param actions: List of extended actions
2339 """
2340 self._orderMode = None
2341 self._actions = None
2342 self.orderMode = orderMode
2343 self.actions = actions
2344
2346 """
2347 Official string representation for class instance.
2348 """
2349 return "ExtensionsConfig(%s, %s)" % (self.orderMode, self.actions)
2350
2352 """
2353 Informal string representation for class instance.
2354 """
2355 return self.__repr__()
2356
2358 """
2359 Definition of equals operator for this class.
2360 @param other: Other object to compare to.
2361 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
2362 """
2363 if other is None:
2364 return 1
2365 if self._orderMode != other._orderMode:
2366 if self._orderMode < other._orderMode:
2367 return -1
2368 else:
2369 return 1
2370 if self._actions != other._actions:
2371 if self._actions < other._actions:
2372 return -1
2373 else:
2374 return 1
2375 return 0
2376
2378 """
2379 Property target used to set the order mode.
2380 The value must be one of L{VALID_ORDER_MODES}.
2381 @raise ValueError: If the value is not valid.
2382 """
2383 if value is not None:
2384 if value not in VALID_ORDER_MODES:
2385 raise ValueError("Order mode must be one of %s." % VALID_ORDER_MODES)
2386 self._orderMode = value
2387
2389 """
2390 Property target used to get the order mode.
2391 """
2392 return self._orderMode
2393
2395 """
2396 Property target used to set the actions list.
2397 Either the value must be C{None} or each element must be an C{ExtendedAction}.
2398 @raise ValueError: If the value is not a C{ExtendedAction}
2399 """
2400 if value is None:
2401 self._actions = None
2402 else:
2403 try:
2404 saved = self._actions
2405 self._actions = ObjectTypeList(ExtendedAction, "ExtendedAction")
2406 self._actions.extend(value)
2407 except Exception, e:
2408 self._actions = saved
2409 raise e
2410
2412 """
2413 Property target used to get the actions list.
2414 """
2415 return self._actions
2416
2417 orderMode = property(_getOrderMode, _setOrderMode, None, "Order mode for extensions, to control execution ordering.")
2418 actions = property(_getActions, _setActions, None, "List of extended actions.")
2419
2420
2421
2422
2423
2424
2426
2427 """
2428 Class representing a Cedar Backup global options configuration.
2429
2430 The options section is used to store global configuration options and
2431 defaults that can be applied to other sections.
2432
2433 As with all of the other classes that represent configuration sections, all
2434 of these values are optional. It is up to some higher-level construct to
2435 decide whether everything they need is filled in. Some validation is done
2436 on non-C{None} assignments through the use of the Python C{property()}
2437 construct.
2438
2439 The following restrictions exist on data in this class:
2440
2441 - The working directory must be an absolute path.
2442 - The starting day must be a day of the week in English, i.e. C{"monday"}, C{"tuesday"}, etc.
2443 - All of the other values must be non-empty strings if they are set to something other than C{None}.
2444 - The overrides list must be a list of C{CommandOverride} objects.
2445 - The hooks list must be a list of C{ActionHook} objects.
2446 - The cback command must be a non-empty string.
2447 - Any managed action name must be a non-empty string matching C{ACTION_NAME_REGEX}
2448
2449 @sort: __init__, __repr__, __str__, __cmp__, startingDay, workingDir,
2450 backupUser, backupGroup, rcpCommand, rshCommand, overrides
2451 """
2452
2453 - def __init__(self, startingDay=None, workingDir=None, backupUser=None,
2454 backupGroup=None, rcpCommand=None, overrides=None,
2455 hooks=None, rshCommand=None, cbackCommand=None,
2456 managedActions=None):
2457 """
2458 Constructor for the C{OptionsConfig} class.
2459
2460 @param startingDay: Day that starts the week.
2461 @param workingDir: Working (temporary) directory to use for backups.
2462 @param backupUser: Effective user that backups should run as.
2463 @param backupGroup: Effective group that backups should run as.
2464 @param rcpCommand: Default rcp-compatible copy command for staging.
2465 @param rshCommand: Default rsh-compatible command to use for remote shells.
2466 @param cbackCommand: Default cback-compatible command to use on managed remote peers.
2467 @param overrides: List of configured command path overrides, if any.
2468 @param hooks: List of configured pre- and post-action hooks.
2469 @param managedActions: Default set of actions that are managed on remote peers.
2470
2471 @raise ValueError: If one of the values is invalid.
2472 """
2473 self._startingDay = None
2474 self._workingDir = None
2475 self._backupUser = None
2476 self._backupGroup = None
2477 self._rcpCommand = None
2478 self._rshCommand = None
2479 self._cbackCommand = None
2480 self._overrides = None
2481 self._hooks = None
2482 self._managedActions = None
2483 self.startingDay = startingDay
2484 self.workingDir = workingDir
2485 self.backupUser = backupUser
2486 self.backupGroup = backupGroup
2487 self.rcpCommand = rcpCommand
2488 self.rshCommand = rshCommand
2489 self.cbackCommand = cbackCommand
2490 self.overrides = overrides
2491 self.hooks = hooks
2492 self.managedActions = managedActions
2493
2495 """
2496 Official string representation for class instance.
2497 """
2498 return "OptionsConfig(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)" % (self.startingDay, self.workingDir,
2499 self.backupUser, self.backupGroup,
2500 self.rcpCommand, self.overrides,
2501 self.hooks, self.rshCommand,
2502 self.cbackCommand, self.managedActions)
2503
2505 """
2506 Informal string representation for class instance.
2507 """
2508 return self.__repr__()
2509
2511 """
2512 Definition of equals operator for this class.
2513 @param other: Other object to compare to.
2514 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
2515 """
2516 if other is None:
2517 return 1
2518 if self._startingDay != other._startingDay:
2519 if self._startingDay < other._startingDay:
2520 return -1
2521 else:
2522 return 1
2523 if self._workingDir != other._workingDir:
2524 if self._workingDir < other._workingDir:
2525 return -1
2526 else:
2527 return 1
2528 if self._backupUser != other._backupUser:
2529 if self._backupUser < other._backupUser:
2530 return -1
2531 else:
2532 return 1
2533 if self._backupGroup != other._backupGroup:
2534 if self._backupGroup < other._backupGroup:
2535 return -1
2536 else:
2537 return 1
2538 if self._rcpCommand != other._rcpCommand:
2539 if self._rcpCommand < other._rcpCommand:
2540 return -1
2541 else:
2542 return 1
2543 if self._rshCommand != other._rshCommand:
2544 if self._rshCommand < other._rshCommand:
2545 return -1
2546 else:
2547 return 1
2548 if self._cbackCommand != other._cbackCommand:
2549 if self._cbackCommand < other._cbackCommand:
2550 return -1
2551 else:
2552 return 1
2553 if self._overrides != other._overrides:
2554 if self._overrides < other._overrides:
2555 return -1
2556 else:
2557 return 1
2558 if self._hooks != other._hooks:
2559 if self._hooks < other._hooks:
2560 return -1
2561 else:
2562 return 1
2563 if self._managedActions != other._managedActions:
2564 if self._managedActions < other._managedActions:
2565 return -1
2566 else:
2567 return 1
2568 return 0
2569
2571 """
2572 Property target used to set the starting day.
2573 If it is not C{None}, the value must be a valid English day of the week,
2574 one of C{"monday"}, C{"tuesday"}, C{"wednesday"}, etc.
2575 @raise ValueError: If the value is not a valid day of the week.
2576 """
2577 if value is not None:
2578 if value not in ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday", ]:
2579 raise ValueError("Starting day must be an English day of the week, i.e. \"monday\".")
2580 self._startingDay = value
2581
2583 """
2584 Property target used to get the starting day.
2585 """
2586 return self._startingDay
2587
2589 """
2590 Property target used to set the working directory.
2591 The value must be an absolute path if it is not C{None}.
2592 It does not have to exist on disk at the time of assignment.
2593 @raise ValueError: If the value is not an absolute path.
2594 @raise ValueError: If the value cannot be encoded properly.
2595 """
2596 if value is not None:
2597 if not os.path.isabs(value):
2598 raise ValueError("Working directory must be an absolute path.")
2599 self._workingDir = encodePath(value)
2600
2602 """
2603 Property target used to get the working directory.
2604 """
2605 return self._workingDir
2606
2608 """
2609 Property target used to set the backup user.
2610 The value must be a non-empty string if it is not C{None}.
2611 @raise ValueError: If the value is an empty string.
2612 """
2613 if value is not None:
2614 if len(value) < 1:
2615 raise ValueError("Backup user must be a non-empty string.")
2616 self._backupUser = value
2617
2619 """
2620 Property target used to get the backup user.
2621 """
2622 return self._backupUser
2623
2625 """
2626 Property target used to set the backup group.
2627 The value must be a non-empty string if it is not C{None}.
2628 @raise ValueError: If the value is an empty string.
2629 """
2630 if value is not None:
2631 if len(value) < 1:
2632 raise ValueError("Backup group must be a non-empty string.")
2633 self._backupGroup = value
2634
2636 """
2637 Property target used to get the backup group.
2638 """
2639 return self._backupGroup
2640
2642 """
2643 Property target used to set the rcp command.
2644 The value must be a non-empty string if it is not C{None}.
2645 @raise ValueError: If the value is an empty string.
2646 """
2647 if value is not None:
2648 if len(value) < 1:
2649 raise ValueError("The rcp command must be a non-empty string.")
2650 self._rcpCommand = value
2651
2653 """
2654 Property target used to get the rcp command.
2655 """
2656 return self._rcpCommand
2657
2659 """
2660 Property target used to set the rsh command.
2661 The value must be a non-empty string if it is not C{None}.
2662 @raise ValueError: If the value is an empty string.
2663 """
2664 if value is not None:
2665 if len(value) < 1:
2666 raise ValueError("The rsh command must be a non-empty string.")
2667 self._rshCommand = value
2668
2670 """
2671 Property target used to get the rsh command.
2672 """
2673 return self._rshCommand
2674
2676 """
2677 Property target used to set the cback command.
2678 The value must be a non-empty string if it is not C{None}.
2679 @raise ValueError: If the value is an empty string.
2680 """
2681 if value is not None:
2682 if len(value) < 1:
2683 raise ValueError("The cback command must be a non-empty string.")
2684 self._cbackCommand = value
2685
2687 """
2688 Property target used to get the cback command.
2689 """
2690 return self._cbackCommand
2691
2693 """
2694 Property target used to set the command path overrides list.
2695 Either the value must be C{None} or each element must be a C{CommandOverride}.
2696 @raise ValueError: If the value is not a C{CommandOverride}
2697 """
2698 if value is None:
2699 self._overrides = None
2700 else:
2701 try:
2702 saved = self._overrides
2703 self._overrides = ObjectTypeList(CommandOverride, "CommandOverride")
2704 self._overrides.extend(value)
2705 except Exception, e:
2706 self._overrides = saved
2707 raise e
2708
2710 """
2711 Property target used to get the command path overrides list.
2712 """
2713 return self._overrides
2714
2716 """
2717 Property target used to set the pre- and post-action hooks list.
2718 Either the value must be C{None} or each element must be an C{ActionHook}.
2719 @raise ValueError: If the value is not a C{CommandOverride}
2720 """
2721 if value is None:
2722 self._hooks = None
2723 else:
2724 try:
2725 saved = self._hooks
2726 self._hooks = ObjectTypeList(ActionHook, "ActionHook")
2727 self._hooks.extend(value)
2728 except Exception, e:
2729 self._hooks = saved
2730 raise e
2731
2733 """
2734 Property target used to get the command path hooks list.
2735 """
2736 return self._hooks
2737
2739 """
2740 Property target used to set the managed actions list.
2741 Elements do not have to exist on disk at the time of assignment.
2742 """
2743 if value is None:
2744 self._managedActions = None
2745 else:
2746 try:
2747 saved = self._managedActions
2748 self._managedActions = RegexMatchList(ACTION_NAME_REGEX, emptyAllowed=False, prefix="Action name")
2749 self._managedActions.extend(value)
2750 except Exception, e:
2751 self._managedActions = saved
2752 raise e
2753
2755 """
2756 Property target used to get the managed actions list.
2757 """
2758 return self._managedActions
2759
2760 startingDay = property(_getStartingDay, _setStartingDay, None, "Day that starts the week.")
2761 workingDir = property(_getWorkingDir, _setWorkingDir, None, "Working (temporary) directory to use for backups.")
2762 backupUser = property(_getBackupUser, _setBackupUser, None, "Effective user that backups should run as.")
2763 backupGroup = property(_getBackupGroup, _setBackupGroup, None, "Effective group that backups should run as.")
2764 rcpCommand = property(_getRcpCommand, _setRcpCommand, None, "Default rcp-compatible copy command for staging.")
2765 rshCommand = property(_getRshCommand, _setRshCommand, None, "Default rsh-compatible command to use for remote shells.")
2766 cbackCommand = property(_getCbackCommand, _setCbackCommand, None, "Default cback-compatible command to use on managed remote peers.")
2767 overrides = property(_getOverrides, _setOverrides, None, "List of configured command path overrides, if any.")
2768 hooks = property(_getHooks, _setHooks, None, "List of configured pre- and post-action hooks.")
2769 managedActions = property(_getManagedActions, _setManagedActions, None, "Default set of actions that are managed on remote peers.")
2770
2771
2772
2773
2774
2775
2777
2778 """
2779 Class representing Cedar Backup global peer configuration.
2780
2781 This section contains a list of local and remote peers in a master's backup
2782 pool. The section is optional. If a master does not define this section,
2783 then all peers are unmanaged, and the stage configuration section must
2784 explicitly list any peer that is to be staged. If this section is
2785 configured, then peers may be managed or unmanaged, and the stage section
2786 peer configuration (if any) completely overrides this configuration.
2787
2788 As with all of the other classes that represent configuration sections, all
2789 of these values are optional. It is up to some higher-level construct to
2790 decide whether everything they need is filled in.
2791
2792 The following restrictions exist on data in this class:
2793
2794 - The list of local peers must contain only C{LocalPeer} objects
2795 - The list of remote peers must contain only C{RemotePeer} objects
2796
2797 @note: Lists within this class are "unordered" for equality comparisons.
2798
2799 @sort: __init__, __repr__, __str__, __cmp__, localPeers, remotePeers
2800 """
2801
2802 - def __init__(self, localPeers=None, remotePeers=None):
2803 """
2804 Constructor for the C{PeersConfig} class.
2805
2806 @param localPeers: List of local peers.
2807 @param remotePeers: List of remote peers.
2808
2809 @raise ValueError: If one of the values is invalid.
2810 """
2811 self._localPeers = None
2812 self._remotePeers = None
2813 self.localPeers = localPeers
2814 self.remotePeers = remotePeers
2815
2817 """
2818 Official string representation for class instance.
2819 """
2820 return "PeersConfig(%s, %s)" % (self.localPeers, self.remotePeers)
2821
2823 """
2824 Informal string representation for class instance.
2825 """
2826 return self.__repr__()
2827
2829 """
2830 Definition of equals operator for this class.
2831 Lists within this class are "unordered" for equality comparisons.
2832 @param other: Other object to compare to.
2833 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
2834 """
2835 if other is None:
2836 return 1
2837 if self._localPeers != other._localPeers:
2838 if self._localPeers < other._localPeers:
2839 return -1
2840 else:
2841 return 1
2842 if self._remotePeers != other._remotePeers:
2843 if self._remotePeers < other._remotePeers:
2844 return -1
2845 else:
2846 return 1
2847 return 0
2848
2850 """
2851 Indicates whether any peers are filled into this object.
2852 @return: Boolean true if any local or remote peers are filled in, false otherwise.
2853 """
2854 return ((self.localPeers is not None and len(self.localPeers) > 0) or
2855 (self.remotePeers is not None and len(self.remotePeers) > 0))
2856
2858 """
2859 Property target used to set the local peers list.
2860 Either the value must be C{None} or each element must be a C{LocalPeer}.
2861 @raise ValueError: If the value is not an absolute path.
2862 """
2863 if value is None:
2864 self._localPeers = None
2865 else:
2866 try:
2867 saved = self._localPeers
2868 self._localPeers = ObjectTypeList(LocalPeer, "LocalPeer")
2869 self._localPeers.extend(value)
2870 except Exception, e:
2871 self._localPeers = saved
2872 raise e
2873
2875 """
2876 Property target used to get the local peers list.
2877 """
2878 return self._localPeers
2879
2881 """
2882 Property target used to set the remote peers list.
2883 Either the value must be C{None} or each element must be a C{RemotePeer}.
2884 @raise ValueError: If the value is not a C{RemotePeer}
2885 """
2886 if value is None:
2887 self._remotePeers = None
2888 else:
2889 try:
2890 saved = self._remotePeers
2891 self._remotePeers = ObjectTypeList(RemotePeer, "RemotePeer")
2892 self._remotePeers.extend(value)
2893 except Exception, e:
2894 self._remotePeers = saved
2895 raise e
2896
2898 """
2899 Property target used to get the remote peers list.
2900 """
2901 return self._remotePeers
2902
2903 localPeers = property(_getLocalPeers, _setLocalPeers, None, "List of local peers.")
2904 remotePeers = property(_getRemotePeers, _setRemotePeers, None, "List of remote peers.")
2905
2906
2907
2908
2909
2910
2912
2913 """
2914 Class representing a Cedar Backup collect configuration.
2915
2916 As with all of the other classes that represent configuration sections, all
2917 of these values are optional. It is up to some higher-level construct to
2918 decide whether everything they need is filled in. Some validation is done
2919 on non-C{None} assignments through the use of the Python C{property()}
2920 construct.
2921
2922 The following restrictions exist on data in this class:
2923
2924 - The target directory must be an absolute path.
2925 - The collect mode must be one of the values in L{VALID_COLLECT_MODES}.
2926 - The archive mode must be one of the values in L{VALID_ARCHIVE_MODES}.
2927 - The ignore file must be a non-empty string.
2928 - Each of the paths in C{absoluteExcludePaths} must be an absolute path
2929 - The collect file list must be a list of C{CollectFile} objects.
2930 - The collect directory list must be a list of C{CollectDir} objects.
2931
2932 For the C{absoluteExcludePaths} list, validation is accomplished through the
2933 L{util.AbsolutePathList} list implementation that overrides common list
2934 methods and transparently does the absolute path validation for us.
2935
2936 For the C{collectFiles} and C{collectDirs} list, validation is accomplished
2937 through the L{util.ObjectTypeList} list implementation that overrides common
2938 list methods and transparently ensures that each element has an appropriate
2939 type.
2940
2941 @note: Lists within this class are "unordered" for equality comparisons.
2942
2943 @sort: __init__, __repr__, __str__, __cmp__, targetDir,
2944 collectMode, archiveMode, ignoreFile, absoluteExcludePaths,
2945 excludePatterns, collectFiles, collectDirs
2946 """
2947
2948 - def __init__(self, targetDir=None, collectMode=None, archiveMode=None, ignoreFile=None,
2949 absoluteExcludePaths=None, excludePatterns=None, collectFiles=None, collectDirs=None):
2950 """
2951 Constructor for the C{CollectConfig} class.
2952
2953 @param targetDir: Directory to collect files into.
2954 @param collectMode: Default collect mode.
2955 @param archiveMode: Default archive mode for collect files.
2956 @param ignoreFile: Default ignore file name.
2957 @param absoluteExcludePaths: List of absolute paths to exclude.
2958 @param excludePatterns: List of regular expression patterns to exclude.
2959 @param collectFiles: List of collect files.
2960 @param collectDirs: List of collect directories.
2961
2962 @raise ValueError: If one of the values is invalid.
2963 """
2964 self._targetDir = None
2965 self._collectMode = None
2966 self._archiveMode = None
2967 self._ignoreFile = None
2968 self._absoluteExcludePaths = None
2969 self._excludePatterns = None
2970 self._collectFiles = None
2971 self._collectDirs = None
2972 self.targetDir = targetDir
2973 self.collectMode = collectMode
2974 self.archiveMode = archiveMode
2975 self.ignoreFile = ignoreFile
2976 self.absoluteExcludePaths = absoluteExcludePaths
2977 self.excludePatterns = excludePatterns
2978 self.collectFiles = collectFiles
2979 self.collectDirs = collectDirs
2980
2982 """
2983 Official string representation for class instance.
2984 """
2985 return "CollectConfig(%s, %s, %s, %s, %s, %s, %s, %s)" % (self.targetDir, self.collectMode, self.archiveMode,
2986 self.ignoreFile, self.absoluteExcludePaths,
2987 self.excludePatterns, self.collectFiles, self.collectDirs)
2988
2990 """
2991 Informal string representation for class instance.
2992 """
2993 return self.__repr__()
2994
2996 """
2997 Definition of equals operator for this class.
2998 Lists within this class are "unordered" for equality comparisons.
2999 @param other: Other object to compare to.
3000 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
3001 """
3002 if other is None:
3003 return 1
3004 if self._targetDir != other._targetDir:
3005 if self._targetDir < other._targetDir:
3006 return -1
3007 else:
3008 return 1
3009 if self._collectMode != other._collectMode:
3010 if self._collectMode < other._collectMode:
3011 return -1
3012 else:
3013 return 1
3014 if self._archiveMode != other._archiveMode:
3015 if self._archiveMode < other._archiveMode:
3016 return -1
3017 else:
3018 return 1
3019 if self._ignoreFile != other._ignoreFile:
3020 if self._ignoreFile < other._ignoreFile:
3021 return -1
3022 else:
3023 return 1
3024 if self._absoluteExcludePaths != other._absoluteExcludePaths:
3025 if self._absoluteExcludePaths < other._absoluteExcludePaths:
3026 return -1
3027 else:
3028 return 1
3029 if self._excludePatterns != other._excludePatterns:
3030 if self._excludePatterns < other._excludePatterns:
3031 return -1
3032 else:
3033 return 1
3034 if self._collectFiles != other._collectFiles:
3035 if self._collectFiles < other._collectFiles:
3036 return -1
3037 else:
3038 return 1
3039 if self._collectDirs != other._collectDirs:
3040 if self._collectDirs < other._collectDirs:
3041 return -1
3042 else:
3043 return 1
3044 return 0
3045
3047 """
3048 Property target used to set the target directory.
3049 The value must be an absolute path if it is not C{None}.
3050 It does not have to exist on disk at the time of assignment.
3051 @raise ValueError: If the value is not an absolute path.
3052 @raise ValueError: If the value cannot be encoded properly.
3053 """
3054 if value is not None:
3055 if not os.path.isabs(value):
3056 raise ValueError("Target directory must be an absolute path.")
3057 self._targetDir = encodePath(value)
3058
3060 """
3061 Property target used to get the target directory.
3062 """
3063 return self._targetDir
3064
3066 """
3067 Property target used to set the collect mode.
3068 If not C{None}, the mode must be one of L{VALID_COLLECT_MODES}.
3069 @raise ValueError: If the value is not valid.
3070 """
3071 if value is not None:
3072 if value not in VALID_COLLECT_MODES:
3073 raise ValueError("Collect mode must be one of %s." % VALID_COLLECT_MODES)
3074 self._collectMode = value
3075
3077 """
3078 Property target used to get the collect mode.
3079 """
3080 return self._collectMode
3081
3083 """
3084 Property target used to set the archive mode.
3085 If not C{None}, the mode must be one of L{VALID_ARCHIVE_MODES}.
3086 @raise ValueError: If the value is not valid.
3087 """
3088 if value is not None:
3089 if value not in VALID_ARCHIVE_MODES:
3090 raise ValueError("Archive mode must be one of %s." % VALID_ARCHIVE_MODES)
3091 self._archiveMode = value
3092
3094 """
3095 Property target used to get the archive mode.
3096 """
3097 return self._archiveMode
3098
3100 """
3101 Property target used to set the ignore file.
3102 The value must be a non-empty string if it is not C{None}.
3103 @raise ValueError: If the value is an empty string.
3104 @raise ValueError: If the value cannot be encoded properly.
3105 """
3106 if value is not None:
3107 if len(value) < 1:
3108 raise ValueError("The ignore file must be a non-empty string.")
3109 self._ignoreFile = encodePath(value)
3110
3112 """
3113 Property target used to get the ignore file.
3114 """
3115 return self._ignoreFile
3116
3118 """
3119 Property target used to set the absolute exclude paths list.
3120 Either the value must be C{None} or each element must be an absolute path.
3121 Elements do not have to exist on disk at the time of assignment.
3122 @raise ValueError: If the value is not an absolute path.
3123 """
3124 if value is None:
3125 self._absoluteExcludePaths = None
3126 else:
3127 try:
3128 saved = self._absoluteExcludePaths
3129 self._absoluteExcludePaths = AbsolutePathList()
3130 self._absoluteExcludePaths.extend(value)
3131 except Exception, e:
3132 self._absoluteExcludePaths = saved
3133 raise e
3134
3136 """
3137 Property target used to get the absolute exclude paths list.
3138 """
3139 return self._absoluteExcludePaths
3140
3142 """
3143 Property target used to set the exclude patterns list.
3144 """
3145 if value is None:
3146 self._excludePatterns = None
3147 else:
3148 try:
3149 saved = self._excludePatterns
3150 self._excludePatterns = RegexList()
3151 self._excludePatterns.extend(value)
3152 except Exception, e:
3153 self._excludePatterns = saved
3154 raise e
3155
3157 """
3158 Property target used to get the exclude patterns list.
3159 """
3160 return self._excludePatterns
3161
3163 """
3164 Property target used to set the collect files list.
3165 Either the value must be C{None} or each element must be a C{CollectFile}.
3166 @raise ValueError: If the value is not a C{CollectFile}
3167 """
3168 if value is None:
3169 self._collectFiles = None
3170 else:
3171 try:
3172 saved = self._collectFiles
3173 self._collectFiles = ObjectTypeList(CollectFile, "CollectFile")
3174 self._collectFiles.extend(value)
3175 except Exception, e:
3176 self._collectFiles = saved
3177 raise e
3178
3180 """
3181 Property target used to get the collect files list.
3182 """
3183 return self._collectFiles
3184
3186 """
3187 Property target used to set the collect dirs list.
3188 Either the value must be C{None} or each element must be a C{CollectDir}.
3189 @raise ValueError: If the value is not a C{CollectDir}
3190 """
3191 if value is None:
3192 self._collectDirs = None
3193 else:
3194 try:
3195 saved = self._collectDirs
3196 self._collectDirs = ObjectTypeList(CollectDir, "CollectDir")
3197 self._collectDirs.extend(value)
3198 except Exception, e:
3199 self._collectDirs = saved
3200 raise e
3201
3203 """
3204 Property target used to get the collect dirs list.
3205 """
3206 return self._collectDirs
3207
3208 targetDir = property(_getTargetDir, _setTargetDir, None, "Directory to collect files into.")
3209 collectMode = property(_getCollectMode, _setCollectMode, None, "Default collect mode.")
3210 archiveMode = property(_getArchiveMode, _setArchiveMode, None, "Default archive mode for collect files.")
3211 ignoreFile = property(_getIgnoreFile, _setIgnoreFile, None, "Default ignore file name.")
3212 absoluteExcludePaths = property(_getAbsoluteExcludePaths, _setAbsoluteExcludePaths, None, "List of absolute paths to exclude.")
3213 excludePatterns = property(_getExcludePatterns, _setExcludePatterns, None, "List of regular expressions patterns to exclude.")
3214 collectFiles = property(_getCollectFiles, _setCollectFiles, None, "List of collect files.")
3215 collectDirs = property(_getCollectDirs, _setCollectDirs, None, "List of collect directories.")
3216
3217
3218
3219
3220
3221
3223
3224 """
3225 Class representing a Cedar Backup stage configuration.
3226
3227 As with all of the other classes that represent configuration sections, all
3228 of these values are optional. It is up to some higher-level construct to
3229 decide whether everything they need is filled in. Some validation is done
3230 on non-C{None} assignments through the use of the Python C{property()}
3231 construct.
3232
3233 The following restrictions exist on data in this class:
3234
3235 - The target directory must be an absolute path
3236 - The list of local peers must contain only C{LocalPeer} objects
3237 - The list of remote peers must contain only C{RemotePeer} objects
3238
3239 @note: Lists within this class are "unordered" for equality comparisons.
3240
3241 @sort: __init__, __repr__, __str__, __cmp__, targetDir, localPeers, remotePeers
3242 """
3243
3244 - def __init__(self, targetDir=None, localPeers=None, remotePeers=None):
3245 """
3246 Constructor for the C{StageConfig} class.
3247
3248 @param targetDir: Directory to stage files into, by peer name.
3249 @param localPeers: List of local peers.
3250 @param remotePeers: List of remote peers.
3251
3252 @raise ValueError: If one of the values is invalid.
3253 """
3254 self._targetDir = None
3255 self._localPeers = None
3256 self._remotePeers = None
3257 self.targetDir = targetDir
3258 self.localPeers = localPeers
3259 self.remotePeers = remotePeers
3260
3262 """
3263 Official string representation for class instance.
3264 """
3265 return "StageConfig(%s, %s, %s)" % (self.targetDir, self.localPeers, self.remotePeers)
3266
3268 """
3269 Informal string representation for class instance.
3270 """
3271 return self.__repr__()
3272
3274 """
3275 Definition of equals operator for this class.
3276 Lists within this class are "unordered" for equality comparisons.
3277 @param other: Other object to compare to.
3278 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
3279 """
3280 if other is None:
3281 return 1
3282 if self._targetDir != other._targetDir:
3283 if self._targetDir < other._targetDir:
3284 return -1
3285 else:
3286 return 1
3287 if self._localPeers != other._localPeers:
3288 if self._localPeers < other._localPeers:
3289 return -1
3290 else:
3291 return 1
3292 if self._remotePeers != other._remotePeers:
3293 if self._remotePeers < other._remotePeers:
3294 return -1
3295 else:
3296 return 1
3297 return 0
3298
3300 """
3301 Indicates whether any peers are filled into this object.
3302 @return: Boolean true if any local or remote peers are filled in, false otherwise.
3303 """
3304 return ((self.localPeers is not None and len(self.localPeers) > 0) or
3305 (self.remotePeers is not None and len(self.remotePeers) > 0))
3306
3308 """
3309 Property target used to set the target directory.
3310 The value must be an absolute path if it is not C{None}.
3311 It does not have to exist on disk at the time of assignment.
3312 @raise ValueError: If the value is not an absolute path.
3313 @raise ValueError: If the value cannot be encoded properly.
3314 """
3315 if value is not None:
3316 if not os.path.isabs(value):
3317 raise ValueError("Target directory must be an absolute path.")
3318 self._targetDir = encodePath(value)
3319
3321 """
3322 Property target used to get the target directory.
3323 """
3324 return self._targetDir
3325
3327 """
3328 Property target used to set the local peers list.
3329 Either the value must be C{None} or each element must be a C{LocalPeer}.
3330 @raise ValueError: If the value is not an absolute path.
3331 """
3332 if value is None:
3333 self._localPeers = None
3334 else:
3335 try:
3336 saved = self._localPeers
3337 self._localPeers = ObjectTypeList(LocalPeer, "LocalPeer")
3338 self._localPeers.extend(value)
3339 except Exception, e:
3340 self._localPeers = saved
3341 raise e
3342
3344 """
3345 Property target used to get the local peers list.
3346 """
3347 return self._localPeers
3348
3350 """
3351 Property target used to set the remote peers list.
3352 Either the value must be C{None} or each element must be a C{RemotePeer}.
3353 @raise ValueError: If the value is not a C{RemotePeer}
3354 """
3355 if value is None:
3356 self._remotePeers = None
3357 else:
3358 try:
3359 saved = self._remotePeers
3360 self._remotePeers = ObjectTypeList(RemotePeer, "RemotePeer")
3361 self._remotePeers.extend(value)
3362 except Exception, e:
3363 self._remotePeers = saved
3364 raise e
3365
3367 """
3368 Property target used to get the remote peers list.
3369 """
3370 return self._remotePeers
3371
3372 targetDir = property(_getTargetDir, _setTargetDir, None, "Directory to stage files into, by peer name.")
3373 localPeers = property(_getLocalPeers, _setLocalPeers, None, "List of local peers.")
3374 remotePeers = property(_getRemotePeers, _setRemotePeers, None, "List of remote peers.")
3375
3376
3377
3378
3379
3380
3382
3383 """
3384 Class representing a Cedar Backup store configuration.
3385
3386 As with all of the other classes that represent configuration sections, all
3387 of these values are optional. It is up to some higher-level construct to
3388 decide whether everything they need is filled in. Some validation is done
3389 on non-C{None} assignments through the use of the Python C{property()}
3390 construct.
3391
3392 The following restrictions exist on data in this class:
3393
3394 - The source directory must be an absolute path.
3395 - The media type must be one of the values in L{VALID_MEDIA_TYPES}.
3396 - The device type must be one of the values in L{VALID_DEVICE_TYPES}.
3397 - The device path must be an absolute path.
3398 - The SCSI id, if provided, must be in the form specified by L{validateScsiId}.
3399 - The drive speed must be an integer >= 1
3400 - The blanking behavior must be a C{BlankBehavior} object
3401
3402 Note that although the blanking factor must be a positive floating point
3403 number, it is stored as a string. This is done so that we can losslessly go
3404 back and forth between XML and object representations of configuration.
3405
3406 @sort: __init__, __repr__, __str__, __cmp__, sourceDir,
3407 mediaType, deviceType, devicePath, deviceScsiId,
3408 driveSpeed, checkData, checkMedia, warnMidnite, noEject, blankBehavior
3409 """
3410
3411 - def __init__(self, sourceDir=None, mediaType=None, deviceType=None,
3412 devicePath=None, deviceScsiId=None, driveSpeed=None,
3413 checkData=False, warnMidnite=False, noEject=False,
3414 checkMedia=False, blankBehavior=None):
3415 """
3416 Constructor for the C{StoreConfig} class.
3417
3418 @param sourceDir: Directory whose contents should be written to media.
3419 @param mediaType: Type of the media (see notes above).
3420 @param deviceType: Type of the device (optional, see notes above).
3421 @param devicePath: Filesystem device name for writer device, i.e. C{/dev/cdrw}.
3422 @param deviceScsiId: SCSI id for writer device, i.e. C{[<method>:]scsibus,target,lun}.
3423 @param driveSpeed: Speed of the drive, i.e. C{2} for 2x drive, etc.
3424 @param checkData: Whether resulting image should be validated.
3425 @param checkMedia: Whether media should be checked before being written to.
3426 @param warnMidnite: Whether to generate warnings for crossing midnite.
3427 @param noEject: Indicates that the writer device should not be ejected.
3428 @param blankBehavior: Controls optimized blanking behavior.
3429
3430 @raise ValueError: If one of the values is invalid.
3431 """
3432 self._sourceDir = None
3433 self._mediaType = None
3434 self._deviceType = None
3435 self._devicePath = None
3436 self._deviceScsiId = None
3437 self._driveSpeed = None
3438 self._checkData = None
3439 self._checkMedia = None
3440 self._warnMidnite = None
3441 self._noEject = None
3442 self._blankBehavior = None
3443 self.sourceDir = sourceDir
3444 self.mediaType = mediaType
3445 self.deviceType = deviceType
3446 self.devicePath = devicePath
3447 self.deviceScsiId = deviceScsiId
3448 self.driveSpeed = driveSpeed
3449 self.checkData = checkData
3450 self.checkMedia = checkMedia
3451 self.warnMidnite = warnMidnite
3452 self.noEject = noEject
3453 self.blankBehavior = blankBehavior
3454
3456 """
3457 Official string representation for class instance.
3458 """
3459 return "StoreConfig(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)" % (self.sourceDir, self.mediaType, self.deviceType,
3460 self.devicePath, self.deviceScsiId, self.driveSpeed,
3461 self.checkData, self.warnMidnite, self.noEject,
3462 self.checkMedia, self.blankBehavior)
3463
3465 """
3466 Informal string representation for class instance.
3467 """
3468 return self.__repr__()
3469
3471 """
3472 Definition of equals operator for this class.
3473 @param other: Other object to compare to.
3474 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
3475 """
3476 if other is None:
3477 return 1
3478 if self._sourceDir != other._sourceDir:
3479 if self._sourceDir < other._sourceDir:
3480 return -1
3481 else:
3482 return 1
3483 if self._mediaType != other._mediaType:
3484 if self._mediaType < other._mediaType:
3485 return -1
3486 else:
3487 return 1
3488 if self._deviceType != other._deviceType:
3489 if self._deviceType < other._deviceType:
3490 return -1
3491 else:
3492 return 1
3493 if self._devicePath != other._devicePath:
3494 if self._devicePath < other._devicePath:
3495 return -1
3496 else:
3497 return 1
3498 if self._deviceScsiId != other._deviceScsiId:
3499 if self._deviceScsiId < other._deviceScsiId:
3500 return -1
3501 else:
3502 return 1
3503 if self._driveSpeed != other._driveSpeed:
3504 if self._driveSpeed < other._driveSpeed:
3505 return -1
3506 else:
3507 return 1
3508 if self._checkData != other._checkData:
3509 if self._checkData < other._checkData:
3510 return -1
3511 else:
3512 return 1
3513 if self._checkMedia != other._checkMedia:
3514 if self._checkMedia < other._checkMedia:
3515 return -1
3516 else:
3517 return 1
3518 if self._warnMidnite != other._warnMidnite:
3519 if self._warnMidnite < other._warnMidnite:
3520 return -1
3521 else:
3522 return 1
3523 if self._noEject != other._noEject:
3524 if self._noEject < other._noEject:
3525 return -1
3526 else:
3527 return 1
3528 if self._blankBehavior != other._blankBehavior:
3529 if self._blankBehavior < other._blankBehavior:
3530 return -1
3531 else:
3532 return 1
3533 return 0
3534
3536 """
3537 Property target used to set the source directory.
3538 The value must be an absolute path if it is not C{None}.
3539 It does not have to exist on disk at the time of assignment.
3540 @raise ValueError: If the value is not an absolute path.
3541 @raise ValueError: If the value cannot be encoded properly.
3542 """
3543 if value is not None:
3544 if not os.path.isabs(value):
3545 raise ValueError("Source directory must be an absolute path.")
3546 self._sourceDir = encodePath(value)
3547
3549 """
3550 Property target used to get the source directory.
3551 """
3552 return self._sourceDir
3553
3564
3570
3572 """
3573 Property target used to set the device type.
3574 The value must be one of L{VALID_DEVICE_TYPES}.
3575 @raise ValueError: If the value is not valid.
3576 """
3577 if value is not None:
3578 if value not in VALID_DEVICE_TYPES:
3579 raise ValueError("Device type must be one of %s." % VALID_DEVICE_TYPES)
3580 self._deviceType = value
3581
3583 """
3584 Property target used to get the device type.
3585 """
3586 return self._deviceType
3587
3589 """
3590 Property target used to set the device path.
3591 The value must be an absolute path if it is not C{None}.
3592 It does not have to exist on disk at the time of assignment.
3593 @raise ValueError: If the value is not an absolute path.
3594 @raise ValueError: If the value cannot be encoded properly.
3595 """
3596 if value is not None:
3597 if not os.path.isabs(value):
3598 raise ValueError("Device path must be an absolute path.")
3599 self._devicePath = encodePath(value)
3600
3602 """
3603 Property target used to get the device path.
3604 """
3605 return self._devicePath
3606
3608 """
3609 Property target used to set the SCSI id
3610 The SCSI id must be valid per L{validateScsiId}.
3611 @raise ValueError: If the value is not valid.
3612 """
3613 if value is None:
3614 self._deviceScsiId = None
3615 else:
3616 self._deviceScsiId = validateScsiId(value)
3617
3619 """
3620 Property target used to get the SCSI id.
3621 """
3622 return self._deviceScsiId
3623
3625 """
3626 Property target used to set the drive speed.
3627 The drive speed must be valid per L{validateDriveSpeed}.
3628 @raise ValueError: If the value is not valid.
3629 """
3630 self._driveSpeed = validateDriveSpeed(value)
3631
3633 """
3634 Property target used to get the drive speed.
3635 """
3636 return self._driveSpeed
3637
3639 """
3640 Property target used to set the check data flag.
3641 No validations, but we normalize the value to C{True} or C{False}.
3642 """
3643 if value:
3644 self._checkData = True
3645 else:
3646 self._checkData = False
3647
3649 """
3650 Property target used to get the check data flag.
3651 """
3652 return self._checkData
3653
3663
3669
3671 """
3672 Property target used to set the midnite warning flag.
3673 No validations, but we normalize the value to C{True} or C{False}.
3674 """
3675 if value:
3676 self._warnMidnite = True
3677 else:
3678 self._warnMidnite = False
3679
3681 """
3682 Property target used to get the midnite warning flag.
3683 """
3684 return self._warnMidnite
3685
3687 """
3688 Property target used to set the no-eject flag.
3689 No validations, but we normalize the value to C{True} or C{False}.
3690 """
3691 if value:
3692 self._noEject = True
3693 else:
3694 self._noEject = False
3695
3697 """
3698 Property target used to get the no-eject flag.
3699 """
3700 return self._noEject
3701
3703 """
3704 Property target used to set blanking behavior configuration.
3705 If not C{None}, the value must be a C{BlankBehavior} object.
3706 @raise ValueError: If the value is not a C{BlankBehavior}
3707 """
3708 if value is None:
3709 self._blankBehavior = None
3710 else:
3711 if not isinstance(value, BlankBehavior):
3712 raise ValueError("Value must be a C{BlankBehavior} object.")
3713 self._blankBehavior = value
3714
3716 """
3717 Property target used to get the blanking behavior configuration.
3718 """
3719 return self._blankBehavior
3720
3721 sourceDir = property(_getSourceDir, _setSourceDir, None, "Directory whose contents should be written to media.")
3722 mediaType = property(_getMediaType, _setMediaType, None, "Type of the media (see notes above).")
3723 deviceType = property(_getDeviceType, _setDeviceType, None, "Type of the device (optional, see notes above).")
3724 devicePath = property(_getDevicePath, _setDevicePath, None, "Filesystem device name for writer device.")
3725 deviceScsiId = property(_getDeviceScsiId, _setDeviceScsiId, None, "SCSI id for writer device (optional, see notes above).")
3726 driveSpeed = property(_getDriveSpeed, _setDriveSpeed, None, "Speed of the drive.")
3727 checkData = property(_getCheckData, _setCheckData, None, "Whether resulting image should be validated.")
3728 checkMedia = property(_getCheckMedia, _setCheckMedia, None, "Whether media should be checked before being written to.")
3729 warnMidnite = property(_getWarnMidnite, _setWarnMidnite, None, "Whether to generate warnings for crossing midnite.")
3730 noEject = property(_getNoEject, _setNoEject, None, "Indicates that the writer device should not be ejected.")
3731 blankBehavior = property(_getBlankBehavior, _setBlankBehavior, None, "Controls optimized blanking behavior.")
3732
3733
3734
3735
3736
3737
3739
3740 """
3741 Class representing a Cedar Backup purge configuration.
3742
3743 As with all of the other classes that represent configuration sections, all
3744 of these values are optional. It is up to some higher-level construct to
3745 decide whether everything they need is filled in. Some validation is done
3746 on non-C{None} assignments through the use of the Python C{property()}
3747 construct.
3748
3749 The following restrictions exist on data in this class:
3750
3751 - The purge directory list must be a list of C{PurgeDir} objects.
3752
3753 For the C{purgeDirs} list, validation is accomplished through the
3754 L{util.ObjectTypeList} list implementation that overrides common list
3755 methods and transparently ensures that each element is a C{PurgeDir}.
3756
3757 @note: Lists within this class are "unordered" for equality comparisons.
3758
3759 @sort: __init__, __repr__, __str__, __cmp__, purgeDirs
3760 """
3761
3763 """
3764 Constructor for the C{Purge} class.
3765 @param purgeDirs: List of purge directories.
3766 @raise ValueError: If one of the values is invalid.
3767 """
3768 self._purgeDirs = None
3769 self.purgeDirs = purgeDirs
3770
3772 """
3773 Official string representation for class instance.
3774 """
3775 return "PurgeConfig(%s)" % self.purgeDirs
3776
3778 """
3779 Informal string representation for class instance.
3780 """
3781 return self.__repr__()
3782
3784 """
3785 Definition of equals operator for this class.
3786 Lists within this class are "unordered" for equality comparisons.
3787 @param other: Other object to compare to.
3788 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
3789 """
3790 if other is None:
3791 return 1
3792 if self._purgeDirs != other._purgeDirs:
3793 if self._purgeDirs < other._purgeDirs:
3794 return -1
3795 else:
3796 return 1
3797 return 0
3798
3800 """
3801 Property target used to set the purge dirs list.
3802 Either the value must be C{None} or each element must be a C{PurgeDir}.
3803 @raise ValueError: If the value is not a C{PurgeDir}
3804 """
3805 if value is None:
3806 self._purgeDirs = None
3807 else:
3808 try:
3809 saved = self._purgeDirs
3810 self._purgeDirs = ObjectTypeList(PurgeDir, "PurgeDir")
3811 self._purgeDirs.extend(value)
3812 except Exception, e:
3813 self._purgeDirs = saved
3814 raise e
3815
3817 """
3818 Property target used to get the purge dirs list.
3819 """
3820 return self._purgeDirs
3821
3822 purgeDirs = property(_getPurgeDirs, _setPurgeDirs, None, "List of directories to purge.")
3823
3824
3825
3826
3827
3828
3830
3831
3832
3833
3834
3835 """
3836 Class representing a Cedar Backup XML configuration document.
3837
3838 The C{Config} class is a Python object representation of a Cedar Backup XML
3839 configuration file. It is intended to be the only Python-language interface
3840 to Cedar Backup configuration on disk for both Cedar Backup itself and for
3841 external applications.
3842
3843 The object representation is two-way: XML data can be used to create a
3844 C{Config} object, and then changes to the object can be propogated back to
3845 disk. A C{Config} object can even be used to create a configuration file
3846 from scratch programmatically.
3847
3848 This class and the classes it is composed from often use Python's
3849 C{property} construct to validate input and limit access to values. Some
3850 validations can only be done once a document is considered "complete"
3851 (see module notes for more details).
3852
3853 Assignments to the various instance variables must match the expected
3854 type, i.e. C{reference} must be a C{ReferenceConfig}. The internal check
3855 uses the built-in C{isinstance} function, so it should be OK to use
3856 subclasses if you want to.
3857
3858 If an instance variable is not set, its value will be C{None}. When an
3859 object is initialized without using an XML document, all of the values
3860 will be C{None}. Even when an object is initialized using XML, some of
3861 the values might be C{None} because not every section is required.
3862
3863 @note: Lists within this class are "unordered" for equality comparisons.
3864
3865 @sort: __init__, __repr__, __str__, __cmp__, extractXml, validate,
3866 reference, extensions, options, collect, stage, store, purge,
3867 _getReference, _setReference, _getExtensions, _setExtensions,
3868 _getOptions, _setOptions, _getPeers, _setPeers, _getCollect,
3869 _setCollect, _getStage, _setStage, _getStore, _setStore,
3870 _getPurge, _setPurge
3871 """
3872
3873
3874
3875
3876
3877 - def __init__(self, xmlData=None, xmlPath=None, validate=True):
3878 """
3879 Initializes a configuration object.
3880
3881 If you initialize the object without passing either C{xmlData} or
3882 C{xmlPath}, then configuration will be empty and will be invalid until it
3883 is filled in properly.
3884
3885 No reference to the original XML data or original path is saved off by
3886 this class. Once the data has been parsed (successfully or not) this
3887 original information is discarded.
3888
3889 Unless the C{validate} argument is C{False}, the L{Config.validate}
3890 method will be called (with its default arguments) against configuration
3891 after successfully parsing any passed-in XML. Keep in mind that even if
3892 C{validate} is C{False}, it might not be possible to parse the passed-in
3893 XML document if lower-level validations fail.
3894
3895 @note: It is strongly suggested that the C{validate} option always be set
3896 to C{True} (the default) unless there is a specific need to read in
3897 invalid configuration from disk.
3898
3899 @param xmlData: XML data representing configuration.
3900 @type xmlData: String data.
3901
3902 @param xmlPath: Path to an XML file on disk.
3903 @type xmlPath: Absolute path to a file on disk.
3904
3905 @param validate: Validate the document after parsing it.
3906 @type validate: Boolean true/false.
3907
3908 @raise ValueError: If both C{xmlData} and C{xmlPath} are passed-in.
3909 @raise ValueError: If the XML data in C{xmlData} or C{xmlPath} cannot be parsed.
3910 @raise ValueError: If the parsed configuration document is not valid.
3911 """
3912 self._reference = None
3913 self._extensions = None
3914 self._options = None
3915 self._peers = None
3916 self._collect = None
3917 self._stage = None
3918 self._store = None
3919 self._purge = None
3920 self.reference = None
3921 self.extensions = None
3922 self.options = None
3923 self.peers = None
3924 self.collect = None
3925 self.stage = None
3926 self.store = None
3927 self.purge = None
3928 if xmlData is not None and xmlPath is not None:
3929 raise ValueError("Use either xmlData or xmlPath, but not both.")
3930 if xmlData is not None:
3931 self._parseXmlData(xmlData)
3932 if validate:
3933 self.validate()
3934 elif xmlPath is not None:
3935 xmlData = open(xmlPath).read()
3936 self._parseXmlData(xmlData)
3937 if validate:
3938 self.validate()
3939
3940
3941
3942
3943
3944
3946 """
3947 Official string representation for class instance.
3948 """
3949 return "Config(%s, %s, %s, %s, %s, %s, %s, %s)" % (self.reference, self.extensions, self.options,
3950 self.peers, self.collect, self.stage, self.store,
3951 self.purge)
3952
3954 """
3955 Informal string representation for class instance.
3956 """
3957 return self.__repr__()
3958
3959
3960
3961
3962
3963
3965 """
3966 Definition of equals operator for this class.
3967 Lists within this class are "unordered" for equality comparisons.
3968 @param other: Other object to compare to.
3969 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
3970 """
3971 if other is None:
3972 return 1
3973 if self._reference != other._reference:
3974 if self._reference < other._reference:
3975 return -1
3976 else:
3977 return 1
3978 if self._extensions != other._extensions:
3979 if self._extensions < other._extensions:
3980 return -1
3981 else:
3982 return 1
3983 if self._options != other._options:
3984 if self._options < other._options:
3985 return -1
3986 else:
3987 return 1
3988 if self._peers != other._peers:
3989 if self._peers < other._peers:
3990 return -1
3991 else:
3992 return 1
3993 if self._collect != other._collect:
3994 if self._collect < other._collect:
3995 return -1
3996 else:
3997 return 1
3998 if self._stage != other._stage:
3999 if self._stage < other._stage:
4000 return -1
4001 else:
4002 return 1
4003 if self._store != other._store:
4004 if self._store < other._store:
4005 return -1
4006 else:
4007 return 1
4008 if self._purge != other._purge:
4009 if self._purge < other._purge:
4010 return -1
4011 else:
4012 return 1
4013 return 0
4014
4015
4016
4017
4018
4019
4021 """
4022 Property target used to set the reference configuration value.
4023 If not C{None}, the value must be a C{ReferenceConfig} object.
4024 @raise ValueError: If the value is not a C{ReferenceConfig}
4025 """
4026 if value is None:
4027 self._reference = None
4028 else:
4029 if not isinstance(value, ReferenceConfig):
4030 raise ValueError("Value must be a C{ReferenceConfig} object.")
4031 self._reference = value
4032
4034 """
4035 Property target used to get the reference configuration value.
4036 """
4037 return self._reference
4038
4039 - def _setExtensions(self, value):
4040 """
4041 Property target used to set the extensions configuration value.
4042 If not C{None}, the value must be a C{ExtensionsConfig} object.
4043 @raise ValueError: If the value is not a C{ExtensionsConfig}
4044 """
4045 if value is None:
4046 self._extensions = None
4047 else:
4048 if not isinstance(value, ExtensionsConfig):
4049 raise ValueError("Value must be a C{ExtensionsConfig} object.")
4050 self._extensions = value
4051
4052 - def _getExtensions(self):
4053 """
4054 Property target used to get the extensions configuration value.
4055 """
4056 return self._extensions
4057
4059 """
4060 Property target used to set the options configuration value.
4061 If not C{None}, the value must be an C{OptionsConfig} object.
4062 @raise ValueError: If the value is not a C{OptionsConfig}
4063 """
4064 if value is None:
4065 self._options = None
4066 else:
4067 if not isinstance(value, OptionsConfig):
4068 raise ValueError("Value must be a C{OptionsConfig} object.")
4069 self._options = value
4070
4072 """
4073 Property target used to get the options configuration value.
4074 """
4075 return self._options
4076
4078 """
4079 Property target used to set the peers configuration value.
4080 If not C{None}, the value must be an C{PeersConfig} object.
4081 @raise ValueError: If the value is not a C{PeersConfig}
4082 """
4083 if value is None:
4084 self._peers = None
4085 else:
4086 if not isinstance(value, PeersConfig):
4087 raise ValueError("Value must be a C{PeersConfig} object.")
4088 self._peers = value
4089
4091 """
4092 Property target used to get the peers configuration value.
4093 """
4094 return self._peers
4095
4097 """
4098 Property target used to set the collect configuration value.
4099 If not C{None}, the value must be a C{CollectConfig} object.
4100 @raise ValueError: If the value is not a C{CollectConfig}
4101 """
4102 if value is None:
4103 self._collect = None
4104 else:
4105 if not isinstance(value, CollectConfig):
4106 raise ValueError("Value must be a C{CollectConfig} object.")
4107 self._collect = value
4108
4110 """
4111 Property target used to get the collect configuration value.
4112 """
4113 return self._collect
4114
4116 """
4117 Property target used to set the stage configuration value.
4118 If not C{None}, the value must be a C{StageConfig} object.
4119 @raise ValueError: If the value is not a C{StageConfig}
4120 """
4121 if value is None:
4122 self._stage = None
4123 else:
4124 if not isinstance(value, StageConfig):
4125 raise ValueError("Value must be a C{StageConfig} object.")
4126 self._stage = value
4127
4129 """
4130 Property target used to get the stage configuration value.
4131 """
4132 return self._stage
4133
4135 """
4136 Property target used to set the store configuration value.
4137 If not C{None}, the value must be a C{StoreConfig} object.
4138 @raise ValueError: If the value is not a C{StoreConfig}
4139 """
4140 if value is None:
4141 self._store = None
4142 else:
4143 if not isinstance(value, StoreConfig):
4144 raise ValueError("Value must be a C{StoreConfig} object.")
4145 self._store = value
4146
4148 """
4149 Property target used to get the store configuration value.
4150 """
4151 return self._store
4152
4154 """
4155 Property target used to set the purge configuration value.
4156 If not C{None}, the value must be a C{PurgeConfig} object.
4157 @raise ValueError: If the value is not a C{PurgeConfig}
4158 """
4159 if value is None:
4160 self._purge = None
4161 else:
4162 if not isinstance(value, PurgeConfig):
4163 raise ValueError("Value must be a C{PurgeConfig} object.")
4164 self._purge = value
4165
4167 """
4168 Property target used to get the purge configuration value.
4169 """
4170 return self._purge
4171
4172 reference = property(_getReference, _setReference, None, "Reference configuration in terms of a C{ReferenceConfig} object.")
4173 extensions = property(_getExtensions, _setExtensions, None, "Extensions configuration in terms of a C{ExtensionsConfig} object.")
4174 options = property(_getOptions, _setOptions, None, "Options configuration in terms of a C{OptionsConfig} object.")
4175 peers = property(_getPeers, _setPeers, None, "Peers configuration in terms of a C{PeersConfig} object.")
4176 collect = property(_getCollect, _setCollect, None, "Collect configuration in terms of a C{CollectConfig} object.")
4177 stage = property(_getStage, _setStage, None, "Stage configuration in terms of a C{StageConfig} object.")
4178 store = property(_getStore, _setStore, None, "Store configuration in terms of a C{StoreConfig} object.")
4179 purge = property(_getPurge, _setPurge, None, "Purge configuration in terms of a C{PurgeConfig} object.")
4180
4181
4182
4183
4184
4185
4187 """
4188 Extracts configuration into an XML document.
4189
4190 If C{xmlPath} is not provided, then the XML document will be returned as
4191 a string. If C{xmlPath} is provided, then the XML document will be written
4192 to the file and C{None} will be returned.
4193
4194 Unless the C{validate} parameter is C{False}, the L{Config.validate}
4195 method will be called (with its default arguments) against the
4196 configuration before extracting the XML. If configuration is not valid,
4197 then an XML document will not be extracted.
4198
4199 @note: It is strongly suggested that the C{validate} option always be set
4200 to C{True} (the default) unless there is a specific need to write an
4201 invalid configuration file to disk.
4202
4203 @param xmlPath: Path to an XML file to create on disk.
4204 @type xmlPath: Absolute path to a file.
4205
4206 @param validate: Validate the document before extracting it.
4207 @type validate: Boolean true/false.
4208
4209 @return: XML string data or C{None} as described above.
4210
4211 @raise ValueError: If configuration within the object is not valid.
4212 @raise IOError: If there is an error writing to the file.
4213 @raise OSError: If there is an error writing to the file.
4214 """
4215 if validate:
4216 self.validate()
4217 xmlData = self._extractXml()
4218 if xmlPath is not None:
4219 open(xmlPath, "w").write(xmlData)
4220 return None
4221 else:
4222 return xmlData
4223
4224 - def validate(self, requireOneAction=True, requireReference=False, requireExtensions=False, requireOptions=True,
4225 requireCollect=False, requireStage=False, requireStore=False, requirePurge=False, requirePeers=False):
4226 """
4227 Validates configuration represented by the object.
4228
4229 This method encapsulates all of the validations that should apply to a
4230 fully "complete" document but are not already taken care of by earlier
4231 validations. It also provides some extra convenience functionality which
4232 might be useful to some people. The process of validation is laid out in
4233 the I{Validation} section in the class notes (above).
4234
4235 @param requireOneAction: Require at least one of the collect, stage, store or purge sections.
4236 @param requireReference: Require the reference section.
4237 @param requireExtensions: Require the extensions section.
4238 @param requireOptions: Require the options section.
4239 @param requirePeers: Require the peers section.
4240 @param requireCollect: Require the collect section.
4241 @param requireStage: Require the stage section.
4242 @param requireStore: Require the store section.
4243 @param requirePurge: Require the purge section.
4244
4245 @raise ValueError: If one of the validations fails.
4246 """
4247 if requireOneAction and (self.collect, self.stage, self.store, self.purge) == (None, None, None, None):
4248 raise ValueError("At least one of the collect, stage, store and purge sections is required.")
4249 if requireReference and self.reference is None:
4250 raise ValueError("The reference is section is required.")
4251 if requireExtensions and self.extensions is None:
4252 raise ValueError("The extensions is section is required.")
4253 if requireOptions and self.options is None:
4254 raise ValueError("The options is section is required.")
4255 if requirePeers and self.peers is None:
4256 raise ValueError("The peers is section is required.")
4257 if requireCollect and self.collect is None:
4258 raise ValueError("The collect is section is required.")
4259 if requireStage and self.stage is None:
4260 raise ValueError("The stage is section is required.")
4261 if requireStore and self.store is None:
4262 raise ValueError("The store is section is required.")
4263 if requirePurge and self.purge is None:
4264 raise ValueError("The purge is section is required.")
4265 self._validateContents()
4266
4267
4268
4269
4270
4271
4273 """
4274 Internal method to parse an XML string into the object.
4275
4276 This method parses the XML document into a DOM tree (C{xmlDom}) and then
4277 calls individual static methods to parse each of the individual
4278 configuration sections.
4279
4280 Most of the validation we do here has to do with whether the document can
4281 be parsed and whether any values which exist are valid. We don't do much
4282 validation as to whether required elements actually exist unless we have
4283 to to make sense of the document (instead, that's the job of the
4284 L{validate} method).
4285
4286 @param xmlData: XML data to be parsed
4287 @type xmlData: String data
4288
4289 @raise ValueError: If the XML cannot be successfully parsed.
4290 """
4291 (xmlDom, parentNode) = createInputDom(xmlData)
4292 self._reference = Config._parseReference(parentNode)
4293 self._extensions = Config._parseExtensions(parentNode)
4294 self._options = Config._parseOptions(parentNode)
4295 self._peers = Config._parsePeers(parentNode)
4296 self._collect = Config._parseCollect(parentNode)
4297 self._stage = Config._parseStage(parentNode)
4298 self._store = Config._parseStore(parentNode)
4299 self._purge = Config._parsePurge(parentNode)
4300
4302 """
4303 Parses a reference configuration section.
4304
4305 We read the following fields::
4306
4307 author //cb_config/reference/author
4308 revision //cb_config/reference/revision
4309 description //cb_config/reference/description
4310 generator //cb_config/reference/generator
4311
4312 @param parentNode: Parent node to search beneath.
4313
4314 @return: C{ReferenceConfig} object or C{None} if the section does not exist.
4315 @raise ValueError: If some filled-in value is invalid.
4316 """
4317 reference = None
4318 sectionNode = readFirstChild(parentNode, "reference")
4319 if sectionNode is not None:
4320 reference = ReferenceConfig()
4321 reference.author = readString(sectionNode, "author")
4322 reference.revision = readString(sectionNode, "revision")
4323 reference.description = readString(sectionNode, "description")
4324 reference.generator = readString(sectionNode, "generator")
4325 return reference
4326 _parseReference = staticmethod(_parseReference)
4327
4329 """
4330 Parses an extensions configuration section.
4331
4332 We read the following fields::
4333
4334 orderMode //cb_config/extensions/order_mode
4335
4336 We also read groups of the following items, one list element per item::
4337
4338 name //cb_config/extensions/action/name
4339 module //cb_config/extensions/action/module
4340 function //cb_config/extensions/action/function
4341 index //cb_config/extensions/action/index
4342 dependencies //cb_config/extensions/action/depends
4343
4344 The extended actions are parsed by L{_parseExtendedActions}.
4345
4346 @param parentNode: Parent node to search beneath.
4347
4348 @return: C{ExtensionsConfig} object or C{None} if the section does not exist.
4349 @raise ValueError: If some filled-in value is invalid.
4350 """
4351 extensions = None
4352 sectionNode = readFirstChild(parentNode, "extensions")
4353 if sectionNode is not None:
4354 extensions = ExtensionsConfig()
4355 extensions.orderMode = readString(sectionNode, "order_mode")
4356 extensions.actions = Config._parseExtendedActions(sectionNode)
4357 return extensions
4358 _parseExtensions = staticmethod(_parseExtensions)
4359
4361 """
4362 Parses a options configuration section.
4363
4364 We read the following fields::
4365
4366 startingDay //cb_config/options/starting_day
4367 workingDir //cb_config/options/working_dir
4368 backupUser //cb_config/options/backup_user
4369 backupGroup //cb_config/options/backup_group
4370 rcpCommand //cb_config/options/rcp_command
4371 rshCommand //cb_config/options/rsh_command
4372 cbackCommand //cb_config/options/cback_command
4373 managedActions //cb_config/options/managed_actions
4374
4375 The list of managed actions is a comma-separated list of action names.
4376
4377 We also read groups of the following items, one list element per
4378 item::
4379
4380 overrides //cb_config/options/override
4381 hooks //cb_config/options/hook
4382
4383 The overrides are parsed by L{_parseOverrides} and the hooks are parsed
4384 by L{_parseHooks}.
4385
4386 @param parentNode: Parent node to search beneath.
4387
4388 @return: C{OptionsConfig} object or C{None} if the section does not exist.
4389 @raise ValueError: If some filled-in value is invalid.
4390 """
4391 options = None
4392 sectionNode = readFirstChild(parentNode, "options")
4393 if sectionNode is not None:
4394 options = OptionsConfig()
4395 options.startingDay = readString(sectionNode, "starting_day")
4396 options.workingDir = readString(sectionNode, "working_dir")
4397 options.backupUser = readString(sectionNode, "backup_user")
4398 options.backupGroup = readString(sectionNode, "backup_group")
4399 options.rcpCommand = readString(sectionNode, "rcp_command")
4400 options.rshCommand = readString(sectionNode, "rsh_command")
4401 options.cbackCommand = readString(sectionNode, "cback_command")
4402 options.overrides = Config._parseOverrides(sectionNode)
4403 options.hooks = Config._parseHooks(sectionNode)
4404 managedActions = readString(sectionNode, "managed_actions")
4405 options.managedActions = Config._parseCommaSeparatedString(managedActions)
4406 return options
4407 _parseOptions = staticmethod(_parseOptions)
4408
4410 """
4411 Parses a peers configuration section.
4412
4413 We read groups of the following items, one list element per
4414 item::
4415
4416 localPeers //cb_config/stage/peer
4417 remotePeers //cb_config/stage/peer
4418
4419 The individual peer entries are parsed by L{_parsePeerList}.
4420
4421 @param parentNode: Parent node to search beneath.
4422
4423 @return: C{StageConfig} object or C{None} if the section does not exist.
4424 @raise ValueError: If some filled-in value is invalid.
4425 """
4426 peers = None
4427 sectionNode = readFirstChild(parentNode, "peers")
4428 if sectionNode is not None:
4429 peers = PeersConfig()
4430 (peers.localPeers, peers.remotePeers) = Config._parsePeerList(sectionNode)
4431 return peers
4432 _parsePeers = staticmethod(_parsePeers)
4433
4435 """
4436 Parses a collect configuration section.
4437
4438 We read the following individual fields::
4439
4440 targetDir //cb_config/collect/collect_dir
4441 collectMode //cb_config/collect/collect_mode
4442 archiveMode //cb_config/collect/archive_mode
4443 ignoreFile //cb_config/collect/ignore_file
4444
4445 We also read groups of the following items, one list element per
4446 item::
4447
4448 absoluteExcludePaths //cb_config/collect/exclude/abs_path
4449 excludePatterns //cb_config/collect/exclude/pattern
4450 collectFiles //cb_config/collect/file
4451 collectDirs //cb_config/collect/dir
4452
4453 The exclusions are parsed by L{_parseExclusions}, the collect files are
4454 parsed by L{_parseCollectFiles}, and the directories are parsed by
4455 L{_parseCollectDirs}.
4456
4457 @param parentNode: Parent node to search beneath.
4458
4459 @return: C{CollectConfig} object or C{None} if the section does not exist.
4460 @raise ValueError: If some filled-in value is invalid.
4461 """
4462 collect = None
4463 sectionNode = readFirstChild(parentNode, "collect")
4464 if sectionNode is not None:
4465 collect = CollectConfig()
4466 collect.targetDir = readString(sectionNode, "collect_dir")
4467 collect.collectMode = readString(sectionNode, "collect_mode")
4468 collect.archiveMode = readString(sectionNode, "archive_mode")
4469 collect.ignoreFile = readString(sectionNode, "ignore_file")
4470 (collect.absoluteExcludePaths, unused, collect.excludePatterns) = Config._parseExclusions(sectionNode)
4471 collect.collectFiles = Config._parseCollectFiles(sectionNode)
4472 collect.collectDirs = Config._parseCollectDirs(sectionNode)
4473 return collect
4474 _parseCollect = staticmethod(_parseCollect)
4475
4477 """
4478 Parses a stage configuration section.
4479
4480 We read the following individual fields::
4481
4482 targetDir //cb_config/stage/staging_dir
4483
4484 We also read groups of the following items, one list element per
4485 item::
4486
4487 localPeers //cb_config/stage/peer
4488 remotePeers //cb_config/stage/peer
4489
4490 The individual peer entries are parsed by L{_parsePeerList}.
4491
4492 @param parentNode: Parent node to search beneath.
4493
4494 @return: C{StageConfig} object or C{None} if the section does not exist.
4495 @raise ValueError: If some filled-in value is invalid.
4496 """
4497 stage = None
4498 sectionNode = readFirstChild(parentNode, "stage")
4499 if sectionNode is not None:
4500 stage = StageConfig()
4501 stage.targetDir = readString(sectionNode, "staging_dir")
4502 (stage.localPeers, stage.remotePeers) = Config._parsePeerList(sectionNode)
4503 return stage
4504 _parseStage = staticmethod(_parseStage)
4505
4507 """
4508 Parses a store configuration section.
4509
4510 We read the following fields::
4511
4512 sourceDir //cb_config/store/source_dir
4513 mediaType //cb_config/store/media_type
4514 deviceType //cb_config/store/device_type
4515 devicePath //cb_config/store/target_device
4516 deviceScsiId //cb_config/store/target_scsi_id
4517 driveSpeed //cb_config/store/drive_speed
4518 checkData //cb_config/store/check_data
4519 checkMedia //cb_config/store/check_media
4520 warnMidnite //cb_config/store/warn_midnite
4521 noEject //cb_config/store/no_eject
4522
4523 Blanking behavior configuration is parsed by the C{_parseBlankBehavior}
4524 method.
4525
4526 @param parentNode: Parent node to search beneath.
4527
4528 @return: C{StoreConfig} object or C{None} if the section does not exist.
4529 @raise ValueError: If some filled-in value is invalid.
4530 """
4531 store = None
4532 sectionNode = readFirstChild(parentNode, "store")
4533 if sectionNode is not None:
4534 store = StoreConfig()
4535 store.sourceDir = readString(sectionNode, "source_dir")
4536 store.mediaType = readString(sectionNode, "media_type")
4537 store.deviceType = readString(sectionNode, "device_type")
4538 store.devicePath = readString(sectionNode, "target_device")
4539 store.deviceScsiId = readString(sectionNode, "target_scsi_id")
4540 store.driveSpeed = readInteger(sectionNode, "drive_speed")
4541 store.checkData = readBoolean(sectionNode, "check_data")
4542 store.checkMedia = readBoolean(sectionNode, "check_media")
4543 store.warnMidnite = readBoolean(sectionNode, "warn_midnite")
4544 store.noEject = readBoolean(sectionNode, "no_eject")
4545 store.blankBehavior = Config._parseBlankBehavior(sectionNode)
4546 return store
4547 _parseStore = staticmethod(_parseStore)
4548
4550 """
4551 Parses a purge configuration section.
4552
4553 We read groups of the following items, one list element per
4554 item::
4555
4556 purgeDirs //cb_config/purge/dir
4557
4558 The individual directory entries are parsed by L{_parsePurgeDirs}.
4559
4560 @param parentNode: Parent node to search beneath.
4561
4562 @return: C{PurgeConfig} object or C{None} if the section does not exist.
4563 @raise ValueError: If some filled-in value is invalid.
4564 """
4565 purge = None
4566 sectionNode = readFirstChild(parentNode, "purge")
4567 if sectionNode is not None:
4568 purge = PurgeConfig()
4569 purge.purgeDirs = Config._parsePurgeDirs(sectionNode)
4570 return purge
4571 _parsePurge = staticmethod(_parsePurge)
4572
4574 """
4575 Reads extended actions data from immediately beneath the parent.
4576
4577 We read the following individual fields from each extended action::
4578
4579 name name
4580 module module
4581 function function
4582 index index
4583 dependencies depends
4584
4585 Dependency information is parsed by the C{_parseDependencies} method.
4586
4587 @param parentNode: Parent node to search beneath.
4588
4589 @return: List of extended actions.
4590 @raise ValueError: If the data at the location can't be read
4591 """
4592 lst = []
4593 for entry in readChildren(parentNode, "action"):
4594 if isElement(entry):
4595 action = ExtendedAction()
4596 action.name = readString(entry, "name")
4597 action.module = readString(entry, "module")
4598 action.function = readString(entry, "function")
4599 action.index = readInteger(entry, "index")
4600 action.dependencies = Config._parseDependencies(entry)
4601 lst.append(action);
4602 if lst == []:
4603 lst = None
4604 return lst
4605 _parseExtendedActions = staticmethod(_parseExtendedActions)
4606
4608 """
4609 Reads exclusions data from immediately beneath the parent.
4610
4611 We read groups of the following items, one list element per item::
4612
4613 absolute exclude/abs_path
4614 relative exclude/rel_path
4615 patterns exclude/pattern
4616
4617 If there are none of some pattern (i.e. no relative path items) then
4618 C{None} will be returned for that item in the tuple.
4619
4620 This method can be used to parse exclusions on both the collect
4621 configuration level and on the collect directory level within collect
4622 configuration.
4623
4624 @param parentNode: Parent node to search beneath.
4625
4626 @return: Tuple of (absolute, relative, patterns) exclusions.
4627 """
4628 sectionNode = readFirstChild(parentNode, "exclude")
4629 if sectionNode is None:
4630 return (None, None, None)
4631 else:
4632 absolute = readStringList(sectionNode, "abs_path")
4633 relative = readStringList(sectionNode, "rel_path")
4634 patterns = readStringList(sectionNode, "pattern")
4635 return (absolute, relative, patterns)
4636 _parseExclusions = staticmethod(_parseExclusions)
4637
4639 """
4640 Reads a list of C{CommandOverride} objects from immediately beneath the parent.
4641
4642 We read the following individual fields::
4643
4644 command command
4645 absolutePath abs_path
4646
4647 @param parentNode: Parent node to search beneath.
4648
4649 @return: List of C{CommandOverride} objects or C{None} if none are found.
4650 @raise ValueError: If some filled-in value is invalid.
4651 """
4652 lst = []
4653 for entry in readChildren(parentNode, "override"):
4654 if isElement(entry):
4655 override = CommandOverride()
4656 override.command = readString(entry, "command")
4657 override.absolutePath = readString(entry, "abs_path")
4658 lst.append(override)
4659 if lst == []:
4660 lst = None
4661 return lst
4662 _parseOverrides = staticmethod(_parseOverrides)
4663
4665 """
4666 Reads a list of C{ActionHook} objects from immediately beneath the parent.
4667
4668 We read the following individual fields::
4669
4670 action action
4671 command command
4672
4673 @param parentNode: Parent node to search beneath.
4674
4675 @return: List of C{ActionHook} objects or C{None} if none are found.
4676 @raise ValueError: If some filled-in value is invalid.
4677 """
4678 lst = []
4679 for entry in readChildren(parentNode, "pre_action_hook"):
4680 if isElement(entry):
4681 hook = PreActionHook()
4682 hook.action = readString(entry, "action")
4683 hook.command = readString(entry, "command")
4684 lst.append(hook)
4685 for entry in readChildren(parentNode, "post_action_hook"):
4686 if isElement(entry):
4687 hook = PostActionHook()
4688 hook.action = readString(entry, "action")
4689 hook.command = readString(entry, "command")
4690 lst.append(hook)
4691 if lst == []:
4692 lst = None
4693 return lst
4694 _parseHooks = staticmethod(_parseHooks)
4695
4697 """
4698 Reads a list of C{CollectFile} objects from immediately beneath the parent.
4699
4700 We read the following individual fields::
4701
4702 absolutePath abs_path
4703 collectMode mode I{or} collect_mode
4704 archiveMode archive_mode
4705
4706 The collect mode is a special case. Just a C{mode} tag is accepted, but
4707 we prefer C{collect_mode} for consistency with the rest of the config
4708 file and to avoid confusion with the archive mode. If both are provided,
4709 only C{mode} will be used.
4710
4711 @param parentNode: Parent node to search beneath.
4712
4713 @return: List of C{CollectFile} objects or C{None} if none are found.
4714 @raise ValueError: If some filled-in value is invalid.
4715 """
4716 lst = []
4717 for entry in readChildren(parentNode, "file"):
4718 if isElement(entry):
4719 cfile = CollectFile()
4720 cfile.absolutePath = readString(entry, "abs_path")
4721 cfile.collectMode = readString(entry, "mode")
4722 if cfile.collectMode is None:
4723 cfile.collectMode = readString(entry, "collect_mode")
4724 cfile.archiveMode = readString(entry, "archive_mode")
4725 lst.append(cfile)
4726 if lst == []:
4727 lst = None
4728 return lst
4729 _parseCollectFiles = staticmethod(_parseCollectFiles)
4730
4732 """
4733 Reads a list of C{CollectDir} objects from immediately beneath the parent.
4734
4735 We read the following individual fields::
4736
4737 absolutePath abs_path
4738 collectMode mode I{or} collect_mode
4739 archiveMode archive_mode
4740 ignoreFile ignore_file
4741 linkDepth link_depth
4742 dereference dereference
4743
4744 The collect mode is a special case. Just a C{mode} tag is accepted for
4745 backwards compatibility, but we prefer C{collect_mode} for consistency
4746 with the rest of the config file and to avoid confusion with the archive
4747 mode. If both are provided, only C{mode} will be used.
4748
4749 We also read groups of the following items, one list element per
4750 item::
4751
4752 absoluteExcludePaths exclude/abs_path
4753 relativeExcludePaths exclude/rel_path
4754 excludePatterns exclude/pattern
4755
4756 The exclusions are parsed by L{_parseExclusions}.
4757
4758 @param parentNode: Parent node to search beneath.
4759
4760 @return: List of C{CollectDir} objects or C{None} if none are found.
4761 @raise ValueError: If some filled-in value is invalid.
4762 """
4763 lst = []
4764 for entry in readChildren(parentNode, "dir"):
4765 if isElement(entry):
4766 cdir = CollectDir()
4767 cdir.absolutePath = readString(entry, "abs_path")
4768 cdir.collectMode = readString(entry, "mode")
4769 if cdir.collectMode is None:
4770 cdir.collectMode = readString(entry, "collect_mode")
4771 cdir.archiveMode = readString(entry, "archive_mode")
4772 cdir.ignoreFile = readString(entry, "ignore_file")
4773 cdir.linkDepth = readInteger(entry, "link_depth")
4774 cdir.dereference = readBoolean(entry, "dereference")
4775 (cdir.absoluteExcludePaths, cdir.relativeExcludePaths, cdir.excludePatterns) = Config._parseExclusions(entry)
4776 lst.append(cdir)
4777 if lst == []:
4778 lst = None
4779 return lst
4780 _parseCollectDirs = staticmethod(_parseCollectDirs)
4781
4783 """
4784 Reads a list of C{PurgeDir} objects from immediately beneath the parent.
4785
4786 We read the following individual fields::
4787
4788 absolutePath <baseExpr>/abs_path
4789 retainDays <baseExpr>/retain_days
4790
4791 @param parentNode: Parent node to search beneath.
4792
4793 @return: List of C{PurgeDir} objects or C{None} if none are found.
4794 @raise ValueError: If the data at the location can't be read
4795 """
4796 lst = []
4797 for entry in readChildren(parentNode, "dir"):
4798 if isElement(entry):
4799 cdir = PurgeDir()
4800 cdir.absolutePath = readString(entry, "abs_path")
4801 cdir.retainDays = readInteger(entry, "retain_days")
4802 lst.append(cdir)
4803 if lst == []:
4804 lst = None
4805 return lst
4806 _parsePurgeDirs = staticmethod(_parsePurgeDirs)
4807
4809 """
4810 Reads remote and local peer data from immediately beneath the parent.
4811
4812 We read the following individual fields for both remote
4813 and local peers::
4814
4815 name name
4816 collectDir collect_dir
4817
4818 We also read the following individual fields for remote peers
4819 only::
4820
4821 remoteUser backup_user
4822 rcpCommand rcp_command
4823 rshCommand rsh_command
4824 cbackCommand cback_command
4825 managed managed
4826 managedActions managed_actions
4827
4828 Additionally, the value in the C{type} field is used to determine whether
4829 this entry is a remote peer. If the type is C{"remote"}, it's a remote
4830 peer, and if the type is C{"local"}, it's a remote peer.
4831
4832 If there are none of one type of peer (i.e. no local peers) then C{None}
4833 will be returned for that item in the tuple.
4834
4835 @param parentNode: Parent node to search beneath.
4836
4837 @return: Tuple of (local, remote) peer lists.
4838 @raise ValueError: If the data at the location can't be read
4839 """
4840 localPeers = []
4841 remotePeers = []
4842 for entry in readChildren(parentNode, "peer"):
4843 if isElement(entry):
4844 peerType = readString(entry, "type")
4845 if peerType == "local":
4846 localPeer = LocalPeer()
4847 localPeer.name = readString(entry, "name")
4848 localPeer.collectDir = readString(entry, "collect_dir")
4849 localPeers.append(localPeer)
4850 elif peerType == "remote":
4851 remotePeer = RemotePeer()
4852 remotePeer.name = readString(entry, "name")
4853 remotePeer.collectDir = readString(entry, "collect_dir")
4854 remotePeer.remoteUser = readString(entry, "backup_user")
4855 remotePeer.rcpCommand = readString(entry, "rcp_command")
4856 remotePeer.rshCommand = readString(entry, "rsh_command")
4857 remotePeer.cbackCommand = readString(entry, "cback_command")
4858 remotePeer.managed = readBoolean(entry, "managed")
4859 managedActions = readString(entry, "managed_actions")
4860 remotePeer.managedActions = Config._parseCommaSeparatedString(managedActions)
4861 remotePeers.append(remotePeer)
4862 if localPeers == []:
4863 localPeers = None
4864 if remotePeers == []:
4865 remotePeers = None
4866 return (localPeers, remotePeers)
4867 _parsePeerList = staticmethod(_parsePeerList)
4868
4870 """
4871 Reads extended action dependency information from a parent node.
4872
4873 We read the following individual fields::
4874
4875 runBefore depends/run_before
4876 runAfter depends/run_after
4877
4878 Each of these fields is a comma-separated list of action names.
4879
4880 The result is placed into an C{ActionDependencies} object.
4881
4882 If the dependencies parent node does not exist, C{None} will be returned.
4883 Otherwise, an C{ActionDependencies} object will always be created, even
4884 if it does not contain any actual dependencies in it.
4885
4886 @param parentNode: Parent node to search beneath.
4887
4888 @return: C{ActionDependencies} object or C{None}.
4889 @raise ValueError: If the data at the location can't be read
4890 """
4891 sectionNode = readFirstChild(parentNode, "depends")
4892 if sectionNode is None:
4893 return None
4894 else:
4895 runBefore = readString(sectionNode, "run_before")
4896 runAfter = readString(sectionNode, "run_after")
4897 beforeList = Config._parseCommaSeparatedString(runBefore)
4898 afterList = Config._parseCommaSeparatedString(runAfter)
4899 return ActionDependencies(beforeList, afterList)
4900 _parseDependencies = staticmethod(_parseDependencies)
4901
4903 """
4904 Parses a list of values out of a comma-separated string.
4905
4906 The items in the list are split by comma, and then have whitespace
4907 stripped. As a special case, if C{commaString} is C{None}, then C{None}
4908 will be returned.
4909
4910 @param commaString: List of values in comma-separated string format.
4911 @return: Values from commaString split into a list, or C{None}.
4912 """
4913 if commaString is None:
4914 return None
4915 else:
4916 pass1 = commaString.split(",")
4917 pass2 = []
4918 for item in pass1:
4919 item = item.strip()
4920 if len(item) > 0:
4921 pass2.append(item)
4922 return pass2
4923 _parseCommaSeparatedString = staticmethod(_parseCommaSeparatedString)
4924
4926 """
4927 Reads a single C{BlankBehavior} object from immediately beneath the parent.
4928
4929 We read the following individual fields::
4930
4931 blankMode blank_behavior/mode
4932 blankFactor blank_behavior/factor
4933
4934 @param parentNode: Parent node to search beneath.
4935
4936 @return: C{BlankBehavior} object or C{None} if none if the section is not found
4937 @raise ValueError: If some filled-in value is invalid.
4938 """
4939 blankBehavior = None
4940 sectionNode = readFirstChild(parentNode, "blank_behavior")
4941 if sectionNode is not None:
4942 blankBehavior = BlankBehavior()
4943 blankBehavior.blankMode = readString(sectionNode, "mode")
4944 blankBehavior.blankFactor = readString(sectionNode, "factor")
4945 return blankBehavior
4946 _parseBlankBehavior = staticmethod(_parseBlankBehavior)
4947
4948
4949
4950
4951
4952
4954 """
4955 Internal method to extract configuration into an XML string.
4956
4957 This method assumes that the internal L{validate} method has been called
4958 prior to extracting the XML, if the caller cares. No validation will be
4959 done internally.
4960
4961 As a general rule, fields that are set to C{None} will be extracted into
4962 the document as empty tags. The same goes for container tags that are
4963 filled based on lists - if the list is empty or C{None}, the container
4964 tag will be empty.
4965 """
4966 (xmlDom, parentNode) = createOutputDom()
4967 Config._addReference(xmlDom, parentNode, self.reference)
4968 Config._addExtensions(xmlDom, parentNode, self.extensions)
4969 Config._addOptions(xmlDom, parentNode, self.options)
4970 Config._addPeers(xmlDom, parentNode, self.peers)
4971 Config._addCollect(xmlDom, parentNode, self.collect)
4972 Config._addStage(xmlDom, parentNode, self.stage)
4973 Config._addStore(xmlDom, parentNode, self.store)
4974 Config._addPurge(xmlDom, parentNode, self.purge)
4975 xmlData = serializeDom(xmlDom)
4976 xmlDom.unlink()
4977 return xmlData
4978
4980 """
4981 Adds a <reference> configuration section as the next child of a parent.
4982
4983 We add the following fields to the document::
4984
4985 author //cb_config/reference/author
4986 revision //cb_config/reference/revision
4987 description //cb_config/reference/description
4988 generator //cb_config/reference/generator
4989
4990 If C{referenceConfig} is C{None}, then no container will be added.
4991
4992 @param xmlDom: DOM tree as from L{createOutputDom}.
4993 @param parentNode: Parent that the section should be appended to.
4994 @param referenceConfig: Reference configuration section to be added to the document.
4995 """
4996 if referenceConfig is not None:
4997 sectionNode = addContainerNode(xmlDom, parentNode, "reference")
4998 addStringNode(xmlDom, sectionNode, "author", referenceConfig.author)
4999 addStringNode(xmlDom, sectionNode, "revision", referenceConfig.revision)
5000 addStringNode(xmlDom, sectionNode, "description", referenceConfig.description)
5001 addStringNode(xmlDom, sectionNode, "generator", referenceConfig.generator)
5002 _addReference = staticmethod(_addReference)
5003
5005 """
5006 Adds an <extensions> configuration section as the next child of a parent.
5007
5008 We add the following fields to the document::
5009
5010 order_mode //cb_config/extensions/order_mode
5011
5012 We also add groups of the following items, one list element per item::
5013
5014 actions //cb_config/extensions/action
5015
5016 The extended action entries are added by L{_addExtendedAction}.
5017
5018 If C{extensionsConfig} is C{None}, then no container will be added.
5019
5020 @param xmlDom: DOM tree as from L{createOutputDom}.
5021 @param parentNode: Parent that the section should be appended to.
5022 @param extensionsConfig: Extensions configuration section to be added to the document.
5023 """
5024 if extensionsConfig is not None:
5025 sectionNode = addContainerNode(xmlDom, parentNode, "extensions")
5026 addStringNode(xmlDom, sectionNode, "order_mode", extensionsConfig.orderMode)
5027 if extensionsConfig.actions is not None:
5028 for action in extensionsConfig.actions:
5029 Config._addExtendedAction(xmlDom, sectionNode, action)
5030 _addExtensions = staticmethod(_addExtensions)
5031
5033 """
5034 Adds a <options> configuration section as the next child of a parent.
5035
5036 We add the following fields to the document::
5037
5038 startingDay //cb_config/options/starting_day
5039 workingDir //cb_config/options/working_dir
5040 backupUser //cb_config/options/backup_user
5041 backupGroup //cb_config/options/backup_group
5042 rcpCommand //cb_config/options/rcp_command
5043 rshCommand //cb_config/options/rsh_command
5044 cbackCommand //cb_config/options/cback_command
5045 managedActions //cb_config/options/managed_actions
5046
5047 We also add groups of the following items, one list element per
5048 item::
5049
5050 overrides //cb_config/options/override
5051 hooks //cb_config/options/pre_action_hook
5052 hooks //cb_config/options/post_action_hook
5053
5054 The individual override items are added by L{_addOverride}. The
5055 individual hook items are added by L{_addHook}.
5056
5057 If C{optionsConfig} is C{None}, then no container will be added.
5058
5059 @param xmlDom: DOM tree as from L{createOutputDom}.
5060 @param parentNode: Parent that the section should be appended to.
5061 @param optionsConfig: Options configuration section to be added to the document.
5062 """
5063 if optionsConfig is not None:
5064 sectionNode = addContainerNode(xmlDom, parentNode, "options")
5065 addStringNode(xmlDom, sectionNode, "starting_day", optionsConfig.startingDay)
5066 addStringNode(xmlDom, sectionNode, "working_dir", optionsConfig.workingDir)
5067 addStringNode(xmlDom, sectionNode, "backup_user", optionsConfig.backupUser)
5068 addStringNode(xmlDom, sectionNode, "backup_group", optionsConfig.backupGroup)
5069 addStringNode(xmlDom, sectionNode, "rcp_command", optionsConfig.rcpCommand)
5070 addStringNode(xmlDom, sectionNode, "rsh_command", optionsConfig.rshCommand)
5071 addStringNode(xmlDom, sectionNode, "cback_command", optionsConfig.cbackCommand)
5072 managedActions = Config._buildCommaSeparatedString(optionsConfig.managedActions)
5073 addStringNode(xmlDom, sectionNode, "managed_actions", managedActions)
5074 if optionsConfig.overrides is not None:
5075 for override in optionsConfig.overrides:
5076 Config._addOverride(xmlDom, sectionNode, override)
5077 if optionsConfig.hooks is not None:
5078 for hook in optionsConfig.hooks:
5079 Config._addHook(xmlDom, sectionNode, hook)
5080 _addOptions = staticmethod(_addOptions)
5081
5082 - def _addPeers(xmlDom, parentNode, peersConfig):
5083 """
5084 Adds a <peers> configuration section as the next child of a parent.
5085
5086 We add groups of the following items, one list element per
5087 item::
5088
5089 localPeers //cb_config/peers/peer
5090 remotePeers //cb_config/peers/peer
5091
5092 The individual local and remote peer entries are added by
5093 L{_addLocalPeer} and L{_addRemotePeer}, respectively.
5094
5095 If C{peersConfig} is C{None}, then no container will be added.
5096
5097 @param xmlDom: DOM tree as from L{createOutputDom}.
5098 @param parentNode: Parent that the section should be appended to.
5099 @param peersConfig: Peers configuration section to be added to the document.
5100 """
5101 if peersConfig is not None:
5102 sectionNode = addContainerNode(xmlDom, parentNode, "peers")
5103 if peersConfig.localPeers is not None:
5104 for localPeer in peersConfig.localPeers:
5105 Config._addLocalPeer(xmlDom, sectionNode, localPeer)
5106 if peersConfig.remotePeers is not None:
5107 for remotePeer in peersConfig.remotePeers:
5108 Config._addRemotePeer(xmlDom, sectionNode, remotePeer)
5109 _addPeers = staticmethod(_addPeers)
5110
5112 """
5113 Adds a <collect> configuration section as the next child of a parent.
5114
5115 We add the following fields to the document::
5116
5117 targetDir //cb_config/collect/collect_dir
5118 collectMode //cb_config/collect/collect_mode
5119 archiveMode //cb_config/collect/archive_mode
5120 ignoreFile //cb_config/collect/ignore_file
5121
5122 We also add groups of the following items, one list element per
5123 item::
5124
5125 absoluteExcludePaths //cb_config/collect/exclude/abs_path
5126 excludePatterns //cb_config/collect/exclude/pattern
5127 collectFiles //cb_config/collect/file
5128 collectDirs //cb_config/collect/dir
5129
5130 The individual collect files are added by L{_addCollectFile} and
5131 individual collect directories are added by L{_addCollectDir}.
5132
5133 If C{collectConfig} is C{None}, then no container will be added.
5134
5135 @param xmlDom: DOM tree as from L{createOutputDom}.
5136 @param parentNode: Parent that the section should be appended to.
5137 @param collectConfig: Collect configuration section to be added to the document.
5138 """
5139 if collectConfig is not None:
5140 sectionNode = addContainerNode(xmlDom, parentNode, "collect")
5141 addStringNode(xmlDom, sectionNode, "collect_dir", collectConfig.targetDir)
5142 addStringNode(xmlDom, sectionNode, "collect_mode", collectConfig.collectMode)
5143 addStringNode(xmlDom, sectionNode, "archive_mode", collectConfig.archiveMode)
5144 addStringNode(xmlDom, sectionNode, "ignore_file", collectConfig.ignoreFile)
5145 if ((collectConfig.absoluteExcludePaths is not None and collectConfig.absoluteExcludePaths != []) or
5146 (collectConfig.excludePatterns is not None and collectConfig.excludePatterns != [])):
5147 excludeNode = addContainerNode(xmlDom, sectionNode, "exclude")
5148 if collectConfig.absoluteExcludePaths is not None:
5149 for absolutePath in collectConfig.absoluteExcludePaths:
5150 addStringNode(xmlDom, excludeNode, "abs_path", absolutePath)
5151 if collectConfig.excludePatterns is not None:
5152 for pattern in collectConfig.excludePatterns:
5153 addStringNode(xmlDom, excludeNode, "pattern", pattern)
5154 if collectConfig.collectFiles is not None:
5155 for collectFile in collectConfig.collectFiles:
5156 Config._addCollectFile(xmlDom, sectionNode, collectFile)
5157 if collectConfig.collectDirs is not None:
5158 for collectDir in collectConfig.collectDirs:
5159 Config._addCollectDir(xmlDom, sectionNode, collectDir)
5160 _addCollect = staticmethod(_addCollect)
5161
5162 - def _addStage(xmlDom, parentNode, stageConfig):
5163 """
5164 Adds a <stage> configuration section as the next child of a parent.
5165
5166 We add the following fields to the document::
5167
5168 targetDir //cb_config/stage/staging_dir
5169
5170 We also add groups of the following items, one list element per
5171 item::
5172
5173 localPeers //cb_config/stage/peer
5174 remotePeers //cb_config/stage/peer
5175
5176 The individual local and remote peer entries are added by
5177 L{_addLocalPeer} and L{_addRemotePeer}, respectively.
5178
5179 If C{stageConfig} is C{None}, then no container will be added.
5180
5181 @param xmlDom: DOM tree as from L{createOutputDom}.
5182 @param parentNode: Parent that the section should be appended to.
5183 @param stageConfig: Stage configuration section to be added to the document.
5184 """
5185 if stageConfig is not None:
5186 sectionNode = addContainerNode(xmlDom, parentNode, "stage")
5187 addStringNode(xmlDom, sectionNode, "staging_dir", stageConfig.targetDir)
5188 if stageConfig.localPeers is not None:
5189 for localPeer in stageConfig.localPeers:
5190 Config._addLocalPeer(xmlDom, sectionNode, localPeer)
5191 if stageConfig.remotePeers is not None:
5192 for remotePeer in stageConfig.remotePeers:
5193 Config._addRemotePeer(xmlDom, sectionNode, remotePeer)
5194 _addStage = staticmethod(_addStage)
5195
5196 - def _addStore(xmlDom, parentNode, storeConfig):
5197 """
5198 Adds a <store> configuration section as the next child of a parent.
5199
5200 We add the following fields to the document::
5201
5202 sourceDir //cb_config/store/source_dir
5203 mediaType //cb_config/store/media_type
5204 deviceType //cb_config/store/device_type
5205 devicePath //cb_config/store/target_device
5206 deviceScsiId //cb_config/store/target_scsi_id
5207 driveSpeed //cb_config/store/drive_speed
5208 checkData //cb_config/store/check_data
5209 checkMedia //cb_config/store/check_media
5210 warnMidnite //cb_config/store/warn_midnite
5211 noEject //cb_config/store/no_eject
5212
5213 Blanking behavior configuration is added by the L{_addBlankBehavior}
5214 method.
5215
5216 If C{storeConfig} is C{None}, then no container will be added.
5217
5218 @param xmlDom: DOM tree as from L{createOutputDom}.
5219 @param parentNode: Parent that the section should be appended to.
5220 @param storeConfig: Store configuration section to be added to the document.
5221 """
5222 if storeConfig is not None:
5223 sectionNode = addContainerNode(xmlDom, parentNode, "store")
5224 addStringNode(xmlDom, sectionNode, "source_dir", storeConfig.sourceDir)
5225 addStringNode(xmlDom, sectionNode, "media_type", storeConfig.mediaType)
5226 addStringNode(xmlDom, sectionNode, "device_type", storeConfig.deviceType)
5227 addStringNode(xmlDom, sectionNode, "target_device", storeConfig.devicePath)
5228 addStringNode(xmlDom, sectionNode, "target_scsi_id", storeConfig.deviceScsiId)
5229 addIntegerNode(xmlDom, sectionNode, "drive_speed", storeConfig.driveSpeed)
5230 addBooleanNode(xmlDom, sectionNode, "check_data", storeConfig.checkData)
5231 addBooleanNode(xmlDom, sectionNode, "check_media", storeConfig.checkMedia)
5232 addBooleanNode(xmlDom, sectionNode, "warn_midnite", storeConfig.warnMidnite)
5233 addBooleanNode(xmlDom, sectionNode, "no_eject", storeConfig.noEject)
5234 Config._addBlankBehavior(xmlDom, sectionNode, storeConfig.blankBehavior)
5235 _addStore = staticmethod(_addStore)
5236
5237 - def _addPurge(xmlDom, parentNode, purgeConfig):
5238 """
5239 Adds a <purge> configuration section as the next child of a parent.
5240
5241 We add the following fields to the document::
5242
5243 purgeDirs //cb_config/purge/dir
5244
5245 The individual directory entries are added by L{_addPurgeDir}.
5246
5247 If C{purgeConfig} is C{None}, then no container will be added.
5248
5249 @param xmlDom: DOM tree as from L{createOutputDom}.
5250 @param parentNode: Parent that the section should be appended to.
5251 @param purgeConfig: Purge configuration section to be added to the document.
5252 """
5253 if purgeConfig is not None:
5254 sectionNode = addContainerNode(xmlDom, parentNode, "purge")
5255 if purgeConfig.purgeDirs is not None:
5256 for purgeDir in purgeConfig.purgeDirs:
5257 Config._addPurgeDir(xmlDom, sectionNode, purgeDir)
5258 _addPurge = staticmethod(_addPurge)
5259
5261 """
5262 Adds an extended action container as the next child of a parent.
5263
5264 We add the following fields to the document::
5265
5266 name action/name
5267 module action/module
5268 function action/function
5269 index action/index
5270 dependencies action/depends
5271
5272 Dependencies are added by the L{_addDependencies} method.
5273
5274 The <action> node itself is created as the next child of the parent node.
5275 This method only adds one action node. The parent must loop for each action
5276 in the C{ExtensionsConfig} object.
5277
5278 If C{action} is C{None}, this method call will be a no-op.
5279
5280 @param xmlDom: DOM tree as from L{createOutputDom}.
5281 @param parentNode: Parent that the section should be appended to.
5282 @param action: Purge directory to be added to the document.
5283 """
5284 if action is not None:
5285 sectionNode = addContainerNode(xmlDom, parentNode, "action")
5286 addStringNode(xmlDom, sectionNode, "name", action.name)
5287 addStringNode(xmlDom, sectionNode, "module", action.module)
5288 addStringNode(xmlDom, sectionNode, "function", action.function)
5289 addIntegerNode(xmlDom, sectionNode, "index", action.index)
5290 Config._addDependencies(xmlDom, sectionNode, action.dependencies)
5291 _addExtendedAction = staticmethod(_addExtendedAction)
5292
5294 """
5295 Adds a command override container as the next child of a parent.
5296
5297 We add the following fields to the document::
5298
5299 command override/command
5300 absolutePath override/abs_path
5301
5302 The <override> node itself is created as the next child of the parent
5303 node. This method only adds one override node. The parent must loop for
5304 each override in the C{OptionsConfig} object.
5305
5306 If C{override} is C{None}, this method call will be a no-op.
5307
5308 @param xmlDom: DOM tree as from L{createOutputDom}.
5309 @param parentNode: Parent that the section should be appended to.
5310 @param override: Command override to be added to the document.
5311 """
5312 if override is not None:
5313 sectionNode = addContainerNode(xmlDom, parentNode, "override")
5314 addStringNode(xmlDom, sectionNode, "command", override.command)
5315 addStringNode(xmlDom, sectionNode, "abs_path", override.absolutePath)
5316 _addOverride = staticmethod(_addOverride)
5317
5318 - def _addHook(xmlDom, parentNode, hook):
5319 """
5320 Adds an action hook container as the next child of a parent.
5321
5322 The behavior varies depending on the value of the C{before} and C{after}
5323 flags on the hook. If the C{before} flag is set, it's a pre-action hook,
5324 and we'll add the following fields::
5325
5326 action pre_action_hook/action
5327 command pre_action_hook/command
5328
5329 If the C{after} flag is set, it's a post-action hook, and we'll add the
5330 following fields::
5331
5332 action post_action_hook/action
5333 command post_action_hook/command
5334
5335 The <pre_action_hook> or <post_action_hook> node itself is created as the
5336 next child of the parent node. This method only adds one hook node. The
5337 parent must loop for each hook in the C{OptionsConfig} object.
5338
5339 If C{hook} is C{None}, this method call will be a no-op.
5340
5341 @param xmlDom: DOM tree as from L{createOutputDom}.
5342 @param parentNode: Parent that the section should be appended to.
5343 @param hook: Command hook to be added to the document.
5344 """
5345 if hook is not None:
5346 if hook.before:
5347 sectionNode = addContainerNode(xmlDom, parentNode, "pre_action_hook")
5348 else:
5349 sectionNode = addContainerNode(xmlDom, parentNode, "post_action_hook")
5350 addStringNode(xmlDom, sectionNode, "action", hook.action)
5351 addStringNode(xmlDom, sectionNode, "command", hook.command)
5352 _addHook = staticmethod(_addHook)
5353
5355 """
5356 Adds a collect file container as the next child of a parent.
5357
5358 We add the following fields to the document::
5359
5360 absolutePath dir/abs_path
5361 collectMode dir/collect_mode
5362 archiveMode dir/archive_mode
5363
5364 Note that for consistency with collect directory handling we'll only emit
5365 the preferred C{collect_mode} tag.
5366
5367 The <file> node itself is created as the next child of the parent node.
5368 This method only adds one collect file node. The parent must loop
5369 for each collect file in the C{CollectConfig} object.
5370
5371 If C{collectFile} is C{None}, this method call will be a no-op.
5372
5373 @param xmlDom: DOM tree as from L{createOutputDom}.
5374 @param parentNode: Parent that the section should be appended to.
5375 @param collectFile: Collect file to be added to the document.
5376 """
5377 if collectFile is not None:
5378 sectionNode = addContainerNode(xmlDom, parentNode, "file")
5379 addStringNode(xmlDom, sectionNode, "abs_path", collectFile.absolutePath)
5380 addStringNode(xmlDom, sectionNode, "collect_mode", collectFile.collectMode)
5381 addStringNode(xmlDom, sectionNode, "archive_mode", collectFile.archiveMode)
5382 _addCollectFile = staticmethod(_addCollectFile)
5383
5385 """
5386 Adds a collect directory container as the next child of a parent.
5387
5388 We add the following fields to the document::
5389
5390 absolutePath dir/abs_path
5391 collectMode dir/collect_mode
5392 archiveMode dir/archive_mode
5393 ignoreFile dir/ignore_file
5394 linkDepth dir/link_depth
5395 dereference dir/dereference
5396
5397 Note that an original XML document might have listed the collect mode
5398 using the C{mode} tag, since we accept both C{collect_mode} and C{mode}.
5399 However, here we'll only emit the preferred C{collect_mode} tag.
5400
5401 We also add groups of the following items, one list element per item::
5402
5403 absoluteExcludePaths dir/exclude/abs_path
5404 relativeExcludePaths dir/exclude/rel_path
5405 excludePatterns dir/exclude/pattern
5406
5407 The <dir> node itself is created as the next child of the parent node.
5408 This method only adds one collect directory node. The parent must loop
5409 for each collect directory in the C{CollectConfig} object.
5410
5411 If C{collectDir} is C{None}, this method call will be a no-op.
5412
5413 @param xmlDom: DOM tree as from L{createOutputDom}.
5414 @param parentNode: Parent that the section should be appended to.
5415 @param collectDir: Collect directory to be added to the document.
5416 """
5417 if collectDir is not None:
5418 sectionNode = addContainerNode(xmlDom, parentNode, "dir")
5419 addStringNode(xmlDom, sectionNode, "abs_path", collectDir.absolutePath)
5420 addStringNode(xmlDom, sectionNode, "collect_mode", collectDir.collectMode)
5421 addStringNode(xmlDom, sectionNode, "archive_mode", collectDir.archiveMode)
5422 addStringNode(xmlDom, sectionNode, "ignore_file", collectDir.ignoreFile)
5423 addIntegerNode(xmlDom, sectionNode, "link_depth", collectDir.linkDepth)
5424 addBooleanNode(xmlDom, sectionNode, "dereference", collectDir.dereference)
5425 if ((collectDir.absoluteExcludePaths is not None and collectDir.absoluteExcludePaths != []) or
5426 (collectDir.relativeExcludePaths is not None and collectDir.relativeExcludePaths != []) or
5427 (collectDir.excludePatterns is not None and collectDir.excludePatterns != [])):
5428 excludeNode = addContainerNode(xmlDom, sectionNode, "exclude")
5429 if collectDir.absoluteExcludePaths is not None:
5430 for absolutePath in collectDir.absoluteExcludePaths:
5431 addStringNode(xmlDom, excludeNode, "abs_path", absolutePath)
5432 if collectDir.relativeExcludePaths is not None:
5433 for relativePath in collectDir.relativeExcludePaths:
5434 addStringNode(xmlDom, excludeNode, "rel_path", relativePath)
5435 if collectDir.excludePatterns is not None:
5436 for pattern in collectDir.excludePatterns:
5437 addStringNode(xmlDom, excludeNode, "pattern", pattern)
5438 _addCollectDir = staticmethod(_addCollectDir)
5439
5441 """
5442 Adds a local 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
5449 Additionally, C{peer/type} is filled in with C{"local"}, since this is a
5450 local peer.
5451
5452 The <peer> node itself is created as the next child of the parent node.
5453 This method only adds one peer node. The parent must loop for each peer
5454 in the C{StageConfig} object.
5455
5456 If C{localPeer} is C{None}, this method call will be a no-op.
5457
5458 @param xmlDom: DOM tree as from L{createOutputDom}.
5459 @param parentNode: Parent that the section should be appended to.
5460 @param localPeer: Purge directory to be added to the document.
5461 """
5462 if localPeer is not None:
5463 sectionNode = addContainerNode(xmlDom, parentNode, "peer")
5464 addStringNode(xmlDom, sectionNode, "name", localPeer.name)
5465 addStringNode(xmlDom, sectionNode, "type", "local")
5466 addStringNode(xmlDom, sectionNode, "collect_dir", localPeer.collectDir)
5467 _addLocalPeer = staticmethod(_addLocalPeer)
5468
5470 """
5471 Adds a remote peer container as the next child of a parent.
5472
5473 We add the following fields to the document::
5474
5475 name peer/name
5476 collectDir peer/collect_dir
5477 remoteUser peer/backup_user
5478 rcpCommand peer/rcp_command
5479 rcpCommand peer/rcp_command
5480 rshCommand peer/rsh_command
5481 cbackCommand peer/cback_command
5482 managed peer/managed
5483 managedActions peer/managed_actions
5484
5485 Additionally, C{peer/type} is filled in with C{"remote"}, since this is a
5486 remote peer.
5487
5488 The <peer> node itself is created as the next child of the parent node.
5489 This method only adds one peer node. The parent must loop for each peer
5490 in the C{StageConfig} object.
5491
5492 If C{remotePeer} is C{None}, this method call will be a no-op.
5493
5494 @param xmlDom: DOM tree as from L{createOutputDom}.
5495 @param parentNode: Parent that the section should be appended to.
5496 @param remotePeer: Purge directory to be added to the document.
5497 """
5498 if remotePeer is not None:
5499 sectionNode = addContainerNode(xmlDom, parentNode, "peer")
5500 addStringNode(xmlDom, sectionNode, "name", remotePeer.name)
5501 addStringNode(xmlDom, sectionNode, "type", "remote")
5502 addStringNode(xmlDom, sectionNode, "collect_dir", remotePeer.collectDir)
5503 addStringNode(xmlDom, sectionNode, "backup_user", remotePeer.remoteUser)
5504 addStringNode(xmlDom, sectionNode, "rcp_command", remotePeer.rcpCommand)
5505 addStringNode(xmlDom, sectionNode, "rsh_command", remotePeer.rshCommand)
5506 addStringNode(xmlDom, sectionNode, "cback_command", remotePeer.cbackCommand)
5507 addBooleanNode(xmlDom, sectionNode, "managed", remotePeer.managed)
5508 managedActions = Config._buildCommaSeparatedString(remotePeer.managedActions)
5509 addStringNode(xmlDom, sectionNode, "managed_actions", managedActions)
5510 _addRemotePeer = staticmethod(_addRemotePeer)
5511
5513 """
5514 Adds a purge directory container as the next child of a parent.
5515
5516 We add the following fields to the document::
5517
5518 absolutePath dir/abs_path
5519 retainDays dir/retain_days
5520
5521 The <dir> node itself is created as the next child of the parent node.
5522 This method only adds one purge directory node. The parent must loop for
5523 each purge directory in the C{PurgeConfig} object.
5524
5525 If C{purgeDir} is C{None}, this method call will be a no-op.
5526
5527 @param xmlDom: DOM tree as from L{createOutputDom}.
5528 @param parentNode: Parent that the section should be appended to.
5529 @param purgeDir: Purge directory to be added to the document.
5530 """
5531 if purgeDir is not None:
5532 sectionNode = addContainerNode(xmlDom, parentNode, "dir")
5533 addStringNode(xmlDom, sectionNode, "abs_path", purgeDir.absolutePath)
5534 addIntegerNode(xmlDom, sectionNode, "retain_days", purgeDir.retainDays)
5535 _addPurgeDir = staticmethod(_addPurgeDir)
5536
5538 """
5539 Adds a extended action dependencies to parent node.
5540
5541 We add the following fields to the document::
5542
5543 runBefore depends/run_before
5544 runAfter depends/run_after
5545
5546 If C{dependencies} is C{None}, this method call will be a no-op.
5547
5548 @param xmlDom: DOM tree as from L{createOutputDom}.
5549 @param parentNode: Parent that the section should be appended to.
5550 @param dependencies: C{ActionDependencies} object to be added to the document
5551 """
5552 if dependencies is not None:
5553 sectionNode = addContainerNode(xmlDom, parentNode, "depends")
5554 runBefore = Config._buildCommaSeparatedString(dependencies.beforeList)
5555 runAfter = Config._buildCommaSeparatedString(dependencies.afterList)
5556 addStringNode(xmlDom, sectionNode, "run_before", runBefore)
5557 addStringNode(xmlDom, sectionNode, "run_after", runAfter)
5558 _addDependencies = staticmethod(_addDependencies)
5559
5561 """
5562 Creates a comma-separated string from a list of values.
5563
5564 As a special case, if C{valueList} is C{None}, then C{None} will be
5565 returned.
5566
5567 @param valueList: List of values to be placed into a string
5568
5569 @return: Values from valueList as a comma-separated string.
5570 """
5571 if valueList is None:
5572 return None
5573 return ",".join(valueList)
5574 _buildCommaSeparatedString = staticmethod(_buildCommaSeparatedString)
5575
5577 """
5578 Adds a blanking behavior container as the next child of a parent.
5579
5580 We add the following fields to the document::
5581
5582 blankMode blank_behavior/mode
5583 blankFactor blank_behavior/factor
5584
5585 The <blank_behavior> node itself is created as the next child of the
5586 parent node.
5587
5588 If C{blankBehavior} is C{None}, this method call will be a no-op.
5589
5590 @param xmlDom: DOM tree as from L{createOutputDom}.
5591 @param parentNode: Parent that the section should be appended to.
5592 @param blankBehavior: Blanking behavior to be added to the document.
5593 """
5594 if blankBehavior is not None:
5595 sectionNode = addContainerNode(xmlDom, parentNode, "blank_behavior")
5596 addStringNode(xmlDom, sectionNode, "mode", blankBehavior.blankMode)
5597 addStringNode(xmlDom, sectionNode, "factor", blankBehavior.blankFactor)
5598 _addBlankBehavior = staticmethod(_addBlankBehavior)
5599
5600
5601
5602
5603
5604
5606 """
5607 Validates configuration contents per rules discussed in module
5608 documentation.
5609
5610 This is the second pass at validation. It ensures that any filled-in
5611 section contains valid data. Any sections which is not set to C{None} is
5612 validated per the rules for that section, laid out in the module
5613 documentation (above).
5614
5615 @raise ValueError: If configuration is invalid.
5616 """
5617 self._validateReference()
5618 self._validateExtensions()
5619 self._validateOptions()
5620 self._validatePeers()
5621 self._validateCollect()
5622 self._validateStage()
5623 self._validateStore()
5624 self._validatePurge()
5625
5627 """
5628 Validates reference configuration.
5629 There are currently no reference-related validations.
5630 @raise ValueError: If reference configuration is invalid.
5631 """
5632 pass
5633
5635 """
5636 Validates extensions configuration.
5637
5638 The list of actions may be either C{None} or an empty list C{[]} if
5639 desired. Each extended action must include a name, a module, and a
5640 function.
5641
5642 Then, if the order mode is None or "index", an index is required; and if
5643 the order mode is "dependency", dependency information is required.
5644
5645 @raise ValueError: If reference configuration is invalid.
5646 """
5647 if self.extensions is not None:
5648 if self.extensions.actions is not None:
5649 names = []
5650 for action in self.extensions.actions:
5651 if action.name is None:
5652 raise ValueError("Each extended action must set a name.")
5653 names.append(action.name)
5654 if action.module is None:
5655 raise ValueError("Each extended action must set a module.")
5656 if action.function is None:
5657 raise ValueError("Each extended action must set a function.")
5658 if self.extensions.orderMode is None or self.extensions.orderMode == "index":
5659 if action.index is None:
5660 raise ValueError("Each extended action must set an index, based on order mode.")
5661 elif self.extensions.orderMode == "dependency":
5662 if action.dependencies is None:
5663 raise ValueError("Each extended action must set dependency information, based on order mode.")
5664 Config._checkUnique("Duplicate extension names exist:", names)
5665
5667 """
5668 Validates options configuration.
5669
5670 All fields must be filled in except the rsh command. The rcp and rsh
5671 commands are used as default values for all remote peers. Remote peers
5672 can also rely on the backup user as the default remote user name if they
5673 choose.
5674
5675 @raise ValueError: If reference configuration is invalid.
5676 """
5677 if self.options is not None:
5678 if self.options.startingDay is None:
5679 raise ValueError("Options section starting day must be filled in.")
5680 if self.options.workingDir is None:
5681 raise ValueError("Options section working directory must be filled in.")
5682 if self.options.backupUser is None:
5683 raise ValueError("Options section backup user must be filled in.")
5684 if self.options.backupGroup is None:
5685 raise ValueError("Options section backup group must be filled in.")
5686 if self.options.rcpCommand is None:
5687 raise ValueError("Options section remote copy command must be filled in.")
5688
5696
5698 """
5699 Validates collect configuration.
5700
5701 The target directory must be filled in. The collect mode, archive mode
5702 and ignore file are all optional. The list of absolute paths to exclude
5703 and patterns to exclude may be either C{None} or an empty list C{[]} if
5704 desired.
5705
5706 Each collect directory entry must contain an absolute path to collect,
5707 and then must either be able to take collect mode, archive mode and
5708 ignore file configuration from the parent C{CollectConfig} object, or
5709 must set each value on its own. The list of absolute paths to exclude,
5710 relative paths to exclude and patterns to exclude may be either C{None}
5711 or an empty list C{[]} if desired. Any list of absolute paths to exclude
5712 or patterns to exclude will be combined with the same list in the
5713 C{CollectConfig} object to make the complete list for a given directory.
5714
5715 @raise ValueError: If collect configuration is invalid.
5716 """
5717 if self.collect is not None:
5718 if self.collect.targetDir is None:
5719 raise ValueError("Collect section target directory must be filled in.")
5720 if self.collect.collectFiles is not None:
5721 for collectFile in self.collect.collectFiles:
5722 if collectFile.absolutePath is None:
5723 raise ValueError("Each collect file must set an absolute path.")
5724 if self.collect.collectMode is None and collectFile.collectMode is None:
5725 raise ValueError("Collect mode must either be set in parent collect section or individual collect file.")
5726 if self.collect.archiveMode is None and collectFile.archiveMode is None:
5727 raise ValueError("Archive mode must either be set in parent collect section or individual collect file.")
5728 if self.collect.collectDirs is not None:
5729 for collectDir in self.collect.collectDirs:
5730 if collectDir.absolutePath is None:
5731 raise ValueError("Each collect directory must set an absolute path.")
5732 if self.collect.collectMode is None and collectDir.collectMode is None:
5733 raise ValueError("Collect mode must either be set in parent collect section or individual collect directory.")
5734 if self.collect.archiveMode is None and collectDir.archiveMode is None:
5735 raise ValueError("Archive mode must either be set in parent collect section or individual collect directory.")
5736 if self.collect.ignoreFile is None and collectDir.ignoreFile is None:
5737 raise ValueError("Ignore file must either be set in parent collect section or individual collect directory.")
5738 if (collectDir.linkDepth is None or collectDir.linkDepth < 1) and collectDir.dereference:
5739 raise ValueError("Dereference flag is only valid when a non-zero link depth is in use.")
5740
5742 """
5743 Validates stage configuration.
5744
5745 The target directory must be filled in, and the peers are
5746 also validated.
5747
5748 Peers are only required in this section if the peers configuration
5749 section is not filled in. However, if any peers are filled in
5750 here, they override the peers configuration and must meet the
5751 validation criteria in L{_validatePeerList}.
5752
5753 @raise ValueError: If stage configuration is invalid.
5754 """
5755 if self.stage is not None:
5756 if self.stage.targetDir is None:
5757 raise ValueError("Stage section target directory must be filled in.")
5758 if self.peers is None:
5759
5760 self._validatePeerList(self.stage.localPeers, self.stage.remotePeers)
5761 else:
5762
5763
5764 if self.stage.hasPeers():
5765 self._validatePeerList(self.stage.localPeers, self.stage.remotePeers)
5766
5768 """
5769 Validates store configuration.
5770
5771 The device type, drive speed, and blanking behavior are optional. All
5772 other values are required. Missing booleans will be set to defaults.
5773
5774 If blanking behavior is provided, then both a blanking mode and a
5775 blanking factor are required.
5776
5777 The image writer functionality in the C{writer} module is supposed to be
5778 able to handle a device speed of C{None}.
5779
5780 Any caller which needs a "real" (non-C{None}) value for the device type
5781 can use C{DEFAULT_DEVICE_TYPE}, which is guaranteed to be sensible.
5782
5783 This is also where we make sure that the media type -- which is already a
5784 valid type -- matches up properly with the device type.
5785
5786 @raise ValueError: If store configuration is invalid.
5787 """
5788 if self.store is not None:
5789 if self.store.sourceDir is None:
5790 raise ValueError("Store section source directory must be filled in.")
5791 if self.store.mediaType is None:
5792 raise ValueError("Store section media type must be filled in.")
5793 if self.store.devicePath is None:
5794 raise ValueError("Store section device path must be filled in.")
5795 if self.store.deviceType == None or self.store.deviceType == "cdwriter":
5796 if self.store.mediaType not in VALID_CD_MEDIA_TYPES:
5797 raise ValueError("Media type must match device type.")
5798 elif self.store.deviceType == "dvdwriter":
5799 if self.store.mediaType not in VALID_DVD_MEDIA_TYPES:
5800 raise ValueError("Media type must match device type.")
5801 if self.store.blankBehavior is not None:
5802 if self.store.blankBehavior.blankMode is None and self.store.blankBehavior.blankFactor is None:
5803 raise ValueError("If blanking behavior is provided, all values must be filled in.")
5804
5806 """
5807 Validates purge configuration.
5808
5809 The list of purge directories may be either C{None} or an empty list
5810 C{[]} if desired. All purge directories must contain a path and a retain
5811 days value.
5812
5813 @raise ValueError: If purge configuration is invalid.
5814 """
5815 if self.purge is not None:
5816 if self.purge.purgeDirs is not None:
5817 for purgeDir in self.purge.purgeDirs:
5818 if purgeDir.absolutePath is None:
5819 raise ValueError("Each purge directory must set an absolute path.")
5820 if purgeDir.retainDays is None:
5821 raise ValueError("Each purge directory must set a retain days value.")
5822
5824 """
5825 Validates the set of local and remote peers.
5826
5827 Local peers must be completely filled in, including both name and collect
5828 directory. Remote peers must also fill in the name and collect
5829 directory, but can leave the remote user and rcp command unset. In this
5830 case, the remote user is assumed to match the backup user from the
5831 options section and rcp command is taken directly from the options
5832 section.
5833
5834 @param localPeers: List of local peers
5835 @param remotePeers: List of remote peers
5836
5837 @raise ValueError: If stage configuration is invalid.
5838 """
5839 if localPeers is None and remotePeers is None:
5840 raise ValueError("Peer list must contain at least one backup peer.")
5841 if localPeers is None and remotePeers is not None:
5842 if len(remotePeers) < 1:
5843 raise ValueError("Peer list must contain at least one backup peer.")
5844 elif localPeers is not None and remotePeers is None:
5845 if len(localPeers) < 1:
5846 raise ValueError("Peer list must contain at least one backup peer.")
5847 elif localPeers is not None and remotePeers is not None:
5848 if len(localPeers) + len(remotePeers) < 1:
5849 raise ValueError("Peer list must contain at least one backup peer.")
5850 names = []
5851 if localPeers is not None:
5852 for localPeer in localPeers:
5853 if localPeer.name is None:
5854 raise ValueError("Local peers must set a name.")
5855 names.append(localPeer.name)
5856 if localPeer.collectDir is None:
5857 raise ValueError("Local peers must set a collect directory.")
5858 if remotePeers is not None:
5859 for remotePeer in remotePeers:
5860 if remotePeer.name is None:
5861 raise ValueError("Remote peers must set a name.")
5862 names.append(remotePeer.name)
5863 if remotePeer.collectDir is None:
5864 raise ValueError("Remote peers must set a collect directory.")
5865 if (self.options is None or self.options.backupUser is None) and remotePeer.remoteUser is None:
5866 raise ValueError("Remote user must either be set in options section or individual remote peer.")
5867 if (self.options is None or self.options.rcpCommand is None) and remotePeer.rcpCommand is None:
5868 raise ValueError("Remote copy command must either be set in options section or individual remote peer.")
5869 if remotePeer.managed:
5870 if (self.options is None or self.options.rshCommand is None) and remotePeer.rshCommand is None:
5871 raise ValueError("Remote shell command must either be set in options section or individual remote peer.")
5872 if (self.options is None or self.options.cbackCommand is None) and remotePeer.cbackCommand is None:
5873 raise ValueError("Remote cback command must either be set in options section or individual remote peer.")
5874 if ((self.options is None or self.options.managedActions is None or len(self.options.managedActions) < 1)
5875 and (remotePeer.managedActions is None or len(remotePeer.managedActions) < 1)):
5876 raise ValueError("Managed actions list must be set in options section or individual remote peer.")
5877 Config._checkUnique("Duplicate peer names exist:", names)
5878
5879
5880
5881
5882
5883
5885 """
5886 Checks that all values are unique.
5887
5888 The values list is checked for duplicate values. If there are
5889 duplicates, an exception is thrown. All duplicate values are listed in
5890 the exception.
5891
5892 @param prefix: Prefix to use in the thrown exception
5893 @param values: List of values to check
5894
5895 @raise ValueError: If there are duplicates in the list
5896 """
5897 values.sort()
5898 duplicates = []
5899 for i in range(1, len(values)):
5900 if values[i-1] == values[i]:
5901 duplicates.append(values[i])
5902 if duplicates:
5903 raise ValueError("%s %s" % (prefix, duplicates))
5904 _checkUnique = staticmethod(_checkUnique)
5905
5906
5907
5908
5909
5910
5912 """
5913 Read a byte size value from an XML document.
5914
5915 A byte size value is an interpreted string value. If the string value
5916 ends with "MB" or "GB", then the string before that is interpreted as
5917 megabytes or gigabytes. Otherwise, it is intepreted as bytes.
5918
5919 @param parent: Parent node to search beneath.
5920 @param name: Name of node to search for.
5921
5922 @return: ByteQuantity parsed from XML document
5923 """
5924 data = readString(parent, name)
5925 if data is None:
5926 return None
5927 data = data.strip()
5928 if data.endswith("KB"):
5929 quantity = data[0:data.rfind("KB")].strip()
5930 units = UNIT_KBYTES
5931 elif data.endswith("MB"):
5932 quantity = data[0:data.rfind("MB")].strip()
5933 units = UNIT_MBYTES;
5934 elif data.endswith("GB"):
5935 quantity = data[0:data.rfind("GB")].strip()
5936 units = UNIT_GBYTES
5937 else:
5938 quantity = data.strip()
5939 units = UNIT_BYTES
5940 return ByteQuantity(quantity, units)
5941
5943 """
5944 Adds a text node as the next child of a parent, to contain a byte size.
5945
5946 If the C{byteQuantity} is None, then the node will be created, but will
5947 be empty (i.e. will contain no text node child).
5948
5949 The size in bytes will be normalized. If it is larger than 1.0 GB, it will
5950 be shown in GB ("1.0 GB"). If it is larger than 1.0 MB ("1.0 MB"), it will
5951 be shown in MB. Otherwise, it will be shown in bytes ("423413").
5952
5953 @param xmlDom: DOM tree as from C{impl.createDocument()}.
5954 @param parentNode: Parent node to create child for.
5955 @param nodeName: Name of the new container node.
5956 @param byteQuantity: ByteQuantity object to put into the XML document
5957
5958 @return: Reference to the newly-created node.
5959 """
5960 if byteQuantity is None:
5961 byteString = None
5962 elif byteQuantity.units == UNIT_KBYTES:
5963 byteString = "%s KB" % byteQuantity.quantity
5964 elif byteQuantity.units == UNIT_MBYTES:
5965 byteString = "%s MB" % byteQuantity.quantity
5966 elif byteQuantity.units == UNIT_GBYTES:
5967 byteString = "%s GB" % byteQuantity.quantity
5968 else:
5969 byteString = byteQuantity.quantity
5970 return addStringNode(xmlDom, parentNode, nodeName, byteString)
5971