From 5d41fffa00e07dc8b469b56be045cf4f7b423713 Mon Sep 17 00:00:00 2001 From: Tim Bielawa Date: Mon, 27 Aug 2012 01:50:52 -0400 Subject: [PATCH 1/6] Groundwork for nagios module. --- library/nagios | 772 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 772 insertions(+) create mode 100644 library/nagios diff --git a/library/nagios b/library/nagios new file mode 100644 index 00000000000..b4c7f1883fa --- /dev/null +++ b/library/nagios @@ -0,0 +1,772 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# This file is largely copied from the Nagios module included in the +# Func project. Original copyright follows: +# +# func-nagios - Schedule downtime and enables/disable notifications +# Copyright © 2011, Red Hat, Inc. +# Tim Bielawa +# +# This software may be freely redistributed under the terms of the GNU +# general public license version 2. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +""" + + +remaining tasks: + + +- figure out why services=foo1,foo2,...fooN doesn't show output for each +fooX + + +- cleanup each methods return statements so they're not doing strange thigs. + +-> really, we only need to exit 'couldnt' write to command file' in ONE place + + +- finish up reading from a config file + + + + +""" + + +import ConfigParser +import types +import time + + +class Nagios(object): + """ + Perform common tasks in Nagios related to downtime and + notifications. + + The complete set of external commands Nagios handles is documented + on their website: + + http://old.nagios.org/developerinfo/externalcommands/commandlist.php + + Note that in the case of `schedule_svc_downtime`, + `enable_svc_notifications`, and `disable_svc_notifications`, the + service argument should be passed as a list. + + Configuration: + + If your nagios cmdfile is not /var/spool/nagios/cmd/nagios.cmd you + can configure this by creating a file called + /etc/ansible/modules/nagios.conf that looks like this: + + [main] + cmdfile = /path/to/your/nagios.cmd + + """ + + def __init__(self, module, **kwargs): + self.module = module + self.action = kwargs['action'] + self.author = kwargs['author'] + self.host = kwargs['host'] + self.minutes = int(kwargs['minutes']) + self.cmdfile = kwargs['cmdfile'] + + if (kwargs['services'] is None) or (kwargs['services'] == 'host'): + self.services = kwargs['services'] + else: + self.services = kwargs['services'].split(',') + + self.command_results = [] + + def _now(self): + """ + The time in seconds since 12:00:00AM Jan 1, 1970 + """ + + return int(time.time()) + + def _write_command(self, cmd): + """ + Write the given command to the Nagios command file + """ + + try: + fp = open(self.cmdfile, 'w') + fp.write(cmd) + fp.flush() + fp.close() + self.command_results.append(cmd.strip()) + except IOError: + self.module.fail_json(msg='unable to write to nagios command file', cmdfile=self.cmdfile) + + def _fmt_dt_str(self, cmd, host, duration, author=None, + comment="Scheduling downtime", start=None, + svc=None, fixed=1, trigger=0): + """ + Format an external-command downtime string. + + cmd - Nagios command ID + host - Host schedule downtime on + duration - Minutes to schedule downtime for + author - Name to file the downtime as + comment - Reason for running this command (upgrade, reboot, etc) + start - Start of downtime in seconds since 12:00AM Jan 1 1970 + Default is to use the entry time (now) + svc - Service to schedule downtime for, omit when for host downtime + fixed - Start now if 1, start when a problem is detected if 0 + trigger - Optional ID of event to start downtime from. Leave as 0 for + fixed downtime. + + Syntax: [submitted] COMMAND;;[] + ;;;;;; + + """ + + entry_time = self._now() + if start is None: + start = entry_time + + hdr = "[%s] %s;%s;" % (entry_time, cmd, host) + duration_s = (duration * 60) + end = start + duration_s + + if not author: + author = self.author + + if svc is not None: + dt_args = [svc, str(start), str(end), str(fixed), str(trigger), + str(duration_s), author, comment] + else: + # Downtime for a host if no svc specified + dt_args = [str(start), str(end), str(fixed), str(trigger), + str(duration_s), author, comment] + + dt_arg_str = ";".join(dt_args) + dt_str = hdr + dt_arg_str + "\n" + + return dt_str + + def _fmt_notif_str(self, cmd, host, svc=None): + """ + Format an external-command notification string. + + cmd - Nagios command ID. + host - Host to en/disable notifications on.. + svc - Service to schedule downtime for. A value is not required + for host downtime. + + Syntax: [submitted] COMMAND;[;] + """ + + entry_time = self._now() + if svc is not None: + notif_str = "[%s] %s;%s;%s\n" % (entry_time, cmd, host, svc) + else: + # Downtime for a host if no svc specified + notif_str = "[%s] %s;%s\n" % (entry_time, cmd, host) + + return notif_str + + def schedule_svc_downtime(self, host, services=[], minutes=30): + """ + This command is used to schedule downtime for a particular + service. + + During the specified downtime, Nagios will not send + notifications out about the service. + + Syntax: SCHEDULE_SVC_DOWNTIME;; + ;;;;;; + + """ + + cmd = "SCHEDULE_SVC_DOWNTIME" + nagios_return = True + return_str_list = [] + for service in services: + dt_cmd_str = self._fmt_dt_str(cmd, host, minutes, svc=service) + nagios_return = nagios_return and self._write_command(dt_cmd_str) + return_str_list.append(dt_cmd_str) + + if nagios_return: + return return_str_list + else: + return "Fail: could not write to the command file" + + def schedule_host_downtime(self, host, minutes=30): + """ + This command is used to schedule downtime for a particular + host. + + During the specified downtime, Nagios will not send + notifications out about the host. + + Syntax: SCHEDULE_HOST_DOWNTIME;;;; + ;;;; + """ + + cmd = "SCHEDULE_HOST_DOWNTIME" + dt_cmd_str = self._fmt_dt_str(cmd, host, minutes) + nagios_return = self._write_command(dt_cmd_str) + + if nagios_return: + return dt_cmd_str + else: + return "Fail: could not write to the command file" + + def schedule_hostgroup_host_downtime(self, hostgroup, minutes=30): + """ + This command is used to schedule downtime for all hosts in a + particular hostgroup. + + During the specified downtime, Nagios will not send + notifications out about the hosts. + + Syntax: SCHEDULE_HOSTGROUP_HOST_DOWNTIME;;; + ;;;;; + """ + + cmd = "SCHEDULE_HOSTGROUP_HOST_DOWNTIME" + dt_cmd_str = self._fmt_dt_str(cmd, hostgroup, minutes) + nagios_return = self._write_command(dt_cmd_str) + + if nagios_return: + return dt_cmd_str + else: + return "Fail: could not write to the command file" + + def schedule_hostgroup_svc_downtime(self, hostgroup, minutes=30): + """ + This command is used to schedule downtime for all services in + a particular hostgroup. + + During the specified downtime, Nagios will not send + notifications out about the services. + + Note that scheduling downtime for services does not + automatically schedule downtime for the hosts those services + are associated with. + + Syntax: SCHEDULE_HOSTGROUP_SVC_DOWNTIME;;; + ;;;;; + """ + + cmd = "SCHEDULE_HOSTGROUP_SVC_DOWNTIME" + dt_cmd_str = self._fmt_dt_str(cmd, hostgroup, minutes) + nagios_return = self._write_command(dt_cmd_str) + + if nagios_return: + return dt_cmd_str + else: + return "Fail: could not write to the command file" + + def schedule_servicegroup_host_downtime(self, servicegroup, minutes=30): + """ + This command is used to schedule downtime for all hosts in a + particular servicegroup. + + During the specified downtime, Nagios will not send + notifications out about the hosts. + + Syntax: SCHEDULE_SERVICEGROUP_HOST_DOWNTIME;; + ;;;;;; + + """ + + cmd = "SCHEDULE_SERVICEGROUP_HOST_DOWNTIME" + dt_cmd_str = self._fmt_dt_str(cmd, servicegroup, minutes) + nagios_return = self._write_command(dt_cmd_str) + + if nagios_return: + return dt_cmd_str + else: + return "Fail: could not write to the command file" + + def schedule_servicegroup_svc_downtime(self, servicegroup, minutes=30): + """ + This command is used to schedule downtime for all services in + a particular servicegroup. + + During the specified downtime, Nagios will not send + notifications out about the services. + + Note that scheduling downtime for services does not + automatically schedule downtime for the hosts those services + are associated with. + + Syntax: SCHEDULE_SERVICEGROUP_SVC_DOWNTIME;; + ;;;;;; + + """ + + cmd = "SCHEDULE_SERVICEGROUP_SVC_DOWNTIME" + dt_cmd_str = self._fmt_dt_str(cmd, servicegroup, minutes) + nagios_return = self._write_command(dt_cmd_str) + + if nagios_return: + return dt_cmd_str + else: + return "Fail: could not write to the command file" + + def disable_host_svc_notifications(self, host): + """ + This command is used to prevent notifications from being sent + out for all services on the specified host. + + Note that this command does not disable notifications from + being sent out about the host. + + Syntax: DISABLE_HOST_SVC_NOTIFICATIONS; + """ + + cmd = "DISABLE_HOST_SVC_NOTIFICATIONS" + notif_str = self._fmt_notif_str(cmd, host) + nagios_return = self._write_command(notif_str) + + if nagios_return: + return notif_str + else: + return "Fail: could not write to the command file" + + def disable_host_notifications(self, host): + """ + This command is used to prevent notifications from being sent + out for the specified host. + + Note that this command does not disable notifications for + services associated with this host. + + Syntax: DISABLE_HOST_NOTIFICATIONS; + """ + + cmd = "DISABLE_HOST_NOTIFICATIONS" + notif_str = self._fmt_notif_str(cmd, host) + nagios_return = self._write_command(notif_str) + + if nagios_return: + return notif_str + else: + return "Fail: could not write to the command file" + + def disable_svc_notifications(self, host, services=[]): + """ + This command is used to prevent notifications from being sent + out for the specified service. + + Note that this command does not disable notifications from + being sent out about the host. + + Syntax: DISABLE_SVC_NOTIFICATIONS;; + """ + + cmd = "DISABLE_SVC_NOTIFICATIONS" + nagios_return = True + return_str_list = [] + for service in services: + notif_str = self._fmt_notif_str(cmd, host, svc=service) + nagios_return = nagios_return and self._write_command(notif_str) + return_str_list.append(notif_str) + + if nagios_return: + return return_str_list + else: + return "Fail: could not write to the command file" + + def disable_servicegroup_host_notifications(self, servicegroup): + """ + This command is used to prevent notifications from being sent + out for all hosts in the specified servicegroup. + + Note that this command does not disable notifications for + services associated with hosts in this service group. + + Syntax: DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS; + """ + + cmd = "DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS" + notif_str = self._fmt_notif_str(cmd, servicegroup) + nagios_return = self._write_command(notif_str) + + if nagios_return: + return notif_str + else: + return "Fail: could not write to the command file" + + def disable_servicegroup_svc_notifications(self, servicegroup): + """ + This command is used to prevent notifications from being sent + out for all services in the specified servicegroup. + + Note that this does not prevent notifications from being sent + out about the hosts in this servicegroup. + + Syntax: DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS; + """ + + cmd = "DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS" + notif_str = self._fmt_notif_str(cmd, servicegroup) + nagios_return = self._write_command(notif_str) + + if nagios_return: + return notif_str + else: + return "Fail: could not write to the command file" + + def disable_hostgroup_host_notifications(self, hostgroup): + """ + Disables notifications for all hosts in a particular + hostgroup. + + Note that this does not disable notifications for the services + associated with the hosts in the hostgroup - see the + DISABLE_HOSTGROUP_SVC_NOTIFICATIONS command for that. + + Syntax: DISABLE_HOSTGROUP_HOST_NOTIFICATIONS; + """ + + cmd = "DISABLE_HOSTGROUP_HOST_NOTIFICATIONS" + notif_str = self._fmt_notif_str(cmd, hostgroup) + nagios_return = self._write_command(notif_str) + + if nagios_return: + return notif_str + else: + return "Fail: could not write to the command file" + + def disable_hostgroup_svc_notifications(self, hostgroup): + """ + Disables notifications for all services associated with hosts + in a particular hostgroup. + + Note that this does not disable notifications for the hosts in + the hostgroup - see the DISABLE_HOSTGROUP_HOST_NOTIFICATIONS + command for that. + + Syntax: DISABLE_HOSTGROUP_SVC_NOTIFICATIONS; + """ + + cmd = "DISABLE_HOSTGROUP_SVC_NOTIFICATIONS" + notif_str = self._fmt_notif_str(cmd, hostgroup) + nagios_return = self._write_command(notif_str) + + if nagios_return: + return notif_str + else: + return "Fail: could not write to the command file" + + def enable_host_notifications(self, host): + """ + Enables notifications for a particular host. + + Note that this command does not enable notifications for + services associated with this host. + + Syntax: ENABLE_HOST_NOTIFICATIONS; + """ + + cmd = "ENABLE_HOST_NOTIFICATIONS" + notif_str = self._fmt_notif_str(cmd, host) + nagios_return = self._write_command(notif_str) + + if nagios_return: + return notif_str + else: + return "Fail: could not write to the command file" + + def enable_host_svc_notifications(self, host): + """ + Enables notifications for all services on the specified host. + + Note that this does not enable notifications for the host. + + Syntax: ENABLE_HOST_SVC_NOTIFICATIONS; + """ + + cmd = "ENABLE_HOST_SVC_NOTIFICATIONS" + notif_str = self._fmt_notif_str(cmd, host) + nagios_return = self._write_command(notif_str) + + if nagios_return: + return notif_str + else: + return "Fail: could not write to the command file" + + def enable_svc_notifications(self, host, services=[]): + """ + Enables notifications for a particular service. + + Note that this does not enable notifications for the host. + + Syntax: ENABLE_SVC_NOTIFICATIONS;; + """ + + cmd = "ENABLE_SVC_NOTIFICATIONS" + nagios_return = True + return_str_list = [] + for service in services: + notif_str = self._fmt_notif_str(cmd, host, svc=service) + nagios_return = nagios_return and self._write_command(notif_str) + return_str_list.append(notif_str) + + if nagios_return: + return return_str_list + else: + return "Fail: could not write to the command file" + + def enable_hostgroup_host_notifications(self, hostgroup): + """ + Enables notifications for all hosts in a particular hostgroup. + + Note that this command does not enable notifications for + services associated with the hosts in this hostgroup. + + Syntax: ENABLE_HOSTGROUP_HOST_NOTIFICATIONS; + """ + + cmd = "ENABLE_HOSTGROUP_HOST_NOTIFICATIONS" + notif_str = self._fmt_notif_str(cmd, hostgroup) + nagios_return = self._write_command(notif_str) + + if nagios_return: + return notif_str + else: + return "Fail: could not write to the command file" + + def enable_hostgroup_svc_notifications(self, hostgroup): + """ + Enables notifications for all services that are associated + with hosts in a particular hostgroup. + + Note that this does not enable notifications for the hosts in + this hostgroup. + + Syntax: ENABLE_HOSTGROUP_SVC_NOTIFICATIONS; + """ + + cmd = "ENABLE_HOSTGROUP_SVC_NOTIFICATIONS" + notif_str = self._fmt_notif_str(cmd, hostgroup) + nagios_return = self._write_command(notif_str) + + if nagios_return: + return notif_str + else: + return "Fail: could not write to the command file" + + def enable_servicegroup_host_notifications(self, servicegroup): + """ + Enables notifications for all hosts that have services that + are members of a particular servicegroup. + + Note that this command does not enable notifications for + services associated with the hosts in this servicegroup. + + Syntax: ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS; + """ + + cmd = "ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS" + notif_str = self._fmt_notif_str(cmd, servicegroup) + nagios_return = self._write_command(notif_str) + + if nagios_return: + return notif_str + else: + return "Fail: could not write to the command file" + + def enable_servicegroup_svc_notifications(self, servicegroup): + """ + Enables notifications for all services that are members of a + particular servicegroup. + + Note that this does not enable notifications for the hosts in + this servicegroup. + + Syntax: ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS; + """ + + cmd = "ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS" + notif_str = self._fmt_notif_str(cmd, servicegroup) + nagios_return = self._write_command(notif_str) + + if nagios_return: + return notif_str + else: + return "Fail: could not write to the command file" + + def silence_host(self, host): + """ + This command is used to prevent notifications from being sent + out for the host and all services on the specified host. + + This is equivalent to calling disable_host_svc_notifications + and disable_host_notifications. + + Syntax: DISABLE_HOST_SVC_NOTIFICATIONS; + Syntax: DISABLE_HOST_NOTIFICATIONS; + """ + + cmd = [ + "DISABLE_HOST_SVC_NOTIFICATIONS", + "DISABLE_HOST_NOTIFICATIONS" + ] + nagios_return = True + return_str_list = [] + for c in cmd: + notif_str = self._fmt_notif_str(c, host) + nagios_return = nagios_return and self._write_command(notif_str) + return_str_list.append(notif_str) + + if nagios_return: + return return_str_list + else: + return "Fail: could not write to the command file" + + def unsilence_host(self, host): + """ + This command is used to enable notifications for the host and + all services on the specified host. + + This is equivalent to calling enable_host_svc_notifications + and enable_host_notifications. + + Syntax: ENABLE_HOST_SVC_NOTIFICATIONS; + Syntax: ENABLE_HOST_NOTIFICATIONS; + """ + + cmd = [ + "ENABLE_HOST_SVC_NOTIFICATIONS", + "ENABLE_HOST_NOTIFICATIONS" + ] + nagios_return = True + return_str_list = [] + for c in cmd: + notif_str = self._fmt_notif_str(c, host) + nagios_return = nagios_return and self._write_command(notif_str) + return_str_list.append(notif_str) + + if nagios_return: + return return_str_list + else: + return "Fail: could not write to the command file" + + def act(self): + """ + Figure out what you want to do from ansible, and then do the + needful (at the earliest). + """ + # host or service downtime? + if self.action == 'downtime': + if self.services == 'host': + self.schedule_host_downtime(self.host, self.minutes) + else: + self.schedule_svc_downtime(self.host, + services=self.services, + minutes=self.minutes) + + # toggle the host AND service alerts + elif self.action == 'silence': + self.silence_host(self.host) + + elif self.action == 'unsilence': + self.unsilence_host(self.host) + + # toggle host/svc alerts + elif self.action == 'enable_alerts': + if self.services == 'host': + self.enable_host_notifications(self.host) + else: + self.enable_svc_notifications(self.host, + services=self.services) + + elif self.action == 'disable_alerts': + if self.services == 'host': + self.disable_host_notifications(self.host) + else: + self.disable_svc_notifications(self.host, + services=self.services) + # wtf? + else: + self.module.fail_json(msg="unknown action specified: '%s'" % \ + self.action) + + self.module.exit_json(nagios_commands=self.command_results, + changed=True) + +###################################################################### +# Ansible module configuration + + +def which_cmdfile(): + CFG = '/etc/ansible/modules/nagios.conf' + default_cmdfile = '/var/spool/nagios/cmd/nagios.cmd' + + try: + c = ConfigParser.read(CFG) + return c.get('main', 'cmdfile', default_cmdfile) + except: + return default_cmdfile + + +###################################################################### +def main(): + ACTION_CHOICES = [ + 'downtime', + 'silence', + 'unsilence', + 'enable_alerts', + 'disable_alerts' + ] + + module = AnsibleModule( + argument_spec=dict( + action=dict(required=True, default=None, choices=ACTION_CHOICES), + author=dict(default='Ansible'), + host=dict(required=True, default=None), + minutes=dict(default=30), + cmdfile=dict(default='/var/spool/nagios/cmd/nagios.cmd'), + services=dict(default=None, aliases=['service']), + ) + ) + + action = module.params['action'] + minutes = module.params['minutes'] + services = module.params['services'] + + ################################################################## + # Required args per action: + # downtime = (minutes, service, host) + # (un)silence = (host) + # (enable/disable)_alerts = (service, host) + # + # AnsibleModule will verify most stuff, we need to verify + # 'minutes' and 'service' manually. + + ################################################################## + if action == 'downtime': + # Make sure there's an actual service selected + if not services: + module.fail_json(msg='no service selected to set downtime for') + # Make sure minutes is a number + try: + m = int(minutes) + if not isinstance(m, types.IntType): + module.fail_json(msg='minutes must be a number') + except: + module.fail_json(msg='invalid entry for minutes') + + ################################################################## + if action in ['enable_alerts', 'disable_alerts']: + if not services: + module.fail_json(msg='a service is required when setting alerts') + + ################################################################## + ansible_nagios = Nagios(module, **module.params) + ansible_nagios.act() + +# this is magic, see lib/ansible/module_common.py +#<> +main() From 62ffeb93a517c48f8b5f5af4a3081c1c5406adbc Mon Sep 17 00:00:00 2001 From: Tim Bielawa Date: Mon, 27 Aug 2012 11:08:16 -0400 Subject: [PATCH 2/6] Services iterate correctly now Cleaned up return methods --- library/nagios | 120 ++++++++----------------------------------------- 1 file changed, 18 insertions(+), 102 deletions(-) diff --git a/library/nagios b/library/nagios index b4c7f1883fa..d10a9cd1672 100644 --- a/library/nagios +++ b/library/nagios @@ -16,25 +16,17 @@ """ - - remaining tasks: - - figure out why services=foo1,foo2,...fooN doesn't show output for each fooX - - cleanup each methods return statements so they're not doing strange thigs. -> really, we only need to exit 'couldnt' write to command file' in ONE place - finish up reading from a config file - - - - """ @@ -96,7 +88,7 @@ class Nagios(object): """ try: - fp = open(self.cmdfile, 'w') + fp = open(self.cmdfile, 'a') fp.write(cmd) fp.flush() fp.close() @@ -186,17 +178,9 @@ class Nagios(object): """ cmd = "SCHEDULE_SVC_DOWNTIME" - nagios_return = True - return_str_list = [] for service in services: dt_cmd_str = self._fmt_dt_str(cmd, host, minutes, svc=service) - nagios_return = nagios_return and self._write_command(dt_cmd_str) - return_str_list.append(dt_cmd_str) - - if nagios_return: - return return_str_list - else: - return "Fail: could not write to the command file" + self._write_command(dt_cmd_str) def schedule_host_downtime(self, host, minutes=30): """ @@ -212,12 +196,7 @@ class Nagios(object): cmd = "SCHEDULE_HOST_DOWNTIME" dt_cmd_str = self._fmt_dt_str(cmd, host, minutes) - nagios_return = self._write_command(dt_cmd_str) - - if nagios_return: - return dt_cmd_str - else: - return "Fail: could not write to the command file" + self._write_command(dt_cmd_str) def schedule_hostgroup_host_downtime(self, hostgroup, minutes=30): """ @@ -233,12 +212,7 @@ class Nagios(object): cmd = "SCHEDULE_HOSTGROUP_HOST_DOWNTIME" dt_cmd_str = self._fmt_dt_str(cmd, hostgroup, minutes) - nagios_return = self._write_command(dt_cmd_str) - - if nagios_return: - return dt_cmd_str - else: - return "Fail: could not write to the command file" + self._write_command(dt_cmd_str) def schedule_hostgroup_svc_downtime(self, hostgroup, minutes=30): """ @@ -258,12 +232,7 @@ class Nagios(object): cmd = "SCHEDULE_HOSTGROUP_SVC_DOWNTIME" dt_cmd_str = self._fmt_dt_str(cmd, hostgroup, minutes) - nagios_return = self._write_command(dt_cmd_str) - - if nagios_return: - return dt_cmd_str - else: - return "Fail: could not write to the command file" + self._write_command(dt_cmd_str) def schedule_servicegroup_host_downtime(self, servicegroup, minutes=30): """ @@ -280,12 +249,7 @@ class Nagios(object): cmd = "SCHEDULE_SERVICEGROUP_HOST_DOWNTIME" dt_cmd_str = self._fmt_dt_str(cmd, servicegroup, minutes) - nagios_return = self._write_command(dt_cmd_str) - - if nagios_return: - return dt_cmd_str - else: - return "Fail: could not write to the command file" + self._write_command(dt_cmd_str) def schedule_servicegroup_svc_downtime(self, servicegroup, minutes=30): """ @@ -306,12 +270,7 @@ class Nagios(object): cmd = "SCHEDULE_SERVICEGROUP_SVC_DOWNTIME" dt_cmd_str = self._fmt_dt_str(cmd, servicegroup, minutes) - nagios_return = self._write_command(dt_cmd_str) - - if nagios_return: - return dt_cmd_str - else: - return "Fail: could not write to the command file" + self._write_command(dt_cmd_str) def disable_host_svc_notifications(self, host): """ @@ -326,12 +285,7 @@ class Nagios(object): cmd = "DISABLE_HOST_SVC_NOTIFICATIONS" notif_str = self._fmt_notif_str(cmd, host) - nagios_return = self._write_command(notif_str) - - if nagios_return: - return notif_str - else: - return "Fail: could not write to the command file" + self._write_command(notif_str) def disable_host_notifications(self, host): """ @@ -346,12 +300,7 @@ class Nagios(object): cmd = "DISABLE_HOST_NOTIFICATIONS" notif_str = self._fmt_notif_str(cmd, host) - nagios_return = self._write_command(notif_str) - - if nagios_return: - return notif_str - else: - return "Fail: could not write to the command file" + self._write_command(notif_str) def disable_svc_notifications(self, host, services=[]): """ @@ -365,17 +314,9 @@ class Nagios(object): """ cmd = "DISABLE_SVC_NOTIFICATIONS" - nagios_return = True - return_str_list = [] for service in services: notif_str = self._fmt_notif_str(cmd, host, svc=service) - nagios_return = nagios_return and self._write_command(notif_str) - return_str_list.append(notif_str) - - if nagios_return: - return return_str_list - else: - return "Fail: could not write to the command file" + self._write_command(notif_str) def disable_servicegroup_host_notifications(self, servicegroup): """ @@ -390,12 +331,7 @@ class Nagios(object): cmd = "DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS" notif_str = self._fmt_notif_str(cmd, servicegroup) - nagios_return = self._write_command(notif_str) - - if nagios_return: - return notif_str - else: - return "Fail: could not write to the command file" + self._write_command(notif_str) def disable_servicegroup_svc_notifications(self, servicegroup): """ @@ -410,12 +346,7 @@ class Nagios(object): cmd = "DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS" notif_str = self._fmt_notif_str(cmd, servicegroup) - nagios_return = self._write_command(notif_str) - - if nagios_return: - return notif_str - else: - return "Fail: could not write to the command file" + self._write_command(notif_str) def disable_hostgroup_host_notifications(self, hostgroup): """ @@ -431,12 +362,7 @@ class Nagios(object): cmd = "DISABLE_HOSTGROUP_HOST_NOTIFICATIONS" notif_str = self._fmt_notif_str(cmd, hostgroup) - nagios_return = self._write_command(notif_str) - - if nagios_return: - return notif_str - else: - return "Fail: could not write to the command file" + self._write_command(notif_str) def disable_hostgroup_svc_notifications(self, hostgroup): """ @@ -452,12 +378,7 @@ class Nagios(object): cmd = "DISABLE_HOSTGROUP_SVC_NOTIFICATIONS" notif_str = self._fmt_notif_str(cmd, hostgroup) - nagios_return = self._write_command(notif_str) - - if nagios_return: - return notif_str - else: - return "Fail: could not write to the command file" + self._write_command(notif_str) def enable_host_notifications(self, host): """ @@ -471,12 +392,7 @@ class Nagios(object): cmd = "ENABLE_HOST_NOTIFICATIONS" notif_str = self._fmt_notif_str(cmd, host) - nagios_return = self._write_command(notif_str) - - if nagios_return: - return notif_str - else: - return "Fail: could not write to the command file" + self._write_command(notif_str) def enable_host_svc_notifications(self, host): """ @@ -510,7 +426,7 @@ class Nagios(object): return_str_list = [] for service in services: notif_str = self._fmt_notif_str(cmd, host, svc=service) - nagios_return = nagios_return and self._write_command(notif_str) + nagios_return = self._write_command(notif_str) and nagios_return return_str_list.append(notif_str) if nagios_return: @@ -617,7 +533,7 @@ class Nagios(object): return_str_list = [] for c in cmd: notif_str = self._fmt_notif_str(c, host) - nagios_return = nagios_return and self._write_command(notif_str) + nagios_return = self._write_command(notif_str) and nagios_return return_str_list.append(notif_str) if nagios_return: @@ -645,7 +561,7 @@ class Nagios(object): return_str_list = [] for c in cmd: notif_str = self._fmt_notif_str(c, host) - nagios_return = nagios_return and self._write_command(notif_str) + nagios_return = self._write_command(notif_str) and nagios_return return_str_list.append(notif_str) if nagios_return: From 9829033a8a85fccee7aaf9a7c75e7add9097708b Mon Sep 17 00:00:00 2001 From: Tim Bielawa Date: Mon, 27 Aug 2012 11:30:13 -0400 Subject: [PATCH 3/6] Now reading from a config file actually works. --- library/nagios | 177 ++++++++++++++++++++++++------------------------- 1 file changed, 87 insertions(+), 90 deletions(-) diff --git a/library/nagios b/library/nagios index d10a9cd1672..627be773844 100644 --- a/library/nagios +++ b/library/nagios @@ -14,19 +14,20 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . - """ -remaining tasks: - -- figure out why services=foo1,foo2,...fooN doesn't show output for each -fooX -- cleanup each methods return statements so they're not doing strange thigs. +Configuration: --> really, we only need to exit 'couldnt' write to command file' in ONE place +If your nagios cmdfile is not /var/spool/nagios/cmd/nagios.cmd you +can configure ansible (on your nagios server) to use the correct +one by making a file called /etc/ansible/modules/nagios.conf that +looks like this: + [main] + cmdfile = /path/to/your/nagios.cmd -- finish up reading from a config file +When calling this module via ansible, use the 'cmdfile' parameter to +set it explicitly. """ @@ -34,7 +35,82 @@ import ConfigParser import types import time +MODULE_CONFIG = '/etc/ansible/modules/nagios.conf' +DEFAULT_CMDFILE = '/var/spool/nagios/cmd/nagios.cmd' + +###################################################################### + + +def which_cmdfile(): + try: + config = ConfigParser.SafeConfigParser({'cmdfile': DEFAULT_CMDFILE}) + config.read(MODULE_CONFIG) + return config.get('main', 'cmdfile') + except: + return DEFAULT_CMDFILE + + +###################################################################### + + +def main(): + ACTION_CHOICES = [ + 'downtime', + 'silence', + 'unsilence', + 'enable_alerts', + 'disable_alerts' + ] + + module = AnsibleModule( + argument_spec=dict( + action=dict(required=True, default=None, choices=ACTION_CHOICES), + author=dict(default='Ansible'), + host=dict(required=True, default=None), + minutes=dict(default=30), + cmdfile=dict(default=which_cmdfile()), + services=dict(default=None, aliases=['service']), + ) + ) + + action = module.params['action'] + minutes = module.params['minutes'] + services = module.params['services'] + + ################################################################## + # Required args per action: + # downtime = (minutes, service, host) + # (un)silence = (host) + # (enable/disable)_alerts = (service, host) + # + # AnsibleModule will verify most stuff, we need to verify + # 'minutes' and 'service' manually. + + ################################################################## + if action == 'downtime': + # Make sure there's an actual service selected + if not services: + module.fail_json(msg='no service selected to set downtime for') + # Make sure minutes is a number + try: + m = int(minutes) + if not isinstance(m, types.IntType): + module.fail_json(msg='minutes must be a number') + except: + module.fail_json(msg='invalid entry for minutes') + + ################################################################## + if action in ['enable_alerts', 'disable_alerts']: + if not services: + module.fail_json(msg='a service is required when setting alerts') + + ################################################################## + ansible_nagios = Nagios(module, **module.params) + ansible_nagios.act() + ################################################################## + +###################################################################### class Nagios(object): """ Perform common tasks in Nagios related to downtime and @@ -48,16 +124,6 @@ class Nagios(object): Note that in the case of `schedule_svc_downtime`, `enable_svc_notifications`, and `disable_svc_notifications`, the service argument should be passed as a list. - - Configuration: - - If your nagios cmdfile is not /var/spool/nagios/cmd/nagios.cmd you - can configure this by creating a file called - /etc/ansible/modules/nagios.conf that looks like this: - - [main] - cmdfile = /path/to/your/nagios.cmd - """ def __init__(self, module, **kwargs): @@ -88,13 +154,14 @@ class Nagios(object): """ try: - fp = open(self.cmdfile, 'a') + fp = open(self.cmdfile, 'w') fp.write(cmd) fp.flush() fp.close() self.command_results.append(cmd.strip()) except IOError: - self.module.fail_json(msg='unable to write to nagios command file', cmdfile=self.cmdfile) + self.module.fail_json(msg='unable to write to nagios command file', + cmdfile=self.cmdfile) def _fmt_dt_str(self, cmd, host, duration, author=None, comment="Scheduling downtime", start=None, @@ -613,76 +680,6 @@ class Nagios(object): changed=True) ###################################################################### -# Ansible module configuration - - -def which_cmdfile(): - CFG = '/etc/ansible/modules/nagios.conf' - default_cmdfile = '/var/spool/nagios/cmd/nagios.cmd' - - try: - c = ConfigParser.read(CFG) - return c.get('main', 'cmdfile', default_cmdfile) - except: - return default_cmdfile - - -###################################################################### -def main(): - ACTION_CHOICES = [ - 'downtime', - 'silence', - 'unsilence', - 'enable_alerts', - 'disable_alerts' - ] - - module = AnsibleModule( - argument_spec=dict( - action=dict(required=True, default=None, choices=ACTION_CHOICES), - author=dict(default='Ansible'), - host=dict(required=True, default=None), - minutes=dict(default=30), - cmdfile=dict(default='/var/spool/nagios/cmd/nagios.cmd'), - services=dict(default=None, aliases=['service']), - ) - ) - - action = module.params['action'] - minutes = module.params['minutes'] - services = module.params['services'] - - ################################################################## - # Required args per action: - # downtime = (minutes, service, host) - # (un)silence = (host) - # (enable/disable)_alerts = (service, host) - # - # AnsibleModule will verify most stuff, we need to verify - # 'minutes' and 'service' manually. - - ################################################################## - if action == 'downtime': - # Make sure there's an actual service selected - if not services: - module.fail_json(msg='no service selected to set downtime for') - # Make sure minutes is a number - try: - m = int(minutes) - if not isinstance(m, types.IntType): - module.fail_json(msg='minutes must be a number') - except: - module.fail_json(msg='invalid entry for minutes') - - ################################################################## - if action in ['enable_alerts', 'disable_alerts']: - if not services: - module.fail_json(msg='a service is required when setting alerts') - - ################################################################## - ansible_nagios = Nagios(module, **module.params) - ansible_nagios.act() - # this is magic, see lib/ansible/module_common.py #<> main() From da2665bcd2574352549d778a255b25d74ad856f2 Mon Sep 17 00:00:00 2001 From: Tim Bielawa Date: Mon, 27 Aug 2012 11:39:52 -0400 Subject: [PATCH 4/6] In-line docs. --- library/nagios | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/library/nagios b/library/nagios index 627be773844..ce8d293409d 100644 --- a/library/nagios +++ b/library/nagios @@ -15,6 +15,26 @@ # along with this program. If not, see . """ +Action Summaries (all must be delegate_to'd a nagios server): + +* Set 30 minutes of downtime for a single service: + action: nagios action=downtime minutes=30 service=httpd host=$inventory_hostname + +* Set 30 minutes of downtime for a few services: + action: nagios action=downtime minutes=30 services=httpd,git,nfs host=$inventory_hostname + +* (Un)Silence all alerts from a host/service: + action: nagios action=silence host=$inventory_hostname + action: nagios action=unsilence host=$inventory_hostname + +* Enable/Disable alerts for a host or service(s): + action: nagios action=enable_alerts service=host host=$inventory_hostname + action: nagios action=disable_alerts services=httpd,git,nfs host=$inventory_hostname + + +Note: 'service' is an alias for 'services'. +Separate multiple services with commas. + Configuration: From 8b8aaa7f76a676b4cfcf0f6985b94f5678186eb4 Mon Sep 17 00:00:00 2001 From: Tim Bielawa Date: Mon, 27 Aug 2012 11:55:38 -0400 Subject: [PATCH 5/6] Fix copying that special character --- library/nagios | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/nagios b/library/nagios index ce8d293409d..6e6d00a8ff0 100644 --- a/library/nagios +++ b/library/nagios @@ -5,7 +5,7 @@ # Func project. Original copyright follows: # # func-nagios - Schedule downtime and enables/disable notifications -# Copyright © 2011, Red Hat, Inc. +# Copyright 2011, Red Hat, Inc. # Tim Bielawa # # This software may be freely redistributed under the terms of the GNU From 98d3e2bfc8dc9697543fe8a0d074f8e39f3a6176 Mon Sep 17 00:00:00 2001 From: Tim Bielawa Date: Mon, 27 Aug 2012 20:01:06 -0400 Subject: [PATCH 6/6] Nagios is executable now --- library/nagios | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 library/nagios diff --git a/library/nagios b/library/nagios old mode 100644 new mode 100755