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