Skip to content
Permalink
Browse files

Add small helper tool cmk-update-config

This program will be executed automatically in these situations

a) During the "omd update" procedure
b) On remote sites after writing the received config when the sites of
the central and remote sites differ.

The purpose of this program is to prepare the Checkmk configuration of
the local site to be read by Checkmk. The configuration files might have
been written with another Checkmk version before which can not be read
into Checkmk without modification.

Currently the tool simply loads and saves the tag, ruleset and host- and
folder configuration every time the cmk-update-config is invoked. It
leaves the transformation of the data structures to the loading
and saving code of Checkmk.

In the future we may extend this program and add transformation mechanics
exclusively to this program to keep the Checkmk program code clean.
To be able to do this we would first need to add some additional featues
like version information to the individual config files.

Change-Id: Ie286927335eafcd73d6be0c82fb88e243af791d4
  • Loading branch information...
LarsMichelsen committed May 12, 2019
1 parent a3d2067 commit 17657baea5193f540d91d64e9a1b1523730a4fb9
@@ -6,7 +6,7 @@
ROOT=/omd/sites/$SITE

make
sudo install -m 755 check_mk livedump mkeventd mkeventd_open514 mkevent mkbackup mkbench $ROOT/bin/
sudo install -m 755 check_mk livedump mkeventd mkeventd_open514 mkevent mkbackup mkbench cmk-update-config $ROOT/bin/
sudo ln -sf check_mk $ROOT/bin/cmk
sudo chown root.omd $ROOT/bin/mkeventd_open514
sudo chmod 750 $ROOT/bin/mkeventd_open514
@@ -0,0 +1,9 @@
#!/usr/bin/env python
# -*- encoding: utf-8; py-indent-offset: 4 -*-

import sys

from cmk.update_config import main

if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))
@@ -172,13 +172,23 @@ def _load_rulesets_recursively(self, folder, only_varname=None):

self._load_folder_rulesets(folder, only_varname)

# Load all rules of all folders
def load(self):
"""Load all rules of all folders"""
self._load_rulesets_recursively(Folder.root_folder())

def save_folder(self, folder):
self._save_folder(folder)

def save(self):
"""Save all rulesets of all folders recursively"""
self._save_rulesets_recursively(Folder.root_folder())

def _save_rulesets_recursively(self, folder):
for subfolder in folder.all_subfolders().values():
self._save_rulesets_recursively(subfolder)

self._save_folder(folder)


class SingleRulesetRecursively(AllRulesets):
def __init__(self, name):
@@ -0,0 +1,150 @@
#!/usr/bin/python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
# +------------------------------------------------------------------+
# | ____ _ _ __ __ _ __ |
# | / ___| |__ ___ ___| | __ | \/ | |/ / |
# | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
# | | |___| | | | __/ (__| < | | | | . \ |
# | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
# | |
# | Copyright Mathias Kettner 2016 mk@mathias-kettner.de |
# +------------------------------------------------------------------+
#
# This file is part of Check_MK.
# The official homepage is at http://mathias-kettner.de/check_mk.
#
# check_mk 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 in version 2. check_mk is distributed
# in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
# out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU General Public License for more de-
# tails. You should have received a copy of the GNU General Public
# License along with GNU Make; see the file COPYING. If not, write
# to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301 USA.
"""Tool for updating Checkmk configuration files after version updates
This command is normally executed automatically at the end of "omd update" on
all sites and on remote sites after receiving a snapshot and does not need to
be called manually.",
"""

from __future__ import (
absolute_import,
division,
print_function,
)

from typing import List # pylint: disable=unused-import
import argparse
import logging # pylint: disable=unused-import
from werkzeug.test import create_environ

import cmk.utils.log
import cmk.utils
import cmk.gui.watolib.tags
import cmk.gui.watolib.hosts_and_folders
import cmk.gui.watolib.rulesets
import cmk.gui.modules
import cmk.gui.config
import cmk.gui.htmllib as htmllib
from cmk.gui.globals import html, current_app
from cmk.gui.http import Request, Response


# TODO: Better make our application available?
class DummyApplication(object):
def __init__(self, environ, start_response):
self._environ = environ
self._start_response = start_response
self.g = {}


class UpdateConfig(object):
def __init__(self, logger, arguments):
# type: (logging.Logger, argparse.Namespace) -> None
super(UpdateConfig, self).__init__()
self._arguments = arguments
self._logger = logger

def run(self):
self._logger.info("Updating Checkmk configuration")
self._initialize_gui_environment()

for step_func, title in self._steps():
self._logger.info(" + %s..." % title)
step_func()

self._logger.info("Done")

def _steps(self):
return [
(self._rewrite_wato_tag_config, "Rewriting WATO tags"),
(self._rewrite_wato_host_and_folder_config, "Rewriting WATO hosts and folders"),
(self._rewrite_wato_rulesets, "Rewriting WATO rulesets"),
]

def _rewrite_wato_tag_config(self):
tag_config_file = cmk.gui.watolib.tags.TagConfigFile()
tag_config = cmk.utils.tags.TagConfig()
tag_config.parse_config(tag_config_file.load_for_reading())
tag_config_file.save(tag_config.get_dict_format())

def _rewrite_wato_host_and_folder_config(self):
root_folder = cmk.gui.watolib.hosts_and_folders.Folder.root_folder()
root_folder.save()
root_folder.rewrite_hosts_files()

def _rewrite_wato_rulesets(self):
all_rulesets = cmk.gui.watolib.rulesets.AllRulesets()
all_rulesets.load()
all_rulesets.save()

def _initialize_gui_environment(self):
environ = dict(create_environ(), REQUEST_URI='')
current_app.set_current(DummyApplication(environ, None))
html.set_current(htmllib.html(Request(environ), Response(is_secure=False)))

cmk.gui.modules.load_all_plugins()
cmk.gui.config.load_config()
cmk.gui.config.set_super_user()


def main(args):
# type: (List[str]) -> int
arguments = parse_arguments(args)

try:
cmk.utils.log.setup_console_logging()
cmk.utils.log.set_verbosity(arguments.verbose)
logger = cmk.utils.log.get_logger("update_config")

logger.debug("parsed arguments: %s", arguments)

UpdateConfig(logger, arguments).run()

except Exception as e:
if arguments.debug:
raise
if logger:
logger.exception("ERROR")
else:
print("ERROR: %s" % e)
return 1
return 0


def parse_arguments(args):
# type: (List[str]) -> argparse.Namespace
p = argparse.ArgumentParser(description=__doc__)
p.add_argument('--debug', action='store_true', help='Debug mode: raise Python exceptions')
p.add_argument(
'-v',
'--verbose',
action='count',
default=0,
help='Verbose mode (use multiple times for more output)')

arguments = p.parse_args(args)
return arguments
@@ -12,6 +12,7 @@ def test_basic_commands(site):
"bin/cmk",
"bin/omd",
"bin/stunnel",
"bin/cmk-update-config",
]

for rel_path in commands:
@@ -0,0 +1,35 @@
import argparse
import sys
import StringIO
import cmk.utils.log
import cmk.update_config as update_config
import cmk.gui.config


def test_parse_arguments_defaults():
assert update_config.parse_arguments([]).__dict__ == {
"debug": False,
"verbose": 0,
}


def test_parse_arguments_verbose():
assert update_config.parse_arguments(["-v"]).verbose == 1
assert update_config.parse_arguments(["-v"] * 2).verbose == 2
assert update_config.parse_arguments(["-v"] * 3).verbose == 3


def test_parse_arguments_debug():
assert update_config.parse_arguments(["--debug"]).debug is True


def test_update_config_init():
update_config.UpdateConfig(cmk.utils.log.logger, argparse.Namespace())


def test_main(monkeypatch):
buf = StringIO.StringIO()
monkeypatch.setattr(sys, "stdout", buf)
monkeypatch.setattr(update_config.UpdateConfig, "run", lambda self: sys.stdout.write("XYZ\n"))
assert update_config.main([]) == 0
assert "XYZ" in buf.getvalue()

0 comments on commit 17657ba

Please sign in to comment.
You can’t perform that action at this time.