diff --git a/nsca_client/models/nsca_check.py b/nsca_client/models/nsca_check.py index c846d881e..a96bb9f60 100644 --- a/nsca_client/models/nsca_check.py +++ b/nsca_client/models/nsca_check.py @@ -1,24 +1,12 @@ # (Copyright) 2015 ABF OSIELL # (Copyright) 2018 Creu Blanca # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - import logging -import os -import shlex -import subprocess - from odoo import _, api, fields, models -from odoo.exceptions import UserError from odoo.tools.safe_eval import safe_eval _logger = logging.getLogger(__name__) -SEND_NSCA_BIN = '/usr/sbin/send_nsca' - - -def is_exe(fpath): - return os.path.isfile(fpath) and os.access(fpath, os.X_OK) - class NscaCheck(models.Model): _name = "nsca.check" @@ -88,7 +76,7 @@ class NscaCheck(models.Model): @api.model def _cron_check(self, check_id): - self._check_send_nsca_command() + self.env['nsca.server']._check_send_nsca_command() check = self.browse(check_id) rc, message, performance = 3, "Unknown", {} try: @@ -116,63 +104,5 @@ class NscaCheck(models.Model): @api.multi def _send_nsca(self, rc, message, performance): - """Send the result of the check to the NSCA daemon.""" for check in self: - msg = message - if len(performance) > 0: - msg += '| ' + ''.join( - ["%s=%s%s;%s;%s;%s;%s" % ( - key, - performance[key]['value'], - performance[key].get('uom', ''), - performance[key].get('warn', ''), - performance[key].get('crit', ''), - performance[key].get('min', ''), - performance[key].get('max', ''), - ) for key in sorted(performance)]) - check_result = self._format_check_result(check, rc, msg) - 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 = check.server_id.node_hostname - 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 -c %s" % ( - check.server_id.name, - check.server_id.port, - check.server_id.config_file_path) - 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.debug("%s: %s", check_result, stdout.strip()) - except Exception as exc: - _logger.error(exc) - - def _check_send_nsca_command(self): - """Check if the NSCA client is installed.""" - if not is_exe(SEND_NSCA_BIN): - raise UserError( - _(u"Command '%s' not found. Please install the NSCA client.\n" - u"On Debian/Ubuntu: apt-get install nsca-client") % ( - SEND_NSCA_BIN)) + check.server_id._send_nsca(check.service, rc, message, performance) diff --git a/nsca_client/models/nsca_server.py b/nsca_client/models/nsca_server.py index 5fed760c8..39cc7f9e2 100644 --- a/nsca_client/models/nsca_server.py +++ b/nsca_client/models/nsca_server.py @@ -4,9 +4,22 @@ import psutil import os +import shlex +import subprocess +import logging -from odoo import api, fields, models +from odoo import api, fields, models, _ from odoo.tools import config +from odoo.exceptions import UserError + + +def is_exe(fpath): + return os.path.isfile(fpath) and os.access(fpath, os.X_OK) + + +_logger = logging.getLogger(__name__) + +SEND_NSCA_BIN = '/usr/sbin/send_nsca' class NscaServer(models.Model): @@ -31,6 +44,14 @@ class NscaServer(models.Model): u"monitoring server.") check_ids = fields.One2many( 'nsca.check', 'server_id', string=u"Checks") + check_count = fields.Integer( + compute='_compute_check_count' + ) + + @api.depends('check_ids') + def _compute_check_count(self): + for r in self: + r.check_count = len(r.check_ids) def _selection_encryption_method(self): return [ @@ -141,3 +162,78 @@ class NscaServer(models.Model): }, } return 0, u"OK", performance + + @api.multi + def _prepare_command(self): + """Prepare the shell command used to send the check result + to the NSCA daemon. + """ + cmd = u"/usr/sbin/send_nsca -H %s -p %s -c %s" % ( + self.name, + self.port, + self.config_file_path) + return shlex.split(cmd) + + @api.model + def _run_command(self, 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.debug("%s: %s", check_result, stdout.strip()) + except Exception as exc: + _logger.error(exc) + + def _check_send_nsca_command(self): + """Check if the NSCA client is installed.""" + if not is_exe(SEND_NSCA_BIN): + raise UserError( + _(u"Command '%s' not found. Please install the NSCA client.\n" + u"On Debian/Ubuntu: apt-get install nsca-client") % ( + SEND_NSCA_BIN)) + + def _format_check_result(self, service, rc, message): + """Format the check result with tabulations as delimiter.""" + message = message.replace('\t', ' ') + hostname = self.node_hostname + check_result = u"%s\t%s\t%s\t%s" % ( + hostname, service, rc, message) + return check_result.encode('utf-8') + + def _send_nsca(self, service, rc, message, performance): + """Send the result of the check to the NSCA daemon.""" + msg = message + if len(performance) > 0: + msg += '| ' + ''.join( + ["%s=%s%s;%s;%s;%s;%s" % ( + key, + performance[key]['value'], + performance[key].get('uom', ''), + performance[key].get('warn', ''), + performance[key].get('crit', ''), + performance[key].get('min', ''), + performance[key].get('max', ''), + ) for key in sorted(performance)]) + check_result = self._format_check_result( + service, rc, msg) + cmd = self._prepare_command() + self._run_command(cmd, check_result) + + @api.multi + def show_checks(self): + self.ensure_one() + action = self.env.ref('nsca_client.action_nsca_check_tree') + result = action.read()[0] + context = {'default_server_id': self.id} + result['context'] = context + result['domain'] = [('server_id', '=', self.id)] + if len(self.check_ids) == 1: + res = self.env.ref('nsca_client.view_nsca_check_form', False) + result['views'] = [(res and res.id or False, 'form')] + result['res_id'] = self.check_ids.id + return result diff --git a/nsca_client/tests/test_nsca.py b/nsca_client/tests/test_nsca.py index bf797d561..99cd5b46f 100644 --- a/nsca_client/tests/test_nsca.py +++ b/nsca_client/tests/test_nsca.py @@ -68,7 +68,7 @@ class TestNsca(TransactionCase): check = self.env['nsca.check'].create({ 'server_id': server.id, 'service': 'test', - 'nsca_model': 'nsca.check', + 'nsca_model': 'nsca.server', 'allow_void_result': False, 'nsca_function': '_check_send_nsca_command' }) @@ -84,13 +84,20 @@ class TestNsca(TransactionCase): 'encryption_method': '3', 'node_hostname': 'odoodev', }) + self.assertEqual(server.check_count, 0) check = self.env['nsca.check'].create({ 'server_id': server.id, 'service': 'test', - 'nsca_model': 'nsca.check', + 'nsca_model': 'nsca.server', 'allow_void_result': True, 'nsca_function': '_check_send_nsca_command' }) + self.assertEqual(server.check_count, 1) + action = server.show_checks() + self.assertEqual(check, self.env['nsca.check'].browse( + action['res_id'])) + self.assertEqual(check, self.env['nsca.check'].search( + action['domain'])) with mock.patch('subprocess.Popen') as post: post.return_value = Popen self.env['nsca.check']._cron_check(check.id,) diff --git a/nsca_client/views/nsca_server.xml b/nsca_client/views/nsca_server.xml index 145ba0d35..4736a7dfc 100644 --- a/nsca_client/views/nsca_server.xml +++ b/nsca_client/views/nsca_server.xml @@ -11,6 +11,15 @@
+
+ +
@@ -21,9 +30,6 @@ - - -