make blkid more verbose

fix permission problem during bootup (Closes: #139)
add support for partitioning of blockdevices ending in a digit (e.g. raid (md) devices)
added fieldset to partition plugin
This commit is contained in:
lars 2007-02-19 01:22:31 +00:00
parent 8e7f0b16a7
commit 1de2ebe176
9 changed files with 92 additions and 62 deletions

View file

@ -30,6 +30,7 @@ REMOVE_ENV_SETTINGS = [ "LANG", "LC", "LC_ALL", "LC_COLLATE", "LC_CTYPE",
"LC_MESSAGES", "LC_NUMERIC", "BASH_ENV", "SHELLOPTS" ]
import os, sys
import signal, atexit
import cryptobox.web.sites
from cryptobox.core.exceptions import *
from optparse import OptionParser
@ -66,13 +67,14 @@ except:
sys.exit(1)
# TODO: change this for the release version [development|production]
SERVER_ENVIRONMENT = "production"
class CryptoBoxWebserver:
'''this class starts the cherrypy webserver and serves the single sites'''
def __init__(self, opts):
"""Configure cherrypy and check the location of the configuration file
"""
self.opts = opts
## check conffile
if not os.access(opts.conffile, os.R_OK) or not os.path.isfile(opts.conffile):
@ -98,18 +100,16 @@ class CryptoBoxWebserver:
"staticFilter.on" : True,
"staticFilter.file": os.path.realpath(os.path.join(opts.datadir, 'favicon.ico'))}
})
## drop privileges to run the cryptobox without root permissions
self.drop_privileges_temporarily()
def bootup_cryptobox(self):
## initialize site class
try:
cherrypy.root = cryptobox.web.sites.WebInterfaceSites(self.conffile)
self.website = cherrypy.root
except (CBConfigError,CBEnvironmentError), err_msg:
sys.stderr.write("Error: the CryptoBox is misconfigured - please fix it!\n")
sys.stderr.write("%s\n" % str(err_msg))
sys.exit(1)
## restore privileges, as we need them to connect to a low socket (<1024)
self.restore_privileges()
raise
def get_user_info(self):
@ -132,31 +132,6 @@ class CryptoBoxWebserver:
return (pw_uid, pw_gid, additional_groups)
def drop_privileges_temporarily(self):
"""Temporarily drop privileges.
"""
if self.opts.user is None:
return
(pw_uid, pw_gid, additional_groups) = self.get_user_info()
try:
os.setegid(pw_gid)
os.seteuid(pw_uid)
except OSError, err_msg:
sys.stderr.write("Failed to drop privileges temporarily: %s\n" % err_msg)
def restore_privileges(self):
"""Restore previously temporarily dropped privileges.
"""
if self.opts.user is None:
return
try:
os.setegid(os.getgid())
os.seteuid(os.getuid())
except OSError, err_msg:
sys.stderr.write("Failed to restore privileges: %s\n" % err_msg)
def change_groups(self):
"""Change the groups of the current process to the ones of the given user
@ -191,10 +166,13 @@ class CryptoBoxWebserver:
def start(self):
try:
## first: change the groups (cherrypy.server.start stores the
## current setting for creating new threads later
## current setting for creating new threads later)
self.change_groups()
cherrypy.server.start(initOnly=True)
self.drop_privileges_permanently()
## this must be done with dropped privileges - otherwise there is
## at least a problem with 'blkid' - see bug #139
self.bootup_cryptobox()
cherrypy.server.wait_for_http_ready()
except cherrypy._cperror.NotReady, err_msg:
sys.stderr.write("Failed to start CryptoBox: %s\n" % err_msg)
@ -357,13 +335,29 @@ if __name__ == "__main__":
options = parseOptions()
## set umask to 022 (aka 755) - octal value
os.umask(022)
## initialize the webserver class (before forking to get some error messages)
## initialize the webserver class
cbw = CryptoBoxWebserver(options)
## remove some environment settings
clean_environment(REMOVE_ENV_SETTINGS)
## fork to background before cbw.start() - otherwise we lose the socket
if options.background:
fork_to_background()
## define the default exit handler
def exit_handler(signum, sigframe):
if hasattr(cbw, "website"):
## are we already up?
cbw.website.cbox.log.info("Shutting down ...")
cbw.website.cleanup()
cherrypy.server.stop()
try:
os.remove(options.pidfile)
except OSError:
pass
os._exit(0)
## the signal handler gets called by a kill signal (usually in background mode)
signal.signal(signal.SIGTERM, exit_handler)
## this exit handler gets called by KeyboardInterrupt and similar ones (foreground)
atexit.register(exit_handler, None, None)
## start the webserver
try:
if options.profile_file:
@ -375,6 +369,7 @@ if __name__ == "__main__":
sys.stderr.write("Failed to start the CryptoBox webserver!\n")
sys.stderr.write("%s\n" % str(err_msg))
sys.stderr.write("Check the log file for details.\n")
cherrypy.server.stop()
sys.exit(1)
## redirect stderr to the webserver's logfile
if options.background:
@ -384,22 +379,7 @@ if __name__ == "__main__":
os.close(2)
os.open(options.logfile, os.O_APPEND)
## startup went fine - fork is done - now we may write the pid file
## write pid file
write_pid_file(options.pidfile)
def exit_handler(signum, sigframe):
cbw.website.cbox.log.info("Shutting down ...")
cbw.website.cleanup()
try:
os.remove(options.pidfile)
except OSError:
pass
os._exit(0)
## the signal handler gets called by a kill signal (usually in background mode)
import signal
signal.signal(signal.SIGTERM, exit_handler)
## this exit handler gets called by KeyboardInterrupt and similar ones (foreground)
import atexit
atexit.register(exit_handler, None, None)
## this will never exit - one of the above exit handlers will get triggered
cherrypy.server.block()

View file

@ -2,7 +2,7 @@
# comma separated list of possible prefixes for accesible devices
# beware: .e.g "/dev/hd" grants access to _all_ harddisks
AllowedDevices = /dev/loop, /dev/ubdb
AllowedDevices = /dev/loop, /dev/ubdb, /dev/md_d127
# use separate config partition? (1=yes / 0=no)
UseConfigPartition = 1

7
debian/changelog vendored
View file

@ -1,3 +1,10 @@
cryptobox (0.3.4-1) unstable; urgency=low
* fixed uid handling during bootup (Closes: '139)
* added support for partitioning of raid devices
-- Lars Kruse <devel@sumpfralle.de> Sat, 17 Feb 2007 11:03:41 +0100
cryptobox (0.3.3-1) unstable; urgency=low
* new upstream release

View file

@ -25,6 +25,7 @@ __revision__ = "$Id"
import subprocess
import os
import re
import logging
import cryptobox.core.tools as cbox_tools
import cryptobox.plugins.base
@ -53,7 +54,6 @@ class partition(cryptobox.plugins.base.CryptoBoxPlugin):
def do_action(self, **args):
"""Show the partitioning form and execute the requested action.
"""
import re
## load default hdf values
self.__prepare_dataset()
## retrieve some values from 'args' - defaults are empty
@ -455,14 +455,14 @@ class partition(cryptobox.plugins.base.CryptoBoxPlugin):
part_num = 1
## maybe a config partition?
if self.with_config_partition:
dev_name = self.blockdevice + str(part_num)
dev_name = self.__get_partition_name(self.blockdevice, part_num)
self.cbox.log.info("formatting config partition (%s)" % dev_name)
if self.__format_one_partition(dev_name, CONFIGPARTITION["fs"]):
self.__set_label_of_partition(dev_name,
self.cbox.prefs["Main"]["ConfigVolumeLabel"])
part_num += 1
## the first data partition
dev_name = self.blockdevice + str(part_num)
dev_name = self.__get_partition_name(self.blockdevice, part_num)
part_type = PARTTYPES[parts[0]["type"]][1]
self.cbox.log.info("formatting partition (%s) as '%s'" % (dev_name, part_type))
yield self.__format_one_partition(dev_name, part_type)
@ -470,7 +470,7 @@ class partition(cryptobox.plugins.base.CryptoBoxPlugin):
## other data partitions
part_num = 5
while parts:
dev_name = self.blockdevice + str(part_num)
dev_name = self.__get_partition_name(self.blockdevice, part_num)
part_type = PARTTYPES[parts[0]["type"]][1]
self.cbox.log.info("formatting partition (%s) as '%s'" % \
(dev_name, part_type))
@ -478,6 +478,21 @@ class partition(cryptobox.plugins.base.CryptoBoxPlugin):
part_num += 1
del parts[0]
return
def __get_partition_name(self, blockdev, number):
"""Return the name of a specific partition of a device
"""
## do we need to put a "p" between name and number?
## TODO: should we check for existence?
if re.search("[0-9]$", blockdev):
## blockdev endswith a digit - we need a 'p'
return "%sp%d" % (blockdev, number)
else:
## no 'p' necessary
return "%s%d" % (blockdev, number)
def __format_one_partition(self, dev_name, fs_type):

View file

@ -1,8 +1,13 @@
<?cs # $Id$ ?>
<?cs call:show_plugin_title() ?>
<?cs call:handle_messages() ?>
<fieldset>
<legend>
<?cs call:show_plugin_icon() ?>
<?cs var:html_escape(Lang.Plugins.partition.Title) ?>
</legend>
<?cs call:show_help(Lang.Plugins.partition.Help.Partitioning) ?>
<?cs if:subcount(Data.Plugins.partition.BlockDevices) > 0 ?>
@ -38,5 +43,7 @@
<?cs /if ?>
</fieldset>
<?cs # a warning will be displayed if there are no disks available ?>

View file

@ -1,8 +1,13 @@
<?cs # $Id$ ?>
<?cs call:show_plugin_title() ?>
<?cs call:handle_messages() ?>
<fieldset>
<legend>
<?cs call:show_plugin_icon() ?>
<?cs var:html_escape(Lang.Plugins.partition.Title) ?>
</legend>
<?cs # show nothing if the harddisk is not partitionable (e.g. still active) ?>
<?cs if:(Data.Plugins.partition.availSize > 0) || (subcount(Data.Plugins.partition.Parts) > 0) ?>
@ -94,3 +99,5 @@
<?cs /if ?>
</fieldset>

View file

@ -10,5 +10,5 @@ __all__ = ['core', 'web', 'plugins', 'tests']
__revision__ = "$Id$"
__version__ = "0.3.3"
__version__ = "0.3.4"

View file

@ -253,18 +253,30 @@ class CryptoBoxSettings:
def get_available_partitions(self):
"""returns a sequence of found config partitions"""
self.log.debug("Retrieving available configuration partitions ...")
proc = subprocess.Popen(
shell = False,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
args = [
self.prefs["Programs"]["blkid"],
"-c", os.path.devnull,
"-t", "LABEL=%s" % self.prefs["Main"]["ConfigVolumeLabel"] ])
(output, error) = proc.communicate()
if output:
return [e.strip().split(":", 1)[0] for e in output.splitlines()]
else:
if proc.returncode == 2:
self.log.info("No configuration partitions found")
return []
elif proc.returncode == 4:
self.log.warn("Failed to call 'blkid' for unknown reasons.")
return []
elif proc.returncode == 0:
if output:
return [e.strip().split(":", 1)[0] for e in output.splitlines()]
else:
return []
else:
self.log.warn("Unknown exit code of 'blkid': %d - %s" \
% (proc.returncode, error))
def prepare_partition(self):

View file

@ -46,10 +46,12 @@ def get_available_partitions():
## ignore lines with: invalid minor/major or extend partitions (size=1)
if re.search('^[0-9]*$', p_major) and \
re.search('^[0-9]*$', p_minor) and (p_size != "1"):
p_parent = re.sub('[1-9]?[0-9]$', '', p_device)
## for some parent devices we have to remove a 'p' (partition)
## an example are partitionable mdadm raid devices (e.g. md1p1)
p_parent = re.sub('p?[1-9]?[0-9]$', '', p_device)
if p_parent == p_device:
if [e for e in ret_list
if re.search('^' + p_parent + '[1-9]?[0-9]$', e)]:
if re.search('^' + p_parent + 'p?[1-9]?[0-9]$', e)]:
## major partition - its children are already in the list
pass
else: