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:
parent
8e7f0b16a7
commit
1de2ebe176
9 changed files with 92 additions and 62 deletions
|
@ -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()
|
||||
|
||||
|
|
|
@ -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
7
debian/changelog
vendored
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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 ?>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -10,5 +10,5 @@ __all__ = ['core', 'web', 'plugins', 'tests']
|
|||
__revision__ = "$Id$"
|
||||
|
||||
|
||||
__version__ = "0.3.3"
|
||||
__version__ = "0.3.4"
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue