diff --git a/nsca_client/README.rst b/nsca_client/README.rst new file mode 100644 index 000000000..d799b56ff --- /dev/null +++ b/nsca_client/README.rst @@ -0,0 +1,112 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +=========== +NSCA Client +=========== + +Send passive alert to your favorite NSCA daemon (Nagios, Shinken...). +This module is based on the Odoo cron system and requires a NSCA client +installed on the system to satisfy the ``/usr/sbin/send_nsca`` command. + +Installation +============ + +To install this module, you need to install a NSCA client. + +On Debian/Ubuntu:: + + $ sudo apt-get install nsca-client + +Then configure the NSCA client in ``/etc/send_nsca.cfg`` (password +and encryption method). + +Configuration +============= + +To configure this module, you need to: + +* Configure your server and a passive service in your moniroting tool + (e.g service ``ODOO MAIL QUEUE`` on host ``MY-SERVER``). +* On Odoo, set the previous hostname in the system parameters:: + + nsca_client.hostname = MY-SERVER + +* Declare your NSCA server in the menu Configuration / Technical / NSCA Client / Servers +* Create NSCA checks in the menu Configuration / Technical / NSCA Client / Checks +* Code the methods which will be called by the NSCA checks. + +Such methods must return a tuple (RC, MESSAGE) where RC is an integer, +and MESSAGE a unicode string. ``RC`` values and the corresponding status are: + +- 0: OK +- 1: WARNING +- 2: CRITICAL +- 3: UNKNOWN + +E.g: + +.. code-block:: python + + class MailMail(models.Model): + _inherit = 'mail.mail' + + @api.model + def nsca_check_mails(self): + mails = self.search([('state', '=', 'exception')]) + if mails: + return (1, u"%s mails not sent" % len(mails)) + return (0, u"OK") + +Usage +===== + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/149/8.0 + +Known issues / Roadmap +====================== + +* Send performance data + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smashing it by providing a detailed and welcomed `feedback +`_. + +Credits +======= + +Images +------ + +* Daniel Foré: `Icon `_ (Elementary theme, GPL). + +Contributors +------------ + +* Sébastien Alix + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit https://odoo-community.org. diff --git a/nsca_client/__init__.py b/nsca_client/__init__.py new file mode 100644 index 000000000..f71417703 --- /dev/null +++ b/nsca_client/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# © 2015 ABF OSIELL +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import models diff --git a/nsca_client/__openerp__.py b/nsca_client/__openerp__.py new file mode 100644 index 000000000..bd70cb762 --- /dev/null +++ b/nsca_client/__openerp__.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# © 2015 ABF OSIELL +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +{ + "name": "NSCA Client", + "summary": "Send passive alerts to monitor your Odoo application.", + "version": "8.0.1.0.0", + "category": "Tools", + "website": "http://osiell.com/", + "author": "ABF OSIELL, Odoo Community Association (OCA)", + "license": "AGPL-3", + "application": False, + "installable": True, + "external_dependencies": { + "bin": ['/usr/sbin/send_nsca'], + }, + "data": [ + "security/ir.model.access.csv", + "data/ir_config_parameter.xml", + "views/nsca_menu.xml", + "views/nsca_check.xml", + "views/nsca_server.xml", + ], + "demo": [ + "demo/demo_data.xml", + ], +} diff --git a/nsca_client/data/ir_config_parameter.xml b/nsca_client/data/ir_config_parameter.xml new file mode 100644 index 000000000..5a7cac83a --- /dev/null +++ b/nsca_client/data/ir_config_parameter.xml @@ -0,0 +1,13 @@ + + + + + + + nsca_client.hostname + localhost + + + + diff --git a/nsca_client/demo/demo_data.xml b/nsca_client/demo/demo_data.xml new file mode 100644 index 000000000..9904136a2 --- /dev/null +++ b/nsca_client/demo/demo_data.xml @@ -0,0 +1,21 @@ + + + + + + nagios.example.net + 5667 + + + + + ODOO MAIL QUEUE + + minutes + mail.mail + nsca_check_mails + + + + + diff --git a/nsca_client/i18n/fr.po b/nsca_client/i18n/fr.po new file mode 100644 index 000000000..2e7331c54 --- /dev/null +++ b/nsca_client/i18n/fr.po @@ -0,0 +1,180 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * nsca_client +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-12-15 12:00+0000\n" +"PO-Revision-Date: 2015-12-15 12:00+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: nsca_client +#: view:nsca.check:nsca_client.view_nsca_check_form +msgid "(1, u\"3 mails not sent\")" +msgstr "(1, u\"3 mails non-envoyés\")" + +#. module: nsca_client +#: view:nsca.check:nsca_client.view_nsca_check_form +msgid "0: OK" +msgstr "0: OK" + +#. module: nsca_client +#: view:nsca.check:nsca_client.view_nsca_check_form +msgid "1: WARNING" +msgstr "1: WARNING" + +#. module: nsca_client +#: view:nsca.check:nsca_client.view_nsca_check_form +msgid "2: CRITICAL" +msgstr "2: CRITICAL" + +#. module: nsca_client +#: view:nsca.check:nsca_client.view_nsca_check_form +msgid "3: UNKNOWN" +msgstr "3: UNKNOWN" + +#. module: nsca_client +#: view:nsca.check:nsca_client.view_nsca_check_form +msgid "Any other RC value will be treated as CRITICAL." +msgstr "Tout autre valeur RC sera traitée comme CRITICAL." + +#. module: nsca_client +#: field:nsca.check,nsca_args:0 +msgid "Arguments" +msgstr "Arguments" + +#. module: nsca_client +#: model:ir.actions.act_window,name:nsca_client.action_nsca_check_tree +#: model:ir.ui.menu,name:nsca_client.menu_action_nsca_check_tree +#: view:nsca.server:nsca_client.view_nsca_server_form +#: field:nsca.server,check_ids:0 +msgid "Checks" +msgstr "Contrôles" + +#. module: nsca_client +#: field:nsca.check,create_uid:0 +#: field:nsca.server,create_uid:0 +msgid "Created by" +msgstr "Créé par" + +#. module: nsca_client +#: field:nsca.check,create_date:0 +#: field:nsca.server,create_date:0 +msgid "Created on" +msgstr "Créé le" + +#. module: nsca_client +#: field:nsca.check,cron_id:0 +msgid "Cron" +msgstr "Cron" + +#. module: nsca_client +#: view:nsca.check:nsca_client.view_nsca_check_form +msgid "E.g." +msgstr "Ex :" + +#. module: nsca_client +#: view:nsca.check:nsca_client.view_nsca_check_form +msgid "Frequency" +msgstr "Fréquence" + +#. module: nsca_client +#: field:nsca.server,name:0 +msgid "Hostname" +msgstr "Serveur" + +#. module: nsca_client +#: field:nsca.check,id:0 +#: field:nsca.server,id:0 +msgid "ID" +msgstr "ID" + +#. module: nsca_client +#: field:nsca.check,write_uid:0 +#: field:nsca.server,write_uid:0 +msgid "Last Updated by" +msgstr "Dernière modification par" + +#. module: nsca_client +#: field:nsca.check,write_date:0 +#: field:nsca.server,write_date:0 +msgid "Last Updated on" +msgstr "Dernière mise à jour le" + +#. module: nsca_client +#: field:nsca.check,nsca_function:0 +msgid "Method" +msgstr "Méthode" + +#. module: nsca_client +#: field:nsca.check,nsca_model:0 +msgid "Model" +msgstr "Modèle" + +#. module: nsca_client +#: code:addons/nsca_client/models/nsca_check.py:52 +#: model:ir.model,name:nsca_client.model_nsca_check +#: view:nsca.check:nsca_client.view_nsca_check_form +#, python-format +msgid "NSCA Check" +msgstr "Contrôle NSCA" + +#. module: nsca_client +#: view:nsca.check:nsca_client.view_nsca_check_tree +msgid "NSCA Checks" +msgstr "Contrôles NSCA" + +#. module: nsca_client +#: model:ir.ui.menu,name:nsca_client.menu_nsca_client +msgid "NSCA Client" +msgstr "Client NSCA" + +#. module: nsca_client +#: model:ir.model,name:nsca_client.model_nsca_server +#: view:nsca.server:nsca_client.view_nsca_server_form +msgid "NSCA Server" +msgstr "Serveur NSCA" + +#. module: nsca_client +#: view:nsca.server:nsca_client.view_nsca_server_tree +msgid "NSCA Servers" +msgstr "Serveurs NSCA" + +#. module: nsca_client +#: field:nsca.server,port:0 +msgid "Port" +msgstr "Port" + +#. module: nsca_client +#: field:nsca.check,server_id:0 +msgid "Server" +msgstr "Serveur" + +#. module: nsca_client +#: model:ir.actions.act_window,name:nsca_client.action_nsca_server_tree +#: model:ir.ui.menu,name:nsca_client.menu_action_nsca_server_tree +msgid "Servers" +msgstr "Serveurs" + +#. module: nsca_client +#: field:nsca.check,service:0 +msgid "Service" +msgstr "Service" + +#. module: nsca_client +#: view:nsca.check:nsca_client.view_nsca_check_form +msgid "Settings" +msgstr "Paramètres" + +#. module: nsca_client +#: view:nsca.check:nsca_client.view_nsca_check_form +msgid "The method must return a tuple (RC, MESSAGE) where RC is an integer:" +msgstr "La méthode doit retourner un tuple (RC, MESSAGE) où RC est un entier :" + diff --git a/nsca_client/i18n/nsca_client.pot b/nsca_client/i18n/nsca_client.pot new file mode 100644 index 000000000..63636c149 --- /dev/null +++ b/nsca_client/i18n/nsca_client.pot @@ -0,0 +1,180 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * nsca_client +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-12-15 11:57+0000\n" +"PO-Revision-Date: 2015-12-15 11:57+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: nsca_client +#: view:nsca.check:nsca_client.view_nsca_check_form +msgid "(1, u\"3 mails not sent\")" +msgstr "" + +#. module: nsca_client +#: view:nsca.check:nsca_client.view_nsca_check_form +msgid "0: OK" +msgstr "" + +#. module: nsca_client +#: view:nsca.check:nsca_client.view_nsca_check_form +msgid "1: WARNING" +msgstr "" + +#. module: nsca_client +#: view:nsca.check:nsca_client.view_nsca_check_form +msgid "2: CRITICAL" +msgstr "" + +#. module: nsca_client +#: view:nsca.check:nsca_client.view_nsca_check_form +msgid "3: UNKNOWN" +msgstr "" + +#. module: nsca_client +#: view:nsca.check:nsca_client.view_nsca_check_form +msgid "Any other RC value will be treated as CRITICAL." +msgstr "" + +#. module: nsca_client +#: field:nsca.check,nsca_args:0 +msgid "Arguments" +msgstr "" + +#. module: nsca_client +#: model:ir.actions.act_window,name:nsca_client.action_nsca_check_tree +#: model:ir.ui.menu,name:nsca_client.menu_action_nsca_check_tree +#: view:nsca.server:nsca_client.view_nsca_server_form +#: field:nsca.server,check_ids:0 +msgid "Checks" +msgstr "" + +#. module: nsca_client +#: field:nsca.check,create_uid:0 +#: field:nsca.server,create_uid:0 +msgid "Created by" +msgstr "" + +#. module: nsca_client +#: field:nsca.check,create_date:0 +#: field:nsca.server,create_date:0 +msgid "Created on" +msgstr "" + +#. module: nsca_client +#: field:nsca.check,cron_id:0 +msgid "Cron" +msgstr "" + +#. module: nsca_client +#: view:nsca.check:nsca_client.view_nsca_check_form +msgid "E.g." +msgstr "" + +#. module: nsca_client +#: view:nsca.check:nsca_client.view_nsca_check_form +msgid "Frequency" +msgstr "" + +#. module: nsca_client +#: field:nsca.server,name:0 +msgid "Hostname" +msgstr "" + +#. module: nsca_client +#: field:nsca.check,id:0 +#: field:nsca.server,id:0 +msgid "ID" +msgstr "" + +#. module: nsca_client +#: field:nsca.check,write_uid:0 +#: field:nsca.server,write_uid:0 +msgid "Last Updated by" +msgstr "" + +#. module: nsca_client +#: field:nsca.check,write_date:0 +#: field:nsca.server,write_date:0 +msgid "Last Updated on" +msgstr "" + +#. module: nsca_client +#: field:nsca.check,nsca_function:0 +msgid "Method" +msgstr "" + +#. module: nsca_client +#: field:nsca.check,nsca_model:0 +msgid "Model" +msgstr "" + +#. module: nsca_client +#: code:addons/nsca_client/models/nsca_check.py:52 +#: model:ir.model,name:nsca_client.model_nsca_check +#: view:nsca.check:nsca_client.view_nsca_check_form +#, python-format +msgid "NSCA Check" +msgstr "" + +#. module: nsca_client +#: view:nsca.check:nsca_client.view_nsca_check_tree +msgid "NSCA Checks" +msgstr "" + +#. module: nsca_client +#: model:ir.ui.menu,name:nsca_client.menu_nsca_client +msgid "NSCA Client" +msgstr "" + +#. module: nsca_client +#: model:ir.model,name:nsca_client.model_nsca_server +#: view:nsca.server:nsca_client.view_nsca_server_form +msgid "NSCA Server" +msgstr "" + +#. module: nsca_client +#: view:nsca.server:nsca_client.view_nsca_server_tree +msgid "NSCA Servers" +msgstr "" + +#. module: nsca_client +#: field:nsca.server,port:0 +msgid "Port" +msgstr "" + +#. module: nsca_client +#: field:nsca.check,server_id:0 +msgid "Server" +msgstr "" + +#. module: nsca_client +#: model:ir.actions.act_window,name:nsca_client.action_nsca_server_tree +#: model:ir.ui.menu,name:nsca_client.menu_action_nsca_server_tree +msgid "Servers" +msgstr "" + +#. module: nsca_client +#: field:nsca.check,service:0 +msgid "Service" +msgstr "" + +#. module: nsca_client +#: view:nsca.check:nsca_client.view_nsca_check_form +msgid "Settings" +msgstr "" + +#. module: nsca_client +#: view:nsca.check:nsca_client.view_nsca_check_form +msgid "The method must return a tuple (RC, MESSAGE) where RC is an integer:" +msgstr "" + diff --git a/nsca_client/models/__init__.py b/nsca_client/models/__init__.py new file mode 100644 index 000000000..32927f70a --- /dev/null +++ b/nsca_client/models/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# © 2015 ABF OSIELL +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import nsca_check, nsca_server diff --git a/nsca_client/models/nsca_check.py b/nsca_client/models/nsca_check.py new file mode 100644 index 000000000..21c6ae3d7 --- /dev/null +++ b/nsca_client/models/nsca_check.py @@ -0,0 +1,128 @@ +# -*- coding: utf-8 -*- +# © 2015 ABF OSIELL +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import logging +import shlex +import subprocess + +from openerp import models, fields, api, _ + +from openerp.addons.base.ir.ir_cron import str2tuple + +_logger = logging.getLogger(__name__) + + +class NscaCheck(models.Model): + _name = "nsca.check" + _description = u"NSCA Check" + _inherits = {'ir.cron': 'cron_id'} + + cron_id = fields.Many2one( + 'ir.cron', string=u"Cron", + required=True, ondelete='cascade', readonly=True) + server_id = fields.Many2one( + 'nsca.server', string=u"Server", required=True) + service = fields.Char(u"Service", required=True) + nsca_model = fields.Char(u"Model") + nsca_function = fields.Char(u"Method") + nsca_args = fields.Char(u"Arguments") + + @api.model + def default_get(self, fields_list): + """Set some default values on the fly, without overriding fields (which + has the side effect to re-create the fields on the current model). + """ + res = super(NscaCheck, self).default_get(fields_list) + NscaServer = self.env['nsca.server'] + res['name'] = 'TEMP' # Required on 'ir.cron', replaced later + res['interval_number'] = 10 + res['interval_type'] = 'minutes' + res['server_id'] = NscaServer.search([])[0].id + return res + + @api.multi + def _force_values(self): + """Force some values: + - Compute the name of the NSCA check to be readable + among the others 'ir.cron' records. + """ + for check in self: + vals = { + 'name': u"%s - %s" % (_(u"NSCA Check"), check.service), + 'model': self._name, + 'function': '_cron_check', + 'args': '(%s,)' % check.id, + 'doall': False, + 'numbercall': -1 + } + super(NscaCheck, check).write(vals) + + @api.model + def create(self, vals): + check = super(NscaCheck, self).create(vals) + check._force_values() + return check + + @api.multi + def write(self, vals): + res = super(NscaCheck, self).write(vals) + if 'service' in vals: + self._force_values() + return res + + @api.model + def _cron_check(self, check_id): + check = self.browse(check_id) + rc, message = 3, "Unknown" + try: + args = str2tuple(check.nsca_args) + NscaModel = self.env[check.nsca_model] + rc, message = getattr(NscaModel, check.nsca_function)(*args) + except Exception, exc: + rc, message = 2, "%s" % exc + _logger.error("%s - %s", check.service, message) + check._send_nsca(rc, message) + return True + + @api.multi + def _send_nsca(self, rc, message): + """Send the result of the check to the NSCA daemon.""" + for check in self: + check_result = self._format_check_result(check, rc, message) + cmd = self._prepare_command(check) + self._run_command(check, cmd, check_result) + + @api.model + def _format_check_result(self, check, rc, message): + """Format the check result with tabulations as delimiter.""" + message = message.replace('\t', ' ') + hostname = self.env['ir.config_parameter'].get_param( + 'nsca_client.hostname', 'localhost') + check_result = u"%s\t%s\t%s\t%s" % ( + hostname, check.service, rc, message) + return check_result.encode('utf-8') + + @api.model + def _prepare_command(self, check): + """Prepare the shell command used to send the check result + to the NSCA daemon. + """ + cmd = u"/usr/sbin/send_nsca -H %s -p %s" % ( + check.server_id.name, check.server_id.port) + return shlex.split(cmd) + + @api.model + def _run_command(self, check, cmd, check_result): + """Send the check result through the '/usr/sbin/send_nsca' command.""" + try: + proc = subprocess.Popen( + cmd, + stdout=subprocess.PIPE, + stdin=subprocess.PIPE, + stderr=subprocess.STDOUT) + stdout = proc.communicate( + input=check_result)[0] + _logger.info("%s: %s", check_result, stdout.strip()) + except Exception, exc: + _logger.error(exc) diff --git a/nsca_client/models/nsca_server.py b/nsca_client/models/nsca_server.py new file mode 100644 index 000000000..596f25eed --- /dev/null +++ b/nsca_client/models/nsca_server.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# © 2015 ABF OSIELL +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import models, fields + + +class NscaServer(models.Model): + _name = "nsca.server" + _description = u"NSCA Server" + + name = fields.Char(u"Hostname", required=True) + port = fields.Integer(u"Port", default=5667, required=True) + check_ids = fields.One2many( + 'nsca.check', 'server_id', string=u"Checks") diff --git a/nsca_client/security/ir.model.access.csv b/nsca_client/security/ir.model.access.csv new file mode 100644 index 000000000..da2d09485 --- /dev/null +++ b/nsca_client/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_nsca_check,access_nsca_check,model_nsca_check,base.group_erp_manager,1,1,1,1 +access_nsca_server,access_nsca_server,model_nsca_server,base.group_erp_manager,1,1,1,1 diff --git a/nsca_client/static/description/icon.png b/nsca_client/static/description/icon.png new file mode 100644 index 000000000..b9f884a28 Binary files /dev/null and b/nsca_client/static/description/icon.png differ diff --git a/nsca_client/views/nsca_check.xml b/nsca_client/views/nsca_check.xml new file mode 100644 index 000000000..87ed38238 --- /dev/null +++ b/nsca_client/views/nsca_check.xml @@ -0,0 +1,78 @@ + + + + + + + + nsca.check.form + nsca.check + +
+ + + + + + + + + + +
+

The method must return a tuple (RC, MESSAGE) where RC is an integer:

+ +
    +
  • 0: OK
  • +
  • 1: WARNING
  • +
  • 2: CRITICAL
  • +
  • 3: UNKNOWN
  • +
+ +

Any other RC value will be treated as CRITICAL.

+

E.g. (1, u"3 mails not sent")

+
+
+
+
+
+
+
+ + + nsca.check.tree + nsca.check + + + + + + + + + + + + Checks + ir.actions.act_window + nsca.check + form + + + ['|', ('active', '=', True), ('active', '=', False)] + + + + +
+
diff --git a/nsca_client/views/nsca_menu.xml b/nsca_client/views/nsca_menu.xml new file mode 100644 index 000000000..4472e82c5 --- /dev/null +++ b/nsca_client/views/nsca_menu.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/nsca_client/views/nsca_server.xml b/nsca_client/views/nsca_server.xml new file mode 100644 index 000000000..d9b98e52f --- /dev/null +++ b/nsca_client/views/nsca_server.xml @@ -0,0 +1,50 @@ + + + + + + + + nsca.server.form + nsca.server + +
+ + + + + + + + + +
+
+
+ + + nsca.server.tree + nsca.server + + + + + + + + + + Servers + ir.actions.act_window + nsca.server + form + + + + + +
+