summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Sivak <msivak@redhat.com>2008-03-14 13:54:03 +0100
committerMartin Sivak <msivak@redhat.com>2008-03-14 13:54:03 +0100
commit020ed3044c04ef342f0ab9fb536b0d940eaca319 (patch)
treea6af85304b641021593ea2dab5a7e95640fb7719
parenta4c5705a47007f1f5db2c171bfe9f35916c8761d (diff)
downloadfirstaidkit-020ed3044c04ef342f0ab9fb536b0d940eaca319.tar.gz
firstaidkit-020ed3044c04ef342f0ab9fb536b0d940eaca319.tar.xz
firstaidkit-020ed3044c04ef342f0ab9fb536b0d940eaca319.zip
Add IssuesPlugin class and basic rpm plugin, which uses the issues approach
-rw-r--r--plugins/plugin_rpm/__init__.py67
-rw-r--r--plugins/plugin_rpm/issue_packages.py64
-rw-r--r--pyfirstaidkit/issue.py98
-rw-r--r--pyfirstaidkit/plugins.py45
4 files changed, 274 insertions, 0 deletions
diff --git a/plugins/plugin_rpm/__init__.py b/plugins/plugin_rpm/__init__.py
new file mode 100644
index 0000000..71fea97
--- /dev/null
+++ b/plugins/plugin_rpm/__init__.py
@@ -0,0 +1,67 @@
+# 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 pyfirstaidkit.plugins import IssuesPlugin,Flow
+from pyfirstaidkit.returns import *
+from pyfirstaidkit.utils import *
+from pyfirstaidkit.reporting import PLUGIN,TASK
+from pyfirstaidkit import Config
+import rpm
+
+from issue_packages import RequiredPackages
+
+class RPMPlugin(IssuesPlugin):
+ """This plugin provides checks for RPM database."""
+ #
+ # Additional flow defprepareion.
+ #
+ flows = Flow.init(IssuesPlugin)
+
+ name = "RPM plugin"
+ version = "0.0.1"
+ author = "Martin Sivak"
+
+ issue_tests = [RequiredPackages]
+
+ @classmethod
+ def getDeps(cls):
+ return set(["root", "experimental", "filesystem"])
+
+ def __init__(self, *args, **kwargs):
+ IssuesPlugin.__init__(self, *args, **kwargs)
+ self.rpm = None
+
+ def prepare(self):
+ self._reporting.info(self.name+" in Prepare task", origin = self, level = PLUGIN)
+ self.rpm = rpm.ts(Config.system.root)
+ IssuesPlugin.prepare(self)
+
+ def backup(self):
+ self._reporting.info(self.name+" in backup task", origin = self, level = PLUGIN)
+ self._result=ReturnSuccess
+
+ def restore(self):
+ self._reporting.info(self.name+" in Restore task", origin = self, level = PLUGIN)
+ self._result=ReturnSuccess
+
+ def clean(self):
+ self._reporting.info(self.name+" in Clean task", origin = self, level = PLUGIN)
+ del self.rpm
+ self._result=ReturnSuccess
+
+def get_plugin():
+ return RPMPlugin
diff --git a/plugins/plugin_rpm/issue_packages.py b/plugins/plugin_rpm/issue_packages.py
new file mode 100644
index 0000000..46db8fe
--- /dev/null
+++ b/plugins/plugin_rpm/issue_packages.py
@@ -0,0 +1,64 @@
+# File name: issue_filesystem.py
+# Date: 2008/03/14
+# Author: Martin Sivak <msivak at redhat dot com>
+#
+# Copyright (C) Red Hat 2008
+#
+# 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
+# in a file called COPYING along with this program; if not, write to
+# the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
+# 02139, USA.
+
+from pyfirstaidkit.issue import Issue
+from pyfirstaidkit.reporting import TASK
+
+class RequiredPackages(Issue):
+ name = "Required Packages"
+ description = "There are some very important packages missing. It is likely your instalation could be damaged."
+
+ packages_list = ["filesystem", "initscripts"]
+
+ def detect(self):
+ result = Issue.detect(self)
+ if result is not None:
+ return result
+
+ architectures = {}
+
+ for p in self.packages_list:
+ architectures[p] = set()
+ mi=self._plugin.rpm.dbMatch("name", p)
+ for hdr in mi:
+ self._plugin._reporting.debug(level = TASK, origin = self, message = "Found package %s with architecture %s" % (p, hdr["arch"]))
+ architectures[p].add(hdr["arch"])
+
+ #is there a common architecture for all the packages?
+ all = reduce(lambda acc,x: acc.union(x), architectures.values(), set())
+ common = reduce(lambda acc,x: acc.intersection(x), architectures.values(), all)
+ self._plugin._reporting.debug(level = TASK, origin = self, message = "Common architecture for all packages is %s" % ("+".join(common),))
+
+ if len(common)==0:
+ self._happened = True
+ else:
+ self._happened = False
+
+ self._detected = True
+ return True
+
+ def fix(self):
+ result = Issue.fix(self)
+ if result is not None:
+ return result
+
+ self._fixed = False
+ return True
diff --git a/pyfirstaidkit/issue.py b/pyfirstaidkit/issue.py
new file mode 100644
index 0000000..caf9822
--- /dev/null
+++ b/pyfirstaidkit/issue.py
@@ -0,0 +1,98 @@
+# File name: issue.py
+# Date: 2008/03/14
+# Author: Martin Sivak <msivak at redhat dot com>
+#
+# Copyright (C) Red Hat 2008
+#
+# 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
+# in a file called COPYING along with this program; if not, write to
+# the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
+# 02139, USA.
+
+class Issue(object):
+ name = "Parent issue"
+ description = "This happens when you use the wrong object in the issues list"
+
+ def __init__(self, plugin):
+ self._plugin = plugin
+ self.reset()
+
+ def detect(self):
+ """Detect if this situation happened and store some information about it, so we can fix it
+Return values:
+ True - detection OK
+ False - detection Failed
+ None - no result, please continue with the operation"""
+
+ #if the issue was fixed. the detection is worthless
+ #if it was detected, no need to do the detection again
+ if self._detected or self._fixed:
+ return not self._fixed and self._detected
+
+ return None #no error, please do the detection (so the child-class knows to actually do something)
+
+ def fix(self):
+ """Fix the situation if needed
+Return values:
+ True - fix OK
+ False - fix Failed
+ None - no result, please continue with the operation"""
+
+ #if the issue was fixed. no need to do the fix again
+ #if it was not detected, the detection si needed too
+ if not self._detected or self._fixed:
+ return self._fixed and self._detected
+
+ return None #no fix error, please do the fix (so the child-class knows to actually do something)
+
+ def happened(self):
+ """Get the 'issue happened' flag.
+Return values:
+ True - YES it happened
+ False - NO, it is OK
+ None - I don't know, there was an error"""
+ #if the issue was fixed or not detected, the detection si needed
+ if not self._detected or self._fixed:
+ return None
+ else:
+ return self._happened
+
+
+ def reset(self):
+ """Reset the object's state"""
+ self._detected = False
+ self._happened = False
+ self._fixed = False
+
+ def __str__(self):
+ s = []
+ if self._fixed:
+ s.append("Fixed")
+ elif self._happened and self._detected:
+ s.append("Detected")
+ elif self._detected:
+ s.append("No problem with")
+ else:
+ s.append("Waiting for check on")
+
+ s.append(self.name)
+
+ if self._happened and self._detected:
+ s.append("--")
+ s.append(self.description)
+
+ return " ".join(s)
+
+ def str(self):
+ return self.__str__()
+
diff --git a/pyfirstaidkit/plugins.py b/pyfirstaidkit/plugins.py
index 7d6080f..07e4c50 100644
--- a/pyfirstaidkit/plugins.py
+++ b/pyfirstaidkit/plugins.py
@@ -20,6 +20,7 @@ from returns import *
from errors import *
from reporting import *
from copy import copy,deepcopy
+from issue import *
import FirstAidKit
import logging
@@ -290,6 +291,50 @@ class Plugin(object):
if self.__class__ is Plugin:
Logger.warning("Fix is an abstract method, it should be used as such.")
+class IssuesPlugin(Plugin):
+ """Simple plugin which uses Issue classes to test more small and INDEPENDENT issues in the system.
+Just fill the issue_tests list with classes describing the tests and let it run."""
+
+ issue_tests = [] #List of Issue classes to check
+
+ def __init__(self, flow, reporting, dependencies, path = None):
+ Plugin.__init__(self, flow, reporting, dependencies, path)
+ self.tests = []
+
+ def prepare(self):
+ """Prepare the issues list"""
+ for i in self.issue_tests:
+ self._reporting.info(level = TASK, origin = self, message = "Preparing tests for '%s'" % (i.name,))
+ self.tests.append(i(plugin = self))
+ self._result=ReturnSuccess
+
+ def diagnose(self):
+ """Diagnose the situation."""
+
+ result = False
+ for i in self.tests:
+ self._reporting.info(level = TASK, origin = self, message = "Investigating '%s'" % (i.name,))
+ result = result or i.detect()
+
+ if result:
+ self._result=ReturnSuccess
+ else:
+ self._result=ReturnFailure
+
+ def fix(self):
+ """Try to fix whatever is wrong in the system."""
+
+ result = False
+ for i in self.tests:
+ self._reporting.info(level = TASK, origin = self, message = "Fixing '%s'" % (i.name,))
+ result = result or i.fix()
+
+ if result:
+ self._result=ReturnSuccess
+ else:
+ self._result=ReturnFailure
+
+
class FlagTrackerPlugin(Plugin):
"""This kind of plugin monitores all the flags in the system and when certain flags
are set, provides some kind of higher level flag.