Module: check_mk
Branch: master
Commit: 7f276d4fe9bdc3278518efd4f46ef4b02b8ea06d
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=7f276d4fe9bdc3…
Author: Tom Baerwinkel <tb(a)mathias-kettner.de>
Date: Fri Mar 1 14:55:00 2019 +0100
7062 Improvement of the graphing with PNP4Nagios for various checks
When PNP4Nagios is used Check_MK tries to use autogenerated graph templates
to paint the graphs of a check. If the capabilities for Check_MKs autogeneration
of graph templates is insufficient Check_MK provides a fallback to handcrafted
templates.
This werk extends the capabilities of Check_MKs autogeneration of PNP templates
and makes a lot of handcrafted PNP templates unnecessary. Therefore, these
templates are removed. This results in an overall more pleasant and uniform
graphing.
PNP4Nagios is used if the raw edition is used or if the enterprise edition is
used together with the Nagios core.
Change-Id: I31c680f89d307e054ff2428b2065a01de484c555
---
.werks/7062 | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/.werks/7062 b/.werks/7062
new file mode 100644
index 0000000..b07a480
--- /dev/null
+++ b/.werks/7062
@@ -0,0 +1,21 @@
+Title: Improvement of the graphing with PNP4Nagios for various checks
+Level: 1
+Component: checks
+Compatible: compat
+Edition: cre
+Version: 1.6.0i1
+Date: 1551447666
+Class: feature
+
+When PNP4Nagios is used Check_MK tries to use autogenerated graph templates
+to paint the graphs of a check. If the capabilities for Check_MKs autogeneration
+of graph templates is insufficient Check_MK provides a fallback to handcrafted
+templates.
+
+This werk extends the capabilities of Check_MKs autogeneration of PNP templates
+and makes a lot of handcrafted PNP templates unnecessary. Therefore, these
+templates are removed. This results in an overall more pleasant and uniform
+graphing.
+
+PNP4Nagios is used if the raw edition is used or if the enterprise edition is
+used together with the Nagios core.
Module: check_mk
Branch: master
Commit: 85cfa9084c5a3391977e91b7c9bb70829319018f
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=85cfa9084c5a33…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Sat Mar 2 19:49:49 2019 +0100
Move some more backup related code to omdlib.backup
Change-Id: Ib42c952853554170c045c50e82847ef6efca322a
---
omd/packages/omd/omdlib/backup.py | 23 +++++++++++++++++++++++
omd/packages/omd/omdlib/main.py | 15 +++------------
2 files changed, 26 insertions(+), 12 deletions(-)
diff --git a/omd/packages/omd/omdlib/backup.py b/omd/packages/omd/omdlib/backup.py
index 661c728..70ca46b 100644
--- a/omd/packages/omd/omdlib/backup.py
+++ b/omd/packages/omd/omdlib/backup.py
@@ -30,6 +30,7 @@ import errno
import socket
import tarfile
import fnmatch
+from typing import Tuple # pylint: disable=unused-import
def backup_site_to_tarfile(site, fh, mode, options, verbose):
@@ -212,3 +213,25 @@ class BackupTarFile(tarfile.TarFile):
if self._sock:
self._resume_all_rrds()
self._sock.close()
+
+
+def get_site_and_version_from_backup(tar):
+ # type: (tarfile.TarFile) -> Tuple[str, str]
+ """Get the first file of the tar archive. Expecting <site>/version symlink
+ for validation reasons."""
+ site_tarinfo = tar.next()
+ if site_tarinfo is None:
+ raise Exception("Failed to detect version of backed up site.")
+
+ try:
+ sitename, version_name = site_tarinfo.name.split("/", 1)
+ except ValueError:
+ raise Exception("Failed to detect version of backed up site. "
+ "Maybe the backup is from an incompatible version.")
+
+ if version_name == "version":
+ version = site_tarinfo.linkname.split('/')[-1]
+ else:
+ raise Exception("Failed to detect version of backed up site.")
+
+ return sitename, version
diff --git a/omd/packages/omd/omdlib/main.py b/omd/packages/omd/omdlib/main.py
index a68023d..a860480 100644
--- a/omd/packages/omd/omdlib/main.py
+++ b/omd/packages/omd/omdlib/main.py
@@ -3610,19 +3610,10 @@ def main_restore(site, args, options=None):
except tarfile.ReadError as e:
bail_out("Failed to open the backup: %s" % e)
- # Get the first file of the tar archive. Expecting <site>/version symlink
- # for validation reasons.
- site_tarinfo = tar.next()
try:
- sitename, version_name = site_tarinfo.name.split("/", 1)
- except ValueError:
- bail_out("Failed to detect version of backed up site. "
- "Maybe the backup is from an incompatible version.")
-
- if version_name == "version":
- version = site_tarinfo.linkname.split('/')[-1]
- else:
- bail_out("Failed to detect version of backed up site.")
+ sitename, version = omdlib.backup.get_site_and_version_from_backup(tar)
+ except Exception as e:
+ bail_out(e)
if not version_exists(version):
bail_out("You need to have version %s installed to be able to restore "
Module: check_mk
Branch: master
Commit: c647025b6b00ac08f9be79daa694913ed6b4fcca
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=c647025b6b00ac…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Mon Mar 4 09:01:39 2019 +0100
7224 FIX Backup/Restore: Fix vanishing files terminating a backup
The "omd backup" mechanism recursively backups all site related
files of a Check_MK site. When files in a site directory, that
is currently being processed vanish, this could lead to failed
backups with errors like this:
C+:
Site backup failed: Traceback (most recent call last):
File "/omd/versions/1.5.0p8.cee/bin/omd", line 4553, in
command_function(args, command_options)
File "/omd/versions/1.5.0p8.cee/bin/omd", line 3711, in main_backup
backup_site_to_tarfile(fh, tar_mode, options)
File "/omd/versions/1.5.0p8.cee/bin/omd", line 3686, in backup_site_to_tarfile
backup_site_files_to_tarfile(tar, options)
File "/omd/versions/1.5.0p8.cee/bin/omd", line 3556, in backup_site_files_to_tarfile
tar.add(g_sitedir, g_sitename, exclude=filter_files)
File "/omd/versions/1.5.0p8.cee/lib/python2.7/tarfile.py", line 2032, in add
recursive, exclude, filter)
File "/omd/versions/1.5.0p8.cee/lib/python2.7/tarfile.py", line 2032, in add
recursive, exclude, filter)
File "/omd/versions/1.5.0p8.cee/lib/python2.7/tarfile.py", line 2032, in add
recursive, exclude, filter)
File "/omd/versions/1.5.0p8.cee/lib/python2.7/tarfile.py", line 2032, in add
recursive, exclude, filter)
File "/omd/versions/1.5.0p8.cee/lib/python2.7/tarfile.py", line 2032, in add
recursive, exclude, filter)
File "/omd/versions/1.5.0p8.cee/lib/python2.7/tarfile.py", line 2009, in add
tarinfo = self.gettarinfo(name, arcname)
File "/omd/versions/1.5.0p8.cee/lib/python2.7/tarfile.py", line 1881, in gettarinfo
statres = os.lstat(name)
OSError: [Errno 2] No such file or directory: '/omd/sites/xyz/var/pnp4nagios/perfdata/hastenichgesehn/Interface_BG4_2OG_VLAN_421.xml.new'
C-:
After this change the backup continues in such a situation
excluding the just vanished file.
Change-Id: Ic76bc983ebd221687e2f249bf6bcb3389f348aa2
---
.werks/7224 | 43 ++++++++++++++++++++
omd/packages/omd/omdlib/backup.py | 18 ++++++++-
tests/unit/omdlib/test_backup.py | 85 +++++++++++++++++++++++++++++++++++++++
3 files changed, 144 insertions(+), 2 deletions(-)
diff --git a/.werks/7224 b/.werks/7224
new file mode 100644
index 0000000..b067d0e
--- /dev/null
+++ b/.werks/7224
@@ -0,0 +1,43 @@
+Title: Backup/Restore: Fix vanishing files terminating a backup
+Level: 2
+Component: omd
+Compatible: compat
+Edition: cre
+Version: 1.6.0i1
+Date: 1551685160
+Class: fix
+
+The "omd backup" mechanism recursively backups all site related
+files of a Check_MK site. When files in a site directory, that
+is currently being processed vanish, this could lead to failed
+backups with errors like this:
+
+C+:
+Site backup failed: Traceback (most recent call last):
+File "/omd/versions/1.5.0p8.cee/bin/omd", line 4553, in
+command_function(args, command_options)
+File "/omd/versions/1.5.0p8.cee/bin/omd", line 3711, in main_backup
+backup_site_to_tarfile(fh, tar_mode, options)
+File "/omd/versions/1.5.0p8.cee/bin/omd", line 3686, in backup_site_to_tarfile
+backup_site_files_to_tarfile(tar, options)
+File "/omd/versions/1.5.0p8.cee/bin/omd", line 3556, in backup_site_files_to_tarfile
+tar.add(g_sitedir, g_sitename, exclude=filter_files)
+File "/omd/versions/1.5.0p8.cee/lib/python2.7/tarfile.py", line 2032, in add
+recursive, exclude, filter)
+File "/omd/versions/1.5.0p8.cee/lib/python2.7/tarfile.py", line 2032, in add
+recursive, exclude, filter)
+File "/omd/versions/1.5.0p8.cee/lib/python2.7/tarfile.py", line 2032, in add
+recursive, exclude, filter)
+File "/omd/versions/1.5.0p8.cee/lib/python2.7/tarfile.py", line 2032, in add
+recursive, exclude, filter)
+File "/omd/versions/1.5.0p8.cee/lib/python2.7/tarfile.py", line 2032, in add
+recursive, exclude, filter)
+File "/omd/versions/1.5.0p8.cee/lib/python2.7/tarfile.py", line 2009, in add
+tarinfo = self.gettarinfo(name, arcname)
+File "/omd/versions/1.5.0p8.cee/lib/python2.7/tarfile.py", line 1881, in gettarinfo
+statres = os.lstat(name)
+OSError: [Errno 2] No such file or directory: '/omd/sites/xyz/var/pnp4nagios/perfdata/hastenichgesehn/Interface_BG4_2OG_VLAN_421.xml.new'
+C-:
+
+After this change the backup continues in such a situation
+excluding the just vanished file.
diff --git a/omd/packages/omd/omdlib/backup.py b/omd/packages/omd/omdlib/backup.py
index 70ca46b..268574c 100644
--- a/omd/packages/omd/omdlib/backup.py
+++ b/omd/packages/omd/omdlib/backup.py
@@ -106,7 +106,7 @@ class BackupTarFile(tarfile.TarFile):
"""We need to use our tarfile class here to perform a rrdcached SUSPEND/RESUME
to prevent writing to individual RRDs during backups."""
- def __init__(self, *args, **kwargs):
+ def __init__(self, name, mode, fileobj, **kwargs):
self._site = kwargs.pop("site")
self._verbose = kwargs.pop("verbose")
self._site_stopped = self._site.is_stopped()
@@ -114,7 +114,21 @@ class BackupTarFile(tarfile.TarFile):
self._sock = None
self._sites_path = os.path.realpath("/omd/sites")
- super(BackupTarFile, self).__init__(*args, **kwargs)
+ super(BackupTarFile, self).__init__(name, mode, fileobj, **kwargs)
+
+ # We override this function to workaround an issue in the builtin add() method in
+ # case it is called in recursive mode and a file vanishes between the os.listdir()
+ # and the first file access (often seen os.lstat()) during backup. Instead of failing
+ # like this we want to skip those files silently during backup.
+ def add(self, name, arcname=None, recursive=True, exclude=None, filter=None): # pylint: disable=redefined-builtin
+ try:
+ super(BackupTarFile, self).add(name, arcname, recursive, exclude, filter)
+ except OSError as e:
+ if e.errno != errno.ENOENT or arcname == self._site.name:
+ raise
+
+ if self._verbose:
+ sys.stdout.write("Skipping vanished file: %s\n" % arcname)
def addfile(self, tarinfo, fileobj=None):
# In case of a stopped site or stopped rrdcached there is no
diff --git a/tests/unit/omdlib/test_backup.py b/tests/unit/omdlib/test_backup.py
new file mode 100644
index 0000000..d6b6942
--- /dev/null
+++ b/tests/unit/omdlib/test_backup.py
@@ -0,0 +1,85 @@
+# encoding: utf-8
+# pylint: disable=redefined-outer-name
+
+import tarfile
+import pytest # type: ignore
+from pathlib2 import Path
+import omdlib
+import omdlib.main
+import omdlib.backup
+
+
+(a)pytest.fixture()
+def site(tmp_path, monkeypatch):
+ monkeypatch.setattr(omdlib, "__version__", "1.3.3i7.cee")
+ omd_root = tmp_path / "site"
+ omd_root.mkdir(parents=True, exist_ok=True)
+ (omd_root / "version").symlink_to("../versions/%s" % omdlib.__version__)
+
+ class UnitTestSite(omdlib.main.SiteContext):
+ @property
+ def dir(self):
+ return str(omd_root)
+
+ return UnitTestSite("unit")
+
+
+def test_backup_site_to_tarfile(site, tmp_path):
+ # Write some file for testing the backup procedure
+ with Path(site.dir + "/test123").open("w", encoding="utf-8") as f:
+ f.write(u"uftauftauftata")
+
+ tar_path = tmp_path / "backup.tar"
+ with tar_path.open("wb") as backup_tar:
+ omdlib.backup.backup_site_to_tarfile(site, backup_tar, mode="w:", options={}, verbose=False)
+
+ with tar_path.open("rb") as backup_tar:
+ tar = tarfile.open(fileobj=backup_tar, mode="r:*")
+ sitename, version = omdlib.backup.get_site_and_version_from_backup(tar)
+ assert sitename == "unit"
+ assert version == "1.3.3i7.cee"
+
+ names = [tarinfo.name for tarinfo in tar]
+ assert "unit/test123" in names
+
+
+def test_backup_site_to_tarfile_broken_link(site, tmp_path):
+ Path(site.dir + "/link").symlink_to("agag")
+
+ tar_path = tmp_path / "backup.tar"
+ with tar_path.open("wb") as backup_tar:
+ omdlib.backup.backup_site_to_tarfile(site, backup_tar, mode="w:", options={}, verbose=False)
+
+ with tar_path.open("rb") as backup_tar:
+ tar = tarfile.open(fileobj=backup_tar, mode="r:*")
+ _sitename, _version = omdlib.backup.get_site_and_version_from_backup(tar)
+
+ link = tar.getmember("unit/link")
+ assert link.linkname == "agag"
+
+
+def test_backup_site_to_tarfile_vanishing_files(site, tmp_path, monkeypatch):
+ test_dir = Path(site.dir) / "xyz"
+ test_file = test_dir / "test_file"
+ test_dir.mkdir(parents=True, exist_ok=True) # pylint: disable=no-member
+ test_file.touch() # pylint: disable=no-member
+
+ orig_add = omdlib.backup.BackupTarFile.add
+
+ def add(self, name, arcname=None, recursive=True, exclude=None, filter=None): # pylint: disable=redefined-builtin
+ # The add() was called for test_dir which then calls os.listdir() and
+ # add() for all found entries. Remove the test_file here to simulate
+ # a vanished file during this step.
+ if arcname == "unit/xyz/test_file":
+ test_file.unlink() # pylint: disable=no-member
+ orig_add(self, name, arcname, recursive, exclude, filter)
+
+ monkeypatch.setattr(omdlib.backup.BackupTarFile, "add", add)
+
+ tar_path = tmp_path / "backup.tar"
+ with tar_path.open("wb") as backup_tar:
+ omdlib.backup.backup_site_to_tarfile(site, backup_tar, mode="w:", options={}, verbose=False)
+
+ with tar_path.open("rb") as backup_tar:
+ tar = tarfile.open(fileobj=backup_tar, mode="r:*")
+ _sitename, _version = omdlib.backup.get_site_and_version_from_backup(tar)
Module: check_mk
Branch: master
Commit: 363fcec610db70d7c4f8338b29f82dc6de66fbb5
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=363fcec610db70…
Author: Moritz Kiemer <mo(a)mathias-kettner.de>
Date: Mon Mar 4 08:14:27 2019 +0100
7204 mk_jolokia.py: Auto-detect product type
The plugin now detects the product type from the jolokia info section,
if the user did not provide it explicitly.
Change-Id: I819878034834837347a9b17f31a3339ebbcbade5
---
.werks/7204 | 12 ++++++++++++
agents/plugins/mk_jolokia.py | 7 +++++--
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/.werks/7204 b/.werks/7204
new file mode 100644
index 0000000..eaab79b
--- /dev/null
+++ b/.werks/7204
@@ -0,0 +1,12 @@
+Title: mk_jolokia.py: Auto-detect product type if not configured
+Level: 1
+Component: checks
+Compatible: compat
+Edition: cre
+Version: 1.6.0i1
+Date: 1551683726
+Class: feature
+
+The plugin now detects the product type from the jolokia info section,
+if the user did not provide it explicitly.
+
diff --git a/agents/plugins/mk_jolokia.py b/agents/plugins/mk_jolokia.py
index 039a003..3bdb85f 100755
--- a/agents/plugins/mk_jolokia.py
+++ b/agents/plugins/mk_jolokia.py
@@ -154,7 +154,8 @@ DEFAULT_CONFIG_TUPLES = (
("service_url", None),
("service_user", None),
("service_password", None),
- ("product", None, "Product description. Available: %s" % \
+ ("product", None, "Product description. Available: %s. If not provided," \
+ " we try to detect the product from the jolokia info section." % \
", ".join(QUERY_SPECS_SPECIFIC.keys())),
("timeout", 1.0, "Connection/read timeout for requests."),
("custom_vars", []),
@@ -492,8 +493,10 @@ def generate_jolokia_info(inst):
info = data.get('info', {})
version = info.get('version', "unknown")
product = info.get('product', "unknown")
- if inst.product:
+ if inst.product is not None:
product = inst.product
+ else:
+ inst.product = product
agentversion = data.get('agent', "unknown")
yield inst.name, product, version, agentversion