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