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