[cedar-backup-svn] SF.net SVN: cedar-backup: [805] cedar-backup2/trunk
Brought to you by:
pronovic
|
From: <pro...@us...> - 2007-12-15 20:52:15
|
Revision: 805
http://cedar-backup.svn.sourceforge.net/cedar-backup/?rev=805&view=rev
Author: pronovic
Date: 2007-12-15 12:52:14 -0800 (Sat, 15 Dec 2007)
Log Message:
-----------
First pass at implementing managed peers
Modified Paths:
--------------
cedar-backup2/trunk/CedarBackup2/actions/stage.py
cedar-backup2/trunk/CedarBackup2/config.py
cedar-backup2/trunk/Changelog
cedar-backup2/trunk/test/configtests.py
Added Paths:
-----------
cedar-backup2/trunk/test/data/cback.conf.21
cedar-backup2/trunk/test/data/cback.conf.22
cedar-backup2/trunk/test/data/cback.conf.23
Modified: cedar-backup2/trunk/CedarBackup2/actions/stage.py
===================================================================
--- cedar-backup2/trunk/CedarBackup2/actions/stage.py 2007-12-15 19:20:09 UTC (rev 804)
+++ cedar-backup2/trunk/CedarBackup2/actions/stage.py 2007-12-15 20:52:14 UTC (rev 805)
@@ -212,8 +212,15 @@
@return: List of L{LocalPeer} objects.
"""
localPeers = []
- if config.stage.localPeers is not None:
- for peer in config.stage.localPeers:
+ configPeers = None
+ if config.stage.hasPeers():
+ logger.debug("Using list of local peers from stage configuration.")
+ configPeers = config.stage.localPeers
+ elif config.peers is not None and config.peers.hasPeers():
+ logger.debug("Using list of local peers from peers configuration.")
+ configPeers = config.peers.localPeers
+ if configPeers is not None:
+ for peer in configPeers:
localPeer = LocalPeer(peer.name, peer.collectDir)
localPeers.append(localPeer)
logger.debug("Found local peer: [%s]" % localPeer.name)
@@ -231,8 +238,15 @@
@return: List of L{RemotePeer} objects.
"""
remotePeers = []
- if config.stage.remotePeers is not None:
- for peer in config.stage.remotePeers:
+ configPeers = None
+ if config.stage.hasPeers():
+ logger.debug("Using list of remote peers from stage configuration.")
+ configPeers = config.stage.remotePeers
+ elif config.peers is not None and config.peers.hasPeers():
+ logger.debug("Using list of remote peers from peers configuration.")
+ configPeers = config.peers.remotePeers
+ if configPeers is not None:
+ for peer in config.peers.remotePeers:
remoteUser = _getRemoteUser(config, peer)
rcpCommand = _getRcpCommand(config, peer)
remotePeer = RemotePeer(peer.name, peer.collectDir, config.options.workingDir,
Modified: cedar-backup2/trunk/CedarBackup2/config.py
===================================================================
--- cedar-backup2/trunk/CedarBackup2/config.py 2007-12-15 19:20:09 UTC (rev 804)
+++ cedar-backup2/trunk/CedarBackup2/config.py 2007-12-15 20:52:14 UTC (rev 805)
@@ -65,8 +65,8 @@
The configuration file format has changed between Cedar Backup 1.x and Cedar
Backup 2.x. Any Cedar Backup 1.x configuration file is also a valid Cedar
Backup 2.x configuration file. However, it doesn't work to go the other
- direction, as the 2.x configuration files may contain additional fields that
- are not accepted by older versions of the software.
+ direction, as the 2.x configuration files contains additional configuration
+ is not accepted by older versions of the software.
XML Configuration Structure
===========================
@@ -81,6 +81,7 @@
- I{reference}: specifies reference information about the file (author, revision, etc)
- I{extensions}: specifies mappings to Cedar Backup extensions (external code)
- I{options}: specifies global configuration options
+ - I{peers}: specifies the set of peers in a master's backup pool
- I{collect}: specifies configuration related to the collect action
- I{stage}: specifies configuration related to the stage action
- I{store}: specifies configuration related to the store action
@@ -162,6 +163,14 @@
for all remote peers in the staging section. Remote peers can also rely on
the backup user as the default remote user name if they choose.
+ I{Peers Validations}
+
+ Local peers must be completely filled in, including both name and collect
+ directory. Remote peers must also fill in the name and collect directory,
+ but can leave the remote user and rcp command unset. In this case, the
+ remote user is assumed to match the backup user from the options section and
+ rcp command is taken directly from the options section.
+
I{Collect Validations}
The target directory must be filled in. The collect mode, archive mode and
@@ -183,11 +192,9 @@
(remote or local) between the two lists of peers. A list with no entries
can be either C{None} or an empty list C{[]} if desired.
- Local peers must be completely filled in, including both name and collect
- directory. Remote peers must also fill in the name and collect directory,
- but can leave the remote user and rcp command unset. In this case, the
- remote user is assumed to match the backup user from the options section and
- rcp command is taken directly from the options section.
+ If a set of peers is provided, this configuration completely overrides
+ configuration in the peers configuration section, and the same validations
+ apply.
I{Store Validations}
@@ -207,7 +214,7 @@
@sort: ActionDependencies, ActionHook, PreActionHook, PostActionHook,
ExtendedAction, CommandOverride, CollectFile, CollectDir, PurgeDir, LocalPeer,
- RemotePeer, ReferenceConfig, ExtensionsConfig, OptionsConfig,
+ RemotePeer, ReferenceConfig, ExtensionsConfig, OptionsConfig, PeersConfig,
CollectConfig, StageConfig, StoreConfig, PurgeConfig, Config,
DEFAULT_DEVICE_TYPE, DEFAULT_MEDIA_TYPE,
VALID_DEVICE_TYPES, VALID_MEDIA_TYPES,
@@ -2372,6 +2379,141 @@
########################################################################
+# PeersConfig class definition
+########################################################################
+
+class PeersConfig(object):
+
+ """
+ Class representing Cedar Backup global peer configuration.
+
+ This section contains a list of local and remote peers in a master's backup
+ pool. The section is optional. If a master does not define this section,
+ then all peers are unmanaged, and the stage configuration section must
+ explicitly list any peer that is to be staged. If this section is
+ configured, then peers may be managed or unmanaged, and the stage section
+ peer configuration (if any) completely overrides this configuration.
+
+ As with all of the other classes that represent configuration sections, all
+ of these values are optional. It is up to some higher-level construct to
+ decide whether everything they need is filled in.
+
+ The following restrictions exist on data in this class:
+
+ - The list of local peers must contain only C{LocalPeer} objects
+ - The list of remote peers must contain only C{RemotePeer} objects
+
+ @note: Lists within this class are "unordered" for equality comparisons.
+
+ @sort: __init__, __repr__, __str__, __cmp__, localPeers, remotePeers
+ """
+
+ def __init__(self, localPeers=None, remotePeers=None):
+ """
+ Constructor for the C{PeersConfig} class.
+
+ @param localPeers: List of local peers.
+ @param remotePeers: List of remote peers.
+
+ @raise ValueError: If one of the values is invalid.
+ """
+ self._localPeers = None
+ self._remotePeers = None
+ self.localPeers = localPeers
+ self.remotePeers = remotePeers
+
+ def __repr__(self):
+ """
+ Official string representation for class instance.
+ """
+ return "PeersConfig(%s, %s)" % (self.localPeers, self.remotePeers)
+
+ def __str__(self):
+ """
+ Informal string representation for class instance.
+ """
+ return self.__repr__()
+
+ def __cmp__(self, other):
+ """
+ Definition of equals operator for this class.
+ Lists within this class are "unordered" for equality comparisons.
+ @param other: Other object to compare to.
+ @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
+ """
+ if other is None:
+ return 1
+ if self._localPeers != other._localPeers:
+ if self._localPeers < other._localPeers:
+ return -1
+ else:
+ return 1
+ if self._remotePeers != other._remotePeers:
+ if self._remotePeers < other._remotePeers:
+ return -1
+ else:
+ return 1
+ return 0
+
+ def hasPeers(self):
+ """
+ Indicates whether any peers are filled into this object.
+ @return: Boolean true if any local or remote peers are filled in, false otherwise.
+ """
+ return ((self.localPeers is not None and len(self.localPeers) > 0) or
+ (self.remotePeers is not None and len(self.remotePeers) > 0))
+
+ def _setLocalPeers(self, value):
+ """
+ Property target used to set the local peers list.
+ Either the value must be C{None} or each element must be a C{LocalPeer}.
+ @raise ValueError: If the value is not an absolute path.
+ """
+ if value is None:
+ self._localPeers = None
+ else:
+ try:
+ saved = self._localPeers
+ self._localPeers = ObjectTypeList(LocalPeer, "LocalPeer")
+ self._localPeers.extend(value)
+ except Exception, e:
+ self._localPeers = saved
+ raise e
+
+ def _getLocalPeers(self):
+ """
+ Property target used to get the local peers list.
+ """
+ return self._localPeers
+
+ def _setRemotePeers(self, value):
+ """
+ Property target used to set the remote peers list.
+ Either the value must be C{None} or each element must be a C{RemotePeer}.
+ @raise ValueError: If the value is not a C{RemotePeer}
+ """
+ if value is None:
+ self._remotePeers = None
+ else:
+ try:
+ saved = self._remotePeers
+ self._remotePeers = ObjectTypeList(RemotePeer, "RemotePeer")
+ self._remotePeers.extend(value)
+ except Exception, e:
+ self._remotePeers = saved
+ raise e
+
+ def _getRemotePeers(self):
+ """
+ Property target used to get the remote peers list.
+ """
+ return self._remotePeers
+
+ localPeers = property(_getLocalPeers, _setLocalPeers, None, "List of local peers.")
+ remotePeers = property(_getRemotePeers, _setRemotePeers, None, "List of remote peers.")
+
+
+########################################################################
# CollectConfig class definition
########################################################################
@@ -2763,6 +2905,14 @@
return 1
return 0
+ def hasPeers(self):
+ """
+ Indicates whether any peers are filled into this object.
+ @return: Boolean true if any local or remote peers are filled in, false otherwise.
+ """
+ return ((self.localPeers is not None and len(self.localPeers) > 0) or
+ (self.remotePeers is not None and len(self.remotePeers) > 0))
+
def _setTargetDir(self, value):
"""
Property target used to set the target directory.
@@ -3324,8 +3474,9 @@
@sort: __init__, __repr__, __str__, __cmp__, extractXml, validate,
reference, extensions, options, collect, stage, store, purge,
_getReference, _setReference, _getExtensions, _setExtensions,
- _getOptions, _setOptions, _getCollect, _setCollect, _getStage,
- _setStage, _getStore, _setStore, _getPurge, _setPurge
+ _getOptions, _setOptions, _getPeers, _setPeers, _getCollect,
+ _setCollect, _getStage, _setStage, _getStore, _setStore,
+ _getPurge, _setPurge
"""
##############
@@ -3370,6 +3521,7 @@
self._reference = None
self._extensions = None
self._options = None
+ self._peers = None
self._collect = None
self._stage = None
self._store = None
@@ -3377,6 +3529,7 @@
self.reference = None
self.extensions = None
self.options = None
+ self.peers = None
self.collect = None
self.stage = None
self.store = None
@@ -3402,8 +3555,9 @@
"""
Official string representation for class instance.
"""
- return "Config(%s, %s, %s, %s, %s, %s, %s)" % (self.reference, self.extensions, self.options,
- self.collect, self.stage, self.store, self.purge)
+ return "Config(%s, %s, %s, %s, %s, %s, %s, %s)" % (self.reference, self.extensions, self.options,
+ self.peers, self.collect, self.stage, self.store,
+ self.purge)
def __str__(self):
"""
@@ -3440,6 +3594,11 @@
return -1
else:
return 1
+ if self._peers != other._peers:
+ if self._peers < other._peers:
+ return -1
+ else:
+ return 1
if self._collect != other._collect:
if self._collect < other._collect:
return -1
@@ -3524,6 +3683,25 @@
"""
return self._options
+ def _setPeers(self, value):
+ """
+ Property target used to set the peers configuration value.
+ If not C{None}, the value must be an C{PeersConfig} object.
+ @raise ValueError: If the value is not a C{PeersConfig}
+ """
+ if value is None:
+ self._peers = None
+ else:
+ if not isinstance(value, PeersConfig):
+ raise ValueError("Value must be a C{PeersConfig} object.")
+ self._peers = value
+
+ def _getPeers(self):
+ """
+ Property target used to get the peers configuration value.
+ """
+ return self._peers
+
def _setCollect(self, value):
"""
Property target used to set the collect configuration value.
@@ -3603,6 +3781,7 @@
reference = property(_getReference, _setReference, None, "Reference configuration in terms of a C{ReferenceConfig} object.")
extensions = property(_getExtensions, _setExtensions, None, "Extensions configuration in terms of a C{ExtensionsConfig} object.")
options = property(_getOptions, _setOptions, None, "Options configuration in terms of a C{OptionsConfig} object.")
+ peers = property(_getPeers, _setPeers, None, "Peers configuration in terms of a C{PeersConfig} object.")
collect = property(_getCollect, _setCollect, None, "Collect configuration in terms of a C{CollectConfig} object.")
stage = property(_getStage, _setStage, None, "Stage configuration in terms of a C{StageConfig} object.")
store = property(_getStore, _setStore, None, "Store configuration in terms of a C{StoreConfig} object.")
@@ -3652,7 +3831,7 @@
return xmlData
def validate(self, requireOneAction=True, requireReference=False, requireExtensions=False, requireOptions=True,
- requireCollect=False, requireStage=False, requireStore=False, requirePurge=False):
+ requireCollect=False, requireStage=False, requireStore=False, requirePurge=False, requirePeers=False):
"""
Validates configuration represented by the object.
@@ -3666,6 +3845,7 @@
@param requireReference: Require the reference section.
@param requireExtensions: Require the extensions section.
@param requireOptions: Require the options section.
+ @param requirePeers: Require the peers section.
@param requireCollect: Require the collect section.
@param requireStage: Require the stage section.
@param requireStore: Require the store section.
@@ -3681,6 +3861,8 @@
raise ValueError("The extensions is section is required.")
if requireOptions and self.options is None:
raise ValueError("The options is section is required.")
+ if requirePeers and self.peers is None:
+ raise ValueError("The peers is section is required.")
if requireCollect and self.collect is None:
raise ValueError("The collect is section is required.")
if requireStage and self.stage is None:
@@ -3719,6 +3901,7 @@
self._reference = Config._parseReference(parentNode)
self._extensions = Config._parseExtensions(parentNode)
self._options = Config._parseOptions(parentNode)
+ self._peers = Config._parsePeers(parentNode)
self._collect = Config._parseCollect(parentNode)
self._stage = Config._parseStage(parentNode)
self._store = Config._parseStore(parentNode)
@@ -3821,6 +4004,31 @@
return options
_parseOptions = staticmethod(_parseOptions)
+ def _parsePeers(parentNode):
+ """
+ Parses a peers configuration section.
+
+ We read groups of the following items, one list element per
+ item::
+
+ localPeers //cb_config/stage/peer
+ remotePeers //cb_config/stage/peer
+
+ The individual peer entries are parsed by L{_parsePeerList}.
+
+ @param parentNode: Parent node to search beneath.
+
+ @return: C{StageConfig} object or C{None} if the section does not exist.
+ @raise ValueError: If some filled-in value is invalid.
+ """
+ peers = None
+ sectionNode = readFirstChild(parentNode, "peers")
+ if sectionNode is not None:
+ peers = PeersConfig()
+ (peers.localPeers, peers.remotePeers) = Config._parsePeerList(sectionNode)
+ return peers
+ _parsePeers = staticmethod(_parsePeers)
+
def _parseCollect(parentNode):
"""
Parses a collect configuration section.
@@ -3877,7 +4085,7 @@
localPeers //cb_config/stage/peer
remotePeers //cb_config/stage/peer
- The individual peer entries are parsed by L{_parsePeers}.
+ The individual peer entries are parsed by L{_parsePeerList}.
@param parentNode: Parent node to search beneath.
@@ -3889,7 +4097,7 @@
if sectionNode is not None:
stage = StageConfig()
stage.targetDir = readString(sectionNode, "staging_dir")
- (stage.localPeers, stage.remotePeers) = Config._parsePeers(sectionNode)
+ (stage.localPeers, stage.remotePeers) = Config._parsePeerList(sectionNode)
return stage
_parseStage = staticmethod(_parseStage)
@@ -4191,7 +4399,7 @@
return lst
_parsePurgeDirs = staticmethod(_parsePurgeDirs)
- def _parsePeers(parentNode):
+ def _parsePeerList(parentNode):
"""
Reads remote and local peer data from immediately beneath the parent.
@@ -4241,7 +4449,7 @@
if remotePeers == []:
remotePeers = None
return (localPeers, remotePeers)
- _parsePeers = staticmethod(_parsePeers)
+ _parsePeerList = staticmethod(_parsePeerList)
def _parseDependencies(parentNode):
"""
@@ -4344,6 +4552,7 @@
Config._addReference(xmlDom, parentNode, self.reference)
Config._addExtensions(xmlDom, parentNode, self.extensions)
Config._addOptions(xmlDom, parentNode, self.options)
+ Config._addPeers(xmlDom, parentNode, self.peers)
Config._addCollect(xmlDom, parentNode, self.collect)
Config._addStage(xmlDom, parentNode, self.stage)
Config._addStore(xmlDom, parentNode, self.store)
@@ -4448,6 +4657,35 @@
Config._addHook(xmlDom, sectionNode, hook)
_addOptions = staticmethod(_addOptions)
+ def _addPeers(xmlDom, parentNode, peersConfig):
+ """
+ Adds a <peers> configuration section as the next child of a parent.
+
+ We add groups of the following items, one list element per
+ item::
+
+ localPeers //cb_config/peers/peer
+ remotePeers //cb_config/peers/peer
+
+ The individual local and remote peer entries are added by
+ L{_addLocalPeer} and L{_addRemotePeer}, respectively.
+
+ If C{peersConfig} is C{None}, then no container will be added.
+
+ @param xmlDom: DOM tree as from L{createOutputDom}.
+ @param parentNode: Parent that the section should be appended to.
+ @param peersConfig: Peers configuration section to be added to the document.
+ """
+ if peersConfig is not None:
+ sectionNode = addContainerNode(xmlDom, parentNode, "peers")
+ if peersConfig.localPeers is not None:
+ for localPeer in peersConfig.localPeers:
+ Config._addLocalPeer(xmlDom, sectionNode, localPeer)
+ if peersConfig.remotePeers is not None:
+ for remotePeer in peersConfig.remotePeers:
+ Config._addRemotePeer(xmlDom, sectionNode, remotePeer)
+ _addPeers = staticmethod(_addPeers)
+
def _addCollect(xmlDom, parentNode, collectConfig):
"""
Adds a <collect> configuration section as the next child of a parent.
@@ -4943,6 +5181,7 @@
self._validateReference()
self._validateExtensions()
self._validateOptions()
+ self._validatePeers()
self._validateCollect()
self._validateStage()
self._validateStore()
@@ -5010,6 +5249,14 @@
if self.options.rcpCommand is None:
raise ValueError("Options section remote copy command must be filled in.")
+ def _validatePeers(self):
+ """
+ Validates peers configuration per rules in L{_validatePeerList}.
+ @raise ValueError: If peers configuration is invalid.
+ """
+ if self.peers is not None:
+ self._validatePeerList(self.peers.localPeers, self.peers.remotePeers)
+
def _validateCollect(self):
"""
Validates collect configuration.
@@ -5056,18 +5303,27 @@
"""
Validates stage configuration.
- The target directory must be filled in. There must be at least one peer
- (remote or local) between the two lists of peers. A list with no entries
- can be either C{None} or an empty list C{[]} if desired.
+ The target directory must be filled in, and the peers are
+ also validated.
- Then, peer list validation (see L{_validatePeerList}) applies as well.
+ Peers are only required in this section if the peers configuration
+ section is not filled in. However, if any peers are filled in
+ here, they override the peers configuration and must meet the
+ validation criteria in L{_validatePeerList}.
@raise ValueError: If stage configuration is invalid.
"""
if self.stage is not None:
if self.stage.targetDir is None:
raise ValueError("Stage section target directory must be filled in.")
- self._validatePeerList(self.stage.localPeers, self.stage.remotePeers)
+ if self.peers is None:
+ # In this case, stage configuration is our only configuration and must be valid.
+ self._validatePeerList(self.stage.localPeers, self.stage.remotePeers)
+ else:
+ # In this case, peers configuration is the default and stage configuration overrides.
+ # Validation is only needed if it's stage configuration is actually filled in.
+ if self.stage.hasPeers():
+ self._validatePeerList(self.stage.localPeers, self.stage.remotePeers)
def _validateStore(self):
"""
@@ -5148,10 +5404,10 @@
raise ValueError("Peer list must contain at least one backup peer.")
elif localPeers is not None and remotePeers is None:
if len(localPeers) < 1:
- raise ValueError("Peerl list must contain at least one backup peer.")
+ raise ValueError("Peer list must contain at least one backup peer.")
elif localPeers is not None and remotePeers is not None:
if len(localPeers) + len(remotePeers) < 1:
- raise ValueError("Peerl list must contain at least one backup peer.")
+ raise ValueError("Peer list must contain at least one backup peer.")
names = []
if localPeers is not None:
for localPeer in localPeers:
Modified: cedar-backup2/trunk/Changelog
===================================================================
--- cedar-backup2/trunk/Changelog 2007-12-15 19:20:09 UTC (rev 804)
+++ cedar-backup2/trunk/Changelog 2007-12-15 20:52:14 UTC (rev 805)
@@ -1,6 +1,10 @@
-Version 2.14.1 unreleased
+Version 2.15.0 unreleased
* Minor documentation tweaks discovered during 3.0 development.
+ * Add support for managed peers, where the mater kicks off remote actions.
+ - Add a new <peers> configuration section (PeersConfig)
+ - Change peers configuration in <stage> to just override <peers>
+ - Modify stage process to take peers list from peers section (if available)
Version 2.14.0 19 Sep 2007
Modified: cedar-backup2/trunk/test/configtests.py
===================================================================
--- cedar-backup2/trunk/test/configtests.py 2007-12-15 19:20:09 UTC (rev 804)
+++ cedar-backup2/trunk/test/configtests.py 2007-12-15 20:52:14 UTC (rev 805)
@@ -105,7 +105,7 @@
from CedarBackup2.config import ActionHook, PreActionHook, PostActionHook, CommandOverride
from CedarBackup2.config import ExtendedAction, ActionDependencies, BlankBehavior
from CedarBackup2.config import CollectFile, CollectDir, PurgeDir, LocalPeer, RemotePeer
-from CedarBackup2.config import ReferenceConfig, ExtensionsConfig, OptionsConfig
+from CedarBackup2.config import ReferenceConfig, ExtensionsConfig, OptionsConfig, PeersConfig
from CedarBackup2.config import CollectConfig, StageConfig, StoreConfig, PurgeConfig, Config
@@ -118,7 +118,8 @@
"cback.conf.5", "cback.conf.6", "cback.conf.7", "cback.conf.8",
"cback.conf.9", "cback.conf.10", "cback.conf.11", "cback.conf.12",
"cback.conf.13", "cback.conf.14", "cback.conf.15", "cback.conf.16",
- "cback.conf.17", "cback.conf.18", "cback.conf.19", "cback.conf.20", ]
+ "cback.conf.17", "cback.conf.18", "cback.conf.19", "cback.conf.20",
+ "cback.conf.21", "cback.conf.22", "cback.conf.23", ]
#######################################################################
@@ -4956,6 +4957,366 @@
self.failUnless(options1 != options2)
+########################
+# TestPeersConfig class
+########################
+
+class TestPeersConfig(unittest.TestCase):
+
+ """Tests for the PeersConfig class."""
+
+ ##################
+ # Utility methods
+ ##################
+
+ def failUnlessAssignRaises(self, exception, object, property, value):
+ """Equivalent of L{failUnlessRaises}, but used for property assignments instead."""
+ failUnlessAssignRaises(self, exception, object, property, value)
+
+
+ ############################
+ # Test __repr__ and __str__
+ ############################
+
+ def testStringFuncs_001(self):
+ """
+ Just make sure that the string functions don't have errors (i.e. bad variable names).
+ """
+ obj = PeersConfig()
+ obj.__repr__()
+ obj.__str__()
+
+
+ ##################################
+ # Test constructor and attributes
+ ##################################
+
+ def testConstructor_001(self):
+ """
+ Test constructor with no values filled in.
+ """
+ peers = PeersConfig()
+ self.failUnlessEqual(None, peers.localPeers)
+ self.failUnlessEqual(None, peers.remotePeers)
+
+ def testConstructor_002(self):
+ """
+ Test constructor with all values filled in, with valid values (empty lists).
+ """
+ peers = PeersConfig([], [])
+ self.failUnlessEqual([], peers.localPeers)
+ self.failUnlessEqual([], peers.remotePeers)
+
+ def testConstructor_003(self):
+ """
+ Test constructor with all values filled in, with valid values (non-empty lists).
+ """
+ peers = PeersConfig([LocalPeer(), ], [RemotePeer(), ])
+ self.failUnlessEqual([LocalPeer(), ], peers.localPeers)
+ self.failUnlessEqual([RemotePeer(), ], peers.remotePeers)
+
+ def testConstructor_004(self):
+ """
+ Test assignment of localPeers attribute, None value.
+ """
+ peers = PeersConfig(localPeers=[])
+ self.failUnlessEqual([], peers.localPeers)
+ peers.localPeers = None
+ self.failUnlessEqual(None, peers.localPeers)
+
+ def testConstructor_005(self):
+ """
+ Test assignment of localPeers attribute, empty list.
+ """
+ peers = PeersConfig()
+ self.failUnlessEqual(None, peers.localPeers)
+ peers.localPeers = []
+ self.failUnlessEqual([], peers.localPeers)
+
+ def testConstructor_006(self):
+ """
+ Test assignment of localPeers attribute, single valid entry.
+ """
+ peers = PeersConfig()
+ self.failUnlessEqual(None, peers.localPeers)
+ peers.localPeers = [LocalPeer(), ]
+ self.failUnlessEqual([LocalPeer(), ], peers.localPeers)
+
+ def testConstructor_007(self):
+ """
+ Test assignment of localPeers attribute, multiple valid
+ entries.
+ """
+ peers = PeersConfig()
+ self.failUnlessEqual(None, peers.localPeers)
+ peers.localPeers = [LocalPeer(name="one"), LocalPeer(name="two"), ]
+ self.failUnlessEqual([LocalPeer(name="one"), LocalPeer(name="two"), ], peers.localPeers)
+
+ def testConstructor_008(self):
+ """
+ Test assignment of localPeers attribute, single invalid entry
+ (None).
+ """
+ peers = PeersConfig()
+ self.failUnlessEqual(None, peers.localPeers)
+ self.failUnlessAssignRaises(ValueError, peers, "localPeers", [None, ])
+ self.failUnlessEqual(None, peers.localPeers)
+
+ def testConstructor_009(self):
+ """
+ Test assignment of localPeers attribute, single invalid entry
+ (not a LocalPeer).
+ """
+ peers = PeersConfig()
+ self.failUnlessEqual(None, peers.localPeers)
+ self.failUnlessAssignRaises(ValueError, peers, "localPeers", [RemotePeer(), ])
+ self.failUnlessEqual(None, peers.localPeers)
+
+ def testConstructor_010(self):
+ """
+ Test assignment of localPeers attribute, mixed valid and
+ invalid entries.
+ """
+ peers = PeersConfig()
+ self.failUnlessEqual(None, peers.localPeers)
+ self.failUnlessAssignRaises(ValueError, peers, "localPeers", [LocalPeer(), RemotePeer(), ])
+ self.failUnlessEqual(None, peers.localPeers)
+
+ def testConstructor_011(self):
+ """
+ Test assignment of remotePeers attribute, None value.
+ """
+ peers = PeersConfig(remotePeers=[])
+ self.failUnlessEqual([], peers.remotePeers)
+ peers.remotePeers = None
+ self.failUnlessEqual(None, peers.remotePeers)
+
+ def testConstructor_012(self):
+ """
+ Test assignment of remotePeers attribute, empty list.
+ """
+ peers = PeersConfig()
+ self.failUnlessEqual(None, peers.remotePeers)
+ peers.remotePeers = []
+ self.failUnlessEqual([], peers.remotePeers)
+
+ def testConstructor_013(self):
+ """
+ Test assignment of remotePeers attribute, single valid entry.
+ """
+ peers = PeersConfig()
+ self.failUnlessEqual(None, peers.remotePeers)
+ peers.remotePeers = [RemotePeer(name="one"), ]
+ self.failUnlessEqual([RemotePeer(name="one"), ], peers.remotePeers)
+
+ def testConstructor_014(self):
+ """
+ Test assignment of remotePeers attribute, multiple valid
+ entries.
+ """
+ peers = PeersConfig()
+ self.failUnlessEqual(None, peers.remotePeers)
+ peers.remotePeers = [RemotePeer(name="one"), RemotePeer(name="two"), ]
+ self.failUnlessEqual([RemotePeer(name="one"), RemotePeer(name="two"), ], peers.remotePeers)
+
+ def testConstructor_015(self):
+ """
+ Test assignment of remotePeers attribute, single invalid entry
+ (None).
+ """
+ peers = PeersConfig()
+ self.failUnlessEqual(None, peers.remotePeers)
+ self.failUnlessAssignRaises(ValueError, peers, "remotePeers", [None, ])
+ self.failUnlessEqual(None, peers.remotePeers)
+
+ def testConstructor_016(self):
+ """
+ Test assignment of remotePeers attribute, single invalid entry
+ (not a RemotePeer).
+ """
+ peers = PeersConfig()
+ self.failUnlessEqual(None, peers.remotePeers)
+ self.failUnlessAssignRaises(ValueError, peers, "remotePeers", [LocalPeer(), ])
+ self.failUnlessEqual(None, peers.remotePeers)
+
+ def testConstructor_017(self):
+ """
+ Test assignment of remotePeers attribute, mixed valid and
+ invalid entries.
+ """
+ peers = PeersConfig()
+ self.failUnlessEqual(None, peers.remotePeers)
+ self.failUnlessAssignRaises(ValueError, peers, "remotePeers", [LocalPeer(), RemotePeer(), ])
+ self.failUnlessEqual(None, peers.remotePeers)
+
+
+ ############################
+ # Test comparison operators
+ ############################
+
+ def testComparison_001(self):
+ """
+ Test comparison of two identical objects, all attributes None.
+ """
+ peers1 = PeersConfig()
+ peers2 = PeersConfig()
+ self.failUnlessEqual(peers1, peers2)
+ self.failUnless(peers1 == peers2)
+ self.failUnless(not peers1 < peers2)
+ self.failUnless(peers1 <= peers2)
+ self.failUnless(not peers1 > peers2)
+ self.failUnless(peers1 >= peers2)
+ self.failUnless(not peers1 != peers2)
+
+ def testComparison_002(self):
+ """
+ Test comparison of two identical objects, all attributes non-None (empty lists).
+ """
+ peers1 = PeersConfig([], [])
+ peers2 = PeersConfig([], [])
+ self.failUnlessEqual(peers1, peers2)
+ self.failUnless(peers1 == peers2)
+ self.failUnless(not peers1 < peers2)
+ self.failUnless(peers1 <= peers2)
+ self.failUnless(not peers1 > peers2)
+ self.failUnless(peers1 >= peers2)
+ self.failUnless(not peers1 != peers2)
+
+ def testComparison_003(self):
+ """
+ Test comparison of two identical objects, all attributes non-None (non-empty lists).
+ """
+ peers1 = PeersConfig([LocalPeer(), ], [RemotePeer(), ])
+ peers2 = PeersConfig([LocalPeer(), ], [RemotePeer(), ])
+ self.failUnlessEqual(peers1, peers2)
+ self.failUnless(peers1 == peers2)
+ self.failUnless(not peers1 < peers2)
+ self.failUnless(peers1 <= peers2)
+ self.failUnless(not peers1 > peers2)
+ self.failUnless(peers1 >= peers2)
+ self.failUnless(not peers1 != peers2)
+
+ def testComparison_004(self):
+ """
+ Test comparison of two differing objects, localPeers differs (one None,
+ one empty).
+ """
+ peers1 = PeersConfig(None, [RemotePeer(), ])
+ peers2 = PeersConfig([], [RemotePeer(), ])
+ self.failIfEqual(peers1, peers2)
+ self.failUnless(not peers1 == peers2)
+ self.failUnless(peers1 < peers2)
+ self.failUnless(peers1 <= peers2)
+ self.failUnless(not peers1 > peers2)
+ self.failUnless(not peers1 >= peers2)
+ self.failUnless(peers1 != peers2)
+
+ def testComparison_005(self):
+ """
+ Test comparison of two differing objects, localPeers differs (one None,
+ one not empty).
+ """
+ peers1 = PeersConfig(None, [RemotePeer(), ])
+ peers2 = PeersConfig([LocalPeer(), ], [RemotePeer(), ])
+ self.failIfEqual(peers1, peers2)
+ self.failUnless(not peers1 == peers2)
+ self.failUnless(peers1 < peers2)
+ self.failUnless(peers1 <= peers2)
+ self.failUnless(not peers1 > peers2)
+ self.failUnless(not peers1 >= peers2)
+ self.failUnless(peers1 != peers2)
+
+ def testComparison_006(self):
+ """
+ Test comparison of two differing objects, localPeers differs (one empty,
+ one not empty).
+ """
+ peers1 = PeersConfig([], [RemotePeer(), ])
+ peers2 = PeersConfig([LocalPeer(), ], [RemotePeer(), ])
+ self.failIfEqual(peers1, peers2)
+ self.failUnless(not peers1 == peers2)
+ self.failUnless(peers1 < peers2)
+ self.failUnless(peers1 <= peers2)
+ self.failUnless(not peers1 > peers2)
+ self.failUnless(not peers1 >= peers2)
+ self.failUnless(peers1 != peers2)
+
+ def testComparison_007(self):
+ """
+ Test comparison of two differing objects, localPeers differs (both not
+ empty).
+ """
+ peers1 = PeersConfig([LocalPeer(name="one"), ], [RemotePeer(), ])
+ peers2 = PeersConfig([LocalPeer(name="two"), ], [RemotePeer(), ])
+ self.failIfEqual(peers1, peers2)
+ self.failUnless(not peers1 == peers2)
+ self.failUnless(peers1 < peers2)
+ self.failUnless(peers1 <= peers2)
+ self.failUnless(not peers1 > peers2)
+ self.failUnless(not peers1 >= peers2)
+ self.failUnless(peers1 != peers2)
+
+ def testComparison_008(self):
+ """
+ Test comparison of two differing objects, remotePeers differs (one None,
+ one empty).
+ """
+ peers1 = PeersConfig([LocalPeer(), ], None)
+ peers2 = PeersConfig([LocalPeer(), ], [])
+ self.failIfEqual(peers1, peers2)
+ self.failUnless(not peers1 == peers2)
+ self.failUnless(peers1 < peers2)
+ self.failUnless(peers1 <= peers2)
+ self.failUnless(not peers1 > peers2)
+ self.failUnless(not peers1 >= peers2)
+ self.failUnless(peers1 != peers2)
+
+ def testComparison_009(self):
+ """
+ Test comparison of two differing objects, remotePeers differs (one None,
+ one not empty).
+ """
+ peers1 = PeersConfig([LocalPeer(), ], None)
+ peers2 = PeersConfig([LocalPeer(), ], [RemotePeer(), ])
+ self.failIfEqual(peers1, peers2)
+ self.failUnless(not peers1 == peers2)
+ self.failUnless(peers1 < peers2)
+ self.failUnless(peers1 <= peers2)
+ self.failUnless(not peers1 > peers2)
+ self.failUnless(not peers1 >= peers2)
+ self.failUnless(peers1 != peers2)
+
+ def testComparison_010(self):
+ """
+ Test comparison of two differing objects, remotePeers differs (one empty,
+ one not empty).
+ """
+ peers1 = PeersConfig([LocalPeer(), ], [])
+ peers2 = PeersConfig([LocalPeer(), ], [RemotePeer(), ])
+ self.failIfEqual(peers1, peers2)
+ self.failUnless(not peers1 == peers2)
+ self.failUnless(peers1 < peers2)
+ self.failUnless(peers1 <= peers2)
+ self.failUnless(not peers1 > peers2)
+ self.failUnless(not peers1 >= peers2)
+ self.failUnless(peers1 != peers2)
+
+ def testComparison_011(self):
+ """
+ Test comparison of two differing objects, remotePeers differs (both not
+ empty).
+ """
+ peers1 = PeersConfig([LocalPeer(), ], [RemotePeer(name="two"), ])
+ peers2 = PeersConfig([LocalPeer(), ], [RemotePeer(name="one"), ])
+ self.failIfEqual(peers1, peers2)
+ self.failUnless(not peers1 == peers2)
+ self.failUnless(not peers1 < peers2)
+ self.failUnless(not peers1 <= peers2)
+ self.failUnless(peers1 > peers2)
+ self.failUnless(peers1 >= peers2)
+ self.failUnless(peers1 != peers2)
+
+
##########################
# TestCollectConfig class
##########################
@@ -7535,6 +7896,7 @@
config1.reference = ReferenceConfig()
config1.extensions = ExtensionsConfig()
config1.options = OptionsConfig()
+ config1.peers = PeersConfig()
config1.collect = CollectConfig()
config1.stage = StageConfig()
config1.store = StoreConfig()
@@ -7544,6 +7906,7 @@
config2.reference = ReferenceConfig()
config2.extensions = ExtensionsConfig()
config2.options = OptionsConfig()
+ config2.peers = PeersConfig()
config2.collect = CollectConfig()
config2.stage = StageConfig()
config2.store = StoreConfig()
@@ -7579,6 +7942,7 @@
config1 = Config()
config1.reference = ReferenceConfig(author="one")
config1.options = OptionsConfig()
+ config1.peers = PeersConfig()
config1.collect = CollectConfig()
config1.stage = StageConfig()
config1.store = StoreConfig()
@@ -7587,6 +7951,7 @@
config2 = Config()
config2.reference = ReferenceConfig(author="two")
config2.options = OptionsConfig()
+ config2.peers = PeersConfig()
config2.collect = CollectConfig()
config2.stage = StageConfig()
config2.store = StoreConfig()
@@ -7623,6 +7988,7 @@
config1.reference = ReferenceConfig()
config1.extensions = ExtensionsConfig(None)
config1.options = OptionsConfig()
+ config1.peers = PeersConfig()
config1.collect = CollectConfig()
config1.stage = StageConfig()
config1.store = StoreConfig()
@@ -7632,6 +7998,7 @@
config2.reference = ReferenceConfig()
config2.extensions = ExtensionsConfig([])
config2.options = OptionsConfig()
+ config2.peers = PeersConfig()
config2.collect = CollectConfig()
config2.stage = StageConfig()
config2.store = StoreConfig()
@@ -7653,6 +8020,7 @@
config1.reference = ReferenceConfig()
config1.extensions = ExtensionsConfig([])
config1.options = OptionsConfig()
+ config1.peers = PeersConfig()
config1.collect = CollectConfig()
config1.stage = StageConfig()
config1.store = StoreConfig()
@@ -7662,6 +8030,7 @@
config2.reference = ReferenceConfig()
config2.extensions = ExtensionsConfig([ExtendedAction("one", "two", "three"), ])
config2.options = OptionsConfig()
+ config2.peers = PeersConfig()
config2.collect = CollectConfig()
config2.stage = StageConfig()
config2.store = StoreConfig()
@@ -7683,15 +8052,17 @@
config1.reference = ReferenceConfig()
config1.extensions = ExtensionsConfig([ExtendedAction("one", "two", "three"), ])
config1.options = OptionsConfig()
+ config1.peers = PeersConfig()
config1.collect = CollectConfig()
config1.stage = StageConfig()
config1.store = StoreConfig()
config1.purge = PurgeConfig()
config2 = Config()
- config1.reference = ReferenceConfig()
- config1.extensions = ExtensionsConfig([ExtendedAction("one", "two", "four"), ])
+ config2.reference = ReferenceConfig()
+ config2.extensions = ExtensionsConfig([ExtendedAction("one", "two", "four"), ])
config2.options = OptionsConfig()
+ config2.peers = PeersConfig()
config2.collect = CollectConfig()
config2.stage = StageConfig()
config2.store = StoreConfig()
@@ -7727,6 +8098,7 @@
config1 = Config()
config1.reference = ReferenceConfig()
config1.options = OptionsConfig(startingDay="tuesday")
+ config1.peers = PeersConfig()
config1.collect = CollectConfig()
config1.stage = StageConfig()
config1.store = StoreConfig()
@@ -7735,6 +8107,7 @@
config2 = Config()
config2.reference = ReferenceConfig()
config2.options = OptionsConfig(startingDay="monday")
+ config2.peers = PeersConfig()
config2.collect = CollectConfig()
config2.stage = StageConfig()
config2.store = StoreConfig()
@@ -7770,6 +8143,7 @@
config1 = Config()
config1.reference = ReferenceConfig()
config1.options = OptionsConfig()
+ config1.peers = PeersConfig()
config1.collect = CollectConfig(collectMode="daily")
config1.stage = StageConfig()
config1.store = StoreConfig()
@@ -7778,6 +8152,7 @@
config2 = Config()
config2.reference = ReferenceConfig()
config2.options = OptionsConfig()
+ config2.peers = PeersConfig()
config2.collect = CollectConfig(collectMode="incr")
config2.stage = StageConfig()
config2.store = StoreConfig()
@@ -7813,6 +8188,7 @@
config1 = Config()
config1.reference = ReferenceConfig()
config1.options = OptionsConfig()
+ config1.peers = PeersConfig()
config1.collect = CollectConfig()
config1.stage = StageConfig(targetDir="/something")
config1.store = StoreConfig()
@@ -7821,6 +8197,7 @@
config2 = Config()
config2.reference = ReferenceConfig()
config2.options = OptionsConfig()
+ config2.peers = PeersConfig()
config2.collect = CollectConfig()
config2.stage = StageConfig(targetDir="/whatever")
config2.store = StoreConfig()
@@ -7856,6 +8233,7 @@
config1 = Config()
config1.reference = ReferenceConfig()
config1.options = OptionsConfig()
+ config1.peers = PeersConfig()
config1.collect = CollectConfig()
config1.stage = StageConfig()
config1.store = StoreConfig(deviceScsiId="ATA:0,0,0")
@@ -7864,6 +8242,7 @@
config2 = Config()
config2.reference = ReferenceConfig()
config2.options = OptionsConfig()
+ config2.peers = PeersConfig()
config2.collect = CollectConfig()
config2.stage = StageConfig()
config2.store = StoreConfig(deviceScsiId="0,0,0")
@@ -7899,6 +8278,7 @@
config1 = Config()
config1.reference = ReferenceConfig()
config1.options = OptionsConfig()
+ config1.peers = PeersConfig()
config1.collect = CollectConfig()
config1.stage = StageConfig()
config1.store = StoreConfig()
@@ -7907,6 +8287,7 @@
config2 = Config()
config2.reference = ReferenceConfig()
config2.options = OptionsConfig()
+ config2.peers = PeersConfig()
config2.collect = CollectConfig()
config2.stage = StageConfig()
config2.store = StoreConfig()
@@ -7920,7 +8301,54 @@
self.failUnless(not config1 >= config2)
self.failUnless(config1 != config2)
+ def testComparison_019(self):
+ """
+ Test comparison of two differing objects, peers differs (one None).
+ """
+ config1 = Config()
+ config2 = Config()
+ config2.peers = PeersConfig()
+ self.failIfEqual(config1, config2)
+ self.failUnless(not config1 == config2)
+ self.failUnless(config1 < config2)
+ self.failUnless(config1 <= config2)
+ self.failUnless(not config1 > config2)
+ self.failUnless(not config1 >= config2)
+ self.failUnless(config1 != config2)
+ def testComparison_020(self):
+ """
+ Test comparison of two identical objects, peers differs.
+ """
+ config1 = Config()
+ config1.reference = ReferenceConfig()
+ config1.extensions = ExtensionsConfig()
+ config1.options = OptionsConfig()
+ config1.peers = PeersConfig()
+ config1.collect = CollectConfig()
+ config1.stage = StageConfig()
+ config1.store = StoreConfig()
+ config1.purge = PurgeConfig()
+
+ config2 = Config()
+ config2.reference = ReferenceConfig()
+ config2.extensions = ExtensionsConfig()
+ config2.options = OptionsConfig()
+ config2.peers = PeersConfig(localPeers=[LocalPeer(),])
+ config2.collect = CollectConfig()
+ config2.stage = StageConfig()
+ config2.store = StoreConfig()
+ config2.purge = PurgeConfig()
+
+ self.failIfEqual(config1, config2)
+ self.failUnless(not config1 == config2)
+ self.failUnless(config1 < config2)
+ self.failUnless(config1 <= config2)
+ self.failUnless(not config1 > config2)
+ self.failUnless(not config1 >= config2)
+ self.failUnless(config1 != config2)
+
+
#########################
# Test certain utilities
#########################
@@ -8897,7 +9325,7 @@
def testValidate_048(self):
"""
- Test that we catch a duplicate local peer name.
+ Test that we catch a duplicate local peer name in stage configuration.
"""
config = Config()
config.options = OptionsConfig(backupUser="ken", rcpCommand="command")
@@ -8914,7 +9342,7 @@
def testValidate_049(self):
"""
- Test that we catch a duplicate remote peer name.
+ Test that we catch a duplicate remote peer name in stage configuration.
"""
config = Config()
config.options = OptionsConfig(backupUser="ken", rcpCommand="command")
@@ -8931,7 +9359,8 @@
def testValidate_050(self):
"""
- Test that we catch a duplicate peer name duplicated between remote and local.
+ Test that we catch a duplicate peer name duplicated between remote and
+ local in stage configuration.
"""
config = Config()
config.options = OptionsConfig(backupUser="ken", rcpCommand="command")
@@ -8946,7 +9375,321 @@
config.stage.remotePeers = [ RemotePeer(name="duplicate", collectDir="/some/path/to/data"), ]
self.failUnlessRaises(ValueError, config._validateStage)
+ def testValidate_051(self):
+ """
+ Test validate on a None peers section.
+ """
+ config = Config()
+ config.peers = None
+ config._validatePeers()
+ def testValidate_052(self):
+ """
+ Test validate on an empty peers section.
+ """
+ config = Config()
+ config.peers = PeersConfig()
+ self.failUnlessRaises(ValueError, config._validatePeers)
+
+ def testValidate_053(self):
+ """
+ Test validate on peers section containing None for the lists.
+ """
+ config = Config()
+ config.peers = PeersConfig()
+ config.peers.localPeers = None
+ config.peers.remotePeers = None
+ self.failUnlessRaises(ValueError, config._validatePeers)
+
+ def testValidate_054(self):
+ """
+ Test validate on peers section containing [] for the lists.
+ """
+ config = Config()
+ config.peers = PeersConfig()
+ config.peers.localPeers = []
+ config.peers.remotePeers = []
+ self.failUnlessRaises(ValueError, config._validatePeers)
+
+ def testValidate_055(self):
+ """
+ Test validate on peers section containing one local peer that is empty.
+ """
+ config = Config()
+ config.peers = PeersConfig()
+ config.peers.localPeers = [LocalPeer(), ]
+ self.failUnlessRaises(ValueError, config._validatePeers)
+
+ def testValidate_056(self):
+ """
+ Test validate on peers section containing local peer with only a name.
+ """
+ config = Config()
+ config.peers = PeersConfig()
+ config.peers.localPeers = [LocalPeer(name="name"), ]
+ self.failUnlessRaises(ValueError, config._validatePeers)
+
+ def testValidate_057(self):
+ """
+ Test validate on peers section containing one local peer with a name and
+ path, None for remote list.
+ """
+ config = Config()
+ config.peers = PeersConfig()
+ config.peers.localPeers = [LocalPeer(name="name", collectDir="/somewhere"), ]
+ config.peers.remotePeers = None
+ config._validatePeers()
+
+ def testValidate_058(self):
+ """
+ Test validate on peers section containing one local peer with a name and
+ path, [] for remote list.
+ """
+ config = Config()
+ config.peers = PeersConfig()
+ config.peers.localPeers = [LocalPeer(name="name", collectDir="/somewhere"), ]
+ config.peers.remotePeers = []
+ config._validatePeers()
+
+ def testValidate_059(self):
+ """
+ Test validate on peers section containing one remote peer that is empty.
+ """
+ config = Config()
+ config.peers = PeersConfig()
+ config.peers.remotePeers = [RemotePeer(), ]
+ self.failUnlessRaises(ValueError, config._validatePeers)
+
+ def testValidate_060(self):
+ """
+ Test validate on peers section containing one remote peer with only a name.
+ """
+ config = Config()
+ config.peers = PeersConfig()
+ config.peers.remotePeers = [RemotePeer(name="blech"), ]
+ self.failUnlessRaises(ValueError, config._validatePeers)
+
+ def testValidate_061(self):
+ """
+ Test validate on peers section containing one remote peer with a name and
+ path, None for local list.
+ """
+ config = Config()
+ config.peers = PeersConfig()
+ config.peers.localPeers = None
+ config.peers.remotePeers = [RemotePeer(name="blech", collectDir="/some/path/to/data"), ]
+ self.failUnlessRaises(ValueError, config._validatePeers)
+ config.options = OptionsConfig(backupUser="ken", rcpCommand="command")
+ config._validatePeers()
+ config.options = None
+ self.failUnlessRaises(ValueError, config._validatePeers)
+ config.peers.remotePeers[-1].remoteUser = "remote"
+ config.peers.remotePeers[-1].rcpCommand = "command"
+ config._validatePeers()
+
+ def testValidate_062(self):
+ """
+ Test validate on peers section containing one remote peer with a name and
+ path, [] for local list.
+ """
+ config = Config()
+ config.peers = PeersConfig()
+ config.peers.localPeers = []
+ config.peers.remotePeers = [RemotePeer(name="blech", collectDir="/some/path/to/data"), ]
+ self.failUnlessRaises(ValueError, config._validatePeers)
+ config.options = OptionsConfig(backupUser="ken", rcpCommand="command")
+ config._validatePeers()
+ config.options = None
+ self.failUnlessRaises(ValueError, config._validatePeers)
+ config.peers.remotePeers[-1].remoteUser = "remote"
+ config.peers.remotePeers[-1].rcpCommand = "command"
+ config._validatePeers()
+
+ def testValidate_063(self):
+ """
+ Test validate on peers section containing one remote and one local peer.
+ """
+ config = Config()
+ config.peers = PeersConfig()
+ config.peers.localPeers = [LocalPeer(name="metoo", collectDir="/nowhere"), ]
+ config.peers.remotePeers = [RemotePeer(name="blech", collectDir="/some/path/to/data"), ]
+ self.failUnlessRaises(ValueError, config._validatePeers)
+ config.options = OptionsConfig(backupUser="ken", rcpCommand="command")
+ config._validatePeers()
+ config.options = None
+ self.failUnlessRaises(ValueError, config._validatePeers)
+ config.peers.remotePeers[-1].remoteUser = "remote"
+ config.peers.remotePeers[-1].rcpCommand = "command"
+ config._validatePeers()
+
+ def testValidate_064(self):
+ """
+ Test validate on peers section containing multiple remote and local peers.
+ """
+ config = Config()
+ config.peers = PeersConfig()
+ config.peers.localPeers = [LocalPeer(name="metoo", collectDir="/nowhere"), LocalPeer("one", "/two"), LocalPeer("a", "/b"), ]
+ config.peers.remotePeers = [RemotePeer(name="blech", collectDir="/some/path/to/data"), RemotePeer("c", "/d"), ]
+ self.failUnlessRaises(ValueError, config._validatePeers)
+ config.options = OptionsConfig(backupUser="ken", rcpCommand="command")
+ config._validatePeers()
+ config.options = None
+ self.failUnlessRaises(ValueError, config._validatePeers)
+ config.peers.remotePeers[-1].remoteUser = "remote"
+ config.peers.remotePeers[-1].rcpCommand = "command"
+ self.failUnlessRaises(ValueError, config._validatePeers)
+ config.peers.remotePeers[0].remoteUser = "remote"
+ config.peers.remotePeers[0].rcpCommand = "command"
+ config._validatePeers()
+
+ def testValidate_065(self):
+ """
+ Test that we catch a duplicate local peer name in peers configuration.
+ """
+ config = Config()
+ config.options = OptionsConfig(backupUser="ken", rcpCommand="command")
+ config.peers = PeersConfig()
+
+ config.peers.localPeers = [ LocalPeer(name="unique1", collectDir="/nowhere"),
+ LocalPeer(name="unique2", collectDir="/nowhere"), ]
+ config._validatePeers()
+
+ config.peers.localPeers = [ LocalPeer(name="duplicate", collectDir="/nowhere"),
+ LocalPeer(name="duplicate", collectDir="/nowhere"), ]
+ self.failUnlessRaises(ValueError, config._validatePeers)
+
+ def testValidate_066(self):
+ """
+ Test that we catch a duplicate remote peer name in peers configuration.
+ """
+ config = Config()
+ config.options = OptionsConfig(backupUser="ken", rcpCommand="command")
+ config.peers = PeersConfig()
+
+ config.peers.remotePeers = [ RemotePeer(name="unique1", collectDir="/some/path/to/data"),
+ RemotePeer(name="unique2", collectDir="/some/path/to/data"), ]
+ config._validatePeers()
+
+ config.peers.remotePeers = [ RemotePeer(name="duplicate", collectDir="/some/path/to/data"),
+ RemotePeer(name="duplicate", collectDir="/some/path/to/data"), ]
+ self.failUnlessRaises(ValueError, config._validatePeers)
+
+ def testValidate_067(self):
+ """
+ Test that we catch a duplicate peer name duplicated between remote and
+ local in peers configuration.
+ """
+ config = Config()
+ config.options = OptionsConfig(backupUser="ken", rcpCommand="command")
+ config.peers = PeersConfig()
+
+ config.peers.localPeers = [ LocalPeer(name="unique1", collectDir="/nowhere"), ]
+ config.peers.remotePeers = [ RemotePeer(name="unique2", collectDir="/some/path/to/data"), ]
+ config._validatePeers()
+
+ config.peers.localPeers = [ LocalPeer(name="duplicate", collectDir="/nowhere"), ]
+ config.peers.remotePeers = [ RemotePeer(name="duplicate", collectDir="/some/path/to/data"), ]
+ self.failUnlessRaises(ValueError, config._validatePeers)
+
+ def testValidate_068(self):
+ """
+ Test that stage peers can be None, if peers configuration is not None.
+ """
+ config = Config()
+ config.options = OptionsConfig(backupUser="ken", rcpCommand="command")
+ config.peers = PeersConfig()
+ config.stage = StageConfig()
+
+ config.peers.localPeers = [ LocalPeer(name="unique1", collectDir="/nowhere"), ]
+ config.peers.remotePeers = [ RemotePeer(name="unique2", collectDir="/some/path/to/data"), ]
+
+ config.stage.targetDir = "/whatever"
+ config.stage.localPeers = None
+ config.stage.remotePeers = None
+
+ config._validatePeers()
+ config._validateStage()
+
+ def testValidate_069(self):
+ """
+ Test that stage peers can be empty lists, if peers configuration is not None.
+ """
+ config = Config()
+ config.options = OptionsConfig(backupUser="ken", rcpCommand="command")
+ config.peers = PeersConfig()
+ config.stage = StageConfig()
+
+ config.peers.localPeers = [ LocalPeer(name="unique1", collectDir="/nowhere"), ]
+ config.peers.remotePeers = [ RemotePeer(name="unique2", collectDir="/some/path/to/data"), ]
+
+ config.stage.targetDir = "/whatever"
+ config.stage.localPeers = []
+ config.stage.remotePeers = []
+
+ config._validatePeers()
+ config._validateStage()
+
+ def testValidate_070(self):
+ """
+ Test that staging local peers must be valid if filled in, even if peers
+ configuration is not None.
+ """
+ config = Config()
+ config.options = OptionsConfig(backupUser="ken", rcpCommand="command")
+ config.peers = PeersConfig()
+ config.stage = StageConfig()
+
+ config.peers.localPeers = [ LocalPeer(name="unique1", collectDir="/nowhere"), ]
+ config.peers.remotePeers = [ RemotePeer(name="unique2", collectDir="/some/path/to/data"), ]
+
+ config.stage.targetDir = "/whatever"
+ config.stage.localPeers = [LocalPeer(), ] # empty local peer is invalid, so validation should catch it
+ config.stage.remotePeers = []
+
+ config._validatePeers()
+ self.failUnlessRaises(ValueError, config._validateStage)
+
+ def testValidate_071(self):
+ """
+ Test that staging remote peers must be valid if filled in, even if peers
+ configuration is not None.
+ """
+ config = Config()
+ config.options = OptionsConfig(backupUser="ken", rcpCommand="command")
+ config.peers = PeersConfig()
+ config.stage = StageConfig()
+
+ config.peers.localPeers = [ LocalPeer(name="unique1", collectDir="/nowhere"), ]
+ config.peers.remotePeers = [ RemotePeer(name="unique2", collectDir="/some/path/to/data"), ]
+
+ config.stage.targetDir = "/whatever"
+ config.stage.localPeers = []
+ config.stage.remotePeers = [RemotePeer(), ] # empty remote peer is invalid, so validation should catch it
+
+ config._validatePeers()
+ self.failUnlessRaises(ValueError, config._validateStage)
+
+ def testValidate_072(self):
+ """
+ Test that staging local and remote peers must be valid if filled in, even
+ if peers configuration is not None.
+ ""...
[truncated message content] |