diff options
author | Joel Andres Granados <jgranado@redhat.com> | 2008-01-02 14:32:07 +0100 |
---|---|---|
committer | Joel Andres Granados <jgranado@redhat.com> | 2008-01-02 14:32:07 +0100 |
commit | 26da06a02b8cbeea5aea9eccc2de55d33ade23bf (patch) | |
tree | 7bb10032a86f8015dcee987697c480ef24d32872 | |
parent | 403519b478ffbe5b433b1fd2fb7babe12c693af2 (diff) | |
download | firstaidkit-26da06a02b8cbeea5aea9eccc2de55d33ade23bf.tar.gz firstaidkit-26da06a02b8cbeea5aea9eccc2de55d33ade23bf.tar.xz firstaidkit-26da06a02b8cbeea5aea9eccc2de55d33ade23bf.zip |
Move from tasker to pyfirstaidkit to try to follow the standard in site-packages.
-rw-r--r-- | pyfirstaidkit/.placeholder | 0 | ||||
-rw-r--r-- | pyfirstaidkit/FirstAidKit.py | 17 | ||||
-rw-r--r-- | pyfirstaidkit/__init__.py | 21 | ||||
-rw-r--r-- | pyfirstaidkit/configuration.py | 102 | ||||
-rw-r--r-- | pyfirstaidkit/errors.py | 29 | ||||
-rw-r--r-- | pyfirstaidkit/interpret.py | 84 | ||||
-rw-r--r-- | pyfirstaidkit/log.py | 25 | ||||
-rw-r--r-- | pyfirstaidkit/plugins.py | 352 | ||||
-rw-r--r-- | pyfirstaidkit/reporting.py | 96 | ||||
-rw-r--r-- | pyfirstaidkit/returns.py | 42 | ||||
-rw-r--r-- | pyfirstaidkit/utils.py | 38 |
11 files changed, 806 insertions, 0 deletions
diff --git a/pyfirstaidkit/.placeholder b/pyfirstaidkit/.placeholder new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/pyfirstaidkit/.placeholder diff --git a/pyfirstaidkit/FirstAidKit.py b/pyfirstaidkit/FirstAidKit.py new file mode 100644 index 0000000..44d6775 --- /dev/null +++ b/pyfirstaidkit/FirstAidKit.py @@ -0,0 +1,17 @@ +# First Aid Kit - diagnostic and repair tool for Linux +# Copyright (C) 2007 Martin Sivak <msivak@redhat.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + diff --git a/pyfirstaidkit/__init__.py b/pyfirstaidkit/__init__.py new file mode 100644 index 0000000..6a31164 --- /dev/null +++ b/pyfirstaidkit/__init__.py @@ -0,0 +1,21 @@ +# First Aid Kit - diagnostic and repair tool for Linux +# Copyright (C) 2007 Martin Sivak <msivak@redhat.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +from interpret import Tasker +from configuration import Config +from log import Logger + diff --git a/pyfirstaidkit/configuration.py b/pyfirstaidkit/configuration.py new file mode 100644 index 0000000..70a626e --- /dev/null +++ b/pyfirstaidkit/configuration.py @@ -0,0 +1,102 @@ +# First Aid Kit - diagnostic and repair tool for Linux +# Copyright (C) 2007 Martin Sivak <msivak@redhat.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import ConfigParser +import os +from cStringIO import StringIO +from shlex import shlex + +if os.environ.has_key("FIRST_AID_KIT_CONF"): + cfgfile = os.environ["FIRST_AID_KIT_CONF"].split(":") +else: + cfgfile = ["/etc/firstaidkit.conf", os.environ["HOME"]+"/.firstaidkit.conf"] + +defaultconfig = """ +[system] +root = /mnt/sysimage + +[plugin] +path = /usr/lib/FirstAidKit/plugins +disabled = + +[operation] +mode = auto +help = False +verbose = False +gui = console + +[log] +method = stdout +""" + +class LockedError(Exception): + pass + +class FAKConfigSection(object): + """Proxy object for one configuration section""" + + def __init__(self, cfg, name): + self.__dict__["section_name"] = name + self.__dict__["configuration"] = cfg + + def __getattr__(self, key): + if not self.__dict__["configuration"].has_section(self.__dict__["section_name"]): + raise ConfigParser.NoSectionError(self.__dict__["section_name"]) + + if not self.__dict__["configuration"].has_option(self.__dict__["section_name"], key): + raise ConfigParser.NoOptionError(key) + + return self.__dict__["configuration"].get(self.__dict__["section_name"], key) + + def __setattr__(self, key, value): + if self.__dict__["configuration"].__dict__.has_key("_lock") and self.__dict__["configuration"].__dict__["_lock"]: + raise LockedError(key) + + if not self.__dict__["configuration"].has_section(self.__dict__["section_name"]): + self.__dict__["configuration"].add_section(self.__dict__["section_name"]) + self.__dict__["configuration"].set(self.__dict__["section_name"], key, value) + + def _list(self, key): + l = [] + lex = shlex(instream = StringIO(getattr(self, key)), posix = True) + token = lex.get_token() + while token!=lex.eof: + l.append(token) + token = lex.get_token() + return l + + +class FAKConfigMixIn(object): + """Enhance ConfigParser so we can use it in the python way (config.section.value)""" + + def __getattr__(self, section): + return FAKConfigSection(self, section) + + def lock(self): + self.__dict__["_lock"] = True + + def unlock(self): + self.__dict__["_lock"] = False + +class FAKConfig(ConfigParser.SafeConfigParser, FAKConfigMixIn): + pass + +Config = FAKConfig() +Config.readfp(StringIO(defaultconfig), "<default>") +Config.read(cfgfile) + + diff --git a/pyfirstaidkit/errors.py b/pyfirstaidkit/errors.py new file mode 100644 index 0000000..61a04be --- /dev/null +++ b/pyfirstaidkit/errors.py @@ -0,0 +1,29 @@ +# First Aid Kit - diagnostic and repair tool for Linux +# Copyright (C) 2007 Martin Sivak <msivak@redhat.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + +class InvalidFlowStateException(Exception): + def __init__(self, flow): + self.message="There appears to be an inconsistency with the %s varialbe. " % flow + def __str__(self): + return self.message + +class InvalidFlowNameException(Exception): + def __init__(self, name, flow): + self.message="There are no flows by the name of %s" % name + def __str__(self): + return self.message diff --git a/pyfirstaidkit/interpret.py b/pyfirstaidkit/interpret.py new file mode 100644 index 0000000..da5671a --- /dev/null +++ b/pyfirstaidkit/interpret.py @@ -0,0 +1,84 @@ +# First Aid Kit - diagnostic and repair tool for Linux +# Copyright (C) 2007 Martin Sivak <msivak@redhat.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +from log import Logger +from plugins import PluginSystem +from reporting import Reports, TASKER +import logging +import copy + +class RunDependencies(object): + """Encapsulate flags used to control the dependencies between plugins""" + def __init__(self): + self._provide = set() + + def provide(self, id): + """Add flag""" + Logger.info("Setting dependency flag %s", id) + self._provide.add(id) + + def require(self, id): + """Return True if flag is present, otherwise false""" + return id in self._provide + +class Tasker: + """The main interpret of tasks described in Config object""" + + def __init__(self, cfg): + self._provide = RunDependencies() + self._config = cfg + self._reporting = Reports() + self.pluginSystem = PluginSystem(reporting = self._reporting, dependencies = self._provide) + + def reporting(self): + return self._reporting + + def pluginsystem(self): + return self.pluginSystem + + def end(self): + """Signalize end of operations to all necessary places""" + self._reporting.end() + + def run(self): + pluginSystem = self.pluginSystem + + if self._config.operation.mode == "auto": + oldlist = set() + actlist = set(pluginSystem.list()) + #iterate through plugins until there is no plugin left or no action performed during whole iteration + while len(actlist)>0 and oldlist!=actlist: + oldlist = copy.copy(actlist) + for plugin in oldlist: + if pluginSystem.autorun(plugin): #False when dependencies are not met + actlist.remove(plugin) + for plugin in actlist: + self._reporting.info("Plugin %s was not called because of unsatisfied dependencies" % (plugin,), origin = TASKER, importance = logging.WARNING) + elif self._config.operation.mode == "flow": + try: + pluginSystem.autorun(self._config.operation.plugin, flow = self._config.operation.flow, dependencies = False) + except InvalidFlowNameException, e: + pass + elif self._config.operation.mode == "plugin": + pluginSystem.autorun(self._config.operation.plugin, dependencies = False) + elif self._config.operation.mode == "task": + pass + else: + Logger.error("Incorrect task specified") + return False + + return True diff --git a/pyfirstaidkit/log.py b/pyfirstaidkit/log.py new file mode 100644 index 0000000..f1adb8d --- /dev/null +++ b/pyfirstaidkit/log.py @@ -0,0 +1,25 @@ +# First Aid Kit - diagnostic and repair tool for Linux +# Copyright (C) 2007 Martin Sivak <msivak@redhat.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import logging +import sys + +Logger = logging.getLogger() +Logger.setLevel(logging.DEBUG) + +Logger.addHandler(logging.StreamHandler(sys.stdout)) + diff --git a/pyfirstaidkit/plugins.py b/pyfirstaidkit/plugins.py new file mode 100644 index 0000000..8d892c8 --- /dev/null +++ b/pyfirstaidkit/plugins.py @@ -0,0 +1,352 @@ +# First Aid Kit - diagnostic and repair tool for Linux +# Copyright (C) 2007 Martin Sivak <msivak@redhat.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +from configuration import Config +from returns import * +from errors import * + +import FirstAidKit +from log import Logger + +import imp +import os +import subprocess +from cStringIO import StringIO + +class Flow(dict): + def __init__(self, rules, description="", *args, **kwargs): + self.description = description + dict.__init__(self, rules, *args, **kwargs) + +class Plugin(object): + # + # Some information vars. + # + name = "Plugin" + version = "0.0.0" + author = "nobody" + # + # Dictionary that holds all the flows. The keys for each flow is its + # name. The flow will be addressed by this name. The plugin developer + # Can add as many flows as he wants. The developer must use the instance. + # obj._flows["name"] = SomeFlow. Be aware that you can overwirhte + # previously added flows. This class attribute has to be overriden by + # each plugin. + # + flows = {} + + # + # The initial and final states are here to give more flexibilty to the + # Development process. All flows will start and end with these two + # Variables. + # + initial = 0 + final = 1 + + # + # The flow to use with the automated repair mode + # + + default_flow = "defflow" + + # + # This is the default flow that all classes deriving from plugin must + # have. As the initial state has no return value it will be indexed + # with the parent of all ReturnValue classes. + # + _defflows = {} + _defflows["defflow"] = Flow({ + initial : {ReturnValue: "prepare"}, + "prepare" : {ReturnValueTrue: "diagnose"}, + "diagnose" : {ReturnValueTrue: "clean", ReturnValueFalse: "backup"}, + "backup" : {ReturnValueTrue: "fix", ReturnValueFalse: "clean"}, + "fix" : {ReturnValueTrue: "clean", ReturnValueFalse: "restore"}, + "restore" : {ReturnValueTrue: "clean", ReturnValueFalse: "clean"}, + "clean" : {ReturnValueTrue: final} + }, description="The default, fully automated, fixing sequence") + + def __init__(self, flow, reporting, dependencies): + """ Initialize the instance. + + flow -- Name of the flow to be used with this instance. + reporting -- object used to report information to the user + dependencies -- object encapsulating the inter-plugin dependency API (require, provide) + + The flow is defined in the __init__ so we don't have to worry about changing it. + """ + self._reporting = reporting + self._dependencies = dependencies + + self.provide = dependencies.provide + self.require = dependencies.require + + # + # state we are in. + # + self._state = Plugin.initial + + # + # Used to hold the return value of the functions in the class. + # + self._result = None #edge from the state we are in + + # + # Choose the flow for the instance. + # + self.defineFlow(flow) + + def call(self, step): + """call one step from plugin""" + self._result = None #mark new unfinished step + self._state = step + return getattr(self, step)() + + @classmethod + def info(cls): + """Returns tuple (Plugin name, Plugin version, Plugin author)""" + return (cls.name, cls.version, cls.author) + + # + # The flow functions. + # + def defineFlow(self, flow): + """Defines the current flow to name. + + flow -- Name of the flow + This function is to be called from the __init__ only. There will be the flows defined by the + Plugin class and the flows defined by the actual plugin. We will first search the Plugin + class and then the plugin itself for the name. + """ + # + # The flow that will be used for the instance. + # + if flow in Plugin._defflows.keys(): + self.cflow = Plugin._defflows[flow] + elif flow in self.__class__.flows.keys(): + self.cflow = self.__class__.flows[flow] + else: + raise InvalidFlowNameException(flow) + + @classmethod + def getFlows(cls): + """Return a set with the names of all possible flows.""" + fatherf = Plugin._defflows.keys() + pluginf = cls.flows.keys() + return set(fatherf+pluginf) + + @classmethod + def getFlow(cls, name): + """Return a Flow object associated with provided name""" + if cls.flows.has_key(name): + return cls.flows[name] + else: + return Plugin._defflows[name] + + #dependency stuff + @classmethod + def getDeps(cls): + """Return list of conditions required to be set before automated run can be done""" + return set() + + #methods available only for instance, see interpreter.py and dependency stuff there + #def require(self, id) + #def provide(self, id) + + #list of all actions provided + def actions(self): + """Returns list of available actions""" + return set(["prepare", "backup", "diagnose", "describe", "fix", "restore", "clean"]) + + def nextstate(self, state=None, result=None): + """Returns next state when analizing self._state, self._result and the self.cflow in automode. + + state -- Name of hte function. + result -- The return value of the previous function + We do not check for validity of the key in the self.cflow. If key is invalid, function will + Traceback. When self._state = self.final the function will traceback. This situation must + be handled outside this function. If an automatica iteration is needed that avoids the + necesity to address the self.final state, use __iter__ and next. + """ + # If any of the vals are missing, we default to the current ones. + if state is None or result is None: + state=self._state + result=self._result + # The self.initial state does not have any return code. + # It will only work with the ReturnValue. + try: + if state == self.initial: + self._state = self.cflow[self.initial][ReturnValue] + else: + self._state = self.cflow[state][result] + return self._state + except KeyError: + raise InvalidFlowStateException(self.cflow) + + # + #iterate protocol allows us to use loops + # + def __iter__(self): + self._state = self.initial + self._result = None + return self + + def next(self): + """Iteration function. + + Will return (self._state, self._result). The function that was executed and the return value. + """ + func = self.nextstate() + if func == self.final: + raise StopIteration() + else: + # Execute the function. + getattr(self, func)() + return (self._state, self._result) + + # + #default (mandatory) plugin actions + # + def prepare(self): + """Initial actions. + + All the actions that must be done before the execution of any plugin function. + This function generaly addresses things that are global to the plugin. + """ + #We want these functions to be overridden by the plugin developer. + if self.__class__ is Plugin: + Logger.warning("Clean is an abstract method, it should be used as such.") + + def clean(self): + """Final actions. + + All the actions that must be done after the exection of all plugin functions. + This function generaly addresses things that are global and need to be closed + off, like file descriptos, or mounted partitions.... + """ + #We want these functions to be overridden by the plugin developer. + if self.__class__ is Plugin: + Logger.warning("Clean is an abstract method, it should be used as such.") + + def backup(self): + """Gather important information needed for restore.""" + #We want these functions to be overridden by the plugin developer. + if self.__class__ is Plugin: + Logger.warning("Clean is an abstract method, it should be used as such.") + + def restore(self): + """Try to restore the previous state described in backup.""" + #We want these functions to be overridden by the plugin developer. + if self.__class__ is Plugin: + Logger.warning("Clean is an abstract method, it should be used as such.") + + def diagnose(self): + """Diagnose the situation.""" + #We want these functions to be overridden by the plugin developer. + if self.__class__ is Plugin: + Logger.warning("Clean is an abstract method, it should be used as such.") + + def fix(self): + """Try to fix whatever is wrong in the system.""" + #We want these functions to be overridden by the plugin developer. + if self.__class__ is Plugin: + Logger.warning("Clean is an abstract method, it should be used as such.") + +class PluginSystem(object): + """Encapsulate all plugin detection and import stuff""" + + def __init__(self, reporting, dependencies, config = Config): + self._path = Config.plugin.path + self._reporting = reporting + self._deps = dependencies + self._plugins = {} + + #create list of potential modules in the path + importlist = set() + for f in os.listdir(self._path): + fullpath = os.path.join(self._path, f) + Logger.debug("Processing file: %s", f) + if os.path.isdir(fullpath) and os.path.isfile(os.path.join(self._path, f, "__init__.py")): + importlist.add(f) + Logger.debug("Adding python module (directory): %s", f) + elif os.path.isfile(fullpath) and (f[-3:]==".so" or f[-3:]==".py"): + importlist.add(f[:-3]) + Logger.debug("Adding python module (file): %s", f) + elif os.path.isfile(fullpath) and (f[-4:]==".pyc" or f[-4:]==".pyo"): + importlist.add(f[:-4]) + Logger.debug("Adding python module (compiled): %s", f) + + #try to import the modules as FirstAidKit.plugins.modulename + for m in importlist: + if m in Config.plugin._list("disabled"): + continue + + imp.acquire_lock() + try: + Logger.debug("Importing module %s from %s", m, self._path) + moduleinfo = imp.find_module(m, [self._path]) + module = imp.load_module(".".join([FirstAidKit.__name__, m]), *moduleinfo) + Logger.debug("... OK") + finally: + imp.release_lock() + + self._plugins[m] = module + + def list(self): + """Return the list of imported plugins""" + return self._plugins.keys() + + def autorun(self, plugin, flow = None, dependencies = True): + """Perform automated run of plugin with condition checking +returns - True if conditions are fully satisfied + False if there is something missing + exception when some other error happens""" + + pklass = self._plugins[plugin].get_plugin() #get top level class of plugin + Logger.info("Plugin information...") + Logger.info("name:%s , version:%s , author:%s " % pklass.info()) + + flows = pklass.getFlows() + Logger.info("Provided flows : %s " % flows) + if flow==None: + flowName = pklass.default_flow + else: + flowName = flow + + Logger.info("Using %s flow" % flowName) + if flowName not in flows: + Logger.error("Flow %s does not exist in plugin %s", flowName, plugin) + raise InvalidFlowNameException(d) + + if dependencies: + deps = pklass.getDeps() + Logger.info("depends on: %s" % (", ".join(deps),)) + for d in deps: + if not self._deps.require(d): + Logger.info("depends on usatisfied condition: %s" % (d,)) + return False + + p = pklass(flowName, reporting = self._reporting, dependencies = self._deps) + for (step, rv) in p: #autorun all the needed steps + Logger.info("Running step %s in plugin %s ...", step, plugin) + Logger.info("%s is current step and %s is result of that step." % (step, rv)) + + return True + + def getplugin(self, plugin): + """Get instance of plugin, so we can call the steps manually""" + return self._plugins[plugin].get_plugin() + diff --git a/pyfirstaidkit/reporting.py b/pyfirstaidkit/reporting.py new file mode 100644 index 0000000..0337340 --- /dev/null +++ b/pyfirstaidkit/reporting.py @@ -0,0 +1,96 @@ +# First Aid Kit - diagnostic and repair tool for Linux +# Copyright (C) 2007 Martin Sivak <msivak@redhat.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import Queue +import logging + +#semantics values +#first the "task" levels for START and STOP +FIRSTAIDKIT = 100 +TASKER = 90 +PLUGINSYSTEM = 80 +PLUGIN = 70 +FLOW = 60 +TASK = 50 + +#semantics +START = 0 +STOP = 1 +PROGRESS = 2 +INFO = 3 +ALERT = 4 +EXCEPTION = 5 +TABLE = 6 #types for arbitrary table-like organized iterables +TREE = 7 #nested iterables organized as tree +END = 1000 #End of operations, final message + +class Reports(object): + """Instances of this class are used as reporting mechanism by which the + plugins can comminucate back to whatever frontend we are using. + + Message has four parts: + origin - who sent the message (name of the plugin, Pluginsystem, ...) + semantics - what action does the message describe + (INFO, ALERT, PROGRESS, START, STOP, DATA, END) + importance - how is that message important (debug, info, error, ...) + this must be number, possibly the same as in logging module + message - the message itself + for INFO and ALERT semantics, this is an arbitrary text + for PROGRESS, this is (x,y) pair denoting progress + (on step x from y steps) or None to hide the progress + for START and STOP, there is no mandatory message and the + importance specifies the level + """ + + def __init__(self, maxsize=-1): + self._queue = Queue.Queue(maxsize = maxsize) + + def put(self, message, origin, semantics, importance = logging.INFO): + return self._queue.put((origin, semantics, importance, message)) + + def get(self, *args, **kwargs): + return self._queue.get(*args, **kwargs) + + + #There will be helper methods inspired by logging module + def end(self): + return self.put(None, None, END, importance = 1000) + + def error(self, message, origin, semantics): + return self.put(message, origin, semantics, importance = logging.ERROR) + + def start(self, message, origin, what = TASK): + return self.put(message, origin, START, importance = what) + def stop(self, message, origin, what = TASK): + return self.put(message, origin, START, importance = what) + + def progress(self, position, maximum, origin, importance = logging.INFO): + return self.put((position, maximum), origin, PROGRESS, importance = importance) + def info(self, message, origin, importance = logging.INFO): + return self.put(message, origin, INFO, importance = importance) + + + def tree(self, message, origin, importance = logging.INFO): + return self.put(message, origin, TREE, importance = importance) + def table(self, message, origin, importance = logging.INFO): + return self.put(message, origin, TABLE, importance = importance) + + def alert(self, message, origin, importance = logging.WARNING): + return self.put(message, origin, ALERT, importance = importance) + def exception(self, message, origin, importance = logging.ERROR): + return self.put(message, origin, EXCEPTION, importance = importance) + diff --git a/pyfirstaidkit/returns.py b/pyfirstaidkit/returns.py new file mode 100644 index 0000000..c169b17 --- /dev/null +++ b/pyfirstaidkit/returns.py @@ -0,0 +1,42 @@ +# First Aid Kit - diagnostic and repair tool for Linux +# Copyright (C) 2007 Martin Sivak <msivak@redhat.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + +# +# These classes expressed here are to be the keys in the flow dictionary. +# In most default cases the values are unimportant. They are placed there +# for printing or other purposes. + +class ReturnValue: + """Its just a parent class for any Return class that might be create. + + The parent has no value. + """ + def __init__(self): + pass + +class ReturnValueTrue(ReturnValue): + def __init__(self): + self.value = True + +class ReturnValueFalse(ReturnValue): + def __init__(self): + self.value = False + +class ReturnValueNone(ReturnValue): + def __init__(self): + self.value = None diff --git a/pyfirstaidkit/utils.py b/pyfirstaidkit/utils.py new file mode 100644 index 0000000..139bb39 --- /dev/null +++ b/pyfirstaidkit/utils.py @@ -0,0 +1,38 @@ +# First Aid Kit - diagnostic and repair tool for Linux +# Copyright (C) 2007 Martin Sivak <msivak@redhat.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import os +import sys +import subprocess + +def spawnvch(executable, params, chroot): #returns errorcode + """Simpliest chroot modification of spawn + executable - path to binary to execute (in chroot!) + params - it's parameters + chroot - directory to chroot to + +Returns the error code returned by process""" + + pid = os.fork() + if pid==0: #child + os.chroot(chroot) + os.execv(executable, params) + os.exit(1) + else: + res = os.waitpid(pid, 0) + return os.WEXITSTATUS(res) + |