From eaf37a872ab07c31db39603d64dd376db8a447f5 Mon Sep 17 00:00:00 2001 From: lars Date: Sun, 17 Feb 2008 18:10:38 +0000 Subject: [PATCH] add "is_parent_of" function to blockdevice module improve pre-defined exceptions improve few failure behaviours --- src/cryptobox/core/blockdevice.py | 42 ++++++++++++++++++ src/cryptobox/core/exceptions.py | 72 +++++++++++++++++++------------ src/cryptobox/core/main.py | 2 +- src/cryptobox/core/settings.py | 8 +++- 4 files changed, 93 insertions(+), 31 deletions(-) diff --git a/src/cryptobox/core/blockdevice.py b/src/cryptobox/core/blockdevice.py index 04479bf..4dc20e1 100644 --- a/src/cryptobox/core/blockdevice.py +++ b/src/cryptobox/core/blockdevice.py @@ -33,6 +33,7 @@ import subprocess import time import logging import cryptobox.core.settings +import cryptobox.core.exceptions OPTIONAL_PROGS = { "lvm": True } """remember which programs don't exist to avoid calling them in vain @@ -99,6 +100,10 @@ class Blockdevices: class Blockdevice: + """don't instantiate this class directly! + + use "_get_blockdevice" instead + """ def __init__(self, dev, sysblock_dir=DEFAULT_SYSBLOCK_DIR, @@ -115,6 +120,11 @@ class Blockdevice: self.devdir = dev self.devnode_dir = devnode_dir self.sysblock_dir = sysblock_dir + ## check if the device is valid + if not os.path.isdir(os.path.join(self.devnode_dir, dev)): + raise cryptobox.core.exceptions.CBInternalError( + "invalid blockdevice given: %s (%s)" % \ + (self.devdir, self.sysblock_dir)) self.name = os.path.basename(self.devdir) ## "reset" below will fill these values self.devnum = None @@ -358,6 +368,38 @@ class Blockdevice: return result + def is_parent_of(self, ask_child): + """check if the blockdevice or any of its children contains the given child + + the result of "foo.is_parent_of(foo)" returns False + + invalid (None) "ask_child" devices return False + + @param ask_child: the blockdevice that is considered to be a possible child + @type ask_child: BlockDevice + @return: True if the child is (even recursively) part of the blockdevice, otherwise False + @rtype: bool + """ + ## return False for non existing device + if ask_child is None: + return False + ## throw exception for invalid call + if not isinstance(ask_child, Blockdevice): + raise cryptobox.core.exceptions.CBInternalError(\ + "invalid arguments for 'is_parent_of'") + ## recursively go through all the children + for child_devname in self.children: + child_dev = get_blockdevice(child_devname) + ## direct child? + if child_dev == ask_child: + return True + ## indirect child? + if child_dev.is_parent_of(ask_child): + return True + ## no matches found + return False + + def __get_dev_related(self, subdir): """return the content of sub directories (e.g. 'holders' or 'slaves') """ diff --git a/src/cryptobox/core/exceptions.py b/src/cryptobox/core/exceptions.py index 43b9561..92d710e 100644 --- a/src/cryptobox/core/exceptions.py +++ b/src/cryptobox/core/exceptions.py @@ -22,30 +22,65 @@ exceptions of the cryptobox package """ + __revision__ = "$Id$" class CBError(Exception): """base class for exceptions of the cryptobox""" - pass + prefix = "general cryptobox error" + + def __init__(self, desc): + self.desc = desc + + def __str__(self): + """Return the error description. + """ + if self.desc: + return "%s: %s" % (self.prefix, self.desc) + else: + return self.prefix + + + +# main exception classes class CBConfigError(CBError): """any kind of error related to the configuration of a cryptobox""" pass +class CBContainerError(CBError): + """Any error raised while manipulating a cryptobox container. + """ + + prefix = "cryptobox container error" + + +class CBEnvironmentError(CBError): + """some part of the environment of the cryptobox is broken + e.g. the wrong version of a required program + """ + + prefix = "cryptobox environment error" + + +class CBInternalError(CBError): + """report any failing internal assertions + + this is always a bug + """ + + prefix = "internal error detected" + + +# specialized exceptions + class CBConfigUnavailableError(CBConfigError): """config file/input was not available at all""" - def __init__(self, source=None): - self.source = source - - def __str__(self): - if self.source: - return "failed to access the configuration of the cryptobox: %s" % self.source - else: - return "failed to access the configuration of the cryptobox" + prefix = "failed to access the configuration of the cryptobox" class CBConfigUndefinedError(CBConfigError): @@ -86,25 +121,6 @@ class CBConfigInvalidValueError(CBConfigError): (self.section, self.name, self.value, self.reason) -class CBEnvironmentError(CBError): - """some part of the environment of the cryptobox is broken - e.g. the wrong version of a required program - """ - - def __init__(self, desc): - self.desc = desc - - def __str__(self): - """Return the error description. - """ - return "misconfiguration detected: %s" % self.desc - - -class CBContainerError(CBError): - """Any error raised while manipulating a cryptobox container. - """ - - class CBCreateError(CBContainerError): """Raised if a container could not be created (formatted). """ diff --git a/src/cryptobox/core/main.py b/src/cryptobox/core/main.py index dfc740e..7ca925f 100644 --- a/src/cryptobox/core/main.py +++ b/src/cryptobox/core/main.py @@ -230,7 +230,7 @@ class CryptoBox: device.devnodes.insert(0, devnode) return True else: - self.log.debug("Skipping device without read and write" \ + self.log.debug("Skipping device without read and write " \ + "permissions: %s" % device.name) self.log.debug("Skipping unusable device: %s" % device.name) return False diff --git a/src/cryptobox/core/settings.py b/src/cryptobox/core/settings.py index 5dbe2c9..821df8a 100644 --- a/src/cryptobox/core/settings.py +++ b/src/cryptobox/core/settings.py @@ -317,9 +317,13 @@ class CryptoBoxSettings: else: raise CBConfigUnavailableError( "failed to load the config file: %s" % config_file) - except IOError: + except IOError, err_msgg: raise CBConfigUnavailableError( - "unable to open the config file: %s" % config_file) + "unable to open the config file (%s): %s" % \ + (config_file, err_msg)) + except configobj.ConfigObjError, err_msg: + raise CBConfigError("failed to load config file (%s): %s" % \ + (config_file, err_msg)) return prefs