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