From da0cbab39b780b72d9848552f3374e6a06882ee8 Mon Sep 17 00:00:00 2001 From: Boris Gallet Date: Wed, 25 Mar 2026 16:41:23 +0100 Subject: [PATCH] [ADD] maintenance_service_http_monitoring: webhook_rocketchat_via_n8n + parameters --- maintenance_service_http_monitoring/README.md | 151 ++++++++++++++++++ .../__manifest__.py | 1 + .../data/ir_config_parameter.xml | 15 ++ .../models/maintenance_equipment.py | 53 ++++++ 4 files changed, 220 insertions(+) create mode 100644 maintenance_service_http_monitoring/README.md create mode 100644 maintenance_service_http_monitoring/data/ir_config_parameter.xml diff --git a/maintenance_service_http_monitoring/README.md b/maintenance_service_http_monitoring/README.md new file mode 100644 index 0000000..63afdf4 --- /dev/null +++ b/maintenance_service_http_monitoring/README.md @@ -0,0 +1,151 @@ +=================================== +maintenance_service_http_monitoring +=================================== + +This module provides automated HTTP availability monitoring for services +defined on maintenance equipment. It periodically checks the HTTP status of +service URLs and automatically creates maintenance requests when services +are detected as unavailable. + +Key features: + +- **Automated HTTP checks**: Scheduled cron job checks all active services +- **Maintenance mode**: Temporarily disable monitoring during planned maintenance +- **Automatic maintenance requests**: Creates corrective maintenance requests + when services fail HTTP checks +- **Status tracking**: Records last HTTP status code and check date per service + +# Installation + +Use Odoo normal module installation procedure to install +`maintenance_service_http_monitoring`. + +This module depends on: +- `maintenance` +- `maintenance_server_data` + +**Python dependencies**: This module requires the `requests` library. + +# Configuration + +## Maintenance Mode Duration + +By default, maintenance mode lasts 4 hours. To change this: + +1. Go to Settings > Technical > System Parameters +2. Create or edit the parameter: + - Key: `maintenance_service_http_monitoring.maintenance_mode_duration` + - Value: Duration in hours (e.g., `8`) + +## Cron Jobs + +Two scheduled actions are installed: + +1. **HTTP Service Monitoring: check all services** + - Runs every 15 minutes + - Checks HTTP status of all active service instances with URLs + +2. **HTTP Service Monitoring: deactivate expired maintenance mode** + - Runs every 15 minutes + - Automatically disables maintenance mode when the end time is reached + +## Webhook Notifications + +Go to **Settings > Technical > Parameters > System Parameters** and configure: + ++--------------------------------------------------------+----------------------------------------+ +| Key | Description | ++========================================================+========================================+ +| ``maintenance_service_http_monitoring.webhook_url`` | Webhook URL (POST endpoint) | ++--------------------------------------------------------+----------------------------------------+ +| ``maintenance_service_http_monitoring.webhook_user`` | Basic Auth username (optional) | ++--------------------------------------------------------+----------------------------------------+ +| ``maintenance_service_http_monitoring.webhook_password``| Basic Auth password (optional) | ++--------------------------------------------------------+----------------------------------------+ + + +# Usage + +## Monitoring Services + +Services are automatically monitored if they have: +- A service URL defined +- An associated equipment +- The equipment is not in maintenance mode +- The service instance is active + +The monitoring checks HTTPS availability (HTTP URLs are automatically +upgraded to HTTPS). A service is considered OK if it returns HTTP 200. + +## Using Maintenance Mode + +When performing planned maintenance on a server: + +1. Go to Maintenance > Equipments +2. Open the equipment record +3. Click "Activer le mode maintenance" (Activate maintenance mode) +4. HTTP monitoring is suspended for this equipment +5. The mode automatically expires after the configured duration +6. Or click "Désactiver le mode maintenance" to end it manually + +## Viewing HTTP Status + +On service instances, you can see: +- **Last HTTP Status Code**: The last received HTTP status (200, 404, 500, etc.) +- **Last HTTP Check Date**: When the last check was performed +- **HTTP Status OK**: Quick visual indicator of service health + +## Automatic Maintenance Requests + +When a service fails HTTP checks: +- A corrective maintenance request is created with prefix "[HTTP KO]" +- The request is linked to the equipment +- Only one request per equipment per day is created +- The request description lists all failing services + +## Webhook notifications + +When a new maintenance request is created (HTTP check failure), the module can +send a webhook notification to an external service (e.g., n8n, Rocket.Chat, Slack). + +The webhook sends a JSON POST with the following structure:: + + { + "id": 42, + "name": "[HTTP KO] Server Name", + "priority": "2", + "description": "Service KO: https://example.com", + "equipment": "Server Name", + "link": "https://odoo.example.com/web#id=42&model=maintenance.request&view_type=form" + } + + +# Known issues / Roadmap + +- Add configurable alert thresholds (e.g., alert after N consecutive failures) +- Add email/notification on service failure +- Support custom HTTP check endpoints (e.g., /health) +- Add support for basic authentication + +# Bug Tracker + +Bugs are tracked on +[our issues website](https://github.com/elabore-coop/maintenance-tools/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 + +## Contributors + +- Stéphan Sainléger + +## Funders + +The development of this module has been financially supported by: + +- Elabore (https://elabore.coop) + +## Maintainer + +This module is maintained by Elabore. diff --git a/maintenance_service_http_monitoring/__manifest__.py b/maintenance_service_http_monitoring/__manifest__.py index 9287423..d0fe809 100644 --- a/maintenance_service_http_monitoring/__manifest__.py +++ b/maintenance_service_http_monitoring/__manifest__.py @@ -8,6 +8,7 @@ "depends": ["base", "maintenance", "maintenance_server_data"], "external_dependencies": {"python": ["requests"]}, "data": [ + "data/ir_config_parameter.xml", "data/cron.xml", "views/service_instance_views.xml", "views/maintenance_equipment_views.xml", diff --git a/maintenance_service_http_monitoring/data/ir_config_parameter.xml b/maintenance_service_http_monitoring/data/ir_config_parameter.xml new file mode 100644 index 0000000..5c40ae5 --- /dev/null +++ b/maintenance_service_http_monitoring/data/ir_config_parameter.xml @@ -0,0 +1,15 @@ + + + + maintenance_service_http_monitoring.webhook_url + + + + maintenance_service_http_monitoring.webhook_user + + + + maintenance_service_http_monitoring.webhook_password + + + diff --git a/maintenance_service_http_monitoring/models/maintenance_equipment.py b/maintenance_service_http_monitoring/models/maintenance_equipment.py index c864f5c..644ffa5 100644 --- a/maintenance_service_http_monitoring/models/maintenance_equipment.py +++ b/maintenance_service_http_monitoring/models/maintenance_equipment.py @@ -1,8 +1,18 @@ +import logging from datetime import timedelta from odoo import api, fields, models +try: + import requests as http_requests +except ImportError: + http_requests = None + +_logger = logging.getLogger(__name__) + +WEBHOOK_TIMEOUT = 10 # seconds + class MaintenanceEquipment(models.Model): _inherit = "maintenance.equipment" @@ -103,8 +113,51 @@ class MaintenanceEquipment(models.Model): vals["maintenance_team_id"] = team.id request = self.env["maintenance.request"].create(vals) self.http_maintenance_request = request.id + self._notify_webhook(request, ko_services) return request + def _notify_webhook(self, request, ko_services): + """Send a webhook notification when a new maintenance request is created.""" + ICP = self.env['ir.config_parameter'].sudo() + webhook_url = ICP.get_param( + 'maintenance_service_http_monitoring.webhook_url', '' + ) + if not webhook_url: + return + webhook_user = ICP.get_param( + 'maintenance_service_http_monitoring.webhook_user', '' + ) + webhook_password = ICP.get_param( + 'maintenance_service_http_monitoring.webhook_password', '' + ) + base_url = ICP.get_param('web.base.url', '') + link = ( + f"{base_url}/web#id={request.id}" + f"&model=maintenance.request&view_type=form" + ) + payload = { + 'id': request.id, + 'name': request.name, + 'description': request.description or '', + 'equipment': self.name, + 'link': link, + } + auth = None + if webhook_user and webhook_password: + auth = (webhook_user, webhook_password) + try: + http_requests.post( + webhook_url, + json=payload, + auth=auth, + timeout=WEBHOOK_TIMEOUT, + ) + except Exception as e: + _logger.warning( + "Webhook notification failed for maintenance request %s: %s", + request.id, e, + ) + def _build_ko_services_description(self, ko_services): lines = [f"Service KO: {s.service_url or s.name}" for s in ko_services] return "\n".join(lines)