summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
authorJoel Andres Granados <jgranado@redhat.com>2008-06-06 14:11:25 +0200
committerJoel Andres Granados <jgranado@redhat.com>2008-06-06 14:11:25 +0200
commit1ff467a036c75da807fff4f8924d7cbadc97e794 (patch)
treea9e1d684cb42d5ec3792fbd7ca1d44725373f5a2 /plugins
parent65f06cb0a0324dcbb1f238918f33f62ddbf4d69a (diff)
downloadfirstaidkit-1ff467a036c75da807fff4f8924d7cbadc97e794.tar.gz
firstaidkit-1ff467a036c75da807fff4f8924d7cbadc97e794.tar.xz
firstaidkit-1ff467a036c75da807fff4f8924d7cbadc97e794.zip
New mdadm configuration plugin.
Diffstat (limited to 'plugins')
-rw-r--r--plugins/plugin_mdadmconf.py160
1 files changed, 160 insertions, 0 deletions
diff --git a/plugins/plugin_mdadmconf.py b/plugins/plugin_mdadmconf.py
new file mode 100644
index 0000000..8f101c7
--- /dev/null
+++ b/plugins/plugin_mdadmconf.py
@@ -0,0 +1,160 @@
+# First Aid Kit - diagnostic and repair tool for Linux
+# Copyright (C) 2008 Joel Andres Granados <jgranado@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 Plugin,Flow
+from pyfirstaidkit.returns import *
+from pyfirstaidkit.utils import *
+from pyfirstaidkit.reporting import PLUGIN
+from pyfirstaidkit.issue import SimpleIssue
+from pyfirstaidkit import Config
+from pyfirstaidkit.errors import *
+
+import os.path
+
+class MdadmConfig(Plugin):
+ """ Addresses the validity and presence of /etc/mdadm.conf """
+ flows = Flow.init(Plugin)
+ name = "mdadm configuration"
+ version = "0.0.1"
+ author = "Joel Andres Granados"
+
+ @classmethod
+ def getDeps(cls):
+ return set(["root", "experimental", "filesystem"])
+
+ def __init__(self, *args, **kwargs):
+ Plugin.__init__(self, *args, **kwargs)
+ self.currentFileDict = {} #what we read from /etc/mdadm.conf
+ self.scannedFileDict = {} #what `mdadm --misc --detail --scan`
+ self.scannedFile = None # what `mdadm --misc --detail --scan` returns
+ self.configFile = os.path.join(Config.system.root,"/etc/mdadm.conf")
+ self.backupName = None
+ self._issue = SimpleIssue(self.name, "mdadm.con misconfigured")
+
+ def prepare(self):
+ # We read the configuration file if it exists
+ if os.path.exists(self.configFile):
+ self._reporting.info("Gathering information from %s."%self.configFile, level = PLUGIN, origin = self)
+ fd = open(self.configFile, "r")
+ for line in fd.readlines():
+ splitline = line.strip("\n").split(" ")
+ if "ARRAY" in splitline:
+ self.currentFileDict[splitline[1]] = splitline
+ fd.close()
+ else:
+ self._reporting.info("File %s was not found."%self.configFile, level = PLUGIN, origin = self)
+
+ # We execute the mdadm command
+ self._reporting.info("Scanning for software raid with mdadm.", level = PLUGIN, origin = self)
+ mdadmargs = ["--misc", "--detail", "--scan"]
+ proc = spawnvch(executable = "mdamd", args = mdadmargs, chroot = Config.system.root)
+ (out, err) = proc.communicate()
+
+ if err == '':
+ # means that the command ran with no errors.
+ for line in out.__str__().split("\n"):
+ splitline = line.strip("\n").split(" ")
+ if "ARRAY" in splitline:
+ self.scannedFileDict[splitline[1]] = splitline
+ self.scannedFileDict = out
+ else:
+ # This should make the flow go to clean. If there is an error we should not trust what mdadm tells us.
+ self._reporting.info("The mdadm command had the following error:%s. The plugin will silently exit."%err,
+ level = PLUGIN, origin = self)
+ self._result = None
+ return
+ self._result = ReturnSuccess
+ self._issue.set(reporting = self._reporting, level = PLUGIN, origin = self)
+
+ def diagnose(self):
+ # If nothing was returned by the mdadm command. we dont have software raid.
+ if len(self.scannedFileDict) == 0:
+ self._reporting.info("There was no sofware raid found by the mdadm command.... Nothing to do.",
+ level = PLUGIN, origin = self)
+ self._result = ReturnSuccess
+ return
+
+ # If there is one difference between the configs, regarding the ARRAYS. We replace the config file.
+ # Lets check for missing arrays in the curren config file.
+ for key, value in self.scannedFileDict.iteritems():
+ if not self.currentFileDict.has_key(key):
+ self._reporting.info("Found that the current mdamd.conf is missing %s."%value, level = PLUGIN, origin = self)
+ self._result = ReturnFailure
+ return
+ # Lets check for additional ARRAYS that should not be there.
+ for key, value in self.currentFileDict.iteritems():
+ if not self.scannedFileDict.has_key(key):
+ self._reporting.info("The followint entry: %s, is in the config file but was not detected by mdadm."%value,
+ level = PLUGIN, origin = self)
+ self._result = ReturnFailure
+ return
+
+ self._reporting.info("There was no problem found with the current mdadm.conf file.", level = PLUGIN, origin = self)
+ self._result = ReturnSuccess
+
+ def backup(self):
+ if os.path.isfile(self.configFile):
+ self.backupName = "mdadmconf"+os.getpid()
+ self._reporting.info("Making a backup of %s."%self.configFile, level = PLUGIN, origin = self)
+ self._backups.backupPath(self.configFile, self.backupName)
+ else:
+ self._reporting.info("It appears that the file %s does not exist. No backup attempt will be made."%self.configFile,
+ level = PLUGIN, origin = self)
+ self._reporting.info("%s does not exist."%self.configFile, level = PLUGIN, origin = self)
+ self._result = ReturnSuccess
+
+ def fix(self):
+ try:
+ self._reporting.info("Going to write configuration to %s."%self.configFile, level = PLUGIN, origin = self)
+ fd = open(self.configFile, "w")
+ fd.write(self.scannedFile)
+ fd.close()
+ self._reporting.info("Configuration file writen.", level = PLUGIN, origin = self)
+ # The original mdadm.conf will be restore to mdadm.conf.firstaidkit, just in case.
+ self._reporting.info("Will put the old mdadm.conf in %s."%os.path.join(Config.system.root,"etc/mdamd.conf"),
+ level = PLUGIN, origin = self)
+ self._backups.restoreName(self.backupName, os.path.join(Config.system.root,"/etc/mdamd.conf"))
+ self.result = ReturnSuccess
+ except IOError:
+ fd.close()
+ self._reporting.info("Error occurred while writing %s."%self.configFile, level = PLUGIN, origin = self)
+ self._result = ReturnFailure
+ self._issue.set(fixed = (self._result == ReturnSuccess), reporting = self._reporting, level = PLUGIN, origin = self)
+
+ def restore(self):
+ if self.backupName is None:
+ # This is the case where there is no config file.
+ self._reporting.info("The backedup file was not present. Assuming that %s was ont present to begin with."%
+ self.configFile, level = PLUGIN, original = self)
+ self._result = ReturnSuccess
+ return
+
+ try:
+ self._reporting.info("Restoring original file.", level = PLUGIN , origin = self)
+ self._backups.restoreName(self.backupName)
+ self._result = ReturnSuccess
+ except BackupException:
+ # This means that the backed up file was lost somewhere.
+ raise GeneralPluginException(self, "Very ugly inconsistency with the backup files.")
+ self._result = ReturnSuccess
+
+ def clean(self):
+ self._result = ReturnSuccess
+
+def get_plugin():
+ return MdadmConfig
+