From 0f3cbcdfd0f3b0c2b2b4d380deafc708ad52364b Mon Sep 17 00:00:00 2001 From: Gardar Thorsteinsson Date: Tue, 12 Oct 2021 11:28:14 +0000 Subject: [PATCH 1/7] naemon support --- adagios/etc/adagios/adagios.conf | 1 - adagios/etc/adagios/adagios_naemon.conf | 115 +++++++++++++++++++++++ adagios/etc/adagios/conf.d/okconfig.conf | 1 - adagios/etc/sudoers.d/adagios_naemon | 3 + 4 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 adagios/etc/adagios/adagios_naemon.conf create mode 100644 adagios/etc/sudoers.d/adagios_naemon diff --git a/adagios/etc/adagios/adagios.conf b/adagios/etc/adagios/adagios.conf index 0a398483e..9b9265783 100644 --- a/adagios/etc/adagios/adagios.conf +++ b/adagios/etc/adagios/adagios.conf @@ -4,7 +4,6 @@ # If set, adagios will use this file to manage your object # definitions. If set to None, adagios will search most common # paths like /etc/nagios/nagios.cfg for it -#nagios_config = "/etc/nagios/nagios.cfg" nagios_config = "/etc/nagios/nagios.cfg" # This should be the URL to your nagios server. If set, then diff --git a/adagios/etc/adagios/adagios_naemon.conf b/adagios/etc/adagios/adagios_naemon.conf new file mode 100644 index 000000000..2e1c312a2 --- /dev/null +++ b/adagios/etc/adagios/adagios_naemon.conf @@ -0,0 +1,115 @@ +# -*- coding: utf-8 -*- + +# nagios_config - Path to your nagios configuration file +# If set, adagios will use this file to manage your object +# definitions. If set to None, adagios will search most common +# paths like /etc/nagios/nagios.cfg for it +nagios_config = "/etc/naemon/naemon.cfg" + +# This should be the URL to your nagios server. If set, then +# Adagios can link you directly from configuration to live object. +# If you don't need this feature. Set nagios_url to '' or None +#nagios_url = "http://mynagiosserver/nagios" +nagios_url = "/thruk" + +# destination_directory - Where adagios will store new objects +# by default. You should make sure that this directory exists +# and nagios.cfg has a cfg_dir=/etc/nagios/adagios/ +destination_directory = "/etc/naemon/adagios/" + +# livestatus_path - Path to livestatus socket +livestatus_path = None +# enable_githandler - If set to true, and your /etc/nagios/ directory +# is a git repository. adagios will automatically commit changes when +# they are made. +enable_githandler = True + +# enable_loghandler - If set to true, all changes adagios makes to +# object definitions will be logged to a file. +enable_loghandler = False + +# auto_reload - If set to True, then nagios is reloaded automatically on +# changes. Not really recommended unless you are sure you want to fire +# a nagios reload after every single change. +auto_reload = False + +# nagios_service - Service name used to start/stop nagios +# Adagios uses this to reload nagios after configuration changes +nagios_service = "naemon" + +# nagios_init_script - Path to init script used to start/stop nagios +# Adagios uses this to reload nagios after configuration changes +nagios_init_script="" + +# nagios_binary - Path to your nagios binary +# Adagios uses this to run "nagios -v /etc/nagios/nagios.cfg" +nagios_binary="/usr/bin/naemon" + + +# escape_html_tags - Escape html tags in status view +# If this is enabled, html code in plugin outputs is escaped. +# If you set this to False, then plugins will be able to inject +# HTML code into adagios web interface +escape_html_tags = True + +# warn_if_selinux_is_active - Check (and warn user) if selinux is running +# You should only turn this off if you have configured your selinux policy +# and know what you are doing +warn_if_selinux_is_active=True + + +# pnp_filepath - Path to pnp4nagios index.php +# This is used for integrated graphs into the status view +# if you do not use pnp or do not need the status view of adagios +# simply change this to any other file that exists +pnp_filepath="/usr/share/nagios/html/pnp4nagios/index.php" + + +# contrib_dir - Path to user contributed views +contrib_dir = "/var/lib/adagios/contrib/" + +# serverside_includes - Path to user contributed includes +# The files located in this directory can be used to include +# user contributed html into the header and footer of every page respectively +serverside_includes = "/etc/adagios/ssi" + +# title_prefix - Title of every page is prefixed with this. +# You can customize this if you have multiple adagios instances +# and you want to distinguish the tabs in browser. +title_prefix = "Adagios -" + + +# enable_pnp4nagios - Enable pnp4nagios support (True by default). +# Disabling this removes the pnp mouse-over graphs as well as the graphs +# tab from the status views. +enable_pnp4nagios = True + +# enable_graphite - Enable graphite integration with graphite +# If set to True, status_detail view of hosts and services +# Will show related graphs. +enable_graphite = False + +# graphite_url - URL to your graphite instance +# If specified, and enable_graphite is set to True, +# connect to this graphite instance +graphite_url = "http://localhost:9091" + +# graphite_querystring - Customize the querystring that is sent to +# graphite's /render? method. {host} {service} and {metric} will all +# be replaced with actual values while {host_} {service_} and {metric_} +# will apply common escaping techniques, i.e.: example.com becomes example_com +graphite_querystring = "target={host_}.{service_}.{metric_}&width=500&height=200&from={from_}d&lineMode=connected&title={title}&target={host_}.{service_}.{metric_}_warn&target={host_}.{service_}.{metric_}_crit" + +# graphite_title - Put this string at the top of graphite graphs +graphite_title = "{host} - {service} - {metric}" + +# A list of strings representing the host/domain names that this Django site can +# serve. This is a security measure to prevent HTTP Host header attacks +# Values in this list can be fully qualified names (e.g. www.example.com) +# A value beginning with a period can be used as a subdomain wildcard: +# '.example.com' will match example.com, www.example.com +# A value of '*' will match anything +# ALLOWED_HOSTS = ['*'] + +# Include configuration options from these config files +include="/etc/adagios/conf.d/*.conf" diff --git a/adagios/etc/adagios/conf.d/okconfig.conf b/adagios/etc/adagios/conf.d/okconfig.conf index b1ef70dd2..2394541ec 100644 --- a/adagios/etc/adagios/conf.d/okconfig.conf +++ b/adagios/etc/adagios/conf.d/okconfig.conf @@ -1,7 +1,6 @@ # Activate the okconfig plugin, but only if okconfig python module exists: try: import okconfig - #plugins['okconfig'] = 'adagios.okconfig_' plugins['okconfig'] = 'okconfig_' except ImportError: pass diff --git a/adagios/etc/sudoers.d/adagios_naemon b/adagios/etc/sudoers.d/adagios_naemon new file mode 100644 index 000000000..2eeec7797 --- /dev/null +++ b/adagios/etc/sudoers.d/adagios_naemon @@ -0,0 +1,3 @@ +Defaults:%naemon !requiretty +%naemon ALL = (root) NOPASSWD: /sbin/service naemon * +%naemon ALL = (root) NOPASSWD: /usr/bin/naemon -v /etc/naemon/naemon.cfg From e4e46826c6d082bbbc087807279594fbcf06b45d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gar=C3=B0ar=20=C3=9Eorsteinsson?= Date: Tue, 12 Oct 2021 13:16:25 +0000 Subject: [PATCH 2/7] Update adagios_naemon.conf --- adagios/etc/adagios/adagios_naemon.conf | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/adagios/etc/adagios/adagios_naemon.conf b/adagios/etc/adagios/adagios_naemon.conf index 2e1c312a2..7ab71e38c 100644 --- a/adagios/etc/adagios/adagios_naemon.conf +++ b/adagios/etc/adagios/adagios_naemon.conf @@ -9,8 +9,9 @@ nagios_config = "/etc/naemon/naemon.cfg" # This should be the URL to your nagios server. If set, then # Adagios can link you directly from configuration to live object. # If you don't need this feature. Set nagios_url to '' or None -#nagios_url = "http://mynagiosserver/nagios" -nagios_url = "/thruk" +# nagios_url = "/thruk" +# Thruk - All Unhandled Problems +nagios_url = "/thruk/#cgi-bin/status.cgi?style=combined&hst_s0_hoststatustypes=4&hst_s0_servicestatustypes=31&hst_s0_hostprops=10&hst_s0_serviceprops=0&svc_s0_hoststatustypes=3&svc_s0_servicestatustypes=28&svc_s0_hostprops=10&svc_s0_serviceprops=10&svc_s0_hostprop=2&svc_s0_hostprop=8&title=All Unhandled Problems" # destination_directory - Where adagios will store new objects # by default. You should make sure that this directory exists From 0b290c27c37340f4f68134719addd8bdb891f6c9 Mon Sep 17 00:00:00 2001 From: Gardar Thorsteinsson Date: Tue, 12 Oct 2021 16:01:24 +0000 Subject: [PATCH 3/7] get latest version using Github API --- adagios/media/js/adagios.coffee | 5 ++--- adagios/media/js/adagios.js | 8 +++----- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/adagios/media/js/adagios.coffee b/adagios/media/js/adagios.coffee index ae4e90d30..667658f0d 100644 --- a/adagios/media/js/adagios.coffee +++ b/adagios/media/js/adagios.coffee @@ -95,11 +95,10 @@ $.extend $.fn.dataTableExt.oStdClasses, $this = $(this) current_version = $('#current_version').text() - $.getJSON("https://opensource.ok.is/cgi-bin/version.cgi?version=#{current_version}&callback=?", (data) -> + $.getJSON("https://api.github.com/repos/opinkerfi/adagios/releases/latest", (data) -> this ).success( (data) -> - $this.text data['version'] - $('a#version_info').attr 'href', data['link'] + $this.text data['tag_name'] ) this diff --git a/adagios/media/js/adagios.js b/adagios/media/js/adagios.js index a5ffc92e1..9bf6f49cf 100644 --- a/adagios/media/js/adagios.js +++ b/adagios/media/js/adagios.js @@ -94,14 +94,12 @@ Generated by coffee-script, any changes should be made to the adagios.coffee fil return false; }); $.fn.adagios_version = function() { - var $this, current_version; + var $this $this = $(this); - current_version = $('#current_version').text(); - $.getJSON("https://opensource.ok.is/cgi-bin/version.cgi?version=" + current_version + "&callback=?", function(data) { + $.getJSON("https://api.github.com/repos/opinkerfi/adagios/releases/latest", function(data) { return this; }).success(function(data) { - $this.text(data['version']); - return $('a#version_info').attr('href', data['link']); + $this.text(data['tag_name']); }); return this; }; From e990f42140a2b106b956907f108a8ef52c29e5a3 Mon Sep 17 00:00:00 2001 From: Gardar Thorsteinsson Date: Thu, 14 Oct 2021 15:45:55 +0000 Subject: [PATCH 4/7] fix path --- contrib/apache_gunicorn_adagios.conf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/apache_gunicorn_adagios.conf b/contrib/apache_gunicorn_adagios.conf index 56719e457..354e8f06e 100644 --- a/contrib/apache_gunicorn_adagios.conf +++ b/contrib/apache_gunicorn_adagios.conf @@ -23,8 +23,8 @@ Alias /media /opt/adagios/adagios/media ProxyPass ! - + RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME} - ProxyPass http://127.0.0.1:8001/ - ProxyPassReverse http://127.0.0.1:8001/ + ProxyPass http://127.0.0.1:8001 + ProxyPassReverse http://127.0.0.1:8001 From e37da5cc7d20af8d2138c6c818e2b9bc884906f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gar=C3=B0ar=20=C3=9Eorsteinsson?= Date: Mon, 15 Nov 2021 20:29:20 +0000 Subject: [PATCH 5/7] fixes for passing settings correctly to pynag --- .gitignore | 3 ++- adagios/context_processors.py | 9 ++++++--- adagios/daemon.py | 21 ++++++++------------- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index 46f978177..2ebf61af6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/gunicorn.py *.pyc *.swp .project @@ -139,4 +140,4 @@ dmypy.json ### VisualStudioCode Patch ### # Ignore all local history of files .history -.ionide \ No newline at end of file +.ionide diff --git a/adagios/context_processors.py b/adagios/context_processors.py index 7e08ee50c..8dbbd49c6 100644 --- a/adagios/context_processors.py +++ b/adagios/context_processors.py @@ -6,12 +6,12 @@ # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. -# +# # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . @@ -91,7 +91,10 @@ def on_page_load(request): def update_global_variables(): """Updates all required global variables.""" - pynag.Model.cfg_file = adagios.settings.nagios_config + # pynag.Model.cfg_file = adagios.settings.nagios_config + if pynag.Model.cfg_file != adagios.settings.nagios_config: + pynag.Model.cfg_file = adagios.settings.nagios_config + Model.ObjectDefinition.objects.reload_cache() def get_current_time(request): diff --git a/adagios/daemon.py b/adagios/daemon.py index c0b5ebf67..169e15094 100644 --- a/adagios/daemon.py +++ b/adagios/daemon.py @@ -6,12 +6,12 @@ # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. -# +# # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . @@ -22,16 +22,11 @@ class Daemon(daemon): def __init__(self): - super(Daemon, self).__init__() - - # Mapping needed - if settings.nagios_binary: - self.nagios_bin = settings.nagios_binary - if settings.nagios_config: - self.nagios_cfg = settings.nagios_config - if settings.nagios_init_script: - self.nagios_init = settings.nagios_init_script - if settings.nagios_service: - self.service_name = settings.nagios_service + super().__init__( + nagios_bin=settings.nagios_binary, + nagios_cfg=settings.nagios_config, + nagios_init=settings.nagios_init_script, + service_name=settings.nagios_service, + ) # vim: sts=4 expandtab autoindent From 5053ac44544d152f1f176526b16218038804545f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gar=C3=B0ar=20=C3=9Eorsteinsson?= Date: Mon, 15 Nov 2021 20:41:16 +0000 Subject: [PATCH 6/7] removed code smell --- adagios/context_processors.py | 1 - 1 file changed, 1 deletion(-) diff --git a/adagios/context_processors.py b/adagios/context_processors.py index 8dbbd49c6..610dc3b13 100644 --- a/adagios/context_processors.py +++ b/adagios/context_processors.py @@ -91,7 +91,6 @@ def on_page_load(request): def update_global_variables(): """Updates all required global variables.""" - # pynag.Model.cfg_file = adagios.settings.nagios_config if pynag.Model.cfg_file != adagios.settings.nagios_config: pynag.Model.cfg_file = adagios.settings.nagios_config Model.ObjectDefinition.objects.reload_cache() From 943f026b98b513772be7a7a5db48223b81d8e76b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gar=C3=B0ar=20=C3=9Eorsteinsson?= Date: Thu, 7 Nov 2024 12:55:59 +0000 Subject: [PATCH 7/7] Fix Expected string error Should fix ValueError: Expected string. Got --- adagios/objectbrowser/forms.py | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/adagios/objectbrowser/forms.py b/adagios/objectbrowser/forms.py index c6542a92d..2e5148c2e 100644 --- a/adagios/objectbrowser/forms.py +++ b/adagios/objectbrowser/forms.py @@ -71,7 +71,6 @@ otherhost,127.0.0.2,generic-host """ - class PynagAutoCompleteField(forms.CharField): """ Behaves like Charfield, but includes data-choices for select2 autocomplete. """ def __init__(self, object_type, inline_help_text=None, complete="shortname", *args, **kwargs): @@ -83,7 +82,7 @@ def __init__(self, object_type, inline_help_text=None, complete="shortname", *ar inline_help_text = inline_help_text.format(object_type=object_type) self.widget.attrs['data-placeholder'] = inline_help_text - # Add autcomplete choices in data-choices + # Add autocomplete choices in data-choices if complete == 'shortname': choices = self.get_all_shortnames(object_type=object_type) elif complete == 'name': @@ -97,8 +96,7 @@ def __init__(self, object_type, inline_help_text=None, complete="shortname", *ar self.widget.attrs['class'] = self.widget.attrs.get('class', '') self.widget.attrs['class'] += ' pynag-autocomplete ' - # Hardcode widget length to 500px, because select2 plays badly - # with css + # Hardcode widget length to 500px, because select2 plays badly with css self.widget.attrs['style'] = self.widget.attrs.get('style', '') self.widget.attrs['style'] += ' width: 500px; ' @@ -109,7 +107,6 @@ def get_all_shortnames(self, object_type): # Remove objects with no shortname shortnames = [x for x in shortnames if x] - return shortnames def get_all_object_names(self, object_type): @@ -128,23 +125,21 @@ def get_all_objects(self, object_type): return objects def prepare_value(self, value): - """ - Takes a comma separated string, removes + if it is prefixed so. Returns a comma seperated string - """ + """Ensures the value is a comma-separated string without a prefixed '+'.""" if value == 'null': return value + elif isinstance(value, list): + return ', '.join(value) elif isinstance(value, string_types): a = AttributeList(value) self.__prefix = a.operator a.operator = '' - a = str(a) - value = a + return str(a) return value class PynagChoiceField(forms.MultipleChoiceField): - - """ multichoicefields that accepts comma seperated input as values """ + """ Multichoice fields that accept comma-separated input as values """ def __init__(self, inline_help_text=_("Select some options"), *args, **kwargs): self.__prefix = '' @@ -154,7 +149,7 @@ def __init__(self, inline_help_text=_("Select some options"), *args, **kwargs): def clean(self, value): """ - Changes list into a comma separated string. Removes duplicates. + Changes list into a comma-separated string. Removes duplicates. """ if not value: return "null" @@ -166,17 +161,16 @@ def clean(self, value): return value def prepare_value(self, value): - """ - Takes a comma separated string, removes + if it is prefixed so. Returns a list - """ + """Converts value to a list if it is a comma-separated string, otherwise handles as list.""" if value is None: return [] + if isinstance(value, list): + return value # Already a list, return as-is if isinstance(value, string_types): self.attributelist = AttributeList(value) self.__prefix = self.attributelist.operator return self.attributelist.fields - else: - raise ValueError("Expected string. Got %s" % type(value)) + return value def set_prefix(self, value): self.__prefix = value