removed dependency on /dev/mapper location from container.py
replaced some functions in container.py with their new blockdevice.py counterparts move "type_id" detection from container.py to blockdevice.py reduce calls of "reset" for blockdevices
This commit is contained in:
parent
3224d59dfe
commit
1270b00a5f
2 changed files with 139 additions and 78 deletions
|
@ -22,6 +22,9 @@
|
|||
These classes detect and filter available blockdevices.
|
||||
'''
|
||||
|
||||
|
||||
#TODO: call blkid only once for all devices and scan the result
|
||||
|
||||
__revision__ = "$Id$"
|
||||
|
||||
|
||||
|
@ -111,11 +114,14 @@ class Blockdevice:
|
|||
self.devnodes = None
|
||||
self.uuid = None
|
||||
self.label = None
|
||||
self.reset()
|
||||
self.reset(empty_cache=False)
|
||||
|
||||
|
||||
def reset(self):
|
||||
def reset(self, empty_cache=True):
|
||||
"""reread the data of the device
|
||||
|
||||
usually we will have to reset the cache, too
|
||||
just in case of first-time initialization, this is not necessary
|
||||
"""
|
||||
CACHE.reset(["blockdevice_info", self.name])
|
||||
self.devnum = self.__get_major_minor()
|
||||
|
@ -128,6 +134,7 @@ class Blockdevice:
|
|||
self.devnodes = self.__get_device_nodes()
|
||||
self.uuid = self.__get_uuid()
|
||||
self.label = self.__get_label()
|
||||
self.type_id = self.__get_type_id()
|
||||
|
||||
|
||||
def is_valid(self):
|
||||
|
@ -569,8 +576,49 @@ class Blockdevice:
|
|||
self.devnodes[0]])
|
||||
(output, error) = proc.communicate()
|
||||
except OSError, err_msg:
|
||||
LOGGER.warning("Failed to call '%s' to determine label: %s" % \
|
||||
(prefs["Programs"]["blkid"], err_msg))
|
||||
LOGGER.warning("Failed to call '%s' to determine label for " \
|
||||
% prefs["Programs"]["blkid"] + "'%s': %s" % \
|
||||
(self.devnodes[0], err_msg))
|
||||
return None
|
||||
if proc.returncode != 0:
|
||||
LOGGER.warning("Execution of '%s' for '%s' failed: %s" % \
|
||||
(prefs["Programs"]["blkid"], self.devnodes[0],
|
||||
error.strip()))
|
||||
return None
|
||||
result = output.strip()
|
||||
if result:
|
||||
return result
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def __get_type_id(self):
|
||||
"""determine the type id of a filesystem contained in a device
|
||||
|
||||
possible results are: ext2, ext3, vfat, reiserfs, swap, ...
|
||||
return None for errors, empty labels and for luks or non-storage devices
|
||||
"""
|
||||
if not self.is_valid():
|
||||
return None
|
||||
if self.is_luks():
|
||||
return None
|
||||
prefs = _load_preferences()
|
||||
try:
|
||||
proc = subprocess.Popen(
|
||||
shell = False,
|
||||
stdout = subprocess.PIPE,
|
||||
stderr = subprocess.PIPE,
|
||||
args = [ prefs["Programs"]["blkid"],
|
||||
"-s", "TYPE",
|
||||
"-o", "value",
|
||||
"-c", os.devnull,
|
||||
"-w", os.devnull,
|
||||
self.devnodes[0]])
|
||||
(output, error) = proc.communicate()
|
||||
except OSError, err_msg:
|
||||
LOGGER.warning("Failed to call '%s' to determine type id for" \
|
||||
% prefs["Programs"]["blkid"] + " '%s': %s" % \
|
||||
(self.devnodes[0], err_msg))
|
||||
return None
|
||||
if proc.returncode != 0:
|
||||
LOGGER.warning("Execution of '%s' for '%s' failed: %s" % \
|
||||
|
|
|
@ -28,6 +28,7 @@ import os
|
|||
import re
|
||||
import time
|
||||
from cryptobox.core.exceptions import *
|
||||
import cryptobox.core.blockdevice
|
||||
|
||||
|
||||
CONTAINERTYPES = {
|
||||
|
@ -51,8 +52,6 @@ class CryptoBoxContainer:
|
|||
"""Manage a container of the CryptoBox
|
||||
"""
|
||||
|
||||
__dmDir = "/dev/mapper"
|
||||
|
||||
|
||||
def __init__(self, device, cbox):
|
||||
"""initialize the container
|
||||
|
@ -68,7 +67,7 @@ class CryptoBoxContainer:
|
|||
self.mount = None
|
||||
self.umount = None
|
||||
self.attributes = None
|
||||
self.reset_object()
|
||||
self.reset_object(reset_device=False)
|
||||
|
||||
|
||||
def get_name(self):
|
||||
|
@ -205,13 +204,15 @@ class CryptoBoxContainer:
|
|||
return self.device.size
|
||||
|
||||
|
||||
def reset_object(self):
|
||||
def reset_object(self, reset_device=True):
|
||||
"""recheck the information about this container
|
||||
|
||||
this is especially useful after changing the type via 'create'
|
||||
the 'device' attribute does not need to be reset during __init__
|
||||
Available since: 0.3.0
|
||||
"""
|
||||
self.device.reset()
|
||||
if reset_device():
|
||||
self.device.reset()
|
||||
self.uuid = self.__get_uuid()
|
||||
self.cont_type = self.__get_type_of_partition()
|
||||
self.fs_type = self.__get_fs_type()
|
||||
|
@ -243,7 +244,8 @@ class CryptoBoxContainer:
|
|||
## no exception was raised during creation -> we can continue
|
||||
## reset the properties (encryption state, ...) of the device
|
||||
self.reset_object()
|
||||
## restore the old name (must be after reset_object)
|
||||
## restore the old name, as the uuid was changed during 'create'
|
||||
## must happen after reset_object
|
||||
try:
|
||||
self.set_name(old_name)
|
||||
except CBNameIsInUse:
|
||||
|
@ -266,6 +268,7 @@ class CryptoBoxContainer:
|
|||
## return if new and old passwords are the same
|
||||
if oldpw == newpw:
|
||||
return
|
||||
#TODO: why can we do this only for non-mounted volumes?
|
||||
if self.is_mounted():
|
||||
raise CBVolumeIsActive("this container is currently active")
|
||||
## remove any potential open luks mapping
|
||||
|
@ -339,13 +342,18 @@ class CryptoBoxContainer:
|
|||
|
||||
def __get_name_of_container(self):
|
||||
"""retrieve the name of the container by querying the database
|
||||
call this function only for the initial setup of the container object"""
|
||||
call this function only for the initial setup of the container object
|
||||
"""
|
||||
found_name = None
|
||||
for key in self.cbox.prefs.volumes_db.keys():
|
||||
if self.cbox.prefs.volumes_db[key]["uuid"] == self.uuid:
|
||||
found_name = key
|
||||
## the name may not be equal to the name of another existing device
|
||||
## otherwise problems regarding the mount directory would arise
|
||||
if found_name:
|
||||
return found_name
|
||||
test_device = cryptobox.core.blockdevice.get_blockdevice(found_name)
|
||||
if (test_device is None) or (test_device == self.device):
|
||||
return found_name
|
||||
## there is no name defined for this uuid - we will propose a good one
|
||||
prefix = self.cbox.prefs["Main"]["DefaultVolumePrefix"]
|
||||
unused_found = False
|
||||
|
@ -388,62 +396,32 @@ class CryptoBoxContainer:
|
|||
|
||||
def __get_type_id_of_partition(self):
|
||||
"returns the type of the partition (see 'man blkid')"
|
||||
proc = subprocess.Popen(
|
||||
shell = False,
|
||||
stdout = subprocess.PIPE,
|
||||
stderr = subprocess.PIPE,
|
||||
args = [ self.cbox.prefs["Programs"]["blkid"],
|
||||
"-s", "TYPE",
|
||||
"-o", "value",
|
||||
"-c", os.devnull,
|
||||
"-w", os.devnull,
|
||||
self.get_device() ])
|
||||
(stdout, stderr) = proc.communicate()
|
||||
if proc.returncode == 0:
|
||||
## we found a uuid
|
||||
return stdout.strip()
|
||||
elif proc.returncode == 2:
|
||||
## failed to find the attribute - no problem
|
||||
return None
|
||||
else:
|
||||
## something strange happened
|
||||
self.cbox.log.warn("retrieving of partition type via 'blkid' failed: %s" % \
|
||||
(stderr.strip(), ))
|
||||
return None
|
||||
return self.device.type_id
|
||||
|
||||
|
||||
def __get_fs_type(self):
|
||||
"returns the filesystem used on a container"
|
||||
## should we handle device mapping or plain device
|
||||
if self.device.is_luks() and self.name:
|
||||
#TODO: replace this by self.device.holders ...
|
||||
container = os.path.join(self.__dmDir, self.name)
|
||||
## can't determine fs while encrypted
|
||||
if not self.is_mounted():
|
||||
return "unavailable"
|
||||
"""returns the filesystem used on a container
|
||||
|
||||
for luks devices: return the type of the encrypted container
|
||||
return None for invalid device, for non-storage devices, ...
|
||||
"""
|
||||
if self.device.is_luks():
|
||||
## luks devices need special care ...
|
||||
if self.device.holders:
|
||||
return cryptobox.core.blockdevice.get_blockdevice(
|
||||
self.device.holders[0]).type_id
|
||||
else:
|
||||
## the encrypted container is not open
|
||||
return None
|
||||
else:
|
||||
container = self.get_device()
|
||||
proc = subprocess.Popen(
|
||||
shell = False,
|
||||
stdout = subprocess.PIPE,
|
||||
stderr = subprocess.PIPE,
|
||||
args = [ self.cbox.prefs["Programs"]["blkid"],
|
||||
"-s","TYPE",
|
||||
container ])
|
||||
(stdout, stderr) = proc.communicate()
|
||||
if proc.returncode == 0:
|
||||
return stdout.split("TYPE=")[1]
|
||||
else:
|
||||
## if something goes wrong don't dig deeper
|
||||
self.cbox.log.warn("Filesystem determination (%s) failed: %s" % \
|
||||
(self.get_device(), stderr.strip()))
|
||||
return "undetermined"
|
||||
return
|
||||
## common (non-luks) devices
|
||||
return self.device.type_id
|
||||
|
||||
|
||||
def __get_mount_point(self):
|
||||
"return the name of the mountpoint of this volume"
|
||||
return os.path.join(self.cbox.prefs["Locations"]["MountParentDir"], self.name)
|
||||
return os.path.join(self.cbox.prefs["Locations"]["MountParentDir"],
|
||||
self.name)
|
||||
|
||||
|
||||
def __mount_luks(self, password):
|
||||
|
@ -457,10 +435,12 @@ class CryptoBoxContainer:
|
|||
if not os.path.exists(self.__get_mount_point()):
|
||||
self.__create_mount_directory(self.__get_mount_point())
|
||||
if not os.path.exists(self.__get_mount_point()):
|
||||
err_msg = "Could not create mountpoint (%s)" % (self.__get_mount_point(), )
|
||||
err_msg = "Could not create mountpoint (%s)" % \
|
||||
(self.__get_mount_point(), )
|
||||
self.cbox.log.error(err_msg)
|
||||
raise CBMountError(err_msg)
|
||||
self.cbox.send_event_notification("premount", self.__get_event_args())
|
||||
self.cbox.send_event_notification("premount",
|
||||
self.__get_event_args())
|
||||
proc = subprocess.Popen(
|
||||
shell = False,
|
||||
stdin = subprocess.PIPE,
|
||||
|
@ -480,6 +460,17 @@ class CryptoBoxContainer:
|
|||
err_msg = "Could not open the luks mapping: %s" % (errout.strip(), )
|
||||
self.cbox.log.warn(err_msg)
|
||||
raise CBMountError(err_msg)
|
||||
## reset device info (reread self.device.holders)
|
||||
self.device.reset()
|
||||
if self.device.holders:
|
||||
## the decrypted blockdevice is available
|
||||
plain_device = cryptobox.core.blockdevice.get_blockdevice(
|
||||
self.device.holders[0]).devnodes[0]
|
||||
else:
|
||||
err_msg = "Could not find the plaintext container for " \
|
||||
+ "'%s': %s" % (self.get_device(), "no hold devices found")
|
||||
self.cbox.log.warn(err_msg)
|
||||
raise CBMountError(err_msg)
|
||||
proc = subprocess.Popen(
|
||||
shell = False,
|
||||
stdin = None,
|
||||
|
@ -489,20 +480,23 @@ class CryptoBoxContainer:
|
|||
self.cbox.prefs["Programs"]["super"],
|
||||
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||
"program", "mount",
|
||||
os.path.join(self.__dmDir, self.name),
|
||||
plain_device,
|
||||
self.__get_mount_point()])
|
||||
proc.wait()
|
||||
if proc.returncode != 0:
|
||||
err_msg = "Could not mount the filesystem: %s" % (proc.stderr.read().strip(), )
|
||||
err_msg = "Could not mount the filesystem: %s" \
|
||||
% (proc.stderr.read().strip(), )
|
||||
self.cbox.log.warn(err_msg)
|
||||
raise CBMountError(err_msg)
|
||||
## chmod the mount directory to 0777 - this is the easy way to avoid problems
|
||||
## this only works for ext2/3 - vfat silently ignore it
|
||||
## chmod the mount directory to 0777
|
||||
## this is the easy way to avoid problems
|
||||
## it only works for ext2/3 - vfat silently ignore it
|
||||
## we mounted vfat partitions with umask=0000
|
||||
try:
|
||||
os.chmod(self.__get_mount_point(), 0777)
|
||||
except OSError:
|
||||
self.cbox.log.warn("Failed to set write permission for the mount directory")
|
||||
self.cbox.log.warn("Failed to set write permission for the " \
|
||||
+ "mount directory")
|
||||
self.cbox.send_event_notification("postmount", self.__get_event_args())
|
||||
|
||||
|
||||
|
@ -522,10 +516,14 @@ class CryptoBoxContainer:
|
|||
self.__get_mount_point()])
|
||||
proc.wait()
|
||||
if proc.returncode != 0:
|
||||
err_msg = "Could not umount the filesystem: %s" % (proc.stderr.read().strip(), )
|
||||
err_msg = "Could not umount the filesystem: %s" % \
|
||||
(proc.stderr.read().strip(), )
|
||||
self.cbox.log.warn(err_msg)
|
||||
raise CBUmountError(err_msg)
|
||||
if os.path.exists(os.path.join(self.__dmDir, self.name)):
|
||||
## reset device (reread self.device.holders)
|
||||
self.device.reset()
|
||||
## are there any dependent devices?
|
||||
if self.device.holders:
|
||||
proc = subprocess.Popen(
|
||||
shell = False,
|
||||
stdin = None,
|
||||
|
@ -574,8 +572,9 @@ class CryptoBoxContainer:
|
|||
err_msg = "Could not mount the filesystem: %s" % (proc.stderr.read().strip(), )
|
||||
self.cbox.log.warn(err_msg)
|
||||
raise CBMountError(err_msg)
|
||||
## chmod the mount directory to 0777 - this is the easy way to avoid problems
|
||||
## this only works for ext2/3 - vfat silently ignore it
|
||||
## chmod the mount directory to 0777
|
||||
## this is the easy way to avoid problems
|
||||
## it only works for ext2/3 - vfat silently ignore it
|
||||
## we mounted vfat partitions with umask=0000
|
||||
try:
|
||||
os.chmod(self.__get_mount_point(), 0777)
|
||||
|
@ -712,8 +711,19 @@ class CryptoBoxContainer:
|
|||
err_msg = "Could not open the new luks mapping: %s" % (errout.strip(), )
|
||||
self.cbox.log.error(err_msg)
|
||||
raise CBCreateError(err_msg)
|
||||
## reset device info (reread self.device.holders)
|
||||
self.device.reset()
|
||||
if self.device.holders:
|
||||
## the decrypted blockdevice is available
|
||||
plain_device = cryptobox.core.blockdevice.get_blockdevice(
|
||||
self.device.holders[0]).devnodes[0]
|
||||
else:
|
||||
err_msg = "Could not find the plaintext container for " \
|
||||
+ "'%s': %s" % (self.get_device(), "no hold devices found")
|
||||
self.cbox.log.warn(err_msg)
|
||||
raise CBMountError(err_msg)
|
||||
def format_luks():
|
||||
"""This function will get called as a seperate thread.
|
||||
"""This function will get called as a separate thread.
|
||||
|
||||
To avoid the non-sharing cpu distribution between the formatting thread
|
||||
and the main interface, we fork and let the parent wait for the child.
|
||||
|
@ -735,7 +745,7 @@ class CryptoBoxContainer:
|
|||
self.cbox.prefs["Programs"]["nice"],
|
||||
self.cbox.prefs["Programs"]["mkfs"],
|
||||
"-t", fs_type,
|
||||
os.path.join(self.__dmDir, self.name)])
|
||||
plain_device ] )
|
||||
loc_data.proc.wait()
|
||||
## wait to allow error detection
|
||||
if loc_data.proc.returncode == 0:
|
||||
|
@ -767,15 +777,16 @@ class CryptoBoxContainer:
|
|||
if (not os.path.islink(abs_dir)) \
|
||||
and os.path.isdir(abs_dir) \
|
||||
and (not os.path.ismount(abs_dir)) \
|
||||
and (os.path.isfile(os.path.join(abs_dir,MOUNT_DIR_MARKER))) \
|
||||
and (os.path.isfile(os.path.join(abs_dir,
|
||||
MOUNT_DIR_MARKER))) \
|
||||
and (len(os.listdir(abs_dir)) == 1):
|
||||
try:
|
||||
os.remove(os.path.join(abs_dir, MOUNT_DIR_MARKER))
|
||||
os.rmdir(abs_dir)
|
||||
except OSError, err_msg:
|
||||
## we do not care too much about unclean cleaning ...
|
||||
self.cbox.log.info("failed to clean a mountpoint (%s): %s" % \
|
||||
(abs_dir, str(err_msg)))
|
||||
self.cbox.log.info("failed to clean a mountpoint (%s): %s" \
|
||||
% (abs_dir, str(err_msg)))
|
||||
|
||||
|
||||
def __create_mount_directory(self, dirname):
|
||||
|
@ -787,7 +798,8 @@ class CryptoBoxContainer:
|
|||
mark_file.close()
|
||||
except OSError, err_msg:
|
||||
## we do not care too much about the marking
|
||||
self.cbox.log.info("failed to mark a mountpoint (%s): %s" % (dirname, str(err_msg)))
|
||||
self.cbox.log.info("failed to mark a mountpoint (%s): %s" % \
|
||||
(dirname, str(err_msg)))
|
||||
|
||||
|
||||
def __get_event_args(self):
|
||||
|
@ -797,5 +809,6 @@ class CryptoBoxContainer:
|
|||
"""
|
||||
type_text = [e for e in CONTAINERTYPES.keys()
|
||||
if CONTAINERTYPES[e] == self.get_type()][0]
|
||||
return [self.get_device(), self.get_name(), type_text, self.__get_mount_point()]
|
||||
return [self.get_device(), self.get_name(), type_text,
|
||||
self.__get_mount_point()]
|
||||
|
||||
|
|
Loading…
Reference in a new issue