# (Copyright) 2015 ABF OSIELL # (Copyright) 2018 Creu Blanca # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). import logging from odoo import _, api, fields, models from odoo.tools.safe_eval import safe_eval _logger = logging.getLogger(__name__) class NscaCheck(models.Model): _name = "nsca.check" _description = "NSCA Check" _inherits = {"ir.cron": "cron_id"} cron_id = fields.Many2one( "ir.cron", string="Cron", required=True, ondelete="cascade", readonly=True ) server_id = fields.Many2one("nsca.server", string="Server", required=True) service = fields.Char(required=True) nsca_model = fields.Char("NSCA Model") nsca_function = fields.Char("Method") nsca_args = fields.Char("Arguments") allow_void_result = fields.Boolean( "Allow void result", default=False, help="By default, a CRITICAL message is sent if the method does not " "return.\nIf checked, no message will be sent in such a case.", ) @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) res["name"] = "TEMP" # Required on 'ir.cron', replaced later res["interval_number"] = 10 res["interval_type"] = "minutes" return res def _force_values(self): """Force some values: - Compute the name of the NSCA check to be readable among the others 'ir.cron' records. """ model = self.env["ir.model"].search([("model", "=", self._name)]) for check in self: vals = { "name": "{} - {}".format(_("NSCA Check"), check.service), "model_id": model.id, "state": "code", "code": "model._cron_check(%s,)" % check.id, "doall": False, "numbercall": -1, } res = super(NscaCheck, check).write(vals) return res @api.model def create(self, vals): if not vals.get("model_id", False): vals["model_id"] = ( self.env["ir.model"].search([("model", "=", self._name)]).id ) if not vals.get("state", False): vals["state"] = "code" check = super(NscaCheck, self).create(vals) check._force_values() return check 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): self.env["nsca.server"]._check_send_nsca_command() check = self.browse(check_id) rc, message, performance = 3, "Unknown", {} try: NscaModel = self.env[check.nsca_model] results = {"model": NscaModel} safe_eval( "result = model.{}({})".format( check.nsca_function, check.nsca_args or "" ), results, mode="exec", nocopy=True, ) result = results["result"] if not result: if check.allow_void_result: return False raise ValueError("'%s' method does not return" % check.nsca_function) if len(result) == 2: rc, message = result else: rc, message, performance = result except Exception as exc: rc, message = 2, "%s" % exc _logger.warning("%s - %s", check.service, message) check._send_nsca(rc, message, performance) return True def _send_nsca(self, rc, message, performance): for check in self: check.server_id._send_nsca(check.service, rc, message, performance)