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