plugin interface implemented

example plugins added: date and network
moved "logs" to plugins
This commit is contained in:
lars 2006-09-12 08:55:20 +00:00
parent 5af79f90b6
commit dba8ca79fd
27 changed files with 483 additions and 174 deletions

View file

@ -26,6 +26,9 @@ class CryptoBox:
put things like logging, conf and oter stuff in here,
that might be used by more classes, it will be passed on to them'''
VERSION = "0.3~1"
def __init__(self, config_file=None):
import CryptoBoxSettings
self.log = self.__getStartupLogger()
@ -141,13 +144,14 @@ class CryptoBoxProps(CryptoBox):
return []
try:
fd = open(log_file, "r")
if maxSize: content = fd.readlines(maxSize)
else: content = fd.readlines()
if maxSize: fd.seek(-maxSize, 2) # seek relative to the end of the file
content = fd.readlines()
fd.close()
except IOError:
self.log.warn("failed to read the log file (%s)" % log_file)
return []
if lines: content = content[-lines:]
content.reverse()
return content

View file

@ -8,6 +8,15 @@ class CryptoBoxError(Exception):
pass
class CBPluginError(CryptoBoxError):
"""should be raised for plugin specific problems"""
class CBPluginActionError(CBPluginError):
"""should be raised when a plugin action failed"""
pass
class CBConfigError(CryptoBoxError):
"""any kind of error related to the configuration of a cryptobox"""
pass

View file

@ -171,6 +171,7 @@ NameDatabase = fileWriteable(default="/var/cache/cryptobox/volumen_names.db")
TemplateDir = directoryExists(default="/usr/share/cryptobox/template")
LangDir = directoryExists(default="/usr/share/cryptobox/lang")
DocDir = directoryExists(default="/usr/share/doc/cryptobox/html")
PluginDir = directoryExists(default="/usr/share/cryptobox/plugins")
[Log]
Level = option("debug", "info", "warn", "error", default="warn")

View file

@ -0,0 +1,76 @@
# $Id$
import imp
import os
import logging
class PluginManager:
"""manage available plugins"""
def __init__(self, plugin_dirs=None):
self.log = logging.getLogger("CryptoBox")
if hasattr(plugin_dirs, "__iter__"):
self.plugin_dirs = [os.path.abspath(dir) for dir in plugin_dirs]
else:
self.plugin_dirs = [os.path.abspath(plugin_dirs)]
def allPlugins(self):
for plfile in self.__getPluginFiles():
yield os.path.basename(plfile)[:-3]
def getPlugin(self, name):
for plfile in self.__getPluginFiles():
if name == os.path.basename(plfile)[:-3]:
return imp.load_source(name, plfile)
else:
return None
def getTemplateFileName(self, plname, template_name):
"""return the name of the template file, if it is part of the mentioned plugin
"""
result = [os.path.join(os.path.dirname(cur_file), template_name + ".cs")
for cur_file in self.__getPluginFiles()
if plname == os.path.basename(cur_file)[:-3]]
for templ_file in result:
if os.access(templ_file, os.R_OK) and os.path.isfile(templ_file):
return templ_file
else:
return None
def loadLanguageData(self, hdf, lang="en"):
for plfile in self.__getPluginFiles():
langdir = os.path.join(os.path.dirname(plfile), "lang")
selected_langfile = os.path.join(langdir, lang + ".hdf")
default_langfile = os.path.join(langdir, "en.hdf")
for langfile in (selected_langfile, default_langfile):
if os.access(langfile, os.R_OK):
self.log.debug("Loading plugin language file: %s" % langfile)
hdf.readFile(langfile)
break
else:
self.log.debug("Couldn't find a plugin language file (%s)" % default_langfile)
def __getPluginFiles(self):
result = []
for dir in [os.path.abspath(e) for e in self.plugin_dirs if os.access(e, os.R_OK) and os.path.isdir(e)]:
for plname in [f for f in os.listdir(dir)]:
pldir = os.path.join(dir, plname)
plfile = os.path.join(pldir, plname + ".py")
if os.path.isfile(plfile) and os.access(plfile, os.R_OK):
result.append(plfile)
return result
if __name__ == "__main__":
x = PluginManager("../plugins")
for a in x.allPlugins():
print "Plugin: %s" % a
print x.getPlugin(a).getStatus()

View file

@ -1,7 +1,7 @@
import os
import CryptoBoxContainer
## useful constant for many functions
## useful constant for some functions
CONT_TYPES = CryptoBoxContainer.CryptoBoxContainer.Types
class WebInterfaceDataset(dict):
@ -16,6 +16,31 @@ class WebInterfaceDataset(dict):
self.__setCryptoBoxState()
def setPluginState(self, plugins):
for pl in plugins.allPlugins():
self["Data.Status.Modules." + pl] = plugins.getPlugin(pl).getStatus(self.cbox)
def setCurrentDiskState(self, device):
for container in self.cbox.getContainerList():
if container.getDevice() == device:
isEncrypted = (container.getType() == CONT_TYPES["luks"]) and 1 or 0
isPlain = (container.getType() == CONT_TYPES["plain"]) and 1 or 0
isMounted = container.isMounted() and 1 or 0
self["Data.CurrentDisk.device"] = container.getDevice()
self["Data.CurrentDisk.name"] = container.getName()
self["Data.CurrentDisk.encryption"] = isEncrypted
self["Data.CurrentDisk.plaintext"] = isPlain
self["Data.CurrentDisk.active"] = isMounted
if isMounted:
(size, avail, used) = container.getCapacity()
percent = used / size
self["Data.CurrentDisk.capacity.used"] = used
self["Data.CurrentDisk.capacity.free"] = avail
self["Data.CurrentDisk.capacity.size"] = size
self["Data.CurrentDisk.capacity.percent"] = percent
def __setConfigValues(self):
self["Settings.TemplateDir"] = os.path.abspath(self.prefs["Locations"]["TemplateDir"])
self["Settings.LanguageDir"] = os.path.abspath(self.prefs["Locations"]["LangDir"])
@ -26,6 +51,7 @@ class WebInterfaceDataset(dict):
def __setCryptoBoxState(self):
self["Data.Version"] = self.cbox.VERSION
avail_counter = 0
active_counter = 0
for container in self.cbox.getContainerList():
@ -45,26 +71,6 @@ class WebInterfaceDataset(dict):
## TODO: open issues: Data.Config.AdminPasswordIsSet
def setCurrentDiskState(self, device):
for container in self.cbox.getContainerList():
if container.getDevice() == device:
isEncrypted = (container.getType() == CONT_TYPES["luks"]) and 1 or 0
isPlain = (container.getType() == CONT_TYPES["plain"]) and 1 or 0
isMounted = container.isMounted() and 1 or 0
self["Data.CurrentDisk.device"] = container.getDevice()
self["Data.CurrentDisk.name"] = container.getName()
self["Data.CurrentDisk.encryption"] = isEncrypted
self["Data.CurrentDisk.plaintext"] = isPlain
self["Data.CurrentDisk.active"] = isMounted
if isMounted:
(size, avail, used) = container.getCapacity()
percent = used / size
self["Data.CurrentDisk.capacity.used"] = used
self["Data.CurrentDisk.capacity.free"] = avail
self["Data.CurrentDisk.capacity.size"] = size
self["Data.CurrentDisk.capacity.percent"] = percent
def __getLanguageName(self, lang):
import neo_cgi, neo_util, neo_cs
hdf_path = os.path.join(self.prefs["Locations"]["LangDir"], lang + ".hdf")

View file

@ -1,6 +1,8 @@
import CryptoBox
import WebInterfaceDataset
import re
from Plugins import PluginManager
from CryptoBoxExceptions import *
class WebInterfaceSites:
'''
@ -14,6 +16,16 @@ class WebInterfaceSites:
self.log = logging.getLogger("CryptoBox")
self.prefs = self.cbox.prefs
self.__resetDataset()
self.plugins = PluginManager(self.prefs["Locations"]["PluginDir"])
self.__exposePlugins()
def __exposePlugins(self):
for plname in self.plugins.allPlugins():
self.log.info("Plugin '%s' loaded" % plname)
## this should be the "easiest" way to expose all modules as URLs
setattr(self, "module_" + plname, self.return_module_action(plname))
setattr(getattr(self, "module_" + plname), "exposed", True)
def __resetDataset(self):
@ -65,12 +77,6 @@ class WebInterfaceSites:
return self.__render("show_status")
def config(self,weblang=""):
self.__resetDataset()
self.__setWebLang(weblang)
pass
def doc(self,page="",weblang=""):
'''prints the offline wikipage
'''
@ -86,22 +92,11 @@ class WebInterfaceSites:
self.dataset["Data.Doc.Page"] ="CryptoBoxUser"
return self.__render("show_doc")
def system(self, shutdowntype="", weblang=""):
# TODO: check weblang
def system(self, weblang=""):
self.__resetDataset()
self.__setWebLang(weblang)
if shutdowntype == "reboot":
self.dataset["Data.Success"] = "ReBoot"
self.dataset["Data.Redirect.Action"] = "show_status"
self.dataset["Data.Redirect.Delay"] = "180"
self.log.info("TODO: call function for system reboot")
elif shutdowntype == "poweroff":
self.dataset["Data.Success"] = "PowerOff"
self.log.info("TODO: call function for system shutdown")
else:
self.log.warn("This shutdown-mode (%s) is not supported." % shutdowntype)
return self.__render("form_system")
@ -315,7 +310,27 @@ class WebInterfaceSites:
return self.__render("show_status")
return self.__render("show_volume")
def return_module_action(self, module):
def handler(**args):
self.__resetDataset()
try:
self.__setWebLang(args["weblang"])
del args["weblang"]
except KeyError:
pass
plugin = self.plugins.getPlugin(module)
try:
nextTemplate = plugin.doAction(self.cbox, **args)
except CBPluginActionError, errMsg:
self.log.debug(errMsg)
self.dataset["Data.Warning"] = errMsg
nextTemplate = "empty"
plugin.prepareForm(self.dataset, self.cbox)
return self.__render(nextTemplate, module)
return handler
'''
## DONE: these functions are pythonized
#################### show_log #######################
@ -403,7 +418,7 @@ class WebInterfaceSites:
return False
def __render(self, template):
def __render(self, template, module=None):
'''renders from clearsilver templates and returns the resulting html
Gets a dictionary with all settings, nessessary for rendering.
@ -411,7 +426,6 @@ class WebInterfaceSites:
object, that calls this render method. This might be bloat but
this way the render method has always a complete, actual set of values.
'''
import os
try:
import neo_cgi, neo_util, neo_cs
@ -421,7 +435,11 @@ class WebInterfaceSites:
sys.stderr.write(errorMsg)
raise ImportError, errorMsg
self.dataset["Data.Action"] = template
module_cs_file = False
if module:
module_cs_file = self.plugins.getTemplateFileName(module, template)
default_cs_file = os.path.join(self.prefs["Locations"]["TemplateDir"], template + ".cs")
self.dataset["Data.TemplateFile"] = module_cs_file or default_cs_file
self.log.info("rendering site: " + template)
cs_path = os.path.join(self.prefs["Locations"]["TemplateDir"], "main.cs")
@ -435,11 +453,16 @@ class WebInterfaceSites:
log.error("Couldn't read language file: %s" % hdf_path)
return "Couldn't read language file: %s" % hdf_path
## add the current state of the plugins to the hdf dataset
self.dataset.setPluginState(self.plugins)
hdf = neo_util.HDF()
hdf.readFile(hdf_path)
self.log.debug(self.dataset)
for key in self.dataset.keys():
hdf.setValue(key,str(self.dataset[key]))
## load languaga data of plugins
self.plugins.loadLanguageData(hdf, lang=self.dataset["Settings.Language"])
cs = neo_cs.CS(hdf)
cs.parseFile(cs_path)
return cs.render()
@ -462,6 +485,7 @@ class WebInterfaceSites:
test.exposed = True
"""
## TODO: check this before anything else
if self.cbox.getAvailableDocLanguages():

View file

@ -32,6 +32,11 @@ LangDir = ../lang
#DocDir = /usr/share/doc/cryptobox/html
DocDir = ../doc/html
# path to the plugin directory
#PluginDir = /usr/share/cryptobox/plugins
PluginDir = ../plugins
[Log]
# possible values are "debug", "info", "warn" and "error" or numbers from

View file

@ -48,6 +48,7 @@ MountParentDir = %s
TemplateDir = ../templates
LangDir = ../lang
DocDir = ../doc/html
PluginDir = ../plugins
[Log]
Level = debug
Destination = file