Package CedarBackup2 :: Module config
[hide private]
[frames] | no frames]

Source Code for Module CedarBackup2.config

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