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