Module: check_mk
Branch: master
Commit: 68b68730033ab28b7bf1835f399614cb1c758331
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=68b68730033ab2…
Author: Andreas Boesl <ab(a)mathias-kettner.de>
Date: Thu Nov 22 17:24:20 2018 +0100
added WK 6691: LDAP sync: Sped up user profile synchronization to slave sites
Change-Id: I95abf6734227b44d83daa3f5568650c760c4267e
---
.werks/6691 | 14 +++++
cmk/gui/plugins/userdb/ldap_connector.py | 94 +++++++++++++++++++++-----------
2 files changed, 75 insertions(+), 33 deletions(-)
diff --git a/.werks/6691 b/.werks/6691
new file mode 100644
index 0000000..8dece46
--- /dev/null
+++ b/.werks/6691
@@ -0,0 +1,14 @@
+Title: LDAP sync: Sped up user profile synchronization to slave sites
+Level: 1
+Component: wato
+Class: feature
+Compatible: compat
+Edition: cre
+State: unknown
+Version: 1.6.0i1
+Date: 1542890636
+
+The background job doing the user synchronization contacted one site after
+another when updating the credentials for one user.
+This werk changes the update mechanism. It now pushes the updated profile
+to all sites at once through multithreading.
diff --git a/cmk/gui/plugins/userdb/ldap_connector.py b/cmk/gui/plugins/userdb/ldap_connector.py
index eac85c7..b3fc8b9 100644
--- a/cmk/gui/plugins/userdb/ldap_connector.py
+++ b/cmk/gui/plugins/userdb/ldap_connector.py
@@ -66,6 +66,8 @@ import ldap
import ldap.filter
from ldap.controls import SimplePagedResultsControl
+from multiprocessing.pool import ThreadPool
+
import cmk
import cmk.paths
import cmk.log
@@ -92,9 +94,11 @@ from cmk.gui.valuespec import (
)
from cmk.gui.i18n import _
from cmk.gui.globals import html
-from cmk.gui.exceptions import MKGeneralException, MKUserError
+from cmk.gui.exceptions import MKGeneralException, MKUserError, RequestTimeout
from cmk.gui.plugins.userdb.utils import UserConnector, user_connector_registry
+import cmk.gui.sites as sites
+
if cmk.is_managed_edition():
import cmk.gui.cme.managed as managed
else:
@@ -1249,7 +1253,7 @@ class LDAPUserConnector(UserConnector):
self._logger.info(
'SYNC FINISHED - Duration: %0.3f sec, Queries: %d' % (duration, self._num_queries))
- import cmk.gui.watolib as watolib # TODO: Cleanup
+ import cmk.gui.watolib as watolib
if changes and config.wato_enabled and not config.is_wato_slave_site():
watolib.add_change("edit-users", "<br>\n".join(changes), add_user=False)
@@ -2100,7 +2104,7 @@ def ldap_needed_attributes_alias(connection, params):
ldap_attribute_plugins['alias'] = {
'title': _('Alias'),
- 'help': _('Populates the alias attribute of the WATO user by syncrhonizing an attribute '
+ 'help': _('Populates the alias attribute of the WATO user by synchronizing an attribute '
'from the LDAP user account. By default the LDAP attribute <tt>cn</tt> is used.'),
'needed_attributes': ldap_needed_attributes_alias,
'sync_func': ldap_sync_alias,
@@ -2548,7 +2552,6 @@ ldap_attribute_plugins['groups_to_roles'] = {
# | |
# '----------------------------------------------------------------------'
-
# In case the sync is done on the master of a distributed setup the auth serial
# is increased on the master, but not on the slaves. The user can not access the
# slave sites anymore with the master sites cookie since the serials differ. In
@@ -2562,49 +2565,74 @@ ldap_attribute_plugins['groups_to_roles'] = {
# time. In this case the implementation does not scale well. We would need to
# change this to some kind of profile bulk sync per site.
# TODO: Should we move this to watolib?
-def synchronize_profile_to_sites(logger, user_id, profile):
- import cmk.gui.sites as sites
- import cmk.gui.watolib as watolib # TODO: Cleanup
+
+class SynchronizationResult(object):
+ def __init__(self, site_id, error_text=None, disabled=False, succeeded=False, failed=False):
+ self.site_id = site_id
+ self.error_text = error_text
+ self.failed = failed
+ self.disabled = disabled
+ self.succeeded = succeeded
+
+
+def synchronize_profile_to_sites(logger, user_id, profile):
+ import cmk.gui.watolib as watolib
remote_sites = [(site_id, config.site(site_id)) for site_id in config.get_login_sites()]
logger.info(
'Credentials changed: %s. Trying to sync to %d sites' % (user_id, len(remote_sites)))
- num_disabled = 0
- num_succeeded = 0
- num_failed = 0
+ synchronization_jobs = []
+ states = sites.states()
+
for site_id, site in remote_sites:
- if not site.get("replication"):
- num_disabled += 1
- continue
+ synchronization_jobs.append((states, site_id, site, user_id, profile))
- if site.get("disabled"):
- num_disabled += 1
- continue
+ pool = ThreadPool()
+ results = pool.map(_sychronize_profile_worker, synchronization_jobs)
+ pool.close()
+ pool.join()
- status = sites.state(site_id, {}).get("state", "unknown")
- if status == "dead":
- result = "Site is dead"
- else:
- try:
- result = watolib.push_user_profile_to_site(site, user_id, profile)
- except Exception as e:
- result = "%s" % e
-
- if result == True:
- num_succeeded += 1
- else:
- num_failed += 1
- logger.info(' FAILED [%s]: %s' % (site_id, result))
- # Add pending entry to make sync possible later for admins
+ for result in results:
+ if result.error_text:
+ logger.info(' FAILED [%s]: %s' % (result.site_id, result.error_text))
if config.wato_enabled:
watolib.add_change(
"edit-users",
- _('Password changed (sync failed: %s)') % result,
+ _('Password changed (sync failed: %s)') % result.error_text,
add_user=False,
- sites=[site_id],
+ sites=[result.site_id],
need_restart=False)
+ num_failed = sum([1 for result in results if result.failed])
+ num_disabled = sum([1 for result in results if result.disabled])
+ num_succeeded = sum([1 for result in results if result.succeeded])
logger.info(
' Disabled: %d, Succeeded: %d, Failed: %d' % (num_disabled, num_succeeded, num_failed))
+
+
+def _sychronize_profile_worker(site_configuration):
+ import cmk.gui.watolib as watolib
+ states, site_id, site, user_id, profile = site_configuration
+
+ if not site.get("replication"):
+ return SynchronizationResult(site_id, disabled=True)
+
+ if site.get("disabled"):
+ return SynchronizationResult(site_id, disabled=True)
+
+ status = states.get(site_id, {}).get("state", "unknown")
+ if status == "dead":
+ return SynchronizationResult(
+ site_id, error_text=_("Site %s is dead") % site_id, failed=True)
+
+ try:
+ result = watolib.push_user_profile_to_site(site, user_id, profile)
+ return SynchronizationResult(site_id, succeeded=True)
+ except RequestTimeout:
+ # This function is currently only used by the background job
+ # which does not have any request timeout set, just in case...
+ raise
+ except Exception, e:
+ return SynchronizationResult(site_id, error_text="%s" % e, failed=True)
Module: check_mk
Branch: master
Commit: ef28290c2d3deec193cf1da87d0e8f4a35f13e22
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=ef28290c2d3dee…
Author: Simon Betz <si(a)mathias-kettner.de>
Date: Wed Nov 28 15:41:25 2018 +0100
6820 aws_ec2_instances_summary: New check which gives an overview of AWS/EC2 instances
Change-Id: If248c2d6a89d5e820a95cdaab9a8d20893877172
---
.werks/6820 | 10 +++++++
agents/special/agent_aws | 10 +++++--
checkman/aws_ec2_instances_summary | 14 +++++++++
checks/aws.include | 33 +++++++++++++++++++++
checks/aws_ec2_instances_summary | 61 ++++++++++++++++++++++++++++++++++++++
5 files changed, 125 insertions(+), 3 deletions(-)
diff --git a/.werks/6820 b/.werks/6820
new file mode 100644
index 0000000..5b63f91
--- /dev/null
+++ b/.werks/6820
@@ -0,0 +1,10 @@
+Title: aws_ec2_instances_summary: New check which gives an overview of AWS/EC2 instances
+Level: 1
+Component: checks
+Compatible: compat
+Edition: cre
+Version: 1.6.0i1
+Date: 1543416042
+Class: feature
+
+
diff --git a/agents/special/agent_aws b/agents/special/agent_aws
index 29892e1..af9a8de 100755
--- a/agents/special/agent_aws
+++ b/agents/special/agent_aws
@@ -172,13 +172,17 @@ class EC2InstancesSummary(AWSSection):
return "ec2_instances_summary"
def _get_raw_result(self):
- pass
+ return self._client.describe_instances()
def _extract_content_from(self, raw_result):
- pass
+ try:
+ return raw_result['Reservations']
+ except KeyError, e:
+ logging.info(e)
+ return
def _format_content(self, content):
- pass
+ return [AWSSectionResult("", content)]
class EC2Instance(AWSSection):
diff --git a/checkman/aws_ec2_instances_summary b/checkman/aws_ec2_instances_summary
new file mode 100644
index 0000000..d935fce
--- /dev/null
+++ b/checkman/aws_ec2_instances_summary
@@ -0,0 +1,14 @@
+title: AWS EC2 Instances Summary
+agents: aws
+catalog: applications
+license: GPL
+distribution: check_mk
+description:
+ This check monitors all AWS EC2 instances and reports
+ a summary of their states.
+
+ If at least one instance is not running the state is WARN
+ otherwise it is OK.
+
+inventory:
+ One summary service is created.
diff --git a/checks/aws.include b/checks/aws.include
new file mode 100644
index 0000000..6792aec
--- /dev/null
+++ b/checks/aws.include
@@ -0,0 +1,33 @@
+#!/usr/bin/python
+# -*- encoding: utf-8; py-indent-offset: 4 -*-
+# +------------------------------------------------------------------+
+# | ____ _ _ __ __ _ __ |
+# | / ___| |__ ___ ___| | __ | \/ | |/ / |
+# | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
+# | | |___| | | | __/ (__| < | | | | . \ |
+# | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
+# | |
+# | Copyright Mathias Kettner 2018 mk(a)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.
+
+
+def parse_aws(info):
+ import json
+ try:
+ return json.loads("".join(info[0]))
+ except (TypeError, IndexError):
+ return
diff --git a/checks/aws_ec2_instances_summary b/checks/aws_ec2_instances_summary
new file mode 100644
index 0000000..50637fe
--- /dev/null
+++ b/checks/aws_ec2_instances_summary
@@ -0,0 +1,61 @@
+#!/usr/bin/python
+# -*- encoding: utf-8; py-indent-offset: 4 -*-
+# +------------------------------------------------------------------+
+# | ____ _ _ __ __ _ __ |
+# | / ___| |__ ___ ___| | __ | \/ | |/ / |
+# | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
+# | | |___| | | | __/ (__| < | | | | . \ |
+# | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
+# | |
+# | Copyright Mathias Kettner 2018 mk(a)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.
+
+
+def inventory_aws_ec2_instances_summary(parsed):
+ if parsed:
+ return [(None, {})]
+
+
+def check_aws_ec2_instances_summary(item, params, parsed):
+ instances_by_state = {}
+ for reservation in parsed:
+ for instance in reservation['Instances']:
+ instances_by_state.setdefault(instance['State']['Name'], [])\
+ .append(instance['InstanceId'])
+
+ yield 0, "Instances: %s" % sum([len(v) for v in instances_by_state.itervalues()])
+
+ long_output = []
+ for instance_state, instances in instances_by_state.iteritems():
+ if instance_state == 'running':
+ state = 0
+ else:
+ state = 1
+ long_output.append("%s: %s" % (instance_state, ", ".join(instances)))
+ yield state, "%s: %s" % (instance_state, len(instances))
+
+ if long_output:
+ yield 0, "\n%s" % "\n".join(long_output)
+
+
+check_info['aws_ec2_instances_summary'] = {
+ 'parse_function': parse_aws,
+ 'inventory_function': inventory_aws_ec2_instances_summary,
+ 'check_function': check_aws_ec2_instances_summary,
+ 'service_description': 'AWS EC2 Instances',
+ 'includes': ['aws.include'],
+}
Module: check_mk
Branch: master
Commit: 06df86ec0181d602543797ed2b9bf4091ced1488
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=06df86ec0181d6…
Author: Simon Betz <si(a)mathias-kettner.de>
Date: Wed Nov 28 14:20:49 2018 +0100
6819 aws_exceptions: New check which collects all exceptions during execution of AWS special agent
Change-Id: I59c104ae3be3d991f2212e3fb50517783573edf5
---
.werks/6819 | 10 ++++++++++
checkman/aws_exceptions | 12 ++++++++++++
checks/aws_exceptions | 47 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 69 insertions(+)
diff --git a/.werks/6819 b/.werks/6819
new file mode 100644
index 0000000..1f5f21d
--- /dev/null
+++ b/.werks/6819
@@ -0,0 +1,10 @@
+Title: aws_exceptions: New check which collects all exceptions during execution of AWS special agent
+Level: 1
+Component: checks
+Compatible: compat
+Edition: cre
+Version: 1.6.0i1
+Date: 1543411225
+Class: feature
+
+
diff --git a/checkman/aws_exceptions b/checkman/aws_exceptions
new file mode 100644
index 0000000..8107b94
--- /dev/null
+++ b/checkman/aws_exceptions
@@ -0,0 +1,12 @@
+title: AWS Exceptions
+agents: aws
+catalog: applications
+license: GPL
+distribution: check_mk
+description:
+ This check collects all exceptions during the execution of the
+ special agent {{agent_aws}} for monitoring Amazon Web Service.
+ If no exceptions occur the check is OK, otherwise CRIT.
+
+inventory:
+ One service is created.
diff --git a/checks/aws_exceptions b/checks/aws_exceptions
new file mode 100644
index 0000000..b2db9fb
--- /dev/null
+++ b/checks/aws_exceptions
@@ -0,0 +1,47 @@
+#!/usr/bin/python
+# -*- encoding: utf-8; py-indent-offset: 4 -*-
+# +------------------------------------------------------------------+
+# | ____ _ _ __ __ _ __ |
+# | / ___| |__ ___ ___| | __ | \/ | |/ / |
+# | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
+# | | |___| | | | __/ (__| < | | | | . \ |
+# | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
+# | |
+# | Copyright Mathias Kettner 2018 mk(a)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.
+
+
+def inventory_aws_exceptions(info):
+ if info:
+ return [(None, {})]
+
+
+def check_aws_exceptions(item, params, info):
+ for line in info:
+ joined_line = " ".join(line)
+ if joined_line == 'No exceptions':
+ state = 0
+ else:
+ state = 2
+ yield state, joined_line
+
+
+check_info['aws_exceptions'] = {
+ 'inventory_function': inventory_aws_exceptions,
+ 'check_function': check_aws_exceptions,
+ 'service_description': 'AWS Exceptions',
+}