Martin Peřina has uploaded a new change for review.

Change subject: kdump: Add kdump plugin
......................................................................

kdump: Add kdump plugin

Adds kdump plugin to install kexec-tools package and configure
fence_kdump to enable kdump detection for the host in engine.

Change-Id: Idda48cb053c7e8747de5434c3681403f739c06b1
Bug-Url: https://bugzilla.redhat.com/1079821
Signed-off-by: Martin Perina <mper...@redhat.com>
---
M configure.ac
M po/POTFILES.in
M src/ovirt_host_deploy/constants.py
M src/plugins/ovirt-host-deploy/Makefile.am
A src/plugins/ovirt-host-deploy/kdump/Makefile.am
A src/plugins/ovirt-host-deploy/kdump/__init__.py
A src/plugins/ovirt-host-deploy/kdump/packages.py
7 files changed, 470 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-host-deploy 
refs/changes/85/28385/1

diff --git a/configure.ac b/configure.ac
index e01d4a0..2b43ea5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -178,6 +178,7 @@
        src/plugins/ovirt-host-deploy/node/Makefile
        src/plugins/ovirt-host-deploy/gluster/Makefile
        src/plugins/ovirt-host-deploy/openstack/Makefile
+       src/plugins/ovirt-host-deploy/kdump/Makefile
        src/java/Makefile
        src/java/pom.xml
        src/interface-3/Makefile
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 638005b..b9995c5 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -6,6 +6,8 @@
 ./src/plugins/ovirt-host-deploy/core/offlinepackager.py
 ./src/plugins/ovirt-host-deploy/gluster/__init__.py
 ./src/plugins/ovirt-host-deploy/gluster/packages.py
+./src/plugins/ovirt-host-deploy/kdump/__init__.py
+./src/plugins/ovirt-host-deploy/kdump/packages.py
 ./src/plugins/ovirt-host-deploy/node/detect.py
 ./src/plugins/ovirt-host-deploy/node/__init__.py
 ./src/plugins/ovirt-host-deploy/node/persist.py
diff --git a/src/ovirt_host_deploy/constants.py 
b/src/ovirt_host_deploy/constants.py
index be2e0b4..6f71311 100644
--- a/src/ovirt_host_deploy/constants.py
+++ b/src/ovirt_host_deploy/constants.py
@@ -61,6 +61,8 @@
         '/etc/neutron/plugins/openvswitch/ovs_neutron_plugin.ini'
     NRPE_CONFIG_FILE = '/etc/nagios/nrpe.cfg'
 
+    KDUMP_CONFIG_FILE = '/etc/kdump.conf'
+
 
 @util.export
 class Defaults(object):
@@ -88,6 +90,15 @@
 
 @util.export
 @util.codegen
+class KdumpEnv(object):
+    ENABLE = 'KDUMP/enable'
+    DESTINATION_ADDRESS = 'KDUMP/destinationAddress'
+    DESTINATION_PORT = 'KDUMP/destinationPort'
+    MESSAGE_INTERVAL = 'KDUMP/messageInterval'
+
+
+@util.export
+@util.codegen
 class VdsmEnv(object):
     VDSM_MINIMUM_VERSION = 'VDSM/vdsmMinimumVersion'
     CERTIFICATE_ENROLLMENT = 'VDSM/certificateEnrollment'
diff --git a/src/plugins/ovirt-host-deploy/Makefile.am 
b/src/plugins/ovirt-host-deploy/Makefile.am
index 6287580..5b3d47f 100644
--- a/src/plugins/ovirt-host-deploy/Makefile.am
+++ b/src/plugins/ovirt-host-deploy/Makefile.am
@@ -29,6 +29,7 @@
        node \
        gluster \
        openstack \
+        kdump \
        $(NULL)
 
 install-data-local:
diff --git a/src/plugins/ovirt-host-deploy/kdump/Makefile.am 
b/src/plugins/ovirt-host-deploy/kdump/Makefile.am
new file mode 100644
index 0000000..3eb1375
--- /dev/null
+++ b/src/plugins/ovirt-host-deploy/kdump/Makefile.am
@@ -0,0 +1,38 @@
+#
+# ovirt-host-deploy -- ovirt host deployer
+# Copyright (C) 2012-2014 Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+include $(top_srcdir)/build/python.inc
+
+MAINTAINERCLEANFILES = \
+       $(srcdir)/Makefile.in \
+       $(NULL)
+
+mydir=$(ovirthostdeployplugindir)/ovirt-host-deploy/kdump
+dist_my_PYTHON = \
+       __init__.py \
+       packages.py \
+       $(NULL)
+
+clean-local: \
+       python-clean \
+       $(NULL)
+
+all-local: \
+       python-syntax-check \
+       $(NULL)
diff --git a/src/plugins/ovirt-host-deploy/kdump/__init__.py 
b/src/plugins/ovirt-host-deploy/kdump/__init__.py
new file mode 100644
index 0000000..c2e2180
--- /dev/null
+++ b/src/plugins/ovirt-host-deploy/kdump/__init__.py
@@ -0,0 +1,35 @@
+#
+# ovirt-host-deploy -- ovirt host deployer
+# Copyright (C) 2012-2014 Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+
+"""fkdump plugin."""
+
+
+from otopi import util
+
+
+from . import packages
+
+
+@util.export
+def createPlugins(context):
+    packages.Plugin(context=context)
+
+
+# vim: expandtab tabstop=4 shiftwidth=4
diff --git a/src/plugins/ovirt-host-deploy/kdump/packages.py 
b/src/plugins/ovirt-host-deploy/kdump/packages.py
new file mode 100644
index 0000000..2cfb3ae
--- /dev/null
+++ b/src/plugins/ovirt-host-deploy/kdump/packages.py
@@ -0,0 +1,382 @@
+#
+# ovirt-host-deploy -- ovirt host deployer
+# Copyright (C) 2012-2014 Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+
+"""kdump packages plugin."""
+
+
+import gettext
+import optparse
+import types
+
+from distutils.version import LooseVersion
+
+_ = lambda m: gettext.dgettext(message=m, domain='ovirt-host-deploy')
+
+
+from otopi import util
+from otopi import plugin
+from otopi import constants as otopicons
+from otopi import filetransaction
+
+
+from ovirt_host_deploy import constants as odeploycons
+
+
+@util.export
+class Plugin(plugin.PluginBase):
+    """Required packages installation.
+
+    Environment:
+        KdumpEnv.ENABLE -- perform kdump detection configuration
+
+    """
+
+    _KEXEC_TOOLS_RPM = 'kexec-tools'
+
+    # min version of kexec-tools per distribution
+    _FC20_MIN_VER = '2.0.4-27.fc20'
+    _EL6_MIN_VER = '2.0.0-274.el6'
+
+    # prefixes marking changes by oVirt
+    _OVIRT_BACKUP_NODES = '# oVirt backup: fence_kdump_nodes '
+    _OVIRT_BACKUP_ARGS = '# oVirt backup: fence_kdump_args '
+
+    # fence_kdump options
+    _OPTION_NODES = 'fence_kdump_nodes '
+    _OPTION_ARGS = 'fence_kdump_args '
+
+    # fence_kump_send arguments
+    _ARG_PORT = '-p'
+    _ARG_INTERVAL = '-i'
+    _ARG_COUNT = '-c'
+    _ARG_FAMILY = '-f'
+    _ARG_VERBOSE = '-v'
+
+    # arguments default values
+    _DEFAULT_VALUES = {
+        _ARG_PORT: '7410',
+        _ARG_INTERVAL: '10',
+        _ARG_COUNT: '0',
+        _ARG_FAMILY: 'auto',
+        _ARG_VERBOSE: False,
+    }
+
+    def __init__(self, context):
+        super(Plugin, self).__init__(context=context)
+        self._enabled = False
+
+    def _strip_comments_from_line(self, line):
+        comment_start = line.find('#')
+        return line[:comment_start - 1] if comment_start != -1 else line
+
+    def _configure_fence_kdump_nodes(
+            self,
+            engine_node,
+            nodes_line,
+            nodes_backup_line
+    ):
+        new_nodes = []
+
+        self.logger.debug("Existing nodes line '%s'", nodes_line)
+        self.logger.debug("Existing nodes backup line '%s'", nodes_backup_line)
+
+        if nodes_line is None:
+            new_nodes.append(self._OPTION_NODES + engine_node + '\n')
+
+        else:
+            stripped_nodes = self._strip_comments_from_line(
+                nodes_line.rstrip('\n')
+            )
+            node_list = stripped_nodes[len(self._OPTION_NODES):].split(' ')
+            if engine_node in set(node_list):
+                # destination address is already part of existing nodes
+                if nodes_backup_line is not None:
+                    new_nodes.append(nodes_backup_line)
+                new_nodes.append(nodes_line)
+
+            else:
+                # create backup of existing settings
+                new_nodes.append(self._OVIRT_BACKUP_NODES + ' 
'.join(node_list))
+                # add destination address to existing nodes
+                new_nodes.append(
+                    stripped_nodes.rstrip('\n') + ' ' + engine_node + '\n'
+                )
+
+        self.logger.debug("New nodes lines: '%s'", new_nodes)
+
+        return new_nodes
+
+    def _parse_fence_kdump_args(self, args_line):
+        parser = optparse.OptionParser()
+        parser.add_option(
+            self._ARG_PORT,
+            '--ipport',
+            dest=self._ARG_PORT,
+            default=self._DEFAULT_VALUES[self._ARG_PORT],
+        )
+        parser.add_option(
+            self._ARG_INTERVAL,
+            '--interval',
+            dest=self._ARG_INTERVAL,
+            default=self._DEFAULT_VALUES[self._ARG_INTERVAL],
+        )
+        parser.add_option(
+            self._ARG_COUNT,
+            '--count',
+            dest=self._ARG_COUNT,
+            default=self._DEFAULT_VALUES[self._ARG_COUNT],
+        )
+        parser.add_option(
+            self._ARG_FAMILY,
+            '--family',
+            dest=self._ARG_FAMILY,
+        )
+        parser.add_option(
+            self._ARG_VERBOSE,
+            '--verbose',
+            dest=self._ARG_VERBOSE,
+            default=self._DEFAULT_VALUES[self._ARG_VERBOSE],
+            action='store_true',
+        )
+
+        (args, opts) = parser.parse_args(args_line.split(' '))
+        self.logger.debug("Parsed args: '%s'", args)
+        self.logger.debug("Parsed opts: '%s'", opts)
+
+        # remove unspecified args without default value from args_map
+        args_map = {}
+        for item in vars(args).items():
+            if item[1] is not None:
+                args_map[item[0]] = item[1]
+        self.logger.debug("Reduced args map: '%s'", args_map)
+
+        return args_map
+
+    def _get_fence_kdump_args_line(self, args_map):
+        items = []
+        for item in args_map.items():
+            # don't include args with default values
+            if item[1] != self._DEFAULT_VALUES[item[0]]:
+                items.append(item[0])
+                # don't include value for boolean options
+                if not isinstance(item[1], types.BooleanType):
+                    items.append(item[1])
+
+        return self._OPTION_ARGS + ' '.join(items) + '\n'
+
+    def _configure_fence_kdump_args(
+            self,
+            port,
+            interval,
+            count,
+            args_line,
+            args_backup_line
+    ):
+        new_args = []
+        args_map = {}
+
+        self.logger.debug("Existing args line '%s'", args_line)
+        self.logger.debug("Existing args backup line '%s'", args_backup_line)
+
+        if args_line is None:
+            args_map[self._ARG_PORT] = port
+            args_map[self._ARG_INTERVAL] = interval
+
+        else:
+            stripped_args = self._strip_comments_from_line(
+                args_line.rstrip('\n')
+            )
+            args_map = self._parse_fence_kdump_args(
+                stripped_args[len(self._OPTION_ARGS):]
+            )
+
+            if (
+                args_map[self._ARG_PORT] != port or
+                args_map[self._ARG_INTERVAL] != interval or
+                args_map[self._ARG_COUNT] != count
+            ):
+                # fence_kdump args need to be modified
+                new_args.append(
+                    self._OVIRT_BACKUP_ARGS
+                    + args_line[len(self._OPTION_ARGS):]
+                )
+
+                # udpate required args
+                args_map[self._ARG_PORT] = port
+                args_map[self._ARG_INTERVAL] = interval
+                args_map[self._ARG_COUNT] = count
+
+            else:
+                if args_backup_line is not None:
+                    new_args.append(args_backup_line)
+
+        new_args_line = self._get_fence_kdump_args_line(args_map)
+        if new_args_line:
+            new_args.append(new_args_line)
+
+        self.logger.debug("New args lines: '%s'", new_args)
+        return new_args
+
+    def _update_kdump_conf(self, content):
+        new_content = []
+        nodes_line = None
+        nodes_backup_line = None
+        args_line = None
+        args_backup_line = None
+
+        for line in content:
+            if line.startswith(self._OPTION_NODES):
+                nodes_line = line
+            elif line.startswith(self._OVIRT_BACKUP_NODES):
+                args_backup_line = line
+            elif line.startswith(self._OPTION_ARGS):
+                args_line = line
+            elif line.startswith(self._OVIRT_BACKUP_ARGS):
+                args_backup_line = line
+            else:
+                new_content.append(line)
+
+        # configure fence_kdump for oVirt
+        new_content.extend(
+            self._configure_fence_kdump_nodes(
+                engine_node=self.environment[
+                    odeploycons.KdumpEnv.DESTINATION_ADDRESS
+                ],
+                nodes_line=nodes_line,
+                nodes_backup_line=nodes_backup_line,
+            )
+        )
+        new_content.extend(
+            self._configure_fence_kdump_args(
+                port=str(
+                    self.environment[
+                        odeploycons.KdumpEnv.DESTINATION_PORT
+                    ]
+                ),
+                interval=str(
+                    self.environment[
+                        odeploycons.KdumpEnv.MESSAGE_INTERVAL
+                    ]
+                ),
+                count=self._DEFAULT_VALUES[self._ARG_COUNT],
+                args_line=args_line,
+                args_backup_line=args_backup_line,
+            )
+        )
+
+        return new_content
+
+    @plugin.event(
+        stage=plugin.Stages.STAGE_INIT,
+    )
+    def _setup(self):
+        self.environment[odeploycons.KdumpEnv.ENABLE] = False
+
+    @plugin.event(
+        stage=plugin.Stages.STAGE_VALIDATION,
+        condition=lambda self: (
+            self.environment[odeploycons.KdumpEnv.ENABLE]
+        ),
+    )
+    def _validation(self):
+        result = self.packager.queryPackages(
+            patterns=(self._KEXEC_TOOLS_RPM,),
+        )
+        if not result:
+            raise RuntimeError(
+                _(
+                    'Cannot locate kexec-tools package'
+                )
+            )
+        entry = result[0]
+        self.logger.debug('Found kexec-tools %s', entry)
+
+        cur_version = '%s-%s' % (
+            entry['version'],
+            entry['release'],
+        )
+
+        if '.el6' in cur_version:
+            min_version = self._EL6_MIN_VER
+        elif '.fc20' in cur_version:
+            min_version = self._FC20_MIN_VER
+        else:
+            min_version = None
+
+        if min_version is None:
+            raise RuntimeError(
+                _(
+                    'Kdump detection is currently supported only in Fedora 20 '
+                    'and EL6 based distributions'
+                )
+            )
+
+        if LooseVersion(min_version) > LooseVersion(cur_version):
+            raise RuntimeError(
+                _(
+                    'kexec-tools package is too old, need {minimum} found '
+                    '{version}'
+                ).format(
+                    minimum=min_version,
+                    version=cur_version,
+                )
+            )
+        self._enabled = True
+
+    @plugin.event(
+        stage=plugin.Stages.STAGE_PACKAGES,
+        condition=lambda self: self._enabled,
+    )
+    def _packages(self):
+        self.packager.installUpdate(
+            packages=(self._KEXEC_TOOLS_RPM,),
+        )
+
+    @plugin.event(
+        stage=plugin.Stages.STAGE_MISC,
+        condition=lambda self: self._enabled
+    )
+    def _reconfigure(self):
+        with open(odeploycons.FileLocations.KDUMP_CONFIG_FILE, 'r') as f:
+            content = f.read().splitlines()
+        new_content = self._update_kdump_conf(content)
+        if content != new_content:
+            self.environment[
+                otopicons.CoreEnv.MAIN_TRANSACTION
+            ].append(
+                filetransaction.FileTransaction(
+                    name=odeploycons.FileLocations.KDUMP_CONFIG_FILE,
+                    content=new_content,
+                    modifiedList=self.environment[
+                        otopicons.CoreEnv.MODIFIED_FILES
+                    ],
+                )
+            )
+
+    @plugin.event(
+        stage=plugin.Stages.STAGE_CLOSEUP,
+        condition=lambda self: self._enabled
+    )
+    def _closeup(self):
+        self.logger.info(_('Restarting kdump'))
+        for state in (False, True):
+            self.services.state('kdump', state)
+
+# vim: expandtab tabstop=4 shiftwidth=4


-- 
To view, visit http://gerrit.ovirt.org/28385
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Idda48cb053c7e8747de5434c3681403f739c06b1
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-host-deploy
Gerrit-Branch: master
Gerrit-Owner: Martin Peřina <mper...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to