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
4750 """
4751 Reads a list of C{ActionHook} objects from immediately beneath the parent.
4752
4753 We read the following individual fields::
4754
4755 action action
4756 command command
4757
4758 @param parentNode: Parent node to search beneath.
4759
4760 @return: List of C{ActionHook} objects or C{None} if none are found.
4761 @raise ValueError: If some filled-in value is invalid.
4762 """
4763 lst = []
4764 for entry in readChildren(parentNode, "pre_action_hook"):
4765 if isElement(entry):
4766 hook = PreActionHook()
4767 hook.action = readString(entry, "action")
4768 hook.command = readString(entry, "command")
4769 lst.append(hook)
4770 for entry in readChildren(parentNode, "post_action_hook"):
4771 if isElement(entry):
4772 hook = PostActionHook()
4773 hook.action = readString(entry, "action")
4774 hook.command = readString(entry, "command")
4775 lst.append(hook)
4776 if lst == []:
4777 lst = None
4778 return lst
4779
4780 @staticmethod
4782 """
4783 Reads a list of C{CollectFile} objects from immediately beneath the parent.
4784
4785 We read the following individual fields::
4786
4787 absolutePath abs_path
4788 collectMode mode I{or} collect_mode
4789 archiveMode archive_mode
4790
4791 The collect mode is a special case. Just a C{mode} tag is accepted, but
4792 we prefer C{collect_mode} for consistency with the rest of the config
4793 file and to avoid confusion with the archive mode. If both are provided,
4794 only C{mode} will be used.
4795
4796 @param parentNode: Parent node to search beneath.
4797
4798 @return: List of C{CollectFile} objects or C{None} if none are found.
4799 @raise ValueError: If some filled-in value is invalid.
4800 """
4801 lst = []
4802 for entry in readChildren(parentNode, "file"):
4803 if isElement(entry):
4804 cfile = CollectFile()
4805 cfile.absolutePath = readString(entry, "abs_path")
4806 cfile.collectMode = readString(entry, "mode")
4807 if cfile.collectMode is None:
4808 cfile.collectMode = readString(entry, "collect_mode")
4809 cfile.archiveMode = readString(entry, "archive_mode")
4810 lst.append(cfile)
4811 if lst == []:
4812 lst = None
4813 return lst
4814
4815 @staticmethod
4817 """
4818 Reads a list of C{CollectDir} objects from immediately beneath the parent.
4819
4820 We read the following individual fields::
4821
4822 absolutePath abs_path
4823 collectMode mode I{or} collect_mode
4824 archiveMode archive_mode
4825 ignoreFile ignore_file
4826 linkDepth link_depth
4827 dereference dereference
4828 recursionLevel recursion_level
4829
4830 The collect mode is a special case. Just a C{mode} tag is accepted for
4831 backwards compatibility, but we prefer C{collect_mode} for consistency
4832 with the rest of the config file and to avoid confusion with the archive
4833 mode. If both are provided, only C{mode} will be used.
4834
4835 We also read groups of the following items, one list element per
4836 item::
4837
4838 absoluteExcludePaths exclude/abs_path
4839 relativeExcludePaths exclude/rel_path
4840 excludePatterns exclude/pattern
4841
4842 The exclusions are parsed by L{_parseExclusions}.
4843
4844 @param parentNode: Parent node to search beneath.
4845
4846 @return: List of C{CollectDir} objects or C{None} if none are found.
4847 @raise ValueError: If some filled-in value is invalid.
4848 """
4849 lst = []
4850 for entry in readChildren(parentNode, "dir"):
4851 if isElement(entry):
4852 cdir = CollectDir()
4853 cdir.absolutePath = readString(entry, "abs_path")
4854 cdir.collectMode = readString(entry, "mode")
4855 if cdir.collectMode is None:
4856 cdir.collectMode = readString(entry, "collect_mode")
4857 cdir.archiveMode = readString(entry, "archive_mode")
4858 cdir.ignoreFile = readString(entry, "ignore_file")
4859 cdir.linkDepth = readInteger(entry, "link_depth")
4860 cdir.dereference = readBoolean(entry, "dereference")
4861 cdir.recursionLevel = readInteger(entry, "recursion_level")
4862 (cdir.absoluteExcludePaths, cdir.relativeExcludePaths, cdir.excludePatterns) = Config._parseExclusions(entry)
4863 lst.append(cdir)
4864 if lst == []:
4865 lst = None
4866 return lst
4867
4868 @staticmethod
4870 """
4871 Reads a list of C{PurgeDir} objects from immediately beneath the parent.
4872
4873 We read the following individual fields::
4874
4875 absolutePath <baseExpr>/abs_path
4876 retainDays <baseExpr>/retain_days
4877
4878 @param parentNode: Parent node to search beneath.
4879
4880 @return: List of C{PurgeDir} objects or C{None} if none are found.
4881 @raise ValueError: If the data at the location can't be read
4882 """
4883 lst = []
4884 for entry in readChildren(parentNode, "dir"):
4885 if isElement(entry):
4886 cdir = PurgeDir()
4887 cdir.absolutePath = readString(entry, "abs_path")
4888 cdir.retainDays = readInteger(entry, "retain_days")
4889 lst.append(cdir)
4890 if lst == []:
4891 lst = None
4892 return lst
4893
4894 @staticmethod
4896 """
4897 Reads remote and local peer data from immediately beneath the parent.
4898
4899 We read the following individual fields for both remote
4900 and local peers::
4901
4902 name name
4903 collectDir collect_dir
4904
4905 We also read the following individual fields for remote peers
4906 only::
4907
4908 remoteUser backup_user
4909 rcpCommand rcp_command
4910 rshCommand rsh_command
4911 cbackCommand cback_command
4912 managed managed
4913 managedActions managed_actions
4914
4915 Additionally, the value in the C{type} field is used to determine whether
4916 this entry is a remote peer. If the type is C{"remote"}, it's a remote
4917 peer, and if the type is C{"local"}, it's a remote peer.
4918
4919 If there are none of one type of peer (i.e. no local peers) then C{None}
4920 will be returned for that item in the tuple.
4921
4922 @param parentNode: Parent node to search beneath.
4923
4924 @return: Tuple of (local, remote) peer lists.
4925 @raise ValueError: If the data at the location can't be read
4926 """
4927 localPeers = []
4928 remotePeers = []
4929 for entry in readChildren(parentNode, "peer"):
4930 if isElement(entry):
4931 peerType = readString(entry, "type")
4932 if peerType == "local":
4933 localPeer = LocalPeer()
4934 localPeer.name = readString(entry, "name")
4935 localPeer.collectDir = readString(entry, "collect_dir")
4936 localPeer.ignoreFailureMode = readString(entry, "ignore_failures")
4937 localPeers.append(localPeer)
4938 elif peerType == "remote":
4939 remotePeer = RemotePeer()
4940 remotePeer.name = readString(entry, "name")
4941 remotePeer.collectDir = readString(entry, "collect_dir")
4942 remotePeer.remoteUser = readString(entry, "backup_user")
4943 remotePeer.rcpCommand = readString(entry, "rcp_command")
4944 remotePeer.rshCommand = readString(entry, "rsh_command")
4945 remotePeer.cbackCommand = readString(entry, "cback_command")
4946 remotePeer.ignoreFailureMode = readString(entry, "ignore_failures")
4947 remotePeer.managed = readBoolean(entry, "managed")
4948 managedActions = readString(entry, "managed_actions")
4949 remotePeer.managedActions = parseCommaSeparatedString(managedActions)
4950 remotePeers.append(remotePeer)
4951 if localPeers == []:
4952 localPeers = None
4953 if remotePeers == []:
4954 remotePeers = None
4955 return (localPeers, remotePeers)
4956
4957 @staticmethod
4959 """
4960 Reads extended action dependency information from a parent node.
4961
4962 We read the following individual fields::
4963
4964 runBefore depends/run_before
4965 runAfter depends/run_after
4966
4967 Each of these fields is a comma-separated list of action names.
4968
4969 The result is placed into an C{ActionDependencies} object.
4970
4971 If the dependencies parent node does not exist, C{None} will be returned.
4972 Otherwise, an C{ActionDependencies} object will always be created, even
4973 if it does not contain any actual dependencies in it.
4974
4975 @param parentNode: Parent node to search beneath.
4976
4977 @return: C{ActionDependencies} object or C{None}.
4978 @raise ValueError: If the data at the location can't be read
4979 """
4980 sectionNode = readFirstChild(parentNode, "depends")
4981 if sectionNode is None:
4982 return None
4983 else:
4984 runBefore = readString(sectionNode, "run_before")
4985 runAfter = readString(sectionNode, "run_after")
4986 beforeList = parseCommaSeparatedString(runBefore)
4987 afterList = parseCommaSeparatedString(runAfter)
4988 return ActionDependencies(beforeList, afterList)
4989
4990 @staticmethod
4992 """
4993 Reads a single C{BlankBehavior} object from immediately beneath the parent.
4994
4995 We read the following individual fields::
4996
4997 blankMode blank_behavior/mode
4998 blankFactor blank_behavior/factor
4999
5000 @param parentNode: Parent node to search beneath.
5001
5002 @return: C{BlankBehavior} object or C{None} if none if the section is not found
5003 @raise ValueError: If some filled-in value is invalid.
5004 """
5005 blankBehavior = None
5006 sectionNode = readFirstChild(parentNode, "blank_behavior")
5007 if sectionNode is not None:
5008 blankBehavior = BlankBehavior()
5009 blankBehavior.blankMode = readString(sectionNode, "mode")
5010 blankBehavior.blankFactor = readString(sectionNode, "factor")
5011 return blankBehavior
5012
5013
5014
5015
5016
5017
5019 """
5020 Internal method to extract configuration into an XML string.
5021
5022 This method assumes that the internal L{validate} method has been called
5023 prior to extracting the XML, if the caller cares. No validation will be
5024 done internally.
5025
5026 As a general rule, fields that are set to C{None} will be extracted into
5027 the document as empty tags. The same goes for container tags that are
5028 filled based on lists - if the list is empty or C{None}, the container
5029 tag will be empty.
5030 """
5031 (xmlDom, parentNode) = createOutputDom()
5032 Config._addReference(xmlDom, parentNode, self.reference)
5033 Config._addExtensions(xmlDom, parentNode, self.extensions)
5034 Config._addOptions(xmlDom, parentNode, self.options)
5035 Config._addPeers(xmlDom, parentNode, self.peers)
5036 Config._addCollect(xmlDom, parentNode, self.collect)
5037 Config._addStage(xmlDom, parentNode, self.stage)
5038 Config._addStore(xmlDom, parentNode, self.store)
5039 Config._addPurge(xmlDom, parentNode, self.purge)
5040 xmlData = serializeDom(xmlDom)
5041 xmlDom.unlink()
5042 return xmlData
5043
5044 @staticmethod
5046 """
5047 Adds a <reference> configuration section as the next child of a parent.
5048
5049 We add the following fields to the document::
5050
5051 author //cb_config/reference/author
5052 revision //cb_config/reference/revision
5053 description //cb_config/reference/description
5054 generator //cb_config/reference/generator
5055
5056 If C{referenceConfig} is C{None}, then no container will be added.
5057
5058 @param xmlDom: DOM tree as from L{createOutputDom}.
5059 @param parentNode: Parent that the section should be appended to.
5060 @param referenceConfig: Reference configuration section to be added to the document.
5061 """
5062 if referenceConfig is not None:
5063 sectionNode = addContainerNode(xmlDom, parentNode, "reference")
5064 addStringNode(xmlDom, sectionNode, "author", referenceConfig.author)
5065 addStringNode(xmlDom, sectionNode, "revision", referenceConfig.revision)
5066 addStringNode(xmlDom, sectionNode, "description", referenceConfig.description)
5067 addStringNode(xmlDom, sectionNode, "generator", referenceConfig.generator)
5068
5069 @staticmethod
5071 """
5072 Adds an <extensions> configuration section as the next child of a parent.
5073
5074 We add the following fields to the document::
5075
5076 order_mode //cb_config/extensions/order_mode
5077
5078 We also add groups of the following items, one list element per item::
5079
5080 actions //cb_config/extensions/action
5081
5082 The extended action entries are added by L{_addExtendedAction}.
5083
5084 If C{extensionsConfig} is C{None}, then no container will be added.
5085
5086 @param xmlDom: DOM tree as from L{createOutputDom}.
5087 @param parentNode: Parent that the section should be appended to.
5088 @param extensionsConfig: Extensions configuration section to be added to the document.
5089 """
5090 if extensionsConfig is not None:
5091 sectionNode = addContainerNode(xmlDom, parentNode, "extensions")
5092 addStringNode(xmlDom, sectionNode, "order_mode", extensionsConfig.orderMode)
5093 if extensionsConfig.actions is not None:
5094 for action in extensionsConfig.actions:
5095 Config._addExtendedAction(xmlDom, sectionNode, action)
5096
5097 @staticmethod
5099 """
5100 Adds a <options> configuration section as the next child of a parent.
5101
5102 We add the following fields to the document::
5103
5104 startingDay //cb_config/options/starting_day
5105 workingDir //cb_config/options/working_dir
5106 backupUser //cb_config/options/backup_user
5107 backupGroup //cb_config/options/backup_group
5108 rcpCommand //cb_config/options/rcp_command
5109 rshCommand //cb_config/options/rsh_command
5110 cbackCommand //cb_config/options/cback_command
5111 managedActions //cb_config/options/managed_actions
5112
5113 We also add groups of the following items, one list element per
5114 item::
5115
5116 overrides //cb_config/options/override
5117 hooks //cb_config/options/pre_action_hook
5118 hooks //cb_config/options/post_action_hook
5119
5120 The individual override items are added by L{_addOverride}. The
5121 individual hook items are added by L{_addHook}.
5122
5123 If C{optionsConfig} is C{None}, then no container will be added.
5124
5125 @param xmlDom: DOM tree as from L{createOutputDom}.
5126 @param parentNode: Parent that the section should be appended to.
5127 @param optionsConfig: Options configuration section to be added to the document.
5128 """
5129 if optionsConfig is not None:
5130 sectionNode = addContainerNode(xmlDom, parentNode, "options")
5131 addStringNode(xmlDom, sectionNode, "starting_day", optionsConfig.startingDay)
5132 addStringNode(xmlDom, sectionNode, "working_dir", optionsConfig.workingDir)
5133 addStringNode(xmlDom, sectionNode, "backup_user", optionsConfig.backupUser)
5134 addStringNode(xmlDom, sectionNode, "backup_group", optionsConfig.backupGroup)
5135 addStringNode(xmlDom, sectionNode, "rcp_command", optionsConfig.rcpCommand)
5136 addStringNode(xmlDom, sectionNode, "rsh_command", optionsConfig.rshCommand)
5137 addStringNode(xmlDom, sectionNode, "cback_command", optionsConfig.cbackCommand)
5138 managedActions = Config._buildCommaSeparatedString(optionsConfig.managedActions)
5139 addStringNode(xmlDom, sectionNode, "managed_actions", managedActions)
5140 if optionsConfig.overrides is not None:
5141 for override in optionsConfig.overrides:
5142 Config._addOverride(xmlDom, sectionNode, override)
5143 if optionsConfig.hooks is not None:
5144 for hook in optionsConfig.hooks:
5145 Config._addHook(xmlDom, sectionNode, hook)
5146
5147 @staticmethod
5148 - def _addPeers(xmlDom, parentNode, peersConfig):
5149 """
5150 Adds a <peers> configuration section as the next child of a parent.
5151
5152 We add groups of the following items, one list element per
5153 item::
5154
5155 localPeers //cb_config/peers/peer
5156 remotePeers //cb_config/peers/peer
5157
5158 The individual local and remote peer entries are added by
5159 L{_addLocalPeer} and L{_addRemotePeer}, respectively.
5160
5161 If C{peersConfig} is C{None}, then no container will be added.
5162
5163 @param xmlDom: DOM tree as from L{createOutputDom}.
5164 @param parentNode: Parent that the section should be appended to.
5165 @param peersConfig: Peers configuration section to be added to the document.
5166 """
5167 if peersConfig is not None:
5168 sectionNode = addContainerNode(xmlDom, parentNode, "peers")
5169 if peersConfig.localPeers is not None:
5170 for localPeer in peersConfig.localPeers:
5171 Config._addLocalPeer(xmlDom, sectionNode, localPeer)
5172 if peersConfig.remotePeers is not None:
5173 for remotePeer in peersConfig.remotePeers:
5174 Config._addRemotePeer(xmlDom, sectionNode, remotePeer)
5175
5176 @staticmethod
5178 """
5179 Adds a <collect> configuration section as the next child of a parent.
5180
5181 We add the following fields to the document::
5182
5183 targetDir //cb_config/collect/collect_dir
5184 collectMode //cb_config/collect/collect_mode
5185 archiveMode //cb_config/collect/archive_mode
5186 ignoreFile //cb_config/collect/ignore_file
5187
5188 We also add groups of the following items, one list element per
5189 item::
5190
5191 absoluteExcludePaths //cb_config/collect/exclude/abs_path
5192 excludePatterns //cb_config/collect/exclude/pattern
5193 collectFiles //cb_config/collect/file
5194 collectDirs //cb_config/collect/dir
5195
5196 The individual collect files are added by L{_addCollectFile} and
5197 individual collect directories are added by L{_addCollectDir}.
5198
5199 If C{collectConfig} is C{None}, then no container will be added.
5200
5201 @param xmlDom: DOM tree as from L{createOutputDom}.
5202 @param parentNode: Parent that the section should be appended to.
5203 @param collectConfig: Collect configuration section to be added to the document.
5204 """
5205 if collectConfig is not None:
5206 sectionNode = addContainerNode(xmlDom, parentNode, "collect")
5207 addStringNode(xmlDom, sectionNode, "collect_dir", collectConfig.targetDir)
5208 addStringNode(xmlDom, sectionNode, "collect_mode", collectConfig.collectMode)
5209 addStringNode(xmlDom, sectionNode, "archive_mode", collectConfig.archiveMode)
5210 addStringNode(xmlDom, sectionNode, "ignore_file", collectConfig.ignoreFile)
5211 if ((collectConfig.absoluteExcludePaths is not None and collectConfig.absoluteExcludePaths != []) or
5212 (collectConfig.excludePatterns is not None and collectConfig.excludePatterns != [])):
5213 excludeNode = addContainerNode(xmlDom, sectionNode, "exclude")
5214 if collectConfig.absoluteExcludePaths is not None:
5215 for absolutePath in collectConfig.absoluteExcludePaths:
5216 addStringNode(xmlDom, excludeNode, "abs_path", absolutePath)
5217 if collectConfig.excludePatterns is not None:
5218 for pattern in collectConfig.excludePatterns:
5219 addStringNode(xmlDom, excludeNode, "pattern", pattern)
5220 if collectConfig.collectFiles is not None:
5221 for collectFile in collectConfig.collectFiles:
5222 Config._addCollectFile(xmlDom, sectionNode, collectFile)
5223 if collectConfig.collectDirs is not None:
5224 for collectDir in collectConfig.collectDirs:
5225 Config._addCollectDir(xmlDom, sectionNode, collectDir)
5226
5227 @staticmethod
5228 - def _addStage(xmlDom, parentNode, stageConfig):
5229 """
5230 Adds a <stage> configuration section as the next child of a parent.
5231
5232 We add the following fields to the document::
5233
5234 targetDir //cb_config/stage/staging_dir
5235
5236 We also add groups of the following items, one list element per
5237 item::
5238
5239 localPeers //cb_config/stage/peer
5240 remotePeers //cb_config/stage/peer
5241
5242 The individual local and remote peer entries are added by
5243 L{_addLocalPeer} and L{_addRemotePeer}, respectively.
5244
5245 If C{stageConfig} is C{None}, then no container will be added.
5246
5247 @param xmlDom: DOM tree as from L{createOutputDom}.
5248 @param parentNode: Parent that the section should be appended to.
5249 @param stageConfig: Stage configuration section to be added to the document.
5250 """
5251 if stageConfig is not None:
5252 sectionNode = addContainerNode(xmlDom, parentNode, "stage")
5253 addStringNode(xmlDom, sectionNode, "staging_dir", stageConfig.targetDir)
5254 if stageConfig.localPeers is not None:
5255 for localPeer in stageConfig.localPeers:
5256 Config._addLocalPeer(xmlDom, sectionNode, localPeer)
5257 if stageConfig.remotePeers is not None:
5258 for remotePeer in stageConfig.remotePeers:
5259 Config._addRemotePeer(xmlDom, sectionNode, remotePeer)
5260
5261 @staticmethod
5262 - def _addStore(xmlDom, parentNode, storeConfig):
5263 """
5264 Adds a <store> configuration section as the next child of a parent.
5265
5266 We add the following fields to the document::
5267
5268 sourceDir //cb_config/store/source_dir
5269 mediaType //cb_config/store/media_type
5270 deviceType //cb_config/store/device_type
5271 devicePath //cb_config/store/target_device
5272 deviceScsiId //cb_config/store/target_scsi_id
5273 driveSpeed //cb_config/store/drive_speed
5274 checkData //cb_config/store/check_data
5275 checkMedia //cb_config/store/check_media
5276 warnMidnite //cb_config/store/warn_midnite
5277 noEject //cb_config/store/no_eject
5278 refreshMediaDelay //cb_config/store/refresh_media_delay
5279 ejectDelay //cb_config/store/eject_delay
5280
5281 Blanking behavior configuration is added by the L{_addBlankBehavior}
5282 method.
5283
5284 If C{storeConfig} is C{None}, then no container will be added.
5285
5286 @param xmlDom: DOM tree as from L{createOutputDom}.
5287 @param parentNode: Parent that the section should be appended to.
5288 @param storeConfig: Store configuration section to be added to the document.
5289 """
5290 if storeConfig is not None:
5291 sectionNode = addContainerNode(xmlDom, parentNode, "store")
5292 addStringNode(xmlDom, sectionNode, "source_dir", storeConfig.sourceDir)
5293 addStringNode(xmlDom, sectionNode, "media_type", storeConfig.mediaType)
5294 addStringNode(xmlDom, sectionNode, "device_type", storeConfig.deviceType)
5295 addStringNode(xmlDom, sectionNode, "target_device", storeConfig.devicePath)
5296 addStringNode(xmlDom, sectionNode, "target_scsi_id", storeConfig.deviceScsiId)
5297 addIntegerNode(xmlDom, sectionNode, "drive_speed", storeConfig.driveSpeed)
5298 addBooleanNode(xmlDom, sectionNode, "check_data", storeConfig.checkData)
5299 addBooleanNode(xmlDom, sectionNode, "check_media", storeConfig.checkMedia)
5300 addBooleanNode(xmlDom, sectionNode, "warn_midnite", storeConfig.warnMidnite)
5301 addBooleanNode(xmlDom, sectionNode, "no_eject", storeConfig.noEject)
5302 addIntegerNode(xmlDom, sectionNode, "refresh_media_delay", storeConfig.refreshMediaDelay)
5303 addIntegerNode(xmlDom, sectionNode, "eject_delay", storeConfig.ejectDelay)
5304 Config._addBlankBehavior(xmlDom, sectionNode, storeConfig.blankBehavior)
5305
5306 @staticmethod
5307 - def _addPurge(xmlDom, parentNode, purgeConfig):
5308 """
5309 Adds a <purge> configuration section as the next child of a parent.
5310
5311 We add the following fields to the document::
5312
5313 purgeDirs //cb_config/purge/dir
5314
5315 The individual directory entries are added by L{_addPurgeDir}.
5316
5317 If C{purgeConfig} is C{None}, then no container will be added.
5318
5319 @param xmlDom: DOM tree as from L{createOutputDom}.
5320 @param parentNode: Parent that the section should be appended to.
5321 @param purgeConfig: Purge configuration section to be added to the document.
5322 """
5323 if purgeConfig is not None:
5324 sectionNode = addContainerNode(xmlDom, parentNode, "purge")
5325 if purgeConfig.purgeDirs is not None:
5326 for purgeDir in purgeConfig.purgeDirs:
5327 Config._addPurgeDir(xmlDom, sectionNode, purgeDir)
5328
5329 @staticmethod
5331 """
5332 Adds an extended action container as the next child of a parent.
5333
5334 We add the following fields to the document::
5335
5336 name action/name
5337 module action/module
5338 function action/function
5339 index action/index
5340 dependencies action/depends
5341
5342 Dependencies are added by the L{_addDependencies} method.
5343
5344 The <action> node itself is created as the next child of the parent node.
5345 This method only adds one action node. The parent must loop for each action
5346 in the C{ExtensionsConfig} object.
5347
5348 If C{action} is C{None}, this method call will be a no-op.
5349
5350 @param xmlDom: DOM tree as from L{createOutputDom}.
5351 @param parentNode: Parent that the section should be appended to.
5352 @param action: Purge directory to be added to the document.
5353 """
5354 if action is not None:
5355 sectionNode = addContainerNode(xmlDom, parentNode, "action")
5356 addStringNode(xmlDom, sectionNode, "name", action.name)
5357 addStringNode(xmlDom, sectionNode, "module", action.module)
5358 addStringNode(xmlDom, sectionNode, "function", action.function)
5359 addIntegerNode(xmlDom, sectionNode, "index", action.index)
5360 Config._addDependencies(xmlDom, sectionNode, action.dependencies)
5361
5362 @staticmethod
5364 """
5365 Adds a command override container as the next child of a parent.
5366
5367 We add the following fields to the document::
5368
5369 command override/command
5370 absolutePath override/abs_path
5371
5372 The <override> node itself is created as the next child of the parent
5373 node. This method only adds one override node. The parent must loop for
5374 each override in the C{OptionsConfig} object.
5375
5376 If C{override} is C{None}, this method call will be a no-op.
5377
5378 @param xmlDom: DOM tree as from L{createOutputDom}.
5379 @param parentNode: Parent that the section should be appended to.
5380 @param override: Command override to be added to the document.
5381 """
5382 if override is not None:
5383 sectionNode = addContainerNode(xmlDom, parentNode, "override")
5384 addStringNode(xmlDom, sectionNode, "command", override.command)
5385 addStringNode(xmlDom, sectionNode, "abs_path", override.absolutePath)
5386
5387 @staticmethod
5388 - def _addHook(xmlDom, parentNode, hook):
5389 """
5390 Adds an action hook container as the next child of a parent.
5391
5392 The behavior varies depending on the value of the C{before} and C{after}
5393 flags on the hook. If the C{before} flag is set, it's a pre-action hook,
5394 and we'll add the following fields::
5395
5396 action pre_action_hook/action
5397 command pre_action_hook/command
5398
5399 If the C{after} flag is set, it's a post-action hook, and we'll add the
5400 following fields::
5401
5402 action post_action_hook/action
5403 command post_action_hook/command
5404
5405 The <pre_action_hook> or <post_action_hook> node itself is created as the
5406 next child of the parent node. This method only adds one hook node. The
5407 parent must loop for each hook in the C{OptionsConfig} object.
5408
5409 If C{hook} is C{None}, this method call will be a no-op.
5410
5411 @param xmlDom: DOM tree as from L{createOutputDom}.
5412 @param parentNode: Parent that the section should be appended to.
5413 @param hook: Command hook to be added to the document.
5414 """
5415 if hook is not None:
5416 if hook.before:
5417 sectionNode = addContainerNode(xmlDom, parentNode, "pre_action_hook")
5418 else:
5419 sectionNode = addContainerNode(xmlDom, parentNode, "post_action_hook")
5420 addStringNode(xmlDom, sectionNode, "action", hook.action)
5421 addStringNode(xmlDom, sectionNode, "command", hook.command)
5422
5423 @staticmethod
5425 """
5426 Adds a collect file container as the next child of a parent.
5427
5428 We add the following fields to the document::
5429
5430 absolutePath dir/abs_path
5431 collectMode dir/collect_mode
5432 archiveMode dir/archive_mode
5433
5434 Note that for consistency with collect directory handling we'll only emit
5435 the preferred C{collect_mode} tag.
5436
5437 The <file> node itself is created as the next child of the parent node.
5438 This method only adds one collect file node. The parent must loop
5439 for each collect file in the C{CollectConfig} object.
5440
5441 If C{collectFile} is C{None}, this method call will be a no-op.
5442
5443 @param xmlDom: DOM tree as from L{createOutputDom}.
5444 @param parentNode: Parent that the section should be appended to.
5445 @param collectFile: Collect file to be added to the document.
5446 """
5447 if collectFile is not None:
5448 sectionNode = addContainerNode(xmlDom, parentNode, "file")
5449 addStringNode(xmlDom, sectionNode, "abs_path", collectFile.absolutePath)
5450 addStringNode(xmlDom, sectionNode, "collect_mode", collectFile.collectMode)
5451 addStringNode(xmlDom, sectionNode, "archive_mode", collectFile.archiveMode)
5452
5453 @staticmethod
5455 """
5456 Adds a collect directory container as the next child of a parent.
5457
5458 We add the following fields to the document::
5459
5460 absolutePath dir/abs_path
5461 collectMode dir/collect_mode
5462 archiveMode dir/archive_mode
5463 ignoreFile dir/ignore_file
5464 linkDepth dir/link_depth
5465 dereference dir/dereference
5466 recursionLevel dir/recursion_level
5467
5468 Note that an original XML document might have listed the collect mode
5469 using the C{mode} tag, since we accept both C{collect_mode} and C{mode}.
5470 However, here we'll only emit the preferred C{collect_mode} tag.
5471
5472 We also add groups of the following items, one list element per item::
5473
5474 absoluteExcludePaths dir/exclude/abs_path
5475 relativeExcludePaths dir/exclude/rel_path
5476 excludePatterns dir/exclude/pattern
5477
5478 The <dir> node itself is created as the next child of the parent node.
5479 This method only adds one collect directory node. The parent must loop
5480 for each collect directory in the C{CollectConfig} object.
5481
5482 If C{collectDir} is C{None}, this method call will be a no-op.
5483
5484 @param xmlDom: DOM tree as from L{createOutputDom}.
5485 @param parentNode: Parent that the section should be appended to.
5486 @param collectDir: Collect directory to be added to the document.
5487 """
5488 if collectDir is not None:
5489 sectionNode = addContainerNode(xmlDom, parentNode, "dir")
5490 addStringNode(xmlDom, sectionNode, "abs_path", collectDir.absolutePath)
5491 addStringNode(xmlDom, sectionNode, "collect_mode", collectDir.collectMode)
5492 addStringNode(xmlDom, sectionNode, "archive_mode", collectDir.archiveMode)
5493 addStringNode(xmlDom, sectionNode, "ignore_file", collectDir.ignoreFile)
5494 addIntegerNode(xmlDom, sectionNode, "link_depth", collectDir.linkDepth)
5495 addBooleanNode(xmlDom, sectionNode, "dereference", collectDir.dereference)
5496 addIntegerNode(xmlDom, sectionNode, "recursion_level", collectDir.recursionLevel)
5497 if ((collectDir.absoluteExcludePaths is not None and collectDir.absoluteExcludePaths != []) or
5498 (collectDir.relativeExcludePaths is not None and collectDir.relativeExcludePaths != []) or
5499 (collectDir.excludePatterns is not None and collectDir.excludePatterns != [])):
5500 excludeNode = addContainerNode(xmlDom, sectionNode, "exclude")
5501 if collectDir.absoluteExcludePaths is not None:
5502 for absolutePath in collectDir.absoluteExcludePaths:
5503 addStringNode(xmlDom, excludeNode, "abs_path", absolutePath)
5504 if collectDir.relativeExcludePaths is not None:
5505 for relativePath in collectDir.relativeExcludePaths:
5506 addStringNode(xmlDom, excludeNode, "rel_path", relativePath)
5507 if collectDir.excludePatterns is not None:
5508 for pattern in collectDir.excludePatterns:
5509 addStringNode(xmlDom, excludeNode, "pattern", pattern)
5510
5511 @staticmethod
5513 """
5514 Adds a local peer container as the next child of a parent.
5515
5516 We add the following fields to the document::
5517
5518 name peer/name
5519 collectDir peer/collect_dir
5520 ignoreFailureMode peer/ignore_failures
5521
5522 Additionally, C{peer/type} is filled in with C{"local"}, since this is a
5523 local peer.
5524
5525 The <peer> node itself is created as the next child of the parent node.
5526 This method only adds one peer node. The parent must loop for each peer
5527 in the C{StageConfig} object.
5528
5529 If C{localPeer} is C{None}, this method call will be a no-op.
5530
5531 @param xmlDom: DOM tree as from L{createOutputDom}.
5532 @param parentNode: Parent that the section should be appended to.
5533 @param localPeer: Purge directory to be added to the document.
5534 """
5535 if localPeer is not None:
5536 sectionNode = addContainerNode(xmlDom, parentNode, "peer")
5537 addStringNode(xmlDom, sectionNode, "name", localPeer.name)
5538 addStringNode(xmlDom, sectionNode, "type", "local")
5539 addStringNode(xmlDom, sectionNode, "collect_dir", localPeer.collectDir)
5540 addStringNode(xmlDom, sectionNode, "ignore_failures", localPeer.ignoreFailureMode)
5541
5542 @staticmethod
5544 """
5545 Adds a remote peer container as the next child of a parent.
5546
5547 We add the following fields to the document::
5548
5549 name peer/name
5550 collectDir peer/collect_dir
5551 remoteUser peer/backup_user
5552 rcpCommand peer/rcp_command
5553 rcpCommand peer/rcp_command
5554 rshCommand peer/rsh_command
5555 cbackCommand peer/cback_command
5556 ignoreFailureMode peer/ignore_failures
5557 managed peer/managed
5558 managedActions peer/managed_actions
5559
5560 Additionally, C{peer/type} is filled in with C{"remote"}, since this is a
5561 remote peer.
5562
5563 The <peer> node itself is created as the next child of the parent node.
5564 This method only adds one peer node. The parent must loop for each peer
5565 in the C{StageConfig} object.
5566
5567 If C{remotePeer} is C{None}, this method call will be a no-op.
5568
5569 @param xmlDom: DOM tree as from L{createOutputDom}.
5570 @param parentNode: Parent that the section should be appended to.
5571 @param remotePeer: Purge directory to be added to the document.
5572 """
5573 if remotePeer is not None:
5574 sectionNode = addContainerNode(xmlDom, parentNode, "peer")
5575 addStringNode(xmlDom, sectionNode, "name", remotePeer.name)
5576 addStringNode(xmlDom, sectionNode, "type", "remote")
5577 addStringNode(xmlDom, sectionNode, "collect_dir", remotePeer.collectDir)
5578 addStringNode(xmlDom, sectionNode, "backup_user", remotePeer.remoteUser)
5579 addStringNode(xmlDom, sectionNode, "rcp_command", remotePeer.rcpCommand)
5580 addStringNode(xmlDom, sectionNode, "rsh_command", remotePeer.rshCommand)
5581 addStringNode(xmlDom, sectionNode, "cback_command", remotePeer.cbackCommand)
5582 addStringNode(xmlDom, sectionNode, "ignore_failures", remotePeer.ignoreFailureMode)
5583 addBooleanNode(xmlDom, sectionNode, "managed", remotePeer.managed)
5584 managedActions = Config._buildCommaSeparatedString(remotePeer.managedActions)
5585 addStringNode(xmlDom, sectionNode, "managed_actions", managedActions)
5586
5587 @staticmethod
5589 """
5590 Adds a purge directory container as the next child of a parent.
5591
5592 We add the following fields to the document::
5593
5594 absolutePath dir/abs_path
5595 retainDays dir/retain_days
5596
5597 The <dir> node itself is created as the next child of the parent node.
5598 This method only adds one purge directory node. The parent must loop for
5599 each purge directory in the C{PurgeConfig} object.
5600
5601 If C{purgeDir} is C{None}, this method call will be a no-op.
5602
5603 @param xmlDom: DOM tree as from L{createOutputDom}.
5604 @param parentNode: Parent that the section should be appended to.
5605 @param purgeDir: Purge directory to be added to the document.
5606 """
5607 if purgeDir is not None:
5608 sectionNode = addContainerNode(xmlDom, parentNode, "dir")
5609 addStringNode(xmlDom, sectionNode, "abs_path", purgeDir.absolutePath)
5610 addIntegerNode(xmlDom, sectionNode, "retain_days", purgeDir.retainDays)
5611
5612 @staticmethod
5614 """
5615 Adds a extended action dependencies to parent node.
5616
5617 We add the following fields to the document::
5618
5619 runBefore depends/run_before
5620 runAfter depends/run_after
5621
5622 If C{dependencies} is C{None}, this method call will be a no-op.
5623
5624 @param xmlDom: DOM tree as from L{createOutputDom}.
5625 @param parentNode: Parent that the section should be appended to.
5626 @param dependencies: C{ActionDependencies} object to be added to the document
5627 """
5628 if dependencies is not None:
5629 sectionNode = addContainerNode(xmlDom, parentNode, "depends")
5630 runBefore = Config._buildCommaSeparatedString(dependencies.beforeList)
5631 runAfter = Config._buildCommaSeparatedString(dependencies.afterList)
5632 addStringNode(xmlDom, sectionNode, "run_before", runBefore)
5633 addStringNode(xmlDom, sectionNode, "run_after", runAfter)
5634
5635 @staticmethod
5637 """
5638 Creates a comma-separated string from a list of values.
5639
5640 As a special case, if C{valueList} is C{None}, then C{None} will be
5641 returned.
5642
5643 @param valueList: List of values to be placed into a string
5644
5645 @return: Values from valueList as a comma-separated string.
5646 """
5647 if valueList is None:
5648 return None
5649 return ",".join(valueList)
5650
5651 @staticmethod
5653 """
5654 Adds a blanking behavior container as the next child of a parent.
5655
5656 We add the following fields to the document::
5657
5658 blankMode blank_behavior/mode
5659 blankFactor blank_behavior/factor
5660
5661 The <blank_behavior> node itself is created as the next child of the
5662 parent node.
5663
5664 If C{blankBehavior} is C{None}, this method call will be a no-op.
5665
5666 @param xmlDom: DOM tree as from L{createOutputDom}.
5667 @param parentNode: Parent that the section should be appended to.
5668 @param blankBehavior: Blanking behavior to be added to the document.
5669 """
5670 if blankBehavior is not None:
5671 sectionNode = addContainerNode(xmlDom, parentNode, "blank_behavior")
5672 addStringNode(xmlDom, sectionNode, "mode", blankBehavior.blankMode)
5673 addStringNode(xmlDom, sectionNode, "factor", blankBehavior.blankFactor)
5674
5675
5676
5677
5678
5679
5681 """
5682 Validates configuration contents per rules discussed in module
5683 documentation.
5684
5685 This is the second pass at validation. It ensures that any filled-in
5686 section contains valid data. Any sections which is not set to C{None} is
5687 validated per the rules for that section, laid out in the module
5688 documentation (above).
5689
5690 @raise ValueError: If configuration is invalid.
5691 """
5692 self._validateReference()
5693 self._validateExtensions()
5694 self._validateOptions()
5695 self._validatePeers()
5696 self._validateCollect()
5697 self._validateStage()
5698 self._validateStore()
5699 self._validatePurge()
5700
5702 """
5703 Validates reference configuration.
5704 There are currently no reference-related validations.
5705 @raise ValueError: If reference configuration is invalid.
5706 """
5707 pass
5708
5710 """
5711 Validates extensions configuration.
5712
5713 The list of actions may be either C{None} or an empty list C{[]} if
5714 desired. Each extended action must include a name, a module, and a
5715 function.
5716
5717 Then, if the order mode is None or "index", an index is required; and if
5718 the order mode is "dependency", dependency information is required.
5719
5720 @raise ValueError: If reference configuration is invalid.
5721 """
5722 if self.extensions is not None:
5723 if self.extensions.actions is not None:
5724 names = []
5725 for action in self.extensions.actions:
5726 if action.name is None:
5727 raise ValueError("Each extended action must set a name.")
5728 names.append(action.name)
5729 if action.module is None:
5730 raise ValueError("Each extended action must set a module.")
5731 if action.function is None:
5732 raise ValueError("Each extended action must set a function.")
5733 if self.extensions.orderMode is None or self.extensions.orderMode == "index":
5734 if action.index is None:
5735 raise ValueError("Each extended action must set an index, based on order mode.")
5736 elif self.extensions.orderMode == "dependency":
5737 if action.dependencies is None:
5738 raise ValueError("Each extended action must set dependency information, based on order mode.")
5739 checkUnique("Duplicate extension names exist:", names)
5740
5742 """
5743 Validates options configuration.
5744
5745 All fields must be filled in except the rsh command. The rcp and rsh
5746 commands are used as default values for all remote peers. Remote peers
5747 can also rely on the backup user as the default remote user name if they
5748 choose.
5749
5750 @raise ValueError: If reference configuration is invalid.
5751 """
5752 if self.options is not None:
5753 if self.options.startingDay is None:
5754 raise ValueError("Options section starting day must be filled in.")
5755 if self.options.workingDir is None:
5756 raise ValueError("Options section working directory must be filled in.")
5757 if self.options.backupUser is None:
5758 raise ValueError("Options section backup user must be filled in.")
5759 if self.options.backupGroup is None:
5760 raise ValueError("Options section backup group must be filled in.")
5761 if self.options.rcpCommand is None:
5762 raise ValueError("Options section remote copy command must be filled in.")
5763
5771
5773 """
5774 Validates collect configuration.
5775
5776 The target directory must be filled in. The collect mode, archive mode,
5777 ignore file, and recursion level are all optional. The list of absolute
5778 paths to exclude and patterns to exclude may be either C{None} or an
5779 empty list C{[]} if desired.
5780
5781 Each collect directory entry must contain an absolute path to collect,
5782 and then must either be able to take collect mode, archive mode and
5783 ignore file configuration from the parent C{CollectConfig} object, or
5784 must set each value on its own. The list of absolute paths to exclude,
5785 relative paths to exclude and patterns to exclude may be either C{None}
5786 or an empty list C{[]} if desired. Any list of absolute paths to exclude
5787 or patterns to exclude will be combined with the same list in the
5788 C{CollectConfig} object to make the complete list for a given directory.
5789
5790 @raise ValueError: If collect configuration is invalid.
5791 """
5792 if self.collect is not None:
5793 if self.collect.targetDir is None:
5794 raise ValueError("Collect section target directory must be filled in.")
5795 if self.collect.collectFiles is not None:
5796 for collectFile in self.collect.collectFiles:
5797 if collectFile.absolutePath is None:
5798 raise ValueError("Each collect file must set an absolute path.")
5799 if self.collect.collectMode is None and collectFile.collectMode is None:
5800 raise ValueError("Collect mode must either be set in parent collect section or individual collect file.")
5801 if self.collect.archiveMode is None and collectFile.archiveMode is None:
5802 raise ValueError("Archive mode must either be set in parent collect section or individual collect file.")
5803 if self.collect.collectDirs is not None:
5804 for collectDir in self.collect.collectDirs:
5805 if collectDir.absolutePath is None:
5806 raise ValueError("Each collect directory must set an absolute path.")
5807 if self.collect.collectMode is None and collectDir.collectMode is None:
5808 raise ValueError("Collect mode must either be set in parent collect section or individual collect directory.")
5809 if self.collect.archiveMode is None and collectDir.archiveMode is None:
5810 raise ValueError("Archive mode must either be set in parent collect section or individual collect directory.")
5811 if self.collect.ignoreFile is None and collectDir.ignoreFile is None:
5812 raise ValueError("Ignore file must either be set in parent collect section or individual collect directory.")
5813 if (collectDir.linkDepth is None or collectDir.linkDepth < 1) and collectDir.dereference:
5814 raise ValueError("Dereference flag is only valid when a non-zero link depth is in use.")
5815
5817 """
5818 Validates stage configuration.
5819
5820 The target directory must be filled in, and the peers are
5821 also validated.
5822
5823 Peers are only required in this section if the peers configuration
5824 section is not filled in. However, if any peers are filled in
5825 here, they override the peers configuration and must meet the
5826 validation criteria in L{_validatePeerList}.
5827
5828 @raise ValueError: If stage configuration is invalid.
5829 """
5830 if self.stage is not None:
5831 if self.stage.targetDir is None:
5832 raise ValueError("Stage section target directory must be filled in.")
5833 if self.peers is None:
5834
5835 self._validatePeerList(self.stage.localPeers, self.stage.remotePeers)
5836 else:
5837
5838
5839 if self.stage.hasPeers():
5840 self._validatePeerList(self.stage.localPeers, self.stage.remotePeers)
5841
5843 """
5844 Validates store configuration.
5845
5846 The device type, drive speed, and blanking behavior are optional. All
5847 other values are required. Missing booleans will be set to defaults.
5848
5849 If blanking behavior is provided, then both a blanking mode and a
5850 blanking factor are required.
5851
5852 The image writer functionality in the C{writer} module is supposed to be
5853 able to handle a device speed of C{None}.
5854
5855 Any caller which needs a "real" (non-C{None}) value for the device type
5856 can use C{DEFAULT_DEVICE_TYPE}, which is guaranteed to be sensible.
5857
5858 This is also where we make sure that the media type -- which is already a
5859 valid type -- matches up properly with the device type.
5860
5861 @raise ValueError: If store configuration is invalid.
5862 """
5863 if self.store is not None:
5864 if self.store.sourceDir is None:
5865 raise ValueError("Store section source directory must be filled in.")
5866 if self.store.mediaType is None:
5867 raise ValueError("Store section media type must be filled in.")
5868 if self.store.devicePath is None:
5869 raise ValueError("Store section device path must be filled in.")
5870 if self.store.deviceType == None or self.store.deviceType == "cdwriter":
5871 if self.store.mediaType not in VALID_CD_MEDIA_TYPES:
5872 raise ValueError("Media type must match device type.")
5873 elif self.store.deviceType == "dvdwriter":
5874 if self.store.mediaType not in VALID_DVD_MEDIA_TYPES:
5875 raise ValueError("Media type must match device type.")
5876 if self.store.blankBehavior is not None:
5877 if self.store.blankBehavior.blankMode is None and self.store.blankBehavior.blankFactor is None:
5878 raise ValueError("If blanking behavior is provided, all values must be filled in.")
5879
5881 """
5882 Validates purge configuration.
5883
5884 The list of purge directories may be either C{None} or an empty list
5885 C{[]} if desired. All purge directories must contain a path and a retain
5886 days value.
5887
5888 @raise ValueError: If purge configuration is invalid.
5889 """
5890 if self.purge is not None:
5891 if self.purge.purgeDirs is not None:
5892 for purgeDir in self.purge.purgeDirs:
5893 if purgeDir.absolutePath is None:
5894 raise ValueError("Each purge directory must set an absolute path.")
5895 if purgeDir.retainDays is None:
5896 raise ValueError("Each purge directory must set a retain days value.")
5897
5899 """
5900 Validates the set of local and remote peers.
5901
5902 Local peers must be completely filled in, including both name and collect
5903 directory. Remote peers must also fill in the name and collect
5904 directory, but can leave the remote user and rcp command unset. In this
5905 case, the remote user is assumed to match the backup user from the
5906 options section and rcp command is taken directly from the options
5907 section.
5908
5909 @param localPeers: List of local peers
5910 @param remotePeers: List of remote peers
5911
5912 @raise ValueError: If stage configuration is invalid.
5913 """
5914 if localPeers is None and remotePeers is None:
5915 raise ValueError("Peer list must contain at least one backup peer.")
5916 if localPeers is None and remotePeers is not None:
5917 if len(remotePeers) < 1:
5918 raise ValueError("Peer list must contain at least one backup peer.")
5919 elif localPeers is not None and remotePeers is None:
5920 if len(localPeers) < 1:
5921 raise ValueError("Peer list must contain at least one backup peer.")
5922 elif localPeers is not None and remotePeers is not None:
5923 if len(localPeers) + len(remotePeers) < 1:
5924 raise ValueError("Peer list must contain at least one backup peer.")
5925 names = []
5926 if localPeers is not None:
5927 for localPeer in localPeers:
5928 if localPeer.name is None:
5929 raise ValueError("Local peers must set a name.")
5930 names.append(localPeer.name)
5931 if localPeer.collectDir is None:
5932 raise ValueError("Local peers must set a collect directory.")
5933 if remotePeers is not None:
5934 for remotePeer in remotePeers:
5935 if remotePeer.name is None:
5936 raise ValueError("Remote peers must set a name.")
5937 names.append(remotePeer.name)
5938 if remotePeer.collectDir is None:
5939 raise ValueError("Remote peers must set a collect directory.")
5940 if (self.options is None or self.options.backupUser is None) and remotePeer.remoteUser is None:
5941 raise ValueError("Remote user must either be set in options section or individual remote peer.")
5942 if (self.options is None or self.options.rcpCommand is None) and remotePeer.rcpCommand is None:
5943 raise ValueError("Remote copy command must either be set in options section or individual remote peer.")
5944 if remotePeer.managed:
5945 if (self.options is None or self.options.rshCommand is None) and remotePeer.rshCommand is None:
5946 raise ValueError("Remote shell command must either be set in options section or individual remote peer.")
5947 if (self.options is None or self.options.cbackCommand is None) and remotePeer.cbackCommand is None:
5948 raise ValueError("Remote cback command must either be set in options section or individual remote peer.")
5949 if ((self.options is None or self.options.managedActions is None or len(self.options.managedActions) < 1)
5950 and (remotePeer.managedActions is None or len(remotePeer.managedActions) < 1)):
5951 raise ValueError("Managed actions list must be set in options section or individual remote peer.")
5952 checkUnique("Duplicate peer names exist:", names)
5953
5960 """
5961 Read a byte size value from an XML document.
5962
5963 A byte size value is an interpreted string value. If the string value
5964 ends with "MB" or "GB", then the string before that is interpreted as
5965 megabytes or gigabytes. Otherwise, it is intepreted as bytes.
5966
5967 @param parent: Parent node to search beneath.
5968 @param name: Name of node to search for.
5969
5970 @return: ByteQuantity parsed from XML document
5971 """
5972 data = readString(parent, name)
5973 if data is None:
5974 return None
5975 data = data.strip()
5976 if data.endswith("KB"):
5977 quantity = data[0:data.rfind("KB")].strip()
5978 units = UNIT_KBYTES
5979 elif data.endswith("MB"):
5980 quantity = data[0:data.rfind("MB")].strip()
5981 units = UNIT_MBYTES
5982 elif data.endswith("GB"):
5983 quantity = data[0:data.rfind("GB")].strip()
5984 units = UNIT_GBYTES
5985 else:
5986 quantity = data.strip()
5987 units = UNIT_BYTES
5988 return ByteQuantity(quantity, units)
5989
5991 """
5992 Adds a text node as the next child of a parent, to contain a byte size.
5993
5994 If the C{byteQuantity} is None, then the node will be created, but will
5995 be empty (i.e. will contain no text node child).
5996
5997 The size in bytes will be normalized. If it is larger than 1.0 GB, it will
5998 be shown in GB ("1.0 GB"). If it is larger than 1.0 MB ("1.0 MB"), it will
5999 be shown in MB. Otherwise, it will be shown in bytes ("423413").
6000
6001 @param xmlDom: DOM tree as from C{impl.createDocument()}.
6002 @param parentNode: Parent node to create child for.
6003 @param nodeName: Name of the new container node.
6004 @param byteQuantity: ByteQuantity object to put into the XML document
6005
6006 @return: Reference to the newly-created node.
6007 """
6008 if byteQuantity is None:
6009 byteString = None
6010 elif byteQuantity.units == UNIT_KBYTES:
6011 byteString = "%s KB" % byteQuantity.quantity
6012 elif byteQuantity.units == UNIT_MBYTES:
6013 byteString = "%s MB" % byteQuantity.quantity
6014 elif byteQuantity.units == UNIT_GBYTES:
6015 byteString = "%s GB" % byteQuantity.quantity
6016 else:
6017 byteString = byteQuantity.quantity
6018 return addStringNode(xmlDom, parentNode, nodeName, byteString)
6019