From: Kenneth D'souza <kdsouza(a)redhat.com>
A cmdline tool to edit and retrieve information from /etc/kdump.conf.
This tool will avoid typos and have basic sanity check for options.
Signed-off-by: Kenneth D'souza <kdsouza(a)redhat.com>
---
kdump-config.py | 281 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 281 insertions(+)
create mode 100755 kdump-config.py
diff --git a/kdump-config.py b/kdump-config.py
new file mode 100755
index 0000000..07b3201
--- /dev/null
+++ b/kdump-config.py
@@ -0,0 +1,281 @@
+#!/usr/bin/python
+# kdump-config.py - cmdline tool to display and manipulate configuration information of /etc/kdump.conf
+# Author: Kenneth D'souza <kdsouza(a)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 sys
+import os
+import stat
+import argparse
+import subprocess
+
+CONFIG_FILE = "/etc/kdump.conf"
+
+
+# Filter comments and optional settings.
+def filter_data(data):
+ comments = []
+ data_without_comments = []
+ for line in data:
+ line = line.strip()
+ if line.startswith('#'):
+ comments.append(line)
+ else:
+ data_without_comments.append(line)
+ return comments, data_without_comments
+
+
+# Get only unique data, avoids duplicate.
+def unique(data_without_comments, option):
+ unique_data = set()
+ for line in data_without_comments:
+ if len(line.split()) > 1:
+ if line.startswith(
+ ("path", "core_collector", "raw", "nfs", "ssh", "kdump_post",
+ "kdump_pre", "extra_bins", "extra_modules", "sshkey",
+ "default", "debug_mem_level", "force_rebuild",
+ "force_no_rebuild", "dracut_args", "fence_kdump_args",
+ "fence_kdump_nodes", "ext2", "ext3", "ext4", "btfs", "minix",
+ "xfs")):
+ if line not in unique_data and not line.startswith(option + ' '):
+ if option == "ssh":
+ if not line.startswith(
+ ("nfs", "raw", "ext4", "ext3", "ext2",
+ "xfs", "btrfs", "minix")):
+ unique_data.add(line)
+ elif option == "nfs":
+ if not line.startswith(
+ ("ssh", "raw", "ext4", "ext3", "ext2", "xfs",
+ "btrfs", "minix")):
+ unique_data.add(line)
+ elif option == "raw":
+ if not line.startswith(
+ ("nfs", "ssh", "ext4", "ext3", "ext2", "xfs",
+ "btrfs", "minix")):
+ unique_data.add(line)
+ elif option in ("ext2", "ext3", "ext4", "xfs", "btrfs",
+ "minix"):
+ if not line.startswith(("ssh", "nfs", "raw")):
+ unique_data.add(line)
+ else:
+ unique_data.add(line)
+ return unique_data
+
+
+# We cannot have both the options set to be 1.
+def check_for_mutual_exculsive(unique_data):
+ for line in unique_data:
+ if line.startswith("force_no_rebuild") or line.startswith(
+ "force_rebuild"):
+ optional = line.split()[1]
+ if optional == value == "1":
+ print("force_no_rebuild and force_rebuild cannot be 1 at the same time.")
+ return True
+ return False
+
+
+# Check if ssh server is set, if not give warning.
+def checks_for_ssh(unique_data):
+ for line in unique_data:
+ if line.find("ssh") != -1:
+ return True
+ return False
+
+
+# Write changes to the file with comments, unique data and optional
+# settings given by the user.
+def replace_value_write(comments, unique_data, option, value, unset_value):
+ try:
+ with open(CONFIG_FILE, "r+") as f:
+ f.seek(0)
+ f.truncate()
+ for item in comments:
+ f.write("%s\n" % item)
+ for i in range(len(unique_data)):
+ f.write("%s\n" % unique_data[i])
+ if not unset_value:
+ append_txt = ("%s %s\n" % (option, value))
+ f.write("%s" % append_txt)
+ f.close()
+ except IOError as reason:
+ print("You need to have root privileges to run this option.")
+ print("%s" % reason)
+
+
+# Read the file only once and save the data.
+def check(CONFIG_FILE, option, value, unset_value):
+ with open(CONFIG_FILE, "r") as f1:
+ data = f1.readlines()
+ comments, data_without_comments = filter_data(data)
+ unique_data = list(unique(data_without_comments, option))
+ unique_data = list(filter(None, unique_data))
+ if option == "force_no_rebuild" or option == "force_rebuild" and value == "1":
+ result = check_for_mutual_exculsive(unique_data)
+ if result:
+ sys.exit(1)
+ if option == "sshkey":
+ result_ssh = checks_for_ssh(unique_data)
+ if not result_ssh:
+ print("Warning: Remember to add an entry for ssh")
+ replace_value_write(comments, unique_data, option, value, unset_value)
+ f1.close()
+
+
+# Check if the device is valid, check the option passed and work accordingly:
+def check_device(option, value):
+ try:
+ if not stat.S_ISBLK(os.lstat(value).st_mode):
+ print("not a valid device '%s'" % value)
+ elif option == "raw":
+ check(CONFIG_FILE, option, args.raw, False)
+ else:
+ cmd = subprocess.Popen(
+ "lsblk --nodeps -p -n -o FSTYPE,UUID %s " % (value),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ shell=True)
+ option = cmd.communicate()[0].strip().decode()
+ fstype, UUID = option.split()
+ if fstype in ("ext2", "ext3", "ext4", "xfs", "btrfs", "minix"):
+ check(CONFIG_FILE, fstype, "UUID=" + UUID, False)
+ else:
+ print("Filesystem '%s' not supported." % fstype)
+ except ValueError:
+ print("'%s' does not contain a valid Filesystem." % value)
+ except Exception:
+ print("not a valid device '%s'" % value)
+
+
+# Check if dump target is mounted:
+def check_mnt(nfs_mount):
+ cmd = subprocess.Popen(
+ "findmnt -t nfs,nfs4 %s -o SOURCE -n " % (nfs_mount),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ shell=True)
+ option = cmd.communicate()[0].strip().decode()
+ if not option.strip():
+ print("Error: Dump target '%s' is probably not mounted or valid" %
+ nfs_mount)
+ else:
+ check(CONFIG_FILE, "nfs", option, False)
+
+
+# Display configuration settings from /etc/kdump.conf:
+def display_show_config(data_without_comments):
+ for item in data_without_comments:
+ print(item)
+
+
+# Check if kdump config file exists.
+try:
+ lines = open(CONFIG_FILE).readlines()
+except IOError as reason:
+ print("Error reading kdump configuration.")
+ exit("%s" % reason)
+
+# Check if no arguments are given.
+if len(sys.argv) < 2:
+ exit("Please specify an action to perform. \nTry `kdump-config --help' for more information.")
+
+parser = argparse.ArgumentParser(
+ description="Please specify an action to perform,")
+parser.add_argument(
+ "--path",
+ help="path represents the file system path in which vmcore will be saved.")
+parser.add_argument("--raw", help=" specify raw device ex: /dev/sdc1")
+parser.add_argument(
+ "--nfs", help="specify nfs-server ex: my.server.com:/export/tmp")
+parser.add_argument("--ssh", help="specify ssh server ex: user(a)my.server.com")
+parser.add_argument(
+ "--sshkey", help="specify the path of the ssh key to use when dumping.")
+parser.add_argument(
+ "--showconfig", action="store_true", help="show configuration settings.")
+parser.add_argument(
+ "--local_fs", help="specify local device ex: /dev/myvg/mylv")
+parser.add_argument("--unset", help="unset a given option ex: path")
+parser.add_argument(
+ "--force_no_rebuild",
+ choices=["1", "0"],
+ help="specify 1 to bypass rebuilding of kdump initrd.")
+parser.add_argument(
+ "--force_rebuild",
+ choices=["1", "0"],
+ help="specify 1 to force rebuilding kdump initrd every time when kdump service starts.")
+parser.add_argument(
+ "--default",
+ choices=["reboot", "halt", "poweroff", "shell", "dump_to_rootfs"],
+ help="Action to perform in case dumping to the intended target fails.")
+
+args = parser.parse_args()
+
+if args.default:
+ option = "default"
+ value = args.default
+ check(CONFIG_FILE, option, value, False)
+
+if args.path:
+ option = "path"
+ value = args.path
+ check(CONFIG_FILE, option, value, False)
+
+if args.showconfig:
+ with open(CONFIG_FILE, "r") as f2:
+ data = f2.readlines()
+ comments, data_without_comments = filter_data(data)
+ display_show_config(data_without_comments)
+
+if args.raw:
+ option = "raw"
+ device = os.path.realpath(args.raw)
+ check_device(option, device)
+
+if args.force_rebuild:
+ option = "force_rebuild"
+ value = args.force_rebuild
+ check(CONFIG_FILE, option, value, False)
+
+if args.force_no_rebuild:
+ option = "force_no_rebuild"
+ value = args.force_no_rebuild
+ check(CONFIG_FILE, option, value, False)
+
+if args.nfs:
+ option = "nfs"
+ value = args.nfs
+ check_mnt(value)
+
+if args.ssh:
+ option = "ssh"
+ value = args.ssh
+ check(CONFIG_FILE, option, value, False)
+
+if args.sshkey:
+ if not os.path.isfile(args.sshkey):
+ exit("Invalid file '%s'" % args.sshkey)
+ option = "sshkey"
+ value = args.sshkey
+ check(CONFIG_FILE, option, value, False)
+
+if args.local_fs:
+ device = os.path.realpath(args.local_fs)
+ option = "local"
+ check_device(option, device)
+
+if args.unset:
+ option = args.unset
+ value = ""
+ check(CONFIG_FILE, option, value, True)
--
2.14.3