Browse Source

[IMP] nsca_client: Pass nsca code to server, in order to allow other integrations, not only checks

pull/1280/head
Enric Tobella 6 years ago
parent
commit
180b020caa
No known key found for this signature in database GPG Key ID: 1A2546A1B7BA2451
  1. 74
      nsca_client/models/nsca_check.py
  2. 98
      nsca_client/models/nsca_server.py
  3. 11
      nsca_client/tests/test_nsca.py
  4. 12
      nsca_client/views/nsca_server.xml

74
nsca_client/models/nsca_check.py

@ -1,24 +1,12 @@
# (Copyright) 2015 ABF OSIELL <http://osiell.com>
# (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)

98
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

11
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,)

12
nsca_client/views/nsca_server.xml

@ -11,6 +11,15 @@
<field name="arch" type="xml">
<form string="NSCA Server">
<sheet>
<div class="oe_button_box" name="button_box">
<button name="show_checks" type="object"
class="oe_stat_button"
icon="fa-check-square">
<field name="check_count" widget="statinfo"
string="Checks"/>
<field name="check_ids" invisible="1"/>
</button>
</div>
<group string="NSCA Server">
<field name="name" style="width: 30%;"/>
<field name="port"/>
@ -21,9 +30,6 @@
<group string="Node identity">
<field name="node_hostname"/>
</group>
<group string="Checks">
<field name="check_ids" nolabel="1"/>
</group>
</sheet>
</form>
</field>

Loading…
Cancel
Save