added setup.py to use distutils for packaging
moved python modules to separate packages below src/ renamed "hook" to "event" to avoid confusionmaster
parent
a66e5d3512
commit
112979b3af
@ -0,0 +1,8 @@
|
||||
include README
|
||||
graft www-data
|
||||
#graft www-data/screenshots
|
||||
graft templates
|
||||
graft lang
|
||||
graft plugins
|
||||
prune commit.log
|
||||
prune package.exclude
|
@ -0,0 +1,173 @@
|
||||
#!/usr/bin/python2.4
|
||||
|
||||
import os, sys
|
||||
import cryptobox.web.sites
|
||||
from cryptobox.core.exceptions import *
|
||||
from optparse import OptionParser
|
||||
|
||||
try:
|
||||
import cherrypy
|
||||
except:
|
||||
print "Could not import the cherrypy module! Try 'apt-get install python-cherrypy'."
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
# TODO: change this for the release version
|
||||
SERVER_ENVIRONMENT = "development"
|
||||
|
||||
class CryptoBoxWebserver:
|
||||
'''this class starts the cherryp webserver and serves the single sites'''
|
||||
|
||||
def __init__(self, opts):
|
||||
## check conffile
|
||||
if not os.access(opts.conffile, os.R_OK) or not os.path.isfile(opts.conffile):
|
||||
sys.stderr.write("Error: could not read configuration file (%s)\n" % opts.conffile)
|
||||
sys.exit(1)
|
||||
## store the absolute path as we will chdir later (for daemons)
|
||||
self.conffile = os.path.realpath(opts.conffile)
|
||||
## initialize site class
|
||||
try:
|
||||
cherrypy.root = cryptobox.web.sites.WebInterfaceSites(self.conffile)
|
||||
except (CBConfigError,CBEnvironmentError), errMsg:
|
||||
sys.stderr.write("Error: the CryptoBox is misconfigured - please fix it!\n")
|
||||
sys.stderr.write("%s\n" % str(errMsg))
|
||||
sys.exit(1)
|
||||
#expose static content:
|
||||
#I currently have no idea how to cleanly extract the stylesheet path from
|
||||
#the config object without an extra cryptobox.core.main.CryptoBoxProps instance.
|
||||
#perhaps put config handling into a separate class in CryptoBox.py?
|
||||
#
|
||||
# the following manual mapping is necessary, as we may not use relative
|
||||
# paths in the config file
|
||||
cherrypy.config.update({
|
||||
"global": {
|
||||
"server.socket_port" : int(opts.port),
|
||||
"server.socket_host" : opts.host,
|
||||
"server.log_to_screen" : not opts.background and opts.verbose,
|
||||
"server.log_tracebacks" : opts.verbose,
|
||||
"server.environment": SERVER_ENVIRONMENT,
|
||||
"server.log_file" : opts.logfile },
|
||||
"/cryptobox-misc": {
|
||||
"staticFilter.on" : True,
|
||||
"staticFilter.dir": os.path.realpath(opts.datadir)}
|
||||
})
|
||||
|
||||
def start(self):
|
||||
cherrypy.server.start()
|
||||
|
||||
|
||||
def fork_to_background():
|
||||
## this is just copy'n'pasted from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/278731
|
||||
## check the original for exhaustive comments
|
||||
try:
|
||||
pid = os.fork()
|
||||
except OSError, errMsg:
|
||||
sys.stderr.write("Error: failed to fork cryptobox daemon process!\n")
|
||||
sys.stderr.write("%s\n" % errMsg)
|
||||
sys.exit(1)
|
||||
if pid == 0: # the first child
|
||||
os.setsid()
|
||||
try:
|
||||
pid = os.fork()
|
||||
except OSError, errMsg:
|
||||
sys.stderr.write("Error: failed to fork second cryptobox daemon process!\n")
|
||||
sys.stderr.write("%s\n" % errMsg)
|
||||
sys.exit(1)
|
||||
if pid == 0: # the second child
|
||||
## we do not change the directory - otherwise there seems to be a race condition with the python interpreter loading this script file
|
||||
#os.chdir(os.path.sep)
|
||||
os.umask(0)
|
||||
else:
|
||||
os._exit(0)
|
||||
else:
|
||||
os._exit(0)
|
||||
|
||||
|
||||
def close_open_files():
|
||||
"""this is only necessary if we want to go into background"""
|
||||
import resource # Resource usage information.
|
||||
maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
|
||||
if (maxfd == resource.RLIM_INFINITY):
|
||||
maxfd = 1024
|
||||
for fd in range(0, maxfd):
|
||||
try:
|
||||
os.close(fd)
|
||||
except OSError: # ERROR, fd wasn't open to begin with (ignored)
|
||||
pass
|
||||
os.open(os.devnull, os.O_RDWR) # standard input (0)
|
||||
os.dup2(0, 1) # standard output (1)
|
||||
os.dup2(0, 2) # standard error (2)
|
||||
|
||||
|
||||
def write_pid_file(pid_file):
|
||||
try:
|
||||
pidf = open(pid_file,"w")
|
||||
pidf.write(str(os.getpid()))
|
||||
pidf.close()
|
||||
except (IOError, OSError), errMsg:
|
||||
sys.stderr.write("Warning: failed to write pid file (%s): %s\n" % (pid_file, errMsg))
|
||||
## it is just a warning - no need to break
|
||||
|
||||
|
||||
def parseOptions():
|
||||
version = "%prog" + cryptobox.core.main.VERSION
|
||||
parser = OptionParser(version=version)
|
||||
parser.set_defaults(conffile="/etc/cryptobox/webserver.conf",
|
||||
pidfile="/var/run/cryptobox/webserver.pid",
|
||||
background=False,
|
||||
datadir="/usr/share/cryptobox/html",
|
||||
logfile="/var/log/cryptobox/webserver.log",
|
||||
port="8080",
|
||||
host="",
|
||||
verbose=True)
|
||||
parser.add_option("-c", "--config", dest="conffile",
|
||||
help="read configuration from FILE", metavar="FILE")
|
||||
parser.add_option("","--pidfile", dest="pidfile",
|
||||
help="write process id to FILE", metavar="FILE")
|
||||
parser.add_option("-B","", dest="background", action="store_true",
|
||||
help="run webserver in background (as daemon)")
|
||||
parser.add_option("-q","", dest="verbose", action="store_false",
|
||||
help="output only errors")
|
||||
parser.add_option("","--datadir", dest="datadir", metavar="DIR",
|
||||
help="set data directory to DIR")
|
||||
parser.add_option("-p","--port", dest="port", metavar="PORT",
|
||||
help="listen on PORT")
|
||||
parser.add_option("-l","--logfile", dest="logfile", metavar="FILE",
|
||||
help="write webserver log to FILE")
|
||||
parser.add_option("","--host", dest="host", metavar="HOST",
|
||||
help="attach to HOST")
|
||||
(options, args) = parser.parse_args()
|
||||
## we do not expect any remaining arguments
|
||||
if len(args) != 0:
|
||||
parser.error("unknown argument: %s" % str(args[0]))
|
||||
if not os.path.isdir(options.datadir) or not os.access(options.datadir,os.X_OK):
|
||||
parser.error("could not access the data directory (%s)" % options.datadir)
|
||||
try:
|
||||
if (int(options.port) < 0) or (int(options.port) > 65535):
|
||||
parser.error("invalid port number: %s" % str(options.port))
|
||||
except ValueError:
|
||||
parser.error("invalid port specified (%s) - it must be a number" % (options.port))
|
||||
return options
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
## process arguments
|
||||
options = parseOptions()
|
||||
## initialize the webserver class (before forking to get some error messages)
|
||||
cbw = CryptoBoxWebserver(options)
|
||||
## run the webserver as a daemon process
|
||||
if options.background: fork_to_background()
|
||||
## write pid file
|
||||
write_pid_file(options.pidfile)
|
||||
## close open files to allow background execution
|
||||
if options.background: close_open_files()
|
||||
## start the webserver
|
||||
try:
|
||||
cbw.start()
|
||||
except CBError, errMsg:
|
||||
sys.stderr.write("Failed to start the CryptoBox webserver!\n")
|
||||
sys.stderr.write("%s\n" % str(errMsg))
|
||||
sys.stderr.write("Check the log file for details.\n")
|
||||
sys.exit(1)
|
||||
sys.exit(0)
|
||||
|
@ -1,110 +0,0 @@
|
||||
#!/usr/bin/python2.4
|
||||
import os
|
||||
import WebInterfaceSites
|
||||
from CryptoBoxExceptions import *
|
||||
import sys
|
||||
|
||||
try:
|
||||
import cherrypy
|
||||
except:
|
||||
print "Could not import the cherrypy module! Try 'apt-get install python-cherrypy'."
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
|
||||
## TODO: it should be possible to override this via commandline arguments
|
||||
PID_FILE = '/var/run/cryptobox/webserver.pid'
|
||||
|
||||
class CryptoBoxWebserver:
|
||||
'''this class starts the cherryp webserver and serves the single sites'''
|
||||
|
||||
def __init__(self):
|
||||
try:
|
||||
cherrypy.root = WebInterfaceSites.WebInterfaceSites()
|
||||
except (CBConfigError,CBEnvironmentError), errMsg:
|
||||
sys.stderr.write("The CryptoBox is misconfigured - please fix it!\n")
|
||||
sys.stderr.write("%s\n" % str(errMsg))
|
||||
sys.exit(1)
|
||||
#expose static content:
|
||||
#I currently have no idea how to cleanly extract the stylesheet path from
|
||||
#the config object without an extra CryptoBox.CryptoBoxProps instance.
|
||||
#perhaps put config handling into a separate class in CryptoBox.py?
|
||||
#
|
||||
# the following manual mapping is necessary, as we may not use relative
|
||||
# paths in the config file
|
||||
cherrypy.config.configMap.update({
|
||||
"/cryptobox-misc": {
|
||||
"staticFilter.on" : True,
|
||||
"staticFilter.dir": os.path.abspath("/usr/share/cryptobox/html" )}
|
||||
})
|
||||
|
||||
def start(self):
|
||||
# just use this config, when we're started directly
|
||||
cherrypy.config.update(file = "/etc/cryptobox/cryptoboxwebserver.conf")
|
||||
cherrypy.server.start()
|
||||
|
||||
|
||||
def fork_to_background():
|
||||
## this is just copy'n'pasted from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/278731
|
||||
## check the original for exhaustive comments
|
||||
try:
|
||||
pid = os.fork()
|
||||
except OSError, errMsg:
|
||||
sys.stderr.write("Failed to fork cryptobox daemon process!\n")
|
||||
sys.stderr.write("%s\n" % errMsg)
|
||||
sys.exit(1)
|
||||
if pid == 0: # the first child
|
||||
os.setsid()
|
||||
try:
|
||||
pid = os.fork()
|
||||
except OSError, errMsg:
|
||||
sys.stderr.write("Failed to fork second cryptobox daemon process!\n")
|
||||
sys.stderr.write("%s\n" % errMsg)
|
||||
sys.exit(1)
|
||||
if pid == 0: # the second child
|
||||
os.chdir(os.path.sep)
|
||||
os.umask(0)
|
||||
else:
|
||||
os._exit(0)
|
||||
else:
|
||||
os._exit(0)
|
||||
import resource # Resource usage information.
|
||||
maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
|
||||
if (maxfd == resource.RLIM_INFINITY):
|
||||
maxfd = 1024
|
||||
for fd in range(0, maxfd):
|
||||
try:
|
||||
os.close(fd)
|
||||
except OSError: # ERROR, fd wasn't open to begin with (ignored)
|
||||
pass
|
||||
os.open(os.devnull, os.O_RDWR) # standard input (0)
|
||||
os.dup2(0, 1) # standard output (1)
|
||||
os.dup2(0, 2) # standard error (2)
|
||||
|
||||
|
||||
def write_pid_file(pid_file):
|
||||
try:
|
||||
pidf = open(pid_file,"w")
|
||||
pidf.write(str(os.getpid()))
|
||||
pidf.close()
|
||||
except (IOError, OSError), errMsg:
|
||||
sys.stderr.write("Failed to write pid file (%s): %s\n" % (pid_file, errMsg))
|
||||
## it is just a warning - no need to break
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
## TODO: add some argument checking: configFile, daemonMode, ...
|
||||
cbw = CryptoBoxWebserver()
|
||||
## run the webserver as a daemon process
|
||||
fork_to_background()
|
||||
## write pid file
|
||||
write_pid_file(PID_FILE)
|
||||
try:
|
||||
cbw.start()
|
||||
except Exceptions, errMsg:
|
||||
sys.stderr.write("Failed to start the CryptoBox webserver!\n")
|
||||
sys.stderr.write("%s\n" % str(errMsg))
|
||||
sys.stderr.write("Check the log file for details.\n")
|
||||
sys.exit(1)
|
||||
sys.exit(0)
|
||||
|
@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# example start script to run a local cryptobox webserver
|
||||
#
|
||||
# we set some en
|
||||
#
|
||||
|
||||
BIN_DIR=$(dirname "$0")
|
||||
|
||||
## add the local python directory to the search path
|
||||
export PYTHONPATH="$BIN_DIR/../src"
|
||||
|
||||
## run the webserver
|
||||
"$BIN_DIR/CryptoBoxWebserver" --config="$BIN_DIR/cryptobox.conf" --pidfile=/tmp/cryptoboxwebserver.pid --logfile=/tmp/cryptoboxwebser.log --port=8080 --datadir="$BIN_DIR/../www-data" "$@"
|
||||
|
@ -1,116 +0,0 @@
|
||||
#!/usr/bin/env python2.4
|
||||
|
||||
"""
|
||||
BEWARE: this script may overwrite the data of one of your loop devices. You
|
||||
should restrict the AllowedDevices directive in cryptobox.conf to exclude
|
||||
your precious black devices from being used by this script.
|
||||
|
||||
the following script runs a number of tests for different parts
|
||||
"""
|
||||
|
||||
from CryptoBox import CryptoBoxProps
|
||||
from CryptoBoxContainer import CryptoBoxContainer
|
||||
import sys
|
||||
|
||||
|
||||
def main():
|
||||
cb = CryptoBoxProps()
|
||||
|
||||
print "Confguration:"
|
||||
print "\tConfig file:\t\t%s" % (cb.prefs.prefs.filename, )
|
||||
print "\tAllowed devices:\t%s" % (cb.prefs["Main"]["AllowedDevices"], )
|
||||
|
||||
"""for e in cb.getContainerList(filterType=CryptoBoxContainer.Types["luks"]):"""
|
||||
for e in cb.getContainerList():
|
||||
print "\t\t%d\t\t%s - %s - %d" % (cb.getContainerList().index(e), e.getDevice(), e.getName(), e.getType())
|
||||
|
||||
if not cb.getContainerList() or len(cb.getContainerList()) < 1:
|
||||
print "no loop devices found for testing"
|
||||
sys.exit(1)
|
||||
|
||||
if len(cb.getContainerList()) > 1:
|
||||
print "I found more than one available loop device - I will stop now to avoid risking data loss."
|
||||
print "Please change the 'AllowedDevices' setting in 'cryptobox.conf' to reduce the number of allowed devices to only one."
|
||||
sys.exit(1)
|
||||
|
||||
testElement = cb.getContainerList()[0]
|
||||
print "\nRunning some tests now ..."
|
||||
if not plain_tests(testElement):
|
||||
print "some previous tests failed - we should stop now"
|
||||
sys.exit(1)
|
||||
luks_tests(testElement)
|
||||
|
||||
|
||||
" ***************** some functions ******************** "
|
||||
|
||||
def luks_tests(e):
|
||||
# umount if necessary
|
||||
try:
|
||||
e.umount()
|
||||
except "MountError":
|
||||
pass
|
||||
|
||||
e.create(e.Types["luks"], "alt")
|
||||
print "\tluks create:\tok"
|
||||
|
||||
e.changePassword("alt","neu")
|
||||
print "\tluks changepw:\tok"
|
||||
|
||||
e.setName("lalla")
|
||||
print "\tluks setName:\tok"
|
||||
|
||||
try:
|
||||
e.mount("neu")
|
||||
except "MountError":
|
||||
pass
|
||||
if e.isMounted(): print "\tluks mount:\tok"
|
||||
else: print "\tluks mount:\tfailed"
|
||||
|
||||
print "\tCapacity (size, free, used) [MB]:\t%s" % (e.getCapacity(), )
|
||||
|
||||
try:
|
||||
e.umount()
|
||||
except "MountError":
|
||||
pass
|
||||
if e.isMounted(): print "\tluks umount:\tfailed"
|
||||
else: print "\tluks umount:\tok"
|
||||
|
||||
if e.isMounted(): return False
|
||||
else: return True
|
||||
|
||||
|
||||
def plain_tests(e):
|
||||
# umount if necessary
|
||||
try:
|
||||
e.umount()
|
||||
except "MountError":
|
||||
pass
|
||||
|
||||
e.create(e.Types["plain"])
|
||||
print "\tplain create:\tok"
|
||||
|
||||
e.setName("plain-lili")
|
||||
print "\tplain setName:\tok"
|
||||
|
||||
try:
|
||||
e.mount()
|
||||
except "MountError":
|
||||
pass
|
||||
if e.isMounted(): print "\tplain mount:\tok"
|
||||
else: print "\tplain mount:\tfailed"
|
||||
|
||||
print "\tCapacity (size, free, used) [MB]:\t%s" % (e.getCapacity(), )
|
||||
|
||||
try:
|
||||
e.umount()
|
||||
except "MountError":
|
||||
pass
|
||||
if e.isMounted(): print "\tplain umount:\tfailed"
|
||||
else: print "\tplain umount:\tok"
|
||||
|
||||
if e.isMounted(): return False
|
||||
else: return True
|
||||
|
||||
# ************ main ****************
|
||||
|
||||
main()
|
@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from distutils.core import setup
|
||||
import distutils.sysconfig
|
||||
import os
|
||||
|
||||
## define some strings (not patterns) to exclude specific files or directories
|
||||
IGNORE_FILES = [ '.svn' ]
|
||||
|
||||
## define the data destination directory (below the python directory - we will fix this for debian in the rules file)
|
||||
datadir = distutils.sysconfig.get_python_lib()
|
||||
## remove installation prefix to get relative path
|
||||
datadir = datadir.replace(distutils.sysconfig.get_config_var("prefix") + os.path.sep, '')
|
||||
datadir = os.path.join(datadir, 'cryptobox','share')
|
||||
|
||||
def getdatafiles(dirs):
|
||||
filelist = []
|
||||
def listfiles(srcdir):
|
||||
## add the files of this directory
|
||||
result = [(os.path.join(datadir,srcdir), [ os.path.join(srcdir, f) for f in os.listdir(srcdir) if os.path.isfile(os.path.join(srcdir, f)) and not f in IGNORE_FILES ])]
|
||||
## add the files in subdirectories
|
||||
for d in os.listdir(os.path.join(srcdir)):
|
||||
if os.path.isdir(os.path.join(srcdir,d)) and not d in IGNORE_FILES:
|
||||
result.extend(listfiles(os.path.join(srcdir,d)))
|
||||
return result
|
||||
for d in dirs:
|
||||
filelist.extend(listfiles(d))
|
||||
return filelist
|
||||
|
||||
|
||||
setup(
|
||||
name = 'cryptobox',
|
||||
version = '0.3.0',
|
||||
description = 'webinterface for handling encrypted disks',
|
||||
author = 'Lars Kruse',
|
||||
author_email = 'devel@sumpfralle.de',
|
||||
maintainer = 'Lars Kruse',
|
||||
maintainer_email = 'devel@sumpfralle.de',
|
||||
license = 'GPL',
|
||||
url = 'http://cryptobox.org',
|
||||
packages = [ 'cryptobox', 'cryptobox.core', 'cryptobox.web', 'cryptobox.plugins', 'cryptobox.tests' ],
|
||||
data_files = getdatafiles(['templates','www-data','lang','plugins','event-scripts','conf-examples']) + [
|
||||
(datadir, ['README']),
|
||||
(datadir, ['CHANGELOG']),
|
||||
(datadir, ['LICENSE'])],
|
||||
package_dir = { 'cryptobox': 'src' },
|
||||
scripts = [ 'bin/CryptoBoxWebserver', 'bin/CryptoBoxRootActions' ],
|
||||
classifiers = [
|
||||
'Development Status :: 2 - Beta',
|
||||
'Environment :: Web Environment',
|
||||
'Intended Audience :: End Users/Desktop',
|
||||
'Intended Audience :: System Administrators',
|
||||
'License :: OSI Approved :: GNU General Public License (GPL)',
|
||||
'Topic :: System :: Systems Administration',
|
||||
'Operating System :: POSIX',
|
||||
'Operating System :: Unix',
|
||||
'Programming Language :: Python'],
|
||||
)
|
||||
|
@ -0,0 +1 @@
|
||||
__all__ = ['core','web','plugins','tests']
|