add "is_parent_of" function to blockdevice module

improve pre-defined exceptions
improve few failure behaviours
This commit is contained in:
lars 2008-02-17 18:10:38 +00:00
parent 42a5e1bcc6
commit eaf37a872a
4 changed files with 93 additions and 31 deletions

View file

@ -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')
"""

View file

@ -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).
"""

View file

@ -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

View file

@ -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