You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

130 lines
4.3 KiB

  1. # -*- coding: utf-8 -*-
  2. # © 2015 ABF OSIELL <http://osiell.com>
  3. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  4. import logging
  5. import shlex
  6. import subprocess
  7. from openerp import _, api, fields, models
  8. from openerp.addons.base.ir.ir_cron import str2tuple
  9. _logger = logging.getLogger(__name__)
  10. class NscaCheck(models.Model):
  11. _name = "nsca.check"
  12. _description = u"NSCA Check"
  13. _inherits = {'ir.cron': 'cron_id'}
  14. cron_id = fields.Many2one(
  15. 'ir.cron', string=u"Cron",
  16. required=True, ondelete='cascade', readonly=True)
  17. server_id = fields.Many2one(
  18. 'nsca.server', string=u"Server", required=True)
  19. service = fields.Char(u"Service", required=True)
  20. nsca_model = fields.Char(u"Model")
  21. nsca_function = fields.Char(u"Method")
  22. nsca_args = fields.Char(u"Arguments")
  23. @api.model
  24. def default_get(self, fields_list):
  25. """Set some default values on the fly, without overriding fields (which
  26. has the side effect to re-create the fields on the current model).
  27. """
  28. res = super(NscaCheck, self).default_get(fields_list)
  29. NscaServer = self.env['nsca.server']
  30. res['name'] = 'TEMP' # Required on 'ir.cron', replaced later
  31. res['interval_number'] = 10
  32. res['interval_type'] = 'minutes'
  33. res['server_id'] = NscaServer.search([])[0].id
  34. return res
  35. @api.multi
  36. def _force_values(self):
  37. """Force some values:
  38. - Compute the name of the NSCA check to be readable
  39. among the others 'ir.cron' records.
  40. """
  41. for check in self:
  42. vals = {
  43. 'name': u"%s - %s" % (_(u"NSCA Check"), check.service),
  44. 'model': self._name,
  45. 'function': '_cron_check',
  46. 'args': '(%s,)' % check.id,
  47. 'doall': False,
  48. 'numbercall': -1
  49. }
  50. super(NscaCheck, check).write(vals)
  51. @api.model
  52. def create(self, vals):
  53. check = super(NscaCheck, self).create(vals)
  54. check._force_values()
  55. return check
  56. @api.multi
  57. def write(self, vals):
  58. res = super(NscaCheck, self).write(vals)
  59. if 'service' in vals:
  60. self._force_values()
  61. return res
  62. @api.model
  63. def _cron_check(self, check_id):
  64. check = self.browse(check_id)
  65. rc, message = 3, "Unknown"
  66. try:
  67. args = str2tuple(check.nsca_args)
  68. NscaModel = self.env[check.nsca_model]
  69. rc, message = getattr(NscaModel, check.nsca_function)(*args)
  70. except Exception, exc:
  71. rc, message = 2, "%s" % exc
  72. _logger.error("%s - %s", check.service, message)
  73. check._send_nsca(rc, message)
  74. return True
  75. @api.multi
  76. def _send_nsca(self, rc, message):
  77. """Send the result of the check to the NSCA daemon."""
  78. for check in self:
  79. check_result = self._format_check_result(check, rc, message)
  80. cmd = self._prepare_command(check)
  81. self._run_command(check, cmd, check_result)
  82. @api.model
  83. def _format_check_result(self, check, rc, message):
  84. """Format the check result with tabulations as delimiter."""
  85. message = message.replace('\t', ' ')
  86. hostname = self.env['ir.config_parameter'].get_param(
  87. 'nsca_client.hostname', 'localhost')
  88. check_result = u"%s\t%s\t%s\t%s" % (
  89. hostname, check.service, rc, message)
  90. return check_result.encode('utf-8')
  91. @api.model
  92. def _prepare_command(self, check):
  93. """Prepare the shell command used to send the check result
  94. to the NSCA daemon.
  95. """
  96. cmd = u"/usr/sbin/send_nsca -H %s -p %s -c %s" % (
  97. check.server_id.name,
  98. check.server_id.port,
  99. check.server_id.config_file_path)
  100. return shlex.split(cmd)
  101. @api.model
  102. def _run_command(self, check, cmd, check_result):
  103. """Send the check result through the '/usr/sbin/send_nsca' command."""
  104. try:
  105. proc = subprocess.Popen(
  106. cmd,
  107. stdout=subprocess.PIPE,
  108. stdin=subprocess.PIPE,
  109. stderr=subprocess.STDOUT)
  110. stdout = proc.communicate(
  111. input=check_result)[0]
  112. _logger.info("%s: %s", check_result, stdout.strip())
  113. except Exception, exc:
  114. _logger.error(exc)