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