Compare commits

..
5 Commits
Author SHA1 Message Date
hcornet c46836ab1c Dix-neuf packs applicatifs : JMX, API REST, SNMP
build / Garde-fou (push) Successful in 11m43s
build / Images Harbor (catalog-sync, Dockerfile.catalog-sync) (push) Successful in 9m57s
build / Images Harbor (web, Dockerfile) (push) Successful in 13m29s
2026-09-12 11:31:25 +02:00
hcornet 9debdcdf9c Chaque pack apporte son propre calendrier de notification
build / Garde-fou (push) Successful in 10m45s
build / Images Harbor (catalog-sync, Dockerfile.catalog-sync) (push) Successful in 9m52s
build / Images Harbor (web, Dockerfile) (push) Successful in 10m0s
2026-09-12 11:02:02 +02:00
hcornet 032982cb28 Le calendrier livre par Centreon figure au projet sans etre recree
build / Images Harbor (catalog-sync, Dockerfile.catalog-sync) (push) Successful in 9m52s
build / Garde-fou (push) Successful in 10m45s
build / Images Harbor (web, Dockerfile) (push) Successful in 13m18s
2026-09-12 10:04:11 +02:00
hcornet bc18f93196 Import d'un pack par la route de fusion, champs fermes, correction des champs vides
build / Images Harbor (catalog-sync, Dockerfile.catalog-sync) (push) Successful in 9m44s
build / Garde-fou (push) Successful in 10m44s
build / Images Harbor (web, Dockerfile) (push) Successful in 13m25s
2026-09-11 21:15:23 +02:00
hcornet ec195cac8f Masquer les packs deja importes dans la fenetre d'import
build / Images Harbor (catalog-sync, Dockerfile.catalog-sync) (push) Successful in 9m52s
build / Images Harbor (web, Dockerfile) (push) Successful in 13m15s
build / Garde-fou (push) Successful in 10m41s
2026-09-11 19:32:39 +02:00
92 changed files with 2550 additions and 132 deletions

No files matched your search

+92
View File
@@ -3,6 +3,98 @@
Format : [Keep a Changelog](https://keepachangelog.com/fr/1.1.0/).
Versionnement sémantique, comme décrit dans [docs/CONVENTIONS.md](docs/CONVENTIONS.md).
## 1.20.0
### Ajouté
- Dix-neuf packs applicatifs : Tomcat, JVM, Kafka, ActiveMQ et ZooKeeper en JMX ; Graylog,
Wazuh, HashiCorp Vault, Jenkins, Grafana, Prometheus, Veeam Enterprise Manager, Microsoft
IIS et Podman en API REST ; HAProxy, Keepalived, Squid et Microsoft DHCP en SNMP ; PHP-FPM
par sa page de statut
- Catalogue porté à 71 packs et 266 sondes, dont 22 en Applications
## 1.19.0
### Ajouté
- Un périmètre créé à la main reprend le dernier calendrier du projet, et propose d'en créer
un — en permanence ou en heures ouvrées — quand il n'y en a aucun
- Un périmètre sans calendrier est signalé dans son écran ; faute de choix, il vise `24x7`
sur le central, et la validation le rappelle
## 1.18.0
### Modifié
- Chaque pack apporte désormais **son propre** calendrier — `TP-App-Apache-24x7`,
`TP-App-Nginx-24x7`, `TP-HW-Printer-RFC3805-Heures-Ouvrees` — au lieu de pointer celui du
central : ajuster les plages d'une technologie ne modifie plus celles de tout le parc
## 1.17.0
### Modifié
- Le calendrier d'un pack figure désormais dans le projet même quand Centreon le livre :
il portait jusqu'ici une absence qui se lisait comme un oubli. Marqué « Centreon », il
montre ses plages, n'est pas recréé, et un bouton permet de forcer sa création si le
central l'a perdu
## 1.16.0
### Corrigé
- **L'import d'un pack n'apportait toujours que les commandes et les modèles.** La correction
annoncée en 1.11.1 n'avait jamais été appliquée : le remplacement dans l'éditeur avait
échoué en silence, et les tests ne couvraient que la route serveur. L'import passe
désormais par `/api/packs/<id>/fusionner`, et deux tests empruntent le chemin réel
- Les champs sans valeur affichaient le mot « undefined », notamment toutes les plages
horaires d'un calendrier neuf
- Un nouvel hôte rejoignait tous les groupes à chaque affichage : le groupe du dernier pack
importé est désormais pré-coché à la création seulement, et se décoche
### Modifié
- Version SNMP, criticité, calendrier d'un périmètre et commande de vérification deviennent
des listes fermées, avec une option « Autre valeur » qui révèle une saisie quand un objet
propre au central est nécessaire
- La couleur du bandeau se choisit dans un sélecteur de couleur
- Les groupes d'hôtes du projet se cochent ; un champ distinct reçoit ceux qui existent déjà
sur le central
- Un calendrier propose trois modèles de plages : en permanence, heures ouvrées, astreinte
## 1.15.0
### Modifié
- Les packs déjà présents dans le projet sont masqués de la fenêtre d'import, avec un
compteur et un lien pour les afficher : les reproposer n'avait aucun effet, l'import
les ignorait
## 1.14.1
### Modifié
- Le nom affiché dans l'interface devient « Forge Centreon », avec pour baseline
« Générateur de configuration pour Centreon avec CLAPI ». Le projet, le dépôt, les images
et le paquet Python restent « Enclume ».
## 1.14.0
### Ajouté
- Page d'aide « Installer SNMP » : configuration de départ sécurisée pour Debian, Ubuntu,
RHEL, Windows et les équipements réseau, avec la vérification depuis le collecteur
- Valeurs standards proposées pour les modèles parents, la version SNMP, le répertoire des
plugins, le collecteur et la criticité
### Modifié
- Moins de saisie libre : chaque champ qui a des valeurs connues les propose désormais
## 1.13.0
### Ajouté
- Chaque pack livre son groupe d'hôtes : importer un pack donne désormais les commandes,
les modèles, le groupe, le calendrier, le périmètre de notification et les prérequis
- La commande de vérification, ses arguments et le fuseau horaire sur l'hôte, où ils ont
leur place — ils n'existaient que sur le modèle d'hôte
- Un hôte créé après l'import d'un pack rejoint automatiquement son groupe
### Modifié
- Le fuseau horaire se choisit dans une liste fermée, alimentée par la base du système :
une faute de frappe ne se voyait qu'à l'exécution sur le central
- La commande de vérification propose celles livrées par Centreon et celles du projet
## 1.12.0
### Ajouté
+12 -2
View File
@@ -37,9 +37,16 @@ prerequis: # facultatif mais précieux
notes: |
Activer le plugin de management et créer un compte en lecture seule.
groupe_hote: # le groupe dans lequel ranger les hôtes
name: HG-App-RabbitMQ
alias: RabbitMQ
notification: # la chaîne d'alerte livrée avec le pack
perimetre: RabbitMQ
calendrier: 24x7 # 24x7 et Heures-Ouvrees sont reconnus
calendrier: # le pack apporte le sien, il ne réutilise pas celui du central
name: TP-App-RabbitMQ-24x7
modele: 24x7 # 24x7 ou Heures-Ouvrees : le rythme copié
alias: RabbitMQ, en permanence
groupe: CG-App-RabbitMQ # CG-<Famille>-<Techno>
criticite: Majeure
impact: "Échanges entre applications interrompus"
@@ -77,10 +84,13 @@ même valeur.
- **Ce qui est commun à l'hôte va sur l'hôte** : ports, comptes, options du plugin. Ce qui est
propre à une sonde va sur la sonde : seuils, filtres.
- **Aucun mot de passe réel.** Valeur vide et `is_password: true`.
- **Un groupe d'hôtes.** Nommé `HG-<Famille>-<Techno>`. Un hôte sans groupe devient
introuvable dès que le parc grandit, et les droits comme les filtres s'appuient dessus.
- **Une chaîne de notification.** Un pack qui supervise sans prévenir personne n'a pas
d'intérêt : `calendrier`, `groupe` et `impact` sont attendus. Choisissez `24x7` pour ce
dont la panne réveille quelqu'un, `Heures-Ouvrees` sinon. Les calendriers livrés par
Centreon — `24x7`, `workhours`, `nonworkhours`, `none` — sont référencés, jamais recréés.
Centreon. Chaque pack apporte **son propre** calendrier, nommé `TP-<Famille>-<Techno>-<rythme>` :
ajuster les plages d'une technologie ne doit pas modifier celles de tout le central.
- **`status: verified`** uniquement si vous avez exécuté ces commandes sur un Centreon. Sinon
`to-verify`, c'est honnête et c'est utile.
- `$CENTREONPLUGINS$` est remplacé par le répertoire de plugins choisi par l'utilisateur.
+5 -1
View File
@@ -10,7 +10,7 @@ Projet indépendant, sans lien avec Centreon SAS.
- **Éditeur libre** : commandes, modèles de service, modèles d'hôte, hôtes. Héritage,
duplication, rattachement des services aux modèles d'hôte.
- **Catalogue de départ** : 52 packs, 224 sondes, importables puis modifiables.
- **Catalogue de départ** : 71 packs, 266 sondes, importables puis modifiables.
- **Validation** avant génération : noms en double, références manquantes, point-virgule
interdit, services rattachés à aucun modèle d'hôte, mots de passe en clair.
- **Quatre fichiers** : `deploy.sh` (avec `--dry-run`), `deploy.clapi` (import CLAPI),
@@ -78,6 +78,10 @@ python3 -m enclume.cli --projet mon-projet.json --out ./sortie
| `GET /api/packs` | catalogue |
| `GET /api/packs/<id>/projet` | un pack converti en objets de projet |
| `POST /api/packs/<id>/fusionner` | ajoute un pack au projet en cours |
| `GET /api/fuseaux` | fuseaux horaires connus du système |
| `GET /api/valeurs-standards` | modèles parents, versions SNMP, criticités |
| `GET /aide/snmp` | installer et sécuriser SNMP, par système |
| `GET /api/commandes-usuelles` | commandes de vérification livrées par Centreon |
| `POST /api/valider` | validation seule |
| `POST /api/generer` | validation et génération des quatre fichiers |
| `POST /telecharger` | archive zip |
+62
View File
@@ -0,0 +1,62 @@
id: app-activemq-jmx
name: Apache ActiveMQ (JMX)
category: applications
status: to-verify
plugin: centreon_activemq_jmx.pl
description: Supervision d'un courtier ActiveMQ via JMX et l'agent Jolokia.
prerequis:
paquets:
debian: [libwww-perl, libjson-xs-perl]
rhel: [perl-libwww-perl, perl-JSON-XS]
notes: |
Deployer l'agent Jolokia dans la JVM supervisee et exposer son point
d'acces au collecteur : les plugins JMX de Centreon passent par lui.
host_template:
name: App-ActiveMQ-JMX-custom
alias: Applicatif ActiveMQ JMX
parents: [generic-active-host-custom]
macros:
- {name: JMXURL, value: "http://localhost:8080/jolokia", description: "URL de l'agent Jolokia"}
- {name: JMXUSERNAME, value: "", description: "Compte Jolokia"}
- {name: JMXPASSWORD, value: "", description: "Mot de passe Jolokia", is_password: true}
- {name: JMXEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-ActiveMQ-JMX
alias: Apache ActiveMQ (JMX)
notification:
perimetre: Apache ActiveMQ (JMX)
calendrier:
name: TP-App-ActiveMQ-JMX-24x7
modele: 24x7
alias: Apache ActiveMQ (JMX), en permanence
groupe: CG-App-ActiveMQ-JMX
criticite: Majeure
impact: "Files de messages bloquees"
options_hote: d,u,r
options_service: w,c,r
intervalle: 30
services:
- name: Queues
alias: Queues
description: Messages en attente dans les files
line: "$CENTREONPLUGINS$/centreon_activemq_jmx.pl --plugin=apps::activemq::jmx::plugin --mode=queues --url='$_HOSTJMXURL$' --username='$_HOSTJMXUSERNAME$' --password='$_HOSTJMXPASSWORD$' $_HOSTJMXEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "80", description: "Seuil warning"}
- {name: CRITICAL, value: "90", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
- name: Topics
alias: Topics
description: Sujets et abonnes
line: "$CENTREONPLUGINS$/centreon_activemq_jmx.pl --plugin=apps::activemq::jmx::plugin --mode=topics --url='$_HOSTJMXURL$' --username='$_HOSTJMXUSERNAME$' --password='$_HOSTJMXPASSWORD$' $_HOSTJMXEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "80", description: "Seuil warning"}
- {name: CRITICAL, value: "90", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
- name: Broker-Usage
alias: Broker-Usage
description: Memoire et stockage du courtier
line: "$CENTREONPLUGINS$/centreon_activemq_jmx.pl --plugin=apps::activemq::jmx::plugin --mode=broker-usage --url='$_HOSTJMXURL$' --username='$_HOSTJMXUSERNAME$' --password='$_HOSTJMXPASSWORD$' $_HOSTJMXEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "80", description: "Seuil warning"}
- {name: CRITICAL, value: "90", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
+7 -1
View File
@@ -13,9 +13,15 @@ host_template:
- {name: APACHEPROTO, value: "http", description: "Protocole (http ou https)"}
- {name: APACHEURLPATH, value: "/server-status/?auto", description: "Chemin de la page mod_status"}
- {name: APACHEEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-Apache
alias: Apache HTTP Server
notification:
perimetre: Apache HTTP Server
calendrier: 24x7
calendrier:
name: TP-App-Apache-24x7
modele: 24x7
alias: Apache HTTP Server, en permanence
groupe: CG-App-Apache
criticite: Majeure
impact: "Sites et applications web indisponibles"
+38
View File
@@ -0,0 +1,38 @@
id: app-dhcp-snmp
name: Microsoft DHCP (SNMP)
category: applications
status: to-verify
plugin: centreon_microsoft_dhcp_snmp.pl
description: Supervision d'un serveur DHCP Microsoft en SNMP (occupation des etendues).
host_template:
name: App-DHCP-SNMP-custom
alias: Applicatif Microsoft DHCP
parents: [generic-active-host-custom]
check_command: check_centreon_ping
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-DHCP-SNMP
alias: Microsoft DHCP (SNMP)
notification:
perimetre: Microsoft DHCP (SNMP)
calendrier:
name: TP-App-DHCP-SNMP-24x7
modele: 24x7
alias: Microsoft DHCP (SNMP), en permanence
groupe: CG-App-DHCP-SNMP
criticite: Critique
impact: "Attribution d'adresses interrompue, postes sans reseau"
options_hote: d,u,r
options_service: w,c,r
intervalle: 30
services:
- name: Subnet-Usage
alias: Subnet-Usage
description: Occupation des etendues
line: "$CENTREONPLUGINS$/centreon_microsoft_dhcp_snmp.pl --plugin=apps::microsoft::dhcp::snmp::plugin --mode=subnet-usage --hostname=$HOSTADDRESS$ --snmp-version='$_HOSTSNMPVERSION$' --snmp-community='$_HOSTSNMPCOMMUNITY$' $_HOSTSNMPEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "", description: "Seuil warning"}
- {name: CRITICAL, value: "", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
+7 -1
View File
@@ -20,9 +20,15 @@ host_template:
- {name: ESUSERNAME, value: "", description: "Compte de supervision"}
- {name: ESPASSWORD, value: "", description: "Mot de passe du compte", is_password: true}
- {name: ESEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-Elasticsearch
alias: Elasticsearch
notification:
perimetre: Elasticsearch
calendrier: 24x7
calendrier:
name: TP-App-Elasticsearch-24x7
modele: 24x7
alias: Elasticsearch, en permanence
groupe: CG-App-Elasticsearch
criticite: Majeure
impact: "Recherche et journalisation degradees"
+41
View File
@@ -0,0 +1,41 @@
id: app-grafana
name: Grafana
category: applications
status: to-verify
plugin: centreon_grafana_restapi.pl
description: Supervision d'un serveur Grafana via son API REST (etat de fonctionnement).
prerequis:
paquets:
debian: [libwww-perl, libjson-xs-perl]
rhel: [perl-libwww-perl, perl-JSON-XS]
host_template:
name: App-Grafana-custom
alias: Applicatif Grafana
parents: [generic-active-host-custom]
macros:
- {name: APIPORT, value: "443", description: "Port de l'API"}
- {name: APIPROTO, value: "https", description: "Protocole d'acces"}
- {name: APITOKEN, value: "", description: "Jeton d'API", is_password: true}
- {name: APIEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-Grafana
alias: Grafana
notification:
perimetre: Grafana
calendrier:
name: TP-App-Grafana-24x7
modele: 24x7
alias: Grafana, en permanence
groupe: CG-App-Grafana
criticite: Mineure
impact: "Tableaux de bord indisponibles"
options_hote: d,u,r
options_service: w,c,r
intervalle: 30
services:
- name: Health
alias: Health
description: Etat de fonctionnement du serveur
line: "$CENTREONPLUGINS$/centreon_grafana_restapi.pl --plugin=apps::grafana::restapi::plugin --mode=health --hostname=$HOSTADDRESS$ --port='$_HOSTAPIPORT$' --proto='$_HOSTAPIPROTO$' --api-token='$_HOSTAPITOKEN$' $_HOSTAPIEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
+50
View File
@@ -0,0 +1,50 @@
id: app-graylog
name: Graylog
category: applications
status: to-verify
plugin: centreon_graylog_restapi.pl
description: Supervision d'un serveur Graylog via son API REST (notifications, recherches).
prerequis:
paquets:
debian: [libwww-perl, libjson-xs-perl]
rhel: [perl-libwww-perl, perl-JSON-XS]
host_template:
name: App-Graylog-custom
alias: Applicatif Graylog
parents: [generic-active-host-custom]
macros:
- {name: APIPORT, value: "443", description: "Port de l'API"}
- {name: APIPROTO, value: "https", description: "Protocole d'acces"}
- {name: APIUSERNAME, value: "centreon", description: "Compte de supervision"}
- {name: APIPASSWORD, value: "", description: "Mot de passe du compte", is_password: true}
- {name: APIEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-Graylog
alias: Graylog
notification:
perimetre: Graylog
calendrier:
name: TP-App-Graylog-24x7
modele: 24x7
alias: Graylog, en permanence
groupe: CG-App-Graylog
criticite: Majeure
impact: "Collecte et recherche de journaux interrompues"
options_hote: d,u,r
options_service: w,c,r
intervalle: 30
services:
- name: Notifications
alias: Notifications
description: Notifications systeme du cluster
line: "$CENTREONPLUGINS$/centreon_graylog_restapi.pl --plugin=apps::graylog::restapi::plugin --mode=notifications --hostname=$HOSTADDRESS$ --port='$_HOSTAPIPORT$' --proto='$_HOSTAPIPROTO$' --api-username='$_HOSTAPIUSERNAME$' --api-password='$_HOSTAPIPASSWORD$' $_HOSTAPIEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
- name: Query
alias: Query
description: Nombre de messages correspondant a une recherche
line: "$CENTREONPLUGINS$/centreon_graylog_restapi.pl --plugin=apps::graylog::restapi::plugin --mode=query --hostname=$HOSTADDRESS$ --port='$_HOSTAPIPORT$' --proto='$_HOSTAPIPROTO$' --api-username='$_HOSTAPIUSERNAME$' --api-password='$_HOSTAPIPASSWORD$' $_HOSTAPIEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "", description: "Seuil warning"}
- {name: CRITICAL, value: "", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
+46
View File
@@ -0,0 +1,46 @@
id: app-haproxy-snmp
name: HAProxy (SNMP)
category: applications
status: to-verify
plugin: centreon_haproxy_snmp.pl
description: Supervision d'un repartiteur HAProxy en SNMP (frontaux, arrieres, sessions).
host_template:
name: App-HAProxy-SNMP-custom
alias: Applicatif HAProxy SNMP
parents: [generic-active-host-custom]
check_command: check_centreon_ping
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-HAProxy-SNMP
alias: HAProxy (SNMP)
notification:
perimetre: HAProxy (SNMP)
calendrier:
name: TP-App-HAProxy-SNMP-24x7
modele: 24x7
alias: HAProxy (SNMP), en permanence
groupe: CG-App-HAProxy-SNMP
criticite: Critique
impact: "Repartition de charge degradee, services web inaccessibles"
options_hote: d,u,r
options_service: w,c,r
intervalle: 30
services:
- name: Frontend-Usage
alias: Frontend-Usage
description: Sessions et trafic des frontaux
line: "$CENTREONPLUGINS$/centreon_haproxy_snmp.pl --plugin=apps::haproxy::snmp::plugin --mode=frontend-usage --hostname=$HOSTADDRESS$ --snmp-version='$_HOSTSNMPVERSION$' --snmp-community='$_HOSTSNMPCOMMUNITY$' $_HOSTSNMPEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "", description: "Seuil warning"}
- {name: CRITICAL, value: "", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
- name: Backend-Usage
alias: Backend-Usage
description: Sessions et etat des arrieres
line: "$CENTREONPLUGINS$/centreon_haproxy_snmp.pl --plugin=apps::haproxy::snmp::plugin --mode=backend-usage --hostname=$HOSTADDRESS$ --snmp-version='$_HOSTSNMPVERSION$' --snmp-community='$_HOSTSNMPCOMMUNITY$' $_HOSTSNMPEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "", description: "Seuil warning"}
- {name: CRITICAL, value: "", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
@@ -0,0 +1,49 @@
id: app-hashicorp-vault
name: HashiCorp Vault
category: applications
status: to-verify
plugin: centreon_hashicorp_vault_restapi.pl
description: Supervision d'un serveur HashiCorp Vault via son API REST (scellement, stockage Raft).
prerequis:
paquets:
debian: [libwww-perl, libjson-xs-perl]
rhel: [perl-libwww-perl, perl-JSON-XS]
host_template:
name: App-Vault-custom
alias: Applicatif HashiCorp Vault
parents: [generic-active-host-custom]
macros:
- {name: APIPORT, value: "443", description: "Port de l'API"}
- {name: APIPROTO, value: "https", description: "Protocole d'acces"}
- {name: APITOKEN, value: "", description: "Jeton d'API", is_password: true}
- {name: APIEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-Vault
alias: HashiCorp Vault
notification:
perimetre: HashiCorp Vault
calendrier:
name: TP-App-Vault-24x7
modele: 24x7
alias: HashiCorp Vault, en permanence
groupe: CG-App-Vault
criticite: Critique
impact: "Secrets inaccessibles, applications dependantes bloquees"
options_hote: d,u,r
options_service: w,c,r
intervalle: 30
services:
- name: Seal-Status
alias: Seal-Status
description: Etat de scellement du coffre
line: "$CENTREONPLUGINS$/centreon_hashicorp_vault_restapi.pl --plugin=apps::hashicorp::vault::restapi::plugin --mode=seal-status --hostname=$HOSTADDRESS$ --port='$_HOSTAPIPORT$' --proto='$_HOSTAPIPROTO$' --api-token='$_HOSTAPITOKEN$' $_HOSTAPIEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
- name: Raft-Storage
alias: Raft-Storage
description: Performances du stockage Raft
line: "$CENTREONPLUGINS$/centreon_hashicorp_vault_restapi.pl --plugin=apps::hashicorp::vault::restapi::plugin --mode=raft-storage --hostname=$HOSTADDRESS$ --port='$_HOSTAPIPORT$' --proto='$_HOSTAPIPROTO$' --api-token='$_HOSTAPITOKEN$' $_HOSTAPIEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "", description: "Seuil warning"}
- {name: CRITICAL, value: "", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
+50
View File
@@ -0,0 +1,50 @@
id: app-iis-restapi
name: Microsoft IIS (API REST)
category: applications
status: to-verify
plugin: centreon_iis_restapi.pl
description: Supervision d'un serveur IIS via l'API REST de l'administration (pools, sites).
prerequis:
paquets:
debian: [libwww-perl, libjson-xs-perl]
rhel: [perl-libwww-perl, perl-JSON-XS]
host_template:
name: App-IIS-custom
alias: Applicatif Microsoft IIS
parents: [generic-active-host-custom]
macros:
- {name: APIPORT, value: "443", description: "Port de l'API"}
- {name: APIPROTO, value: "https", description: "Protocole d'acces"}
- {name: APIUSERNAME, value: "centreon", description: "Compte de supervision"}
- {name: APIPASSWORD, value: "", description: "Mot de passe du compte", is_password: true}
- {name: APIEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-IIS
alias: Microsoft IIS (API REST)
notification:
perimetre: Microsoft IIS (API REST)
calendrier:
name: TP-App-IIS-24x7
modele: 24x7
alias: Microsoft IIS (API REST), en permanence
groupe: CG-App-IIS
criticite: Majeure
impact: "Sites et applications web indisponibles"
options_hote: d,u,r
options_service: w,c,r
intervalle: 30
services:
- name: Application-Pools
alias: Application-Pools
description: Etat des pools d'applications
line: "$CENTREONPLUGINS$/centreon_iis_restapi.pl --plugin=apps::microsoft::iis::restapi::plugin --mode=application-pools --hostname=$HOSTADDRESS$ --port='$_HOSTAPIPORT$' --proto='$_HOSTAPIPROTO$' --api-username='$_HOSTAPIUSERNAME$' --api-password='$_HOSTAPIPASSWORD$' $_HOSTAPIEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
- name: Web-Sites
alias: Web-Sites
description: Trafic et connexions des sites
line: "$CENTREONPLUGINS$/centreon_iis_restapi.pl --plugin=apps::microsoft::iis::restapi::plugin --mode=web-sites --hostname=$HOSTADDRESS$ --port='$_HOSTAPIPORT$' --proto='$_HOSTAPIPROTO$' --api-username='$_HOSTAPIUSERNAME$' --api-password='$_HOSTAPIPASSWORD$' $_HOSTAPIEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "", description: "Seuil warning"}
- {name: CRITICAL, value: "", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
+49
View File
@@ -0,0 +1,49 @@
id: app-jenkins
name: Jenkins
category: applications
status: to-verify
plugin: centreon_jenkins_restapi.pl
description: Supervision d'un serveur Jenkins via son API REST (etat des travaux).
prerequis:
paquets:
debian: [libwww-perl, libjson-xs-perl]
rhel: [perl-libwww-perl, perl-JSON-XS]
host_template:
name: App-Jenkins-custom
alias: Applicatif Jenkins
parents: [generic-active-host-custom]
macros:
- {name: APIPORT, value: "443", description: "Port de l'API"}
- {name: APIPROTO, value: "https", description: "Protocole d'acces"}
- {name: APITOKEN, value: "", description: "Jeton d'API", is_password: true}
- {name: APIEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-Jenkins
alias: Jenkins
notification:
perimetre: Jenkins
calendrier:
name: TP-App-Jenkins-24x7
modele: 24x7
alias: Jenkins, en permanence
groupe: CG-App-Jenkins
criticite: Mineure
impact: "Chaines d'integration continue a l'arret"
options_hote: d,u,r
options_service: w,c,r
intervalle: 30
services:
- name: Jobs
alias: Jobs
description: Etat des travaux
line: "$CENTREONPLUGINS$/centreon_jenkins_restapi.pl --plugin=apps::jenkins::restapi::plugin --mode=jobs --hostname=$HOSTADDRESS$ --port='$_HOSTAPIPORT$' --proto='$_HOSTAPIPROTO$' --api-token='$_HOSTAPITOKEN$' $_HOSTAPIEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "", description: "Seuil warning"}
- {name: CRITICAL, value: "", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
- name: Nodes
alias: Nodes
description: Etat des agents de construction
line: "$CENTREONPLUGINS$/centreon_jenkins_restapi.pl --plugin=apps::jenkins::restapi::plugin --mode=nodes --hostname=$HOSTADDRESS$ --port='$_HOSTAPIPORT$' --proto='$_HOSTAPIPROTO$' --api-token='$_HOSTAPITOKEN$' $_HOSTAPIEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
+70
View File
@@ -0,0 +1,70 @@
id: app-jvm-jmx
name: Machine virtuelle Java (JMX)
category: applications
status: to-verify
plugin: centreon_java_jvm.pl
description: Supervision d'une machine virtuelle Java via JMX et l'agent Jolokia.
prerequis:
paquets:
debian: [libwww-perl, libjson-xs-perl]
rhel: [perl-libwww-perl, perl-JSON-XS]
notes: |
Deployer l'agent Jolokia dans la JVM supervisee et exposer son point
d'acces au collecteur : les plugins JMX de Centreon passent par lui.
host_template:
name: App-JVM-JMX-custom
alias: Applicatif JVM JMX
parents: [generic-active-host-custom]
macros:
- {name: JMXURL, value: "http://localhost:8080/jolokia", description: "URL de l'agent Jolokia"}
- {name: JMXUSERNAME, value: "", description: "Compte Jolokia"}
- {name: JMXPASSWORD, value: "", description: "Mot de passe Jolokia", is_password: true}
- {name: JMXEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-JVM-JMX
alias: Machine virtuelle Java (JMX)
notification:
perimetre: Machine virtuelle Java (JMX)
calendrier:
name: TP-App-JVM-JMX-24x7
modele: 24x7
alias: Machine virtuelle Java (JMX), en permanence
groupe: CG-App-JVM-JMX
criticite: Majeure
impact: "Application Java degradee ou arretee"
options_hote: d,u,r
options_service: w,c,r
intervalle: 30
services:
- name: Memory
alias: Memory
description: Memoire utilisee par la JVM
line: "$CENTREONPLUGINS$/centreon_java_jvm.pl --plugin=apps::java::jvm::plugin --mode=memory --url='$_HOSTJMXURL$' --username='$_HOSTJMXUSERNAME$' --password='$_HOSTJMXPASSWORD$' $_HOSTJMXEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "80", description: "Seuil warning"}
- {name: CRITICAL, value: "90", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
- name: Gc
alias: Gc
description: Ramasse-miettes
line: "$CENTREONPLUGINS$/centreon_java_jvm.pl --plugin=apps::java::jvm::plugin --mode=gcutil --url='$_HOSTJMXURL$' --username='$_HOSTJMXUSERNAME$' --password='$_HOSTJMXPASSWORD$' $_HOSTJMXEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "80", description: "Seuil warning"}
- {name: CRITICAL, value: "90", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
- name: Threads
alias: Threads
description: Fils d'execution
line: "$CENTREONPLUGINS$/centreon_java_jvm.pl --plugin=apps::java::jvm::plugin --mode=threads --url='$_HOSTJMXURL$' --username='$_HOSTJMXUSERNAME$' --password='$_HOSTJMXPASSWORD$' $_HOSTJMXEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "80", description: "Seuil warning"}
- {name: CRITICAL, value: "90", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
- name: Class-Count
alias: Class-Count
description: Classes chargees
line: "$CENTREONPLUGINS$/centreon_java_jvm.pl --plugin=apps::java::jvm::plugin --mode=class-count --url='$_HOSTJMXURL$' --username='$_HOSTJMXUSERNAME$' --password='$_HOSTJMXPASSWORD$' $_HOSTJMXEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "80", description: "Seuil warning"}
- {name: CRITICAL, value: "90", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
+62
View File
@@ -0,0 +1,62 @@
id: app-kafka-jmx
name: Apache Kafka (JMX)
category: applications
status: to-verify
plugin: centreon_kafka_jmx.pl
description: Supervision d'un courtier Kafka via JMX et l'agent Jolokia.
prerequis:
paquets:
debian: [libwww-perl, libjson-xs-perl]
rhel: [perl-libwww-perl, perl-JSON-XS]
notes: |
Deployer l'agent Jolokia dans la JVM supervisee et exposer son point
d'acces au collecteur : les plugins JMX de Centreon passent par lui.
host_template:
name: App-Kafka-JMX-custom
alias: Applicatif Kafka JMX
parents: [generic-active-host-custom]
macros:
- {name: JMXURL, value: "http://localhost:8080/jolokia", description: "URL de l'agent Jolokia"}
- {name: JMXUSERNAME, value: "", description: "Compte Jolokia"}
- {name: JMXPASSWORD, value: "", description: "Mot de passe Jolokia", is_password: true}
- {name: JMXEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-Kafka-JMX
alias: Apache Kafka (JMX)
notification:
perimetre: Apache Kafka (JMX)
calendrier:
name: TP-App-Kafka-JMX-24x7
modele: 24x7
alias: Apache Kafka (JMX), en permanence
groupe: CG-App-Kafka-JMX
criticite: Majeure
impact: "Echanges entre applications interrompus"
options_hote: d,u,r
options_service: w,c,r
intervalle: 30
services:
- name: Broker-Status
alias: Broker-Status
description: Etat du courtier et partitions
line: "$CENTREONPLUGINS$/centreon_kafka_jmx.pl --plugin=apps::kafka::jmx::plugin --mode=brokers --url='$_HOSTJMXURL$' --username='$_HOSTJMXUSERNAME$' --password='$_HOSTJMXPASSWORD$' $_HOSTJMXEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "80", description: "Seuil warning"}
- {name: CRITICAL, value: "90", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
- name: Topics
alias: Topics
description: Trafic par sujet
line: "$CENTREONPLUGINS$/centreon_kafka_jmx.pl --plugin=apps::kafka::jmx::plugin --mode=topics --url='$_HOSTJMXURL$' --username='$_HOSTJMXUSERNAME$' --password='$_HOSTJMXPASSWORD$' $_HOSTJMXEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "80", description: "Seuil warning"}
- {name: CRITICAL, value: "90", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
- name: Global
alias: Global
description: Statistiques globales du cluster
line: "$CENTREONPLUGINS$/centreon_kafka_jmx.pl --plugin=apps::kafka::jmx::plugin --mode=global --url='$_HOSTJMXURL$' --username='$_HOSTJMXUSERNAME$' --password='$_HOSTJMXPASSWORD$' $_HOSTJMXEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "80", description: "Seuil warning"}
- {name: CRITICAL, value: "90", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
@@ -0,0 +1,36 @@
id: app-keepalived-snmp
name: Keepalived (SNMP)
category: applications
status: to-verify
plugin: centreon_keepalived_snmp.pl
description: Supervision de l'etat VRRP d'un noeud Keepalived en SNMP.
host_template:
name: App-Keepalived-SNMP-custom
alias: Applicatif Keepalived SNMP
parents: [generic-active-host-custom]
check_command: check_centreon_ping
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-Keepalived-SNMP
alias: Keepalived (SNMP)
notification:
perimetre: Keepalived (SNMP)
calendrier:
name: TP-App-Keepalived-SNMP-24x7
modele: 24x7
alias: Keepalived (SNMP), en permanence
groupe: CG-App-Keepalived-SNMP
criticite: Critique
impact: "Bascule d'adresse virtuelle compromise"
options_hote: d,u,r
options_service: w,c,r
intervalle: 30
services:
- name: Vrrp-Status
alias: Vrrp-Status
description: Etat des instances VRRP
line: "$CENTREONPLUGINS$/centreon_keepalived_snmp.pl --plugin=apps::keepalived::snmp::plugin --mode=vrrp-status --hostname=$HOSTADDRESS$ --snmp-version='$_HOSTSNMPVERSION$' --snmp-community='$_HOSTSNMPCOMMUNITY$' $_HOSTSNMPEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
+7 -1
View File
@@ -13,9 +13,15 @@ host_template:
- {name: NGINXPROTO, value: "http", description: "Protocole (http ou https)"}
- {name: NGINXURLPATH, value: "/nginx_status", description: "Chemin de la page stub_status"}
- {name: NGINXEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-Nginx
alias: Nginx
notification:
perimetre: Nginx
calendrier: 24x7
calendrier:
name: TP-App-Nginx-24x7
modele: 24x7
alias: Nginx, en permanence
groupe: CG-App-Nginx
criticite: Majeure
impact: "Sites et applications web indisponibles"
+54
View File
@@ -0,0 +1,54 @@
id: app-php-fpm
name: PHP-FPM
category: applications
status: to-verify
plugin: centreon_php_fpm_web.pl
description: Supervision d'un pool PHP-FPM via sa page de statut (processus, file d'attente, requetes).
prerequis:
paquets:
debian: [libwww-perl]
rhel: [perl-libwww-perl]
notes: |
Activer pm.status_path dans la configuration du pool, et exposer ce chemin
au collecteur depuis le serveur web.
host_template:
name: App-PHP-FPM-custom
alias: Applicatif PHP-FPM
parents: [generic-active-host-custom]
macros:
- {name: FPMPORT, value: "80", description: "Port du serveur web"}
- {name: FPMPROTO, value: "http", description: "Protocole d'acces"}
- {name: FPMURLPATH, value: "/status", description: "Chemin de la page de statut"}
- {name: FPMEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-PHP-FPM
alias: PHP-FPM
notification:
perimetre: PHP-FPM
calendrier:
name: TP-App-PHP-FPM-24x7
modele: 24x7
alias: PHP-FPM, en permanence
groupe: CG-App-PHP-FPM
criticite: Majeure
impact: "Applications PHP indisponibles ou saturees"
options_hote: d,u,r
options_service: w,c,r
intervalle: 30
services:
- name: Processes
alias: Processes
description: Processus actifs, inactifs et file d'attente
line: "$CENTREONPLUGINS$/centreon_php_fpm_web.pl --plugin=apps::php::fpm::web::plugin --mode=usage --hostname=$HOSTADDRESS$ --port='$_HOSTFPMPORT$' --proto='$_HOSTFPMPROTO$' --urlpath='$_HOSTFPMURLPATH$' --warning-active-processes='$_SERVICEWARNING$' --critical-active-processes='$_SERVICECRITICAL$' $_HOSTFPMEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "", description: "Seuil warning sur les processus actifs"}
- {name: CRITICAL, value: "", description: "Seuil critical sur les processus actifs"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
- name: Listen-Queue
alias: Listen-Queue
description: File d'attente des connexions
line: "$CENTREONPLUGINS$/centreon_php_fpm_web.pl --plugin=apps::php::fpm::web::plugin --mode=usage --hostname=$HOSTADDRESS$ --port='$_HOSTFPMPORT$' --proto='$_HOSTFPMPROTO$' --urlpath='$_HOSTFPMURLPATH$' --warning-listen-queue='$_SERVICEWARNING$' --critical-listen-queue='$_SERVICECRITICAL$' $_HOSTFPMEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "1", description: "Seuil warning sur la file d'attente"}
- {name: CRITICAL, value: "10", description: "Seuil critical sur la file d'attente"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
+43
View File
@@ -0,0 +1,43 @@
id: app-prometheus
name: Prometheus
category: applications
status: to-verify
plugin: centreon_prometheus_api.pl
description: Supervision d'un serveur Prometheus via son API REST (cibles).
prerequis:
paquets:
debian: [libwww-perl, libjson-xs-perl]
rhel: [perl-libwww-perl, perl-JSON-XS]
host_template:
name: App-Prometheus-custom
alias: Applicatif Prometheus
parents: [generic-active-host-custom]
macros:
- {name: APIPORT, value: "443", description: "Port de l'API"}
- {name: APIPROTO, value: "https", description: "Protocole d'acces"}
- {name: APITOKEN, value: "", description: "Jeton d'API", is_password: true}
- {name: APIEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-Prometheus
alias: Prometheus
notification:
perimetre: Prometheus
calendrier:
name: TP-App-Prometheus-24x7
modele: 24x7
alias: Prometheus, en permanence
groupe: CG-App-Prometheus
criticite: Mineure
impact: "Collecte de metriques interrompue"
options_hote: d,u,r
options_service: w,c,r
intervalle: 30
services:
- name: Targets
alias: Targets
description: Etat des cibles de collecte
line: "$CENTREONPLUGINS$/centreon_prometheus_api.pl --plugin=cloud::prometheus::restapi::plugin --mode=targets --hostname=$HOSTADDRESS$ --port='$_HOSTAPIPORT$' --proto='$_HOSTAPIPROTO$' --api-token='$_HOSTAPITOKEN$' $_HOSTAPIEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "", description: "Seuil warning"}
- {name: CRITICAL, value: "", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
+7 -1
View File
@@ -21,9 +21,15 @@ host_template:
- {name: RABBITUSERNAME, value: "centreon", description: "Compte de supervision"}
- {name: RABBITPASSWORD, value: "", description: "Mot de passe du compte", is_password: true}
- {name: RABBITEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-RabbitMQ
alias: RabbitMQ
notification:
perimetre: RabbitMQ
calendrier: 24x7
calendrier:
name: TP-App-RabbitMQ-24x7
modele: 24x7
alias: RabbitMQ, en permanence
groupe: CG-App-RabbitMQ
criticite: Majeure
impact: "Echanges entre applications interrompus"
+54
View File
@@ -0,0 +1,54 @@
id: app-squid-snmp
name: Squid (SNMP)
category: applications
status: to-verify
plugin: centreon_squid_snmp.pl
description: Supervision d'un mandataire Squid en SNMP (cache, trafic, ressources).
host_template:
name: App-Squid-SNMP-custom
alias: Applicatif Squid SNMP
parents: [generic-active-host-custom]
check_command: check_centreon_ping
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-Squid-SNMP
alias: Squid (SNMP)
notification:
perimetre: Squid (SNMP)
calendrier:
name: TP-App-Squid-SNMP-24x7
modele: 24x7
alias: Squid (SNMP), en permanence
groupe: CG-App-Squid-SNMP
criticite: Majeure
impact: "Acces web des postes bloque ou ralenti"
options_hote: d,u,r
options_service: w,c,r
intervalle: 30
services:
- name: Cache-Usage
alias: Cache-Usage
description: Taux de succes et occupation du cache
line: "$CENTREONPLUGINS$/centreon_squid_snmp.pl --plugin=apps::squid::snmp::plugin --mode=cache-usage --hostname=$HOSTADDRESS$ --snmp-version='$_HOSTSNMPVERSION$' --snmp-community='$_HOSTSNMPCOMMUNITY$' $_HOSTSNMPEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "", description: "Seuil warning"}
- {name: CRITICAL, value: "", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
- name: Traffic
alias: Traffic
description: Trafic HTTP et ICP
line: "$CENTREONPLUGINS$/centreon_squid_snmp.pl --plugin=apps::squid::snmp::plugin --mode=traffic --hostname=$HOSTADDRESS$ --snmp-version='$_HOSTSNMPVERSION$' --snmp-community='$_HOSTSNMPCOMMUNITY$' $_HOSTSNMPEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "", description: "Seuil warning"}
- {name: CRITICAL, value: "", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
- name: System
alias: System
description: Processeur et memoire du service
line: "$CENTREONPLUGINS$/centreon_squid_snmp.pl --plugin=apps::squid::snmp::plugin --mode=system --hostname=$HOSTADDRESS$ --snmp-version='$_HOSTSNMPVERSION$' --snmp-community='$_HOSTSNMPCOMMUNITY$' $_HOSTSNMPEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "", description: "Seuil warning"}
- {name: CRITICAL, value: "", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
+70
View File
@@ -0,0 +1,70 @@
id: app-tomcat-jmx
name: Apache Tomcat (JMX)
category: applications
status: to-verify
plugin: centreon_tomcat_jmx.pl
description: Supervision d'un serveur Tomcat via JMX et l'agent Jolokia.
prerequis:
paquets:
debian: [libwww-perl, libjson-xs-perl]
rhel: [perl-libwww-perl, perl-JSON-XS]
notes: |
Deployer l'agent Jolokia dans la JVM supervisee et exposer son point
d'acces au collecteur : les plugins JMX de Centreon passent par lui.
host_template:
name: App-Tomcat-JMX-custom
alias: Applicatif Tomcat JMX
parents: [generic-active-host-custom]
macros:
- {name: JMXURL, value: "http://localhost:8080/jolokia", description: "URL de l'agent Jolokia"}
- {name: JMXUSERNAME, value: "", description: "Compte Jolokia"}
- {name: JMXPASSWORD, value: "", description: "Mot de passe Jolokia", is_password: true}
- {name: JMXEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-Tomcat-JMX
alias: Apache Tomcat (JMX)
notification:
perimetre: Apache Tomcat (JMX)
calendrier:
name: TP-App-Tomcat-JMX-24x7
modele: 24x7
alias: Apache Tomcat (JMX), en permanence
groupe: CG-App-Tomcat-JMX
criticite: Majeure
impact: "Applications Java hebergees indisponibles"
options_hote: d,u,r
options_service: w,c,r
intervalle: 30
services:
- name: Memory
alias: Memory
description: Memoire de la JVM
line: "$CENTREONPLUGINS$/centreon_tomcat_jmx.pl --plugin=apps::tomcat::jmx::plugin --mode=memory-detailed --url='$_HOSTJMXURL$' --username='$_HOSTJMXUSERNAME$' --password='$_HOSTJMXPASSWORD$' $_HOSTJMXEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "80", description: "Seuil warning"}
- {name: CRITICAL, value: "90", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
- name: Threads
alias: Threads
description: Fils d'execution
line: "$CENTREONPLUGINS$/centreon_tomcat_jmx.pl --plugin=apps::tomcat::jmx::plugin --mode=threads --url='$_HOSTJMXURL$' --username='$_HOSTJMXUSERNAME$' --password='$_HOSTJMXPASSWORD$' $_HOSTJMXEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "80", description: "Seuil warning"}
- {name: CRITICAL, value: "90", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
- name: Sessions
alias: Sessions
description: Sessions des applications web
line: "$CENTREONPLUGINS$/centreon_tomcat_jmx.pl --plugin=apps::tomcat::jmx::plugin --mode=sessions --url='$_HOSTJMXURL$' --username='$_HOSTJMXUSERNAME$' --password='$_HOSTJMXPASSWORD$' $_HOSTJMXEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "80", description: "Seuil warning"}
- {name: CRITICAL, value: "90", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
- name: Requests
alias: Requests
description: Requetes traitees par les connecteurs
line: "$CENTREONPLUGINS$/centreon_tomcat_jmx.pl --plugin=apps::tomcat::jmx::plugin --mode=connector-usage --url='$_HOSTJMXURL$' --username='$_HOSTJMXUSERNAME$' --password='$_HOSTJMXPASSWORD$' $_HOSTJMXEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "80", description: "Seuil warning"}
- {name: CRITICAL, value: "90", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
+50
View File
@@ -0,0 +1,50 @@
id: app-veeam-vbem
name: Veeam Backup Enterprise Manager
category: applications
status: to-verify
plugin: centreon_veeam_vbem_restapi.pl
description: Supervision de Veeam Backup Enterprise Manager via son API REST (travaux, depots).
prerequis:
paquets:
debian: [libwww-perl, libjson-xs-perl]
rhel: [perl-libwww-perl, perl-JSON-XS]
host_template:
name: App-Veeam-VBEM-custom
alias: Applicatif Veeam Enterprise Manager
parents: [generic-active-host-custom]
macros:
- {name: APIPORT, value: "443", description: "Port de l'API"}
- {name: APIPROTO, value: "https", description: "Protocole d'acces"}
- {name: APIUSERNAME, value: "centreon", description: "Compte de supervision"}
- {name: APIPASSWORD, value: "", description: "Mot de passe du compte", is_password: true}
- {name: APIEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-Veeam-VBEM
alias: Veeam Backup Enterprise Manager
notification:
perimetre: Veeam Backup Enterprise Manager
calendrier:
name: TP-App-Veeam-VBEM-24x7
modele: 24x7
alias: Veeam Backup Enterprise Manager, en permanence
groupe: CG-App-Veeam-VBEM
criticite: Critique
impact: "Sauvegardes non verifiees, restauration compromise"
options_hote: d,u,r
options_service: w,c,r
intervalle: 30
services:
- name: Job-Status
alias: Job-Status
description: Etat des travaux de sauvegarde
line: "$CENTREONPLUGINS$/centreon_veeam_vbem_restapi.pl --plugin=apps::backup::veeam::vbem::restapi::plugin --mode=job-status --hostname=$HOSTADDRESS$ --port='$_HOSTAPIPORT$' --proto='$_HOSTAPIPROTO$' --api-username='$_HOSTAPIUSERNAME$' --api-password='$_HOSTAPIPASSWORD$' $_HOSTAPIEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
- name: Repository-Usage
alias: Repository-Usage
description: Occupation des depots
line: "$CENTREONPLUGINS$/centreon_veeam_vbem_restapi.pl --plugin=apps::backup::veeam::vbem::restapi::plugin --mode=repository-usage --hostname=$HOSTADDRESS$ --port='$_HOSTAPIPORT$' --proto='$_HOSTAPIPROTO$' --api-username='$_HOSTAPIUSERNAME$' --api-password='$_HOSTAPIPASSWORD$' $_HOSTAPIEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "", description: "Seuil warning"}
- {name: CRITICAL, value: "", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
+50
View File
@@ -0,0 +1,50 @@
id: app-wazuh
name: Wazuh
category: applications
status: to-verify
plugin: centreon_wazuh_restapi.pl
description: Supervision d'un gestionnaire Wazuh via son API REST (agents, processus).
prerequis:
paquets:
debian: [libwww-perl, libjson-xs-perl]
rhel: [perl-libwww-perl, perl-JSON-XS]
host_template:
name: App-Wazuh-custom
alias: Applicatif Wazuh
parents: [generic-active-host-custom]
macros:
- {name: APIPORT, value: "443", description: "Port de l'API"}
- {name: APIPROTO, value: "https", description: "Protocole d'acces"}
- {name: APIUSERNAME, value: "centreon", description: "Compte de supervision"}
- {name: APIPASSWORD, value: "", description: "Mot de passe du compte", is_password: true}
- {name: APIEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-Wazuh
alias: Wazuh
notification:
perimetre: Wazuh
calendrier:
name: TP-App-Wazuh-24x7
modele: 24x7
alias: Wazuh, en permanence
groupe: CG-App-Wazuh
criticite: Critique
impact: "Detection d'intrusion et conformite hors service"
options_hote: d,u,r
options_service: w,c,r
intervalle: 30
services:
- name: Agents
alias: Agents
description: Etat de connexion des agents
line: "$CENTREONPLUGINS$/centreon_wazuh_restapi.pl --plugin=apps::wazuh::restapi::plugin --mode=agents --hostname=$HOSTADDRESS$ --port='$_HOSTAPIPORT$' --proto='$_HOSTAPIPROTO$' --api-username='$_HOSTAPIUSERNAME$' --api-password='$_HOSTAPIPASSWORD$' $_HOSTAPIEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "", description: "Seuil warning"}
- {name: CRITICAL, value: "", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
- name: Manager
alias: Manager
description: Processus du gestionnaire
line: "$CENTREONPLUGINS$/centreon_wazuh_restapi.pl --plugin=apps::wazuh::restapi::plugin --mode=manager --hostname=$HOSTADDRESS$ --port='$_HOSTAPIPORT$' --proto='$_HOSTAPIPROTO$' --api-username='$_HOSTAPIUSERNAME$' --api-password='$_HOSTAPIPASSWORD$' $_HOSTAPIEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
@@ -0,0 +1,62 @@
id: app-zookeeper-jmx
name: Apache ZooKeeper (JMX)
category: applications
status: to-verify
plugin: centreon_zookeeper_jmx.pl
description: Supervision d'un noeud ZooKeeper via JMX et l'agent Jolokia.
prerequis:
paquets:
debian: [libwww-perl, libjson-xs-perl]
rhel: [perl-libwww-perl, perl-JSON-XS]
notes: |
Deployer l'agent Jolokia dans la JVM supervisee et exposer son point
d'acces au collecteur : les plugins JMX de Centreon passent par lui.
host_template:
name: App-ZooKeeper-JMX-custom
alias: Applicatif ZooKeeper JMX
parents: [generic-active-host-custom]
macros:
- {name: JMXURL, value: "http://localhost:8080/jolokia", description: "URL de l'agent Jolokia"}
- {name: JMXUSERNAME, value: "", description: "Compte Jolokia"}
- {name: JMXPASSWORD, value: "", description: "Mot de passe Jolokia", is_password: true}
- {name: JMXEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-ZooKeeper-JMX
alias: Apache ZooKeeper (JMX)
notification:
perimetre: Apache ZooKeeper (JMX)
calendrier:
name: TP-App-ZooKeeper-JMX-24x7
modele: 24x7
alias: Apache ZooKeeper (JMX), en permanence
groupe: CG-App-ZooKeeper-JMX
criticite: Majeure
impact: "Coordination du cluster perdue"
options_hote: d,u,r
options_service: w,c,r
intervalle: 30
services:
- name: Connections
alias: Connections
description: Connexions clientes
line: "$CENTREONPLUGINS$/centreon_zookeeper_jmx.pl --plugin=apps::zookeeper::jmx::plugin --mode=connections --url='$_HOSTJMXURL$' --username='$_HOSTJMXUSERNAME$' --password='$_HOSTJMXPASSWORD$' $_HOSTJMXEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "80", description: "Seuil warning"}
- {name: CRITICAL, value: "90", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
- name: Latency
alias: Latency
description: Latence des requetes
line: "$CENTREONPLUGINS$/centreon_zookeeper_jmx.pl --plugin=apps::zookeeper::jmx::plugin --mode=latency --url='$_HOSTJMXURL$' --username='$_HOSTJMXUSERNAME$' --password='$_HOSTJMXPASSWORD$' $_HOSTJMXEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "80", description: "Seuil warning"}
- {name: CRITICAL, value: "90", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
- name: Packets
alias: Packets
description: Paquets emis et recus
line: "$CENTREONPLUGINS$/centreon_zookeeper_jmx.pl --plugin=apps::zookeeper::jmx::plugin --mode=packets --url='$_HOSTJMXURL$' --username='$_HOSTJMXUSERNAME$' --password='$_HOSTJMXPASSWORD$' $_HOSTJMXEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "80", description: "Seuil warning"}
- {name: CRITICAL, value: "90", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
+7 -1
View File
@@ -20,9 +20,15 @@ host_template:
- {name: MONGOUSERNAME, value: "centreon", description: "Compte de supervision"}
- {name: MONGOPASSWORD, value: "", description: "Mot de passe du compte", is_password: true}
- {name: MONGOEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-MongoDB
alias: MongoDB
notification:
perimetre: MongoDB
calendrier: 24x7
calendrier:
name: TP-App-MongoDB-24x7
modele: 24x7
alias: MongoDB, en permanence
groupe: CG-App-MongoDB
criticite: Majeure
impact: "Bases de donnees inaccessibles"
+7 -1
View File
@@ -22,9 +22,15 @@ prerequis:
droit VIEW SERVER STATE pour le compte de supervision.
verifications:
- "/usr/lib/centreon/plugins/centreon_mssql.pl --plugin=database::mssql::plugin --list-mode"
groupe_hote:
name: HG-App-DB-MSSQL
alias: Microsoft SQL Server
notification:
perimetre: Microsoft SQL Server
calendrier: 24x7
calendrier:
name: TP-App-DB-MSSQL-24x7
modele: 24x7
alias: Microsoft SQL Server, en permanence
groupe: CG-App-DB-MSSQL
criticite: Majeure
impact: "Bases de donnees inaccessibles"
+7 -1
View File
@@ -23,9 +23,15 @@ prerequis:
GRANT REPLICATION CLIENT, PROCESS, SELECT ON *.* TO 'centreon'@'%';
verifications:
- "/usr/lib/centreon/plugins/centreon_mysql.pl --plugin=database::mysql::plugin --list-mode"
groupe_hote:
name: HG-App-DB-MySQL
alias: MySQL / MariaDB
notification:
perimetre: MySQL / MariaDB
calendrier: 24x7
calendrier:
name: TP-App-DB-MySQL-24x7
modele: 24x7
alias: MySQL / MariaDB, en permanence
groupe: CG-App-DB-MySQL
criticite: Majeure
impact: "Bases de donnees inaccessibles"
+7 -1
View File
@@ -21,9 +21,15 @@ prerequis:
definir ORACLE_HOME et LD_LIBRARY_PATH pour l'utilisateur centreon-engine.
verifications:
- "/usr/lib/centreon/plugins/centreon_oracle.pl --plugin=database::oracle::plugin --list-mode"
groupe_hote:
name: HG-App-DB-Oracle
alias: Oracle Database
notification:
perimetre: Oracle Database
calendrier: 24x7
calendrier:
name: TP-App-DB-Oracle-24x7
modele: 24x7
alias: Oracle Database, en permanence
groupe: CG-App-DB-Oracle
criticite: Majeure
impact: "Bases de donnees inaccessibles"
+7 -1
View File
@@ -24,9 +24,15 @@ prerequis:
GRANT pg_monitor TO centreon;
verifications:
- "/usr/lib/centreon/plugins/centreon_postgres.pl --plugin=database::postgres::plugin --list-mode"
groupe_hote:
name: HG-App-DB-PostgreSQL
alias: PostgreSQL
notification:
perimetre: PostgreSQL
calendrier: 24x7
calendrier:
name: TP-App-DB-PostgreSQL-24x7
modele: 24x7
alias: PostgreSQL, en permanence
groupe: CG-App-DB-PostgreSQL
criticite: Majeure
impact: "Bases de donnees inaccessibles"
+7 -1
View File
@@ -19,9 +19,15 @@ host_template:
- {name: REDISPORT, value: "6379", description: "Port d'ecoute"}
- {name: REDISPASSWORD, value: "", description: "Mot de passe", is_password: true}
- {name: REDISEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-Redis
alias: Redis
notification:
perimetre: Redis
calendrier: 24x7
calendrier:
name: TP-App-Redis-24x7
modele: 24x7
alias: Redis, en permanence
groupe: CG-App-Redis
criticite: Majeure
impact: "Cache applicatif indisponible, degradation des temps de reponse"
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-Dell-iDRAC-SNMP
alias: Serveur Dell (iDRAC SNMP)
notification:
perimetre: Serveur Dell (iDRAC SNMP)
calendrier: 24x7
calendrier:
name: TP-HW-Dell-iDRAC-SNMP-24x7
modele: 24x7
alias: Serveur Dell (iDRAC SNMP), en permanence
groupe: CG-HW-Dell-iDRAC-SNMP
criticite: Majeure
impact: "Materiel serveur en defaut"
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-HP-Proliant-SNMP
alias: Serveur HP ProLiant (iLO SNMP)
notification:
perimetre: Serveur HP ProLiant (iLO SNMP)
calendrier: 24x7
calendrier:
name: TP-HW-HP-Proliant-SNMP-24x7
modele: 24x7
alias: Serveur HP ProLiant (iLO SNMP), en permanence
groupe: CG-HW-HP-Proliant-SNMP
criticite: Majeure
impact: "Materiel serveur en defaut"
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-Alcatel-OmniSwitch
alias: Switch Alcatel OmniSwitch (SNMP)
notification:
perimetre: Switch Alcatel OmniSwitch (SNMP)
calendrier: 24x7
calendrier:
name: TP-HW-Alcatel-OmniSwitch-24x7
modele: 24x7
alias: Switch Alcatel OmniSwitch (SNMP), en permanence
groupe: CG-HW-Alcatel-OmniSwitch
criticite: Critique
impact: "Coupure reseau sur le perimetre desservi"
+7 -1
View File
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-Aruba-Instant
alias: Bornes wifi Aruba Instant (SNMP)
notification:
perimetre: Bornes wifi Aruba Instant
calendrier: 24x7
calendrier:
name: TP-HW-Aruba-Instant-24x7
modele: 24x7
alias: Bornes wifi Aruba Instant (SNMP), en permanence
groupe: CG-HW-Aruba-Instant
criticite: Majeure
impact: "Couverture wifi degradee ou absente sur le site"
+7 -1
View File
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-Aruba-SNMP
alias: Switch Aruba (SNMP)
notification:
perimetre: Switch Aruba (SNMP)
calendrier: 24x7
calendrier:
name: TP-HW-Aruba-SNMP-24x7
modele: 24x7
alias: Switch Aruba (SNMP), en permanence
groupe: CG-HW-Aruba-SNMP
criticite: Critique
impact: "Coupure reseau sur le perimetre desservi"
+7 -1
View File
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-Cisco-SNMP
alias: Switch / routeur Cisco (SNMP)
notification:
perimetre: Switch / routeur Cisco (SNMP)
calendrier: 24x7
calendrier:
name: TP-HW-Cisco-SNMP-24x7
modele: 24x7
alias: Switch / routeur Cisco (SNMP), en permanence
groupe: CG-HW-Cisco-SNMP
criticite: Critique
impact: "Coupure reseau sur le perimetre desservi"
+7 -1
View File
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-Cisco-WLC
alias: Controleur wifi Cisco WLC (SNMP)
notification:
perimetre: Controleur wifi Cisco WLC
calendrier: 24x7
calendrier:
name: TP-HW-Cisco-WLC-24x7
modele: 24x7
alias: Controleur wifi Cisco WLC (SNMP), en permanence
groupe: CG-HW-Cisco-WLC
criticite: Majeure
impact: "Couverture wifi degradee ou absente sur le site"
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-Dell-PowerConnect
alias: Switch Dell PowerConnect et N-Series (SNMP)
notification:
perimetre: Switch Dell PowerConnect et N-Series (SNMP)
calendrier: 24x7
calendrier:
name: TP-HW-Dell-PowerConnect-24x7
modele: 24x7
alias: Switch Dell PowerConnect et N-Series (SNMP), en permanence
groupe: CG-HW-Dell-PowerConnect
criticite: Critique
impact: "Coupure reseau sur le perimetre desservi"
+7 -1
View File
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-Extreme-SNMP
alias: Switch Extreme Networks (SNMP)
notification:
perimetre: Switch Extreme Networks (SNMP)
calendrier: 24x7
calendrier:
name: TP-HW-Extreme-SNMP-24x7
modele: 24x7
alias: Switch Extreme Networks (SNMP), en permanence
groupe: CG-HW-Extreme-SNMP
criticite: Critique
impact: "Coupure reseau sur le perimetre desservi"
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-Fortinet-FortiGate-SNMP
alias: Firewall Fortinet FortiGate (SNMP)
notification:
perimetre: Firewall Fortinet FortiGate (SNMP)
calendrier: 24x7
calendrier:
name: TP-HW-Fortinet-FortiGate-SNMP-24x7
modele: 24x7
alias: Firewall Fortinet FortiGate (SNMP), en permanence
groupe: CG-HW-Fortinet-FortiGate-SNMP
criticite: Critique
impact: "Pare-feu en defaut, acces reseau compromis"
+7 -1
View File
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-HP-Procurve-SNMP
alias: Switch HP ProCurve et Aruba (SNMP)
notification:
perimetre: Switch HP ProCurve et Aruba (SNMP)
calendrier: 24x7
calendrier:
name: TP-HW-HP-Procurve-SNMP-24x7
modele: 24x7
alias: Switch HP ProCurve et Aruba (SNMP), en permanence
groupe: CG-HW-HP-Procurve-SNMP
criticite: Critique
impact: "Coupure reseau sur le perimetre desservi"
+7 -1
View File
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-Huawei-SNMP
alias: Switch et routeur Huawei (SNMP)
notification:
perimetre: Switch et routeur Huawei (SNMP)
calendrier: 24x7
calendrier:
name: TP-HW-Huawei-SNMP-24x7
modele: 24x7
alias: Switch et routeur Huawei (SNMP), en permanence
groupe: CG-HW-Huawei-SNMP
criticite: Critique
impact: "Coupure reseau sur le perimetre desservi"
+7 -1
View File
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-Juniper-JunOS-SNMP
alias: Juniper JunOS (SNMP)
notification:
perimetre: Juniper JunOS (SNMP)
calendrier: 24x7
calendrier:
name: TP-HW-Juniper-JunOS-SNMP-24x7
modele: 24x7
alias: Juniper JunOS (SNMP), en permanence
groupe: CG-HW-Juniper-JunOS-SNMP
criticite: Critique
impact: "Coupure reseau sur le perimetre desservi"
+7 -1
View File
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-MikroTik-SNMP
alias: MikroTik RouterOS (SNMP)
notification:
perimetre: MikroTik RouterOS (SNMP)
calendrier: 24x7
calendrier:
name: TP-HW-MikroTik-SNMP-24x7
modele: 24x7
alias: MikroTik RouterOS (SNMP), en permanence
groupe: CG-HW-MikroTik-SNMP
criticite: Majeure
impact: "Coupure reseau sur le perimetre desservi"
+7 -1
View File
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-PaloAlto-SNMP
alias: Pare-feu Palo Alto (SNMP)
notification:
perimetre: Pare-feu Palo Alto (SNMP)
calendrier: 24x7
calendrier:
name: TP-HW-PaloAlto-SNMP-24x7
modele: 24x7
alias: Pare-feu Palo Alto (SNMP), en permanence
groupe: CG-HW-PaloAlto-SNMP
criticite: Critique
impact: "Pare-feu en defaut, acces reseau compromis"
+7 -1
View File
@@ -16,9 +16,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-pfSense-SNMP
alias: Pare-feu pfSense (SNMP)
notification:
perimetre: Pare-feu pfSense (SNMP)
calendrier: 24x7
calendrier:
name: TP-HW-pfSense-SNMP-24x7
modele: 24x7
alias: Pare-feu pfSense (SNMP), en permanence
groupe: CG-HW-pfSense-SNMP
criticite: Critique
impact: "Pare-feu en defaut, acces reseau compromis"
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-Ruckus-ZoneDirector
alias: Controleur wifi Ruckus ZoneDirector (SNMP)
notification:
perimetre: Controleur wifi Ruckus
calendrier: 24x7
calendrier:
name: TP-HW-Ruckus-ZoneDirector-24x7
modele: 24x7
alias: Controleur wifi Ruckus ZoneDirector (SNMP), en permanence
groupe: CG-HW-Ruckus-ZoneDirector
criticite: Majeure
impact: "Couverture wifi degradee ou absente sur le site"
+7 -1
View File
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-Stormshield-SNMP
alias: Pare-feu Stormshield (SNMP)
notification:
perimetre: Pare-feu Stormshield (SNMP)
calendrier: 24x7
calendrier:
name: TP-HW-Stormshield-SNMP-24x7
modele: 24x7
alias: Pare-feu Stormshield (SNMP), en permanence
groupe: CG-HW-Stormshield-SNMP
criticite: Critique
impact: "Pare-feu en defaut, acces reseau compromis"
+7 -1
View File
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-Ubiquiti-SNMP
alias: Ubiquiti UniFi et EdgeMax (SNMP)
notification:
perimetre: Ubiquiti UniFi et EdgeMax (SNMP)
calendrier: 24x7
calendrier:
name: TP-HW-Ubiquiti-SNMP-24x7
modele: 24x7
alias: Ubiquiti UniFi et EdgeMax (SNMP), en permanence
groupe: CG-HW-Ubiquiti-SNMP
criticite: Majeure
impact: "Coupure reseau ou wifi sur le perimetre desservi"
+7 -1
View File
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-OS-AIX-SNMP
alias: AIX (SNMP)
notification:
perimetre: AIX (SNMP)
calendrier: 24x7
calendrier:
name: TP-OS-AIX-SNMP-24x7
modele: 24x7
alias: AIX (SNMP), en permanence
groupe: CG-OS-AIX-SNMP
criticite: Majeure
impact: "Serveur indisponible ou degrade"
+7 -1
View File
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-OS-FreeBSD-SNMP
alias: FreeBSD (SNMP)
notification:
perimetre: FreeBSD (SNMP)
calendrier: 24x7
calendrier:
name: TP-OS-FreeBSD-SNMP-24x7
modele: 24x7
alias: FreeBSD (SNMP), en permanence
groupe: CG-OS-FreeBSD-SNMP
criticite: Majeure
impact: "Serveur indisponible ou degrade"
+7 -1
View File
@@ -19,9 +19,15 @@ prerequis:
notes: |
Cote client supervise : installer l'agent NRPE, declarer l'adresse du
collecteur dans allowed_hosts, et definir les commandes appelees.
groupe_hote:
name: HG-OS-Linux-NRPE
alias: Linux (NRPE)
notification:
perimetre: Linux (NRPE)
calendrier: 24x7
calendrier:
name: TP-OS-Linux-NRPE-24x7
modele: 24x7
alias: Linux (NRPE), en permanence
groupe: CG-OS-Linux-NRPE
criticite: Majeure
impact: "Serveur indisponible ou degrade"
+7 -1
View File
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-OS-Linux-SNMP
alias: Linux (SNMP)
notification:
perimetre: Linux (SNMP)
calendrier: 24x7
calendrier:
name: TP-OS-Linux-SNMP-24x7
modele: 24x7
alias: Linux (SNMP), en permanence
groupe: CG-OS-Linux-SNMP
criticite: Majeure
impact: "Serveur indisponible ou degrade"
+7 -1
View File
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-OS-Solaris-SNMP
alias: Solaris (SNMP)
notification:
perimetre: Solaris (SNMP)
calendrier: 24x7
calendrier:
name: TP-OS-Solaris-SNMP-24x7
modele: 24x7
alias: Solaris (SNMP), en permanence
groupe: CG-OS-Solaris-SNMP
criticite: Majeure
impact: "Serveur indisponible ou degrade"
@@ -13,9 +13,15 @@ host_template:
macros:
- {name: NSCLIENTPORT, value: "12489", description: "Port d'ecoute NSClient++"}
- {name: NSCLIENTPASSWORD, value: "", description: "Mot de passe NSClient++", is_password: true}
groupe_hote:
name: HG-OS-Windows-NSClient
alias: Windows (NSClient++ / check_nt)
notification:
perimetre: Windows (NSClient++ / check_nt)
calendrier: 24x7
calendrier:
name: TP-OS-Windows-NSClient-24x7
modele: 24x7
alias: Windows (NSClient++ / check_nt), en permanence
groupe: CG-OS-Windows-NSClient
criticite: Majeure
impact: "Serveur indisponible ou degrade"
+7 -1
View File
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-OS-Windows-SNMP
alias: Windows (SNMP)
notification:
perimetre: Windows (SNMP)
calendrier: 24x7
calendrier:
name: TP-OS-Windows-SNMP-24x7
modele: 24x7
alias: Windows (SNMP), en permanence
groupe: CG-OS-Windows-SNMP
criticite: Majeure
impact: "Serveur indisponible ou degrade"
+7 -1
View File
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-Printer-RFC3805
alias: Imprimante reseau (RFC 3805)
notification:
perimetre: Imprimante reseau (RFC 3805)
calendrier: Heures-Ouvrees
calendrier:
name: TP-HW-Printer-RFC3805-Heures-Ouvrees
modele: Heures-Ouvrees
alias: Imprimante reseau (RFC 3805), heures ouvrees
groupe: CG-HW-Printer-RFC3805
criticite: Mineure
impact: "Impression indisponible ou consommable epuise"
+7 -1
View File
@@ -20,9 +20,15 @@ host_template:
- {name: LDAPBINDDN, value: "", description: "Compte de connexion (DN complet)"}
- {name: LDAPBINDPASSWORD, value: "", description: "Mot de passe du compte", is_password: true}
- {name: LDAPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-LDAP
alias: Annuaire LDAP
notification:
perimetre: Annuaire LDAP
calendrier: 24x7
calendrier:
name: TP-App-LDAP-24x7
modele: 24x7
alias: Annuaire LDAP, en permanence
groupe: CG-App-LDAP
criticite: Critique
impact: "Authentification et annuaire indisponibles, la plupart des applications s'arretent"
+7 -1
View File
@@ -9,9 +9,15 @@ host_template:
alias: Applicatif Protocoles reseau
parents: [generic-active-host-custom]
macros: []
groupe_hote:
name: HG-App-Protocols
alias: Services reseau standards (HTTP, TCP, DNS, NTP, SSH)
notification:
perimetre: Services reseau standards (HTTP, TCP, DNS, NTP, SSH)
calendrier: 24x7
calendrier:
name: TP-App-Protocols-24x7
modele: 24x7
alias: Services reseau standards (HTTP, TCP, DNS, NTP, SSH), en permanence
groupe: CG-App-Protocols
criticite: Majeure
impact: "Service reseau expose indisponible"
+7 -1
View File
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-OS-Generic-SNMP
alias: Equipement generique (SNMP standard)
notification:
perimetre: Equipement generique (SNMP standard)
calendrier: 24x7
calendrier:
name: TP-OS-Generic-SNMP-24x7
modele: 24x7
alias: Equipement generique (SNMP standard), en permanence
groupe: CG-OS-Generic-SNMP
criticite: Majeure
impact: "Serveur indisponible ou degrade"
+7 -1
View File
@@ -19,9 +19,15 @@ host_template:
- {name: UNITYUSERNAME, value: "centreon", description: "Compte de supervision"}
- {name: UNITYPASSWORD, value: "", description: "Mot de passe du compte", is_password: true}
- {name: UNITYEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-EMC-Unity
alias: Baie Dell EMC Unity (API REST)
notification:
perimetre: Baie Dell EMC Unity
calendrier: 24x7
calendrier:
name: TP-HW-EMC-Unity-24x7
modele: 24x7
alias: Baie Dell EMC Unity (API REST), en permanence
groupe: CG-HW-EMC-Unity
criticite: Critique
impact: "Stockage partage en defaut, machines et applications menacees"
+7 -1
View File
@@ -19,9 +19,15 @@ host_template:
- {name: MSAUSERNAME, value: "monitor", description: "Compte de supervision"}
- {name: MSAPASSWORD, value: "", description: "Mot de passe du compte", is_password: true}
- {name: MSAEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-HP-MSA
alias: Baie HPE MSA et P2000 (API XML)
notification:
perimetre: Baie HPE MSA
calendrier: 24x7
calendrier:
name: TP-HW-HP-MSA-24x7
modele: 24x7
alias: Baie HPE MSA et P2000 (API XML), en permanence
groupe: CG-HW-HP-MSA
criticite: Critique
impact: "Stockage partage en defaut, machines et applications menacees"
+7 -1
View File
@@ -18,9 +18,15 @@ host_template:
macros:
- {name: STORWIZEUSERNAME, value: "centreon", description: "Compte de supervision"}
- {name: STORWIZEEXTRAOPTIONS, value: "", description: "Options supplementaires, dont la cle SSH"}
groupe_hote:
name: HG-HW-IBM-Storwize
alias: Baie IBM Storwize et FlashSystem (SSH)
notification:
perimetre: Baie IBM Storwize
calendrier: 24x7
calendrier:
name: TP-HW-IBM-Storwize-24x7
modele: 24x7
alias: Baie IBM Storwize et FlashSystem (SSH), en permanence
groupe: CG-HW-IBM-Storwize
criticite: Critique
impact: "Stockage partage en defaut, machines et applications menacees"
+7 -1
View File
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-NetApp-ONTAP-SNMP
alias: Baie NetApp ONTAP (SNMP)
notification:
perimetre: Baie NetApp ONTAP (SNMP)
calendrier: 24x7
calendrier:
name: TP-HW-NetApp-ONTAP-SNMP-24x7
modele: 24x7
alias: Baie NetApp ONTAP (SNMP), en permanence
groupe: CG-HW-NetApp-ONTAP-SNMP
criticite: Critique
impact: "Stockage partage en defaut"
+7 -1
View File
@@ -17,9 +17,15 @@ host_template:
macros:
- {name: PURETOKEN, value: "", description: "Jeton d'API", is_password: true}
- {name: PUREEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-PureStorage
alias: Baie Pure Storage (API REST)
notification:
perimetre: Baie Pure Storage
calendrier: 24x7
calendrier:
name: TP-HW-PureStorage-24x7
modele: 24x7
alias: Baie Pure Storage (API REST), en permanence
groupe: CG-HW-PureStorage
criticite: Critique
impact: "Stockage partage en defaut, machines et applications menacees"
+7 -1
View File
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-QNAP-SNMP
alias: NAS QNAP (SNMP)
notification:
perimetre: NAS QNAP
calendrier: 24x7
calendrier:
name: TP-HW-QNAP-SNMP-24x7
modele: 24x7
alias: NAS QNAP (SNMP), en permanence
groupe: CG-HW-QNAP-SNMP
criticite: Majeure
impact: "Stockage et sauvegardes en defaut"
+7 -1
View File
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-Synology-SNMP
alias: NAS Synology (SNMP)
notification:
perimetre: NAS Synology (SNMP)
calendrier: 24x7
calendrier:
name: TP-HW-Synology-SNMP-24x7
modele: 24x7
alias: NAS Synology (SNMP), en permanence
groupe: CG-HW-Synology-SNMP
criticite: Majeure
impact: "Stockage et sauvegardes en defaut"
+7 -1
View File
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-APC-UPS-SNMP
alias: Onduleur APC (SNMP)
notification:
perimetre: Onduleur APC (SNMP)
calendrier: 24x7
calendrier:
name: TP-HW-APC-UPS-SNMP-24x7
modele: 24x7
alias: Onduleur APC (SNMP), en permanence
groupe: CG-HW-APC-UPS-SNMP
criticite: Critique
impact: "Alimentation electrique menacee"
+7 -1
View File
@@ -12,9 +12,15 @@ host_template:
check_command_args: "!3!200,20%!400,50%"
macros:
- {name: SNMPEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-HW-UPS-RFC1628
alias: Onduleur standard (RFC 1628)
notification:
perimetre: Onduleur standard (RFC 1628)
calendrier: 24x7
calendrier:
name: TP-HW-UPS-RFC1628-24x7
modele: 24x7
alias: Onduleur standard (RFC 1628), en permanence
groupe: CG-HW-UPS-RFC1628
criticite: Critique
impact: "Alimentation electrique menacee"
+7 -1
View File
@@ -12,9 +12,15 @@ host_template:
- {name: DOCKERPORT, value: "2376", description: "Port de l'API Docker"}
- {name: DOCKERPROTO, value: "https", description: "Protocole d'acces a l'API"}
- {name: DOCKEREXTRAOPTIONS, value: "", description: "Options supplementaires (certificats, api-version)"}
groupe_hote:
name: HG-App-Docker
alias: Docker (API REST)
notification:
perimetre: Docker (API REST)
calendrier: 24x7
calendrier:
name: TP-App-Docker-24x7
modele: 24x7
alias: Docker (API REST), en permanence
groupe: CG-App-Docker
criticite: Majeure
impact: "Conteneurs applicatifs arretes ou degrades"
+50
View File
@@ -0,0 +1,50 @@
id: app-podman
name: Podman (API REST)
category: virtualization
status: to-verify
plugin: centreon_podman_restapi.pl
description: Supervision d'un hote Podman via son API REST (conteneurs, pods).
prerequis:
paquets:
debian: [libwww-perl, libjson-xs-perl]
rhel: [perl-libwww-perl, perl-JSON-XS]
host_template:
name: App-Podman-custom
alias: Applicatif Podman
parents: [generic-active-host-custom]
macros:
- {name: APIPORT, value: "443", description: "Port de l'API"}
- {name: APIPROTO, value: "https", description: "Protocole d'acces"}
- {name: APIUSERNAME, value: "centreon", description: "Compte de supervision"}
- {name: APIPASSWORD, value: "", description: "Mot de passe du compte", is_password: true}
- {name: APIEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-Podman
alias: Podman (API REST)
notification:
perimetre: Podman (API REST)
calendrier:
name: TP-App-Podman-24x7
modele: 24x7
alias: Podman (API REST), en permanence
groupe: CG-App-Podman
criticite: Majeure
impact: "Conteneurs applicatifs arretes ou degrades"
options_hote: d,u,r
options_service: w,c,r
intervalle: 30
services:
- name: Container-Usage
alias: Container-Usage
description: Consommation des conteneurs
line: "$CENTREONPLUGINS$/centreon_podman_restapi.pl --plugin=apps::podman::restapi::plugin --mode=container-usage --hostname=$HOSTADDRESS$ --port='$_HOSTAPIPORT$' --proto='$_HOSTAPIPROTO$' --api-username='$_HOSTAPIUSERNAME$' --api-password='$_HOSTAPIPASSWORD$' $_HOSTAPIEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: WARNING, value: "", description: "Seuil warning"}
- {name: CRITICAL, value: "", description: "Seuil critical"}
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
- name: Pod-Usage
alias: Pod-Usage
description: Etat des pods
line: "$CENTREONPLUGINS$/centreon_podman_restapi.pl --plugin=apps::podman::restapi::plugin --mode=pod-usage --hostname=$HOSTADDRESS$ --port='$_HOSTAPIPORT$' --proto='$_HOSTAPIPROTO$' --api-username='$_HOSTAPIUSERNAME$' --api-password='$_HOSTAPIPASSWORD$' $_HOSTAPIEXTRAOPTIONS$ $_SERVICEEXTRAOPTIONS$"
macros:
- {name: EXTRAOPTIONS, value: "", description: "Options supplementaires"}
+7 -1
View File
@@ -21,9 +21,15 @@ host_template:
- {name: PVEUSERNAME, value: "centreon@pve", description: "Compte de supervision"}
- {name: PVEPASSWORD, value: "", description: "Mot de passe du compte", is_password: true}
- {name: PVEEXTRAOPTIONS, value: "", description: "Options supplementaires passees au plugin"}
groupe_hote:
name: HG-App-Proxmox
alias: Proxmox VE (API REST)
notification:
perimetre: Proxmox VE (API REST)
calendrier: 24x7
calendrier:
name: TP-App-Proxmox-24x7
modele: 24x7
alias: Proxmox VE (API REST), en permanence
groupe: CG-App-Proxmox
criticite: Critique
impact: "Hyperviseur en defaut, machines virtuelles menacees"
+7 -1
View File
@@ -21,9 +21,15 @@ prerequis:
notes: |
Le connecteur Centreon VMware doit tourner et declarer un container
pointant sur le vCenter, avec un compte en lecture seule.
groupe_hote:
name: HG-App-VMware-ESX
alias: VMware ESXi (connecteur Centreon VMware)
notification:
perimetre: VMware ESXi (connecteur Centreon VMware)
calendrier: 24x7
calendrier:
name: TP-App-VMware-ESX-24x7
modele: 24x7
alias: VMware ESXi (connecteur Centreon VMware), en permanence
groupe: CG-App-VMware-ESX
criticite: Critique
impact: "Hyperviseur en defaut, machines virtuelles menacees"
+20
View File
@@ -38,11 +38,31 @@ Et enfin la revue humaine, qui ne s'automatise pas :
on l'insère ? Point-virgule pour le CLAPI, `@` et `:` pour une URL de connexion, guillemet
simple pour le shell, `%` pour un fichier ini lu par configparser. **Quatre** incidents sur
ce seul motif — c'est le premier endroit où regarder.
- une modification a-t-elle **réellement** été appliquée ? Une correction annoncée en 1.11.1
n'avait jamais pris : le texte recherché avait changé entre-temps. Relire le fichier après
l'édition, et faire passer un test par le chemin réel, pas seulement par la couche voisine.
- une valeur déjà encodée traverse-t-elle un second format qui réinterprète son encodage ?
C'est la variante du piège précédent : `%40` est correct dans une URL, et devient une
interpolation dans un ini.
- ce qui est écrit en base a-t-il traversé `strip_secrets` ?
## Un principe : le moins de saisie libre possible
Chaque champ de texte libre est une occasion de faute de frappe qui ne se verra qu'au
déploiement sur le central. Un champ nouveau doit donc, dans l'ordre de préférence :
1. **une liste fermée** quand les valeurs possibles sont connues et finies — un fuseau
horaire, un type de commande, une version SNMP ;
2. **une liste ouverte avec suggestions** quand des valeurs existent déjà sur le central que
nous ne connaissons pas — un modèle parent, un groupe d'hôtes, une commande de
vérification ;
3. **la saisie libre** seulement pour ce qui est propre à l'utilisateur : un nom, une
description, un seuil.
Et quand une valeur juste est majoritairement la même, elle est **préremplie**. Un projet
vide part avec `/usr/lib/centreon/plugins`, `generic-active-host-custom` et `Central` :
l'utilisateur corrige si son installation diffère, il ne devine pas.
## Nommage
| Objet | Règle | Exemple |
+14
View File
@@ -15,6 +15,20 @@ indisponibles ».
Il reste une chose à faire de votre côté : **mettre des contacts dans le groupe**. Enclume
crée le groupe vide, faute de connaître vos utilisateurs.
### Chaque pack apporte son calendrier
Un pack ne réutilise pas les calendriers du central : il crée le sien,
`TP-App-Apache-24x7`, `TP-HW-Printer-RFC3805-Heures-Ouvrees`. Ajuster les plages d'une
technologie ne touche alors qu'elle, et non tout ce qui pointait `24x7`.
Le rythme copié à la création est `24x7` pour ce dont la panne réveille quelqu'un,
`Heures-Ouvrees` sinon. Les plages restent modifiables ensuite, comme n'importe quel objet
du projet.
Si vous préférez viser un calendrier existant sur votre central — `24x7`, `workhours` —
saisissez-le dans le périmètre : il apparaîtra dans le projet marqué « Centreon » et ne sera
pas recréé, `TP;ADD` échouant sur un objet existant.
## Le principe
Un **périmètre** regroupe ce qui différencie réellement un domaine d'un autre :
+2
View File
@@ -115,6 +115,7 @@ class Pack:
services: list[Service]
prerequis: dict[str, Any] = field(default_factory=dict)
notification: dict[str, Any] = field(default_factory=dict)
groupe_hote: dict[str, Any] = field(default_factory=dict)
source_file: str = ""
@property
@@ -149,6 +150,7 @@ class Pack:
services=[Service.from_dict(s) for s in raw.get("services") or []],
prerequis=raw.get("prerequis") or {},
notification=raw.get("notification") or {},
groupe_hote=raw.get("groupe_hote") or {},
source_file=source_file,
)
+12 -2
View File
@@ -74,7 +74,7 @@ def build_plan(project: Project) -> Plan:
own_commands = {c.name for c in project.commands}
own_htpl = {h.name for h in project.host_templates}
own_tp = {c.name for c in project.calendriers}
own_tp = {c.name for c in project.calendriers if c.creer}
def ref_command(name: str) -> str:
"""Un objet du projet est prefixe ; un objet deja present sur le central ne l'est pas."""
@@ -144,9 +144,12 @@ def build_plan(project: Project) -> Plan:
del_htpl.append(Op("HTPL", "DEL", [full(htpl.name)]))
# --- Notifications : calendriers, commandes, contacts -------------------
if project.calendriers:
if any(c.creer for c in project.calendriers):
plan.ops.append(Op("#", "#", comment="Calendriers de notification"))
for calendrier in project.calendriers:
if not calendrier.creer:
# Livre par Centreon : on s'y refere, on ne le recree pas.
continue
plan.ops.append(Op("TP", "ADD", [full(calendrier.name), calendrier.alias or calendrier.name]))
for jour in JOURS:
plage = calendrier.jours.get(jour)
@@ -252,6 +255,13 @@ def build_plan(project: Project) -> Plan:
],
)
)
for param, valeur in (
("check_command", ref_command(host.check_command) if host.check_command else ""),
("check_command_arguments", host.check_command_args),
("timezone", host.timezone),
):
if valeur:
plan.ops.append(Op("HOST", "setparam", [host.name, param, valeur]))
for macro in host.macros:
plan.ops.append(Op("HOST", "setmacro", _macro_values(host.name, macro, fields)))
plan.ops.append(Op("HOST", "applytpl", [host.name]))
+31 -4
View File
@@ -193,6 +193,9 @@ class Host:
templates: list[str] = field(default_factory=list)
poller: str = "Central"
hostgroups: list[str] = field(default_factory=list)
check_command: str = ""
check_command_args: str = ""
timezone: str = ""
macros: list[Macro] = field(default_factory=list)
@classmethod
@@ -205,6 +208,9 @@ class Host:
poller=_clean(raw.get("poller")) or "Central",
# Ancien format : une chaine unique separee par | ou par virgule.
hostgroups=_liste(raw.get("hostgroups")),
check_command=_clean(raw.get("check_command")),
check_command_args=_clean(raw.get("check_command_args")),
timezone=_clean(raw.get("timezone")),
macros=[Macro.from_dict(m) for m in raw.get("macros") or []],
)
@@ -239,6 +245,10 @@ class Calendrier:
name: str = ""
alias: str = ""
jours: dict[str, str] = field(default_factory=dict)
# Certains calendriers existent des l'installation de Centreon : les
# recreer ferait echouer le deploiement. Ils figurent quand meme dans le
# projet, pour qu'on voie a quoi les perimetres se referent.
creer: bool = True
@classmethod
def from_dict(cls, raw: dict[str, Any]) -> Calendrier:
@@ -247,6 +257,7 @@ class Calendrier:
name=_clean(raw.get("name")),
alias=_clean(raw.get("alias")),
jours={j: _clean(jours.get(j)) for j in JOURS if _clean(jours.get(j))},
creer=bool(raw.get("creer", True)),
)
@@ -468,6 +479,16 @@ class Project:
# Validation
# --------------------------------------------------------------------------- #
def fuseaux_horaires() -> list[str]:
"""Fuseaux connus du systeme, au format attendu par Centreon."""
try:
import zoneinfo
return sorted(zoneinfo.available_timezones())
except Exception:
return []
def validate(project: Project) -> list[dict[str, str]]:
"""Retourne la liste des problemes, du bloquant au simple avertissement."""
@@ -532,6 +553,11 @@ def validate(project: Project) -> list[dict[str, str]]:
for htpl in project.host_templates:
_check_macros(htpl.macros, f"Modele d'hote {htpl.name}", issues)
connus = set(fuseaux_horaires())
for objet in (*project.host_templates, *project.hosts):
if objet.timezone and connus and objet.timezone.lstrip(":") not in connus:
error(f"{objet.name} : fuseau horaire inconnu, {objet.timezone}")
groupes = {g.name for g in project.groupes_hotes}
for host in project.hosts:
for groupe in host.hostgroups:
@@ -557,9 +583,10 @@ def validate(project: Project) -> list[dict[str, str]]:
calendriers = {c.name for c in project.calendriers}
for perimetre in project.perimetres:
if not perimetre.calendrier:
error(f"Perimetre {perimetre.name} : aucun calendrier de notification.")
elif perimetre.calendrier not in calendriers:
# Un calendrier vide devient 24x7 a la lecture : le perimetre pointe
# alors le calendrier du central, ce que l'avertissement ci-dessous
# signale.
if perimetre.calendrier not in calendriers:
warn(
f"Perimetre {perimetre.name} : le calendrier {perimetre.calendrier} n'est pas "
"dans le projet, il devra exister sur le central."
@@ -589,7 +616,7 @@ def validate(project: Project) -> list[dict[str, str]]:
error(f"Perimetre {perimetre.name} : option de service inconnue, {lettre}")
for calendrier in project.calendriers:
if not calendrier.jours:
if calendrier.creer and not calendrier.jours:
warn(f"Calendrier {calendrier.name} : aucune plage horaire, il ne notifiera jamais.")
for paquet in (*project.prerequis.paquets_debian, *project.prerequis.paquets_rhel):
+34 -4
View File
@@ -10,6 +10,7 @@ from .catalog import Pack
from .model import (
Calendrier,
Command,
GroupeHote,
HostTemplate,
Macro,
Perimetre,
@@ -76,20 +77,49 @@ def pack_to_project(
htpl.snmp_community = "public"
project.host_templates = [htpl]
# --- Groupe d'hotes livre avec le pack ----------------------------------
# Un hote sans groupe devient introuvable des que le parc grandit, et les
# droits comme les filtres s'appuient dessus. Le pack en propose donc un.
if pack.groupe_hote:
project.groupes_hotes = [
GroupeHote(
name=str(pack.groupe_hote.get("name") or ""),
alias=str(pack.groupe_hote.get("alias") or pack.name),
)
]
# --- Chaine de notification --------------------------------------------
notification = pack.notification or {}
perimetre_nom = ""
if notification:
calendrier_nom = str(notification.get("calendrier") or "24x7")
modele = CALENDRIERS_STANDARD.get(calendrier_nom)
if modele and calendrier_nom not in CALENDRIERS_CENTREON:
calendrier = notification.get("calendrier")
if isinstance(calendrier, dict):
# Le pack apporte son propre calendrier : modifier les plages
# d'Apache ne doit pas toucher celles de tout le central.
calendrier_nom = str(calendrier.get("name") or "")
modele = CALENDRIERS_STANDARD.get(str(calendrier.get("modele") or "24x7"))
project.calendriers = [
Calendrier(
name=calendrier_nom,
alias=str(modele["alias"]),
alias=str(calendrier.get("alias") or modele["alias"]),
jours=dict(modele["jours"]),
creer=True,
)
]
else:
# Ancienne forme : une reference a un calendrier existant.
calendrier_nom = str(calendrier or "24x7")
modele = CALENDRIERS_STANDARD.get(calendrier_nom)
if modele:
project.calendriers = [
Calendrier(
name=calendrier_nom,
alias=str(modele["alias"]),
jours=dict(modele["jours"]),
creer=calendrier_nom not in CALENDRIERS_CENTREON,
)
]
perimetre_nom = str(notification.get("perimetre") or pack.name)
project.perimetres = [
+421 -48
View File
@@ -152,7 +152,11 @@ function nouvelObjet(type) {
if (type === 'groupehote') return { name: '', alias: '' };
if (type === 'calendrier') return { name: '', alias: '', jours: {} };
if (type === 'perimetre') return {
name: '', description: '', calendrier: '', contacts: [], groupe: '',
name: '', description: '',
calendrier: projet.calendriers.length
? projet.calendriers[projet.calendriers.length - 1].name
: '',
contacts: [], groupe: '',
options_hote: 'd,u,r', options_service: 'w,c,u,r', intervalle: 30,
application: '', responsable: '', procedure: '', criticite: '', impact: '',
couleur: '#2f6f9f',
@@ -173,7 +177,9 @@ function rendreRail() {
className: 'rail-reglages' + (selection.type === 'reglages' ? ' actif' : ''),
type: 'button',
textContent: 'Reglages du projet',
onclick: function () { selection = { type: 'reglages', index: 0 }; rendre(); }
onclick: function () { selection = { type: 'reglages', index: 0 }; chargerStandards();
rendre(); }
}));
Object.keys(LISTES).forEach(function (type) {
@@ -205,6 +211,9 @@ function rendreRail() {
if (type === 'stpl' && objet.host_templates.length === 0) {
item.appendChild(elt('span', { className: 'tag warn', textContent: 'non rattache' }));
}
if (type === 'calendrier' && objet.creer === false) {
item.appendChild(elt('span', { className: 'tag ok', textContent: 'Centreon' }));
}
section.appendChild(item);
});
rail.appendChild(section);
@@ -278,8 +287,8 @@ function rendreReglages(main) {
}));
var grille = elt('div', { className: 'grille' });
grille.appendChild(champ('Prefixe applique aux objets crees', projet, 'prefix', { placeholder: 'ex. ACME-' }));
grille.appendChild(champ('Repertoire des plugins', projet, 'plugins_dir'));
grille.appendChild(champ('Collecteur cible', projet, 'poller'));
grille.appendChild(champPropose('Repertoire des plugins', projet, 'plugins_dir', 'repertoires_plugins'));
grille.appendChild(champPropose('Collecteur cible', projet, 'poller', 'collecteurs'));
grille.appendChild(champ('Repertoire des scripts de notification', projet, 'notif_dir'));
main.appendChild(grille);
main.appendChild(caseACocher("Ajouter APPLYCFG a la fin des scripts", projet, 'apply_config'));
@@ -354,7 +363,7 @@ function rendreStpl(main, stpl) {
var grille = elt('div', { className: 'grille' });
grille.appendChild(champ('Nom du modele', stpl, 'name', { rail: true }));
grille.appendChild(champ('Alias', stpl, 'alias'));
grille.appendChild(champ('Modele parent', stpl, 'parent'));
grille.appendChild(champPropose('Modele parent', stpl, 'parent', 'modeles_service'));
grille.appendChild(champSelectListe('Commande de controle', stpl, 'command',
projet.commands.map(function (c) { return c.name; })));
main.appendChild(grille);
@@ -392,14 +401,19 @@ function rendreHtpl(main, htpl) {
var grille = elt('div', { className: 'grille' });
grille.appendChild(champ('Nom du modele', htpl, 'name', { rail: true, placeholder: 'OS-Linux-SNMP-custom' }));
grille.appendChild(champ('Alias', htpl, 'alias'));
grille.appendChild(champListe('Modeles parents', htpl, 'parents'));
grille.appendChild(champ('Fuseau horaire', htpl, 'timezone', { placeholder: ':Europe/Paris' }));
grille.appendChild(champListeSuggeree('Modeles parents', htpl, 'parents',
(STANDARDS && STANDARDS.modeles_hote) || ['generic-active-host-custom'], 'liste-modeles-hote'));
grille.appendChild(champFuseau('Fuseau horaire', htpl, 'timezone'));
main.appendChild(grille);
var grille2 = elt('div', { className: 'grille' });
grille2.appendChild(champ('Commande de verification', htpl, 'check_command', { placeholder: 'check_centreon_ping' }));
grille2.appendChild(champCommandeVerification('Commande de verification', htpl, 'check_command'));
grille2.appendChild(champ('Arguments', htpl, 'check_command_args', { placeholder: '!3!200,20%!400,50%' }));
grille2.appendChild(champ('Version SNMP', htpl, 'snmp_version', { placeholder: '2c' }));
grille2.appendChild(champChoix('Version SNMP', htpl, 'snmp_version', [
{ valeur: '1', libelle: '1 (obsolete)' },
{ valeur: '2c', libelle: '2c' },
{ valeur: '3', libelle: '3 (authentifiee et chiffree)' }
], { vide: 'Pas de supervision SNMP', autreAutorise: false }));
grille2.appendChild(champ('Communaute SNMP', htpl, 'snmp_community'));
main.appendChild(grille2);
@@ -422,15 +436,41 @@ function rendreHtpl(main, htpl) {
}
function rendreHost(main, host) {
// Les projets enregistres avant la 1.12 portaient une chaine unique.
if (!Array.isArray(host.hostgroups)) {
host.hostgroups = String(host.hostgroups || '')
.split(/[|,]/).map(function (v) { return v.trim(); }).filter(Boolean);
}
if (!Array.isArray(host.templates)) host.templates = [];
var grille = elt('div', { className: 'grille' });
grille.appendChild(champ("Nom de l'hote", host, 'name', { rail: true }));
grille.appendChild(champ('Alias', host, 'alias'));
grille.appendChild(champ('Adresse IP ou DNS', host, 'address'));
grille.appendChild(champ('Collecteur', host, 'poller'));
grille.appendChild(champListeSuggeree("Groupes d'hotes", host, 'hostgroups',
projet.groupes_hotes.map(function (g) { return g.name; }), 'liste-groupes-hotes'));
grille.appendChild(champPropose('Collecteur', host, 'poller', 'collecteurs'));
grille.appendChild(champCommandeVerification('Commande de verification', host, 'check_command'));
grille.appendChild(champ('Arguments de la commande', host, 'check_command_args', { placeholder: '!3!200,20%!400,50%' }));
grille.appendChild(champFuseau('Fuseau horaire', host, 'timezone'));
main.appendChild(grille);
main.appendChild(sousTitre("Groupes d'hotes",
'Cochez les groupes du projet auxquels cet hote appartient.'));
if (!projet.groupes_hotes.length) {
main.appendChild(elt('p', {
className: 'lede',
textContent: 'Aucun groupe dans le projet. Ajoutez-en un dans « Groupes d\u2019hotes », '
+ 'ou saisissez ci-dessous un groupe qui existe deja sur votre central.'
}));
} else {
var casesGroupes = elt('div', { className: 'cases' });
projet.groupes_hotes.forEach(function (groupe) {
casesGroupes.appendChild(caseListe(groupe.name, host.hostgroups, groupe.name));
});
main.appendChild(casesGroupes);
}
main.appendChild(champGroupesExternes(host));
main.appendChild(sousTitre("Modeles d'hote appliques", ''));
var cases = elt('div', { className: 'cases' });
projet.host_templates.forEach(function (htpl) {
@@ -458,6 +498,26 @@ function rendreGroupeHote(main, groupe) {
}
function rendreCalendrier(main, calendrier) {
if (calendrier.creer === undefined) calendrier.creer = true;
if (!calendrier.creer) {
var note = elt('div', { className: 'notice' });
note.appendChild(elt('b', { textContent: 'Calendrier livre par Centreon' }));
note.appendChild(elt('p', {
textContent: 'Ce calendrier existe des l\u2019installation : les perimetres s\u2019y referent, '
+ 'mais il ne sera pas cree. Le recreer ferait echouer le deploiement sur un objet '
+ 'deja present.'
}));
var barre = elt('div', { className: 'barre' });
barre.appendChild(elt('button', {
type: 'button', className: 'small',
textContent: 'Le creer quand meme, il est absent de mon central',
onclick: function () { calendrier.creer = true; sauver(); rendre(); }
}));
note.appendChild(barre);
main.appendChild(note);
}
var grille = elt('div', { className: 'grille' });
grille.appendChild(champ('Nom du calendrier', calendrier, 'name', { rail: true, placeholder: 'Heures-Ouvrees' }));
grille.appendChild(champ('Alias', calendrier, 'alias', { placeholder: '8h-18h du lundi au vendredi' }));
@@ -466,9 +526,43 @@ function rendreCalendrier(main, calendrier) {
main.appendChild(sousTitre('Plages horaires',
'Format Centreon : 08:00-18:00, ou plusieurs plages separees par une virgule. Vide = pas de notification ce jour.'));
if (!calendrier.jours) calendrier.jours = {};
if (!calendrier.creer) {
var apercuPlages = elt('div', { className: 'puces' });
JOURS.forEach(function (jour) {
var plage = calendrier.jours[jour[0]];
if (plage) apercuPlages.appendChild(elt('span', { className: 'puce', textContent: jour[1] + ' : ' + plage }));
});
main.appendChild(sousTitre('Plages horaires', 'telles que Centreon les definit'));
main.appendChild(apercuPlages);
return;
}
var raccourcis = elt('div', { className: 'barre' });
[
['En permanence', '00:00-24:00', JOURS.map(function (j) { return j[0]; })],
['Heures ouvrees', '08:00-18:00', ['monday', 'tuesday', 'wednesday', 'thursday', 'friday']],
['Astreinte nuit et week-end', '00:00-08:00,18:00-24:00', JOURS.map(function (j) { return j[0]; })]
].forEach(function (modele) {
raccourcis.appendChild(elt('button', {
type: 'button', className: 'small', textContent: modele[0],
onclick: function () {
calendrier.jours = {};
modele[2].forEach(function (jour) { calendrier.jours[jour] = modele[1]; });
sauver(); rendreMain();
}
}));
});
raccourcis.appendChild(elt('button', {
type: 'button', className: 'small danger', textContent: 'Tout vider',
onclick: function () { calendrier.jours = {}; sauver(); rendreMain(); }
}));
main.appendChild(raccourcis);
var jours = elt('div', { className: 'grille' });
JOURS.forEach(function (jour) {
jours.appendChild(champ(jour[1], calendrier.jours, jour[0], { placeholder: '08:00-18:00' }));
if (calendrier.jours[jour[0]] === undefined) calendrier.jours[jour[0]] = '';
jours.appendChild(champ(jour[1], calendrier.jours, jour[0], { placeholder: 'aucune plage' }));
});
main.appendChild(jours);
}
@@ -476,8 +570,16 @@ function rendreCalendrier(main, calendrier) {
function rendrePerimetre(main, perimetre) {
var grille = elt('div', { className: 'grille' });
grille.appendChild(champ('Nom du perimetre', perimetre, 'name', { rail: true, placeholder: 'Applicatif Facturation' }));
grille.appendChild(champSelectListe('Calendrier', perimetre, 'calendrier',
projet.calendriers.map(function (c) { return c.name; })));
var calendriers = projet.calendriers.map(function (c) {
return { valeur: c.name, libelle: c.name + ' \u2014 calendrier du projet' };
});
// Ceux que Centreon livre a l'installation : ils existent toujours.
[['24x7', 'en permanence'], ['workhours', 'heures ouvrees'],
['nonworkhours', 'hors heures ouvrees'], ['none', 'jamais']].forEach(function (c) {
calendriers.push({ valeur: c[0], libelle: c[0] + ' \u2014 ' + c[1] + ', livre par Centreon' });
});
grille.appendChild(champChoix('Calendrier', perimetre, 'calendrier', calendriers));
main.appendChild(barreCalendrier(perimetre));
main.appendChild(grille);
main.appendChild(champ('Description', perimetre, 'description'));
@@ -499,10 +601,11 @@ function rendrePerimetre(main, perimetre) {
var contexte = elt('div', { className: 'grille' });
contexte.appendChild(champ('Application', perimetre, 'application', { placeholder: 'Facturation' }));
contexte.appendChild(champ('Responsable', perimetre, 'responsable', { placeholder: 'Equipe finance' }));
contexte.appendChild(champ('Criticite', perimetre, 'criticite', { placeholder: 'Majeure' }));
contexte.appendChild(champChoix('Criticite', perimetre, 'criticite',
['Critique', 'Majeure', 'Mineure', 'Information'], { autreAutorise: false }));
contexte.appendChild(champ('Impact metier', perimetre, 'impact', { placeholder: 'Facturation client bloquee' }));
contexte.appendChild(champ('Procedure de reprise (URL)', perimetre, 'procedure', { placeholder: 'https://wiki/...' }));
contexte.appendChild(champ('Couleur du bandeau', perimetre, 'couleur', { placeholder: '#2f6f9f' }));
contexte.appendChild(champCouleur('Couleur du bandeau', perimetre, 'couleur'));
main.appendChild(contexte);
main.appendChild(champ('Sujet du message, hote', perimetre, 'sujet_hote'));
@@ -535,6 +638,144 @@ function rendrePerimetre(main, perimetre) {
main.appendChild(apercu);
}
var STANDARDS = null;
function chargerStandards() {
if (STANDARDS) return Promise.resolve(STANDARDS);
return fetch('/api/valeurs-standards').then(function (r) { return r.json(); })
.then(function (v) { STANDARDS = v || {}; return STANDARDS; })
.catch(function () { STANDARDS = {}; return STANDARDS; });
}
// Champ ferme : liste deroulante, avec une option « Autre » qui revele une
// saisie quand une valeur propre au central est necessaire.
function champChoix(libelle, objet, cle, valeurs, options) {
options = options || {};
var label = elt('label', { className: 'field' });
label.appendChild(elt('span', { textContent: libelle }));
var select = elt('select');
select.appendChild(elt('option', { value: '', textContent: options.vide || 'Non defini' }));
valeurs.forEach(function (v) {
var texte = (typeof v === 'object') ? (v.libelle || v.valeur) : v;
var valeur = (typeof v === 'object') ? v.valeur : v;
var option = elt('option', { value: valeur, textContent: texte });
if (objet[cle] === valeur) option.selected = true;
select.appendChild(option);
});
var connues = valeurs.map(function (v) { return (typeof v === 'object') ? v.valeur : v; });
var horsListe = objet[cle] && connues.indexOf(objet[cle]) === -1;
if (options.autreAutorise !== false) {
var autre = elt('option', { value: '__autre__', textContent: 'Autre valeur...' });
if (horsListe) autre.selected = true;
select.appendChild(autre);
}
label.appendChild(select);
var saisie = elt('input', { type: 'text', value: horsListe ? objet[cle] : '' });
saisie.placeholder = options.placeholder || 'Valeur presente sur votre central';
saisie.hidden = !horsListe;
saisie.addEventListener('input', function () { objet[cle] = saisie.value; sauver(); });
label.appendChild(saisie);
select.addEventListener('change', function () {
if (select.value === '__autre__') {
saisie.hidden = false;
saisie.focus();
objet[cle] = saisie.value;
} else {
saisie.hidden = true;
objet[cle] = select.value;
}
sauver();
if (options.rafraichir) rendreMain();
});
return label;
}
// Champ a valeurs proposees : la liste vient du serveur, la saisie reste
// possible pour ce qui existe deja sur un central particulier.
function champPropose(libelle, objet, cle, nomListe, options) {
options = options || {};
var label = elt('label', { className: 'field' });
label.appendChild(elt('span', { textContent: libelle }));
var identifiant = 'liste-' + nomListe;
var input = elt('input', { type: 'text', value: objet[cle] || '' });
if (options.placeholder) input.placeholder = options.placeholder;
input.setAttribute('list', identifiant);
input.addEventListener('input', function () { objet[cle] = input.value; sauver(); });
label.appendChild(input);
var datalist = elt('datalist', { id: identifiant });
label.appendChild(datalist);
chargerStandards().then(function (valeurs) {
(valeurs[nomListe] || []).forEach(function (v) {
datalist.appendChild(elt('option', { value: v }));
});
(options.enPlus || []).forEach(function (v) {
datalist.appendChild(elt('option', { value: v }));
});
});
return label;
}
var FUSEAUX = null;
var COMMANDES_USUELLES = null;
function chargerFuseaux() {
if (FUSEAUX) return Promise.resolve(FUSEAUX);
return fetch('/api/fuseaux').then(function (r) { return r.json(); })
.then(function (liste) { FUSEAUX = Array.isArray(liste) ? liste : []; return FUSEAUX; })
.catch(function () { FUSEAUX = []; return FUSEAUX; });
}
function chargerCommandesUsuelles() {
if (COMMANDES_USUELLES) return Promise.resolve(COMMANDES_USUELLES);
return fetch('/api/commandes-usuelles').then(function (r) { return r.json(); })
.then(function (liste) { COMMANDES_USUELLES = Array.isArray(liste) ? liste : []; return COMMANDES_USUELLES; })
.catch(function () { COMMANDES_USUELLES = []; return COMMANDES_USUELLES; });
}
// Champ ferme : la valeur est choisie dans une liste, jamais saisie. Un fuseau
// mal orthographie ne se voit qu'a l'execution sur le central.
function champFuseau(libelle, objet, cle) {
var label = elt('label', { className: 'field' });
label.appendChild(elt('span', { textContent: libelle }));
var select = elt('select');
select.appendChild(elt('option', { value: '', textContent: 'Celui du serveur central' }));
label.appendChild(select);
chargerFuseaux().then(function (liste) {
liste.forEach(function (fuseau) {
var option = elt('option', { value: fuseau, textContent: fuseau });
if (objet[cle] === fuseau) option.selected = true;
select.appendChild(option);
});
// Une valeur heritee d'un ancien projet doit rester visible.
if (objet[cle] && liste.indexOf(objet[cle]) === -1) {
var inconnu = elt('option', { value: objet[cle], textContent: objet[cle] + ' (inconnu)' });
inconnu.selected = true;
select.appendChild(inconnu);
}
});
select.addEventListener('change', function () { objet[cle] = select.value; sauver(); });
return label;
}
// Commande de verification : celles du projet et celles livrees par Centreon.
function champCommandeVerification(libelle, objet, cle) {
var valeurs = (COMMANDES_USUELLES || []).map(function (c) {
return { valeur: c.nom, libelle: c.nom + ' \u2014 ' + c.description };
});
projet.commands.forEach(function (c) {
valeurs.push({ valeur: c.name, libelle: c.name + ' \u2014 commande du projet' });
});
return champChoix(libelle, objet, cle, valeurs, { vide: 'Celle du modele parent' });
}
var MACROS_CENTREON = null;
function chargerMacros() {
@@ -706,7 +947,89 @@ function ouvrirApercu(perimetre, pour) {
}).catch(function () { notifier('Apercu indisponible.', 'erreur'); });
}
// Sans calendrier, un perimetre ne notifie jamais. Plutot que de laisser
// l'utilisateur deviner, on lui propose d'en creer un a la bonne cadence.
function barreCalendrier(perimetre) {
var bloc = elt('div');
var connu = projet.calendriers.some(function (c) { return c.name === perimetre.calendrier; });
if (!perimetre.calendrier) {
var manque = elt('div', { className: 'notice bad' });
manque.appendChild(elt('b', { textContent: 'Aucun calendrier' }));
manque.appendChild(elt('p', {
textContent: 'Sans calendrier, ce perimetre ne notifiera jamais.'
}));
bloc.appendChild(manque);
}
if (!connu) {
var barre = elt('div', { className: 'barre' });
[
['Creer un calendrier en permanence', '24x7', '00:00-24:00',
['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday']],
['Creer un calendrier en heures ouvrees', 'Heures-Ouvrees', '08:00-18:00',
['monday', 'tuesday', 'wednesday', 'thursday', 'friday']]
].forEach(function (modele) {
barre.appendChild(elt('button', {
type: 'button', className: 'small', textContent: modele[0],
onclick: function () {
if (!perimetre.name) {
notifier('Nommez le perimetre avant de creer son calendrier.', 'attention');
return;
}
var slug = perimetre.name.replace(/[^A-Za-z0-9]+/g, '-').replace(/^-|-$/g, '');
var nom = 'TP-' + slug + '-' + modele[1];
if (!projet.calendriers.some(function (c) { return c.name === nom; })) {
var jours = {};
modele[3].forEach(function (jour) { jours[jour] = modele[2]; });
projet.calendriers.push({
name: nom,
alias: perimetre.name + ', ' + (modele[1] === '24x7' ? 'en permanence' : 'heures ouvrees'),
jours: jours,
creer: true
});
}
perimetre.calendrier = nom;
sauver(); rendre();
notifier('Calendrier ' + nom + ' cree et rattache.', 'succes');
}
}));
});
bloc.appendChild(barre);
}
return bloc;
}
// Cases a cocher qui composent une liste de lettres, comme Centreon l'attend.
// Groupes qui existent deja sur le central : ils ne sont pas dans le projet,
// donc pas cochables, mais doivent pouvoir etre indiques.
function champGroupesExternes(host) {
var connus = projet.groupes_hotes.map(function (g) { return g.name; });
var label = elt('label', { className: 'field' });
label.appendChild(elt('span', {
textContent: 'Autres groupes, deja presents sur le central (separes par une virgule)'
}));
var externes = host.hostgroups.filter(function (g) { return connus.indexOf(g) === -1; });
var input = elt('input', { type: 'text', value: externes.join(', ') });
input.addEventListener('input', function () {
var saisis = input.value.split(',').map(function (v) { return v.trim(); }).filter(Boolean);
var coches = host.hostgroups.filter(function (g) { return connus.indexOf(g) !== -1; });
host.hostgroups = coches.concat(saisis);
sauver();
});
label.appendChild(input);
return label;
}
function champCouleur(libelle, objet, cle) {
var label = elt('label', { className: 'field' });
label.appendChild(elt('span', { textContent: libelle }));
var input = elt('input', { type: 'color', value: objet[cle] || '#2f6f9f' });
input.addEventListener('input', function () { objet[cle] = input.value; sauver(); });
label.appendChild(input);
return label;
}
function champOptions(libelle, objet, cle, options) {
var bloc = elt('label', { className: 'field' });
bloc.appendChild(elt('span', { textContent: libelle }));
@@ -851,7 +1174,11 @@ function champ(libelle, objet, cle, options) {
options = options || {};
var label = elt('label', { className: 'field' });
label.appendChild(elt('span', { textContent: libelle }));
var input = elt('input', { type: options.type || 'text', value: objet[cle] });
var valeurCourante = objet[cle];
var input = elt('input', {
type: options.type || 'text',
value: (valeurCourante === undefined || valeurCourante === null) ? '' : valeurCourante
});
if (options.placeholder) input.placeholder = options.placeholder;
input.addEventListener('input', function () {
objet[cle] = options.type === 'number' ? parseInt(input.value || '0', 10) : input.value;
@@ -866,7 +1193,7 @@ function champZone(libelle, objet, cle, options) {
options = options || {};
var label = elt('label', { className: 'field' });
label.appendChild(elt('span', { textContent: libelle }));
var zone = elt('textarea', { rows: 5, value: objet[cle] });
var zone = elt('textarea', { rows: 5, value: objet[cle] == null ? '' : objet[cle] });
zone.addEventListener('input', function () { objet[cle] = zone.value; sauver(); });
label.appendChild(zone);
if (options.aide) label.appendChild(elt('small', { textContent: options.aide }));
@@ -890,7 +1217,8 @@ function champSelect(libelle, objet, cle, choix) {
function champSelectListe(libelle, objet, cle, valeurs) {
var label = elt('label', { className: 'field' });
label.appendChild(elt('span', { textContent: libelle }));
var input = elt('input', { type: 'text', value: objet[cle], list: 'liste-' + cle });
var input = elt('input', { type: 'text', value: objet[cle] == null ? '' : objet[cle] });
input.setAttribute('list', 'liste-' + cle);
var datalist = elt('datalist', { id: 'liste-' + cle });
valeurs.forEach(function (v) { datalist.appendChild(elt('option', { value: v })); });
input.addEventListener('input', function () { objet[cle] = input.value; sauver(); });
@@ -1038,6 +1366,11 @@ function titreCatalogue(packs) {
return packs ? 'Importer un pack (' + packs.length + ')' : 'Importer un pack';
}
// Un pack est deja dans le projet si son modele d'hote y figure.
function packImporte(pack) {
return projet.host_templates.some(function (h) { return h.name === pack.host_template; });
}
function majTitreModale(texte) {
var titre = document.getElementById('modal-titre');
if (titre) titre.textContent = texte;
@@ -1047,11 +1380,33 @@ function ouvrirCataloguePacks() {
ouvrirModale(titreCatalogue(packsCache), function (corps) {
var recherche = elt('input', { type: 'text', placeholder: 'Filtrer par nom, technologie, plugin...' });
corps.appendChild(recherche);
var note = elt('div', { className: 'note-masques' });
corps.appendChild(note);
var resultats = elt('div', { className: 'packs' });
corps.appendChild(resultats);
// Les packs deja dans le projet sont masques : les reproposer n'aurait
// aucun effet, l'import les ignorerait.
var montrerImportes = false;
function afficher(packs) {
resultats.innerHTML = '';
note.innerHTML = '';
if (Array.isArray(packs) && !montrerImportes) {
var importes = packs.filter(packImporte);
packs = packs.filter(function (p) { return !packImporte(p); });
if (importes.length) {
note.appendChild(elt('span', {
textContent: importes.length + ' pack(s) deja dans le projet, masque(s). '
}));
note.appendChild(elt('button', {
type: 'button', className: 'small', textContent: 'Les afficher',
onclick: function () { montrerImportes = true; filtrer(); }
}));
}
}
if (Array.isArray(packs) && packsCache) {
majTitreModale(
packs.length === packsCache.length
@@ -1067,9 +1422,13 @@ function ouvrirCataloguePacks() {
return;
}
packs.forEach(function (pack) {
var ligne = elt('div', { className: 'pack-ligne' });
var deja = packImporte(pack);
var ligne = elt('div', { className: 'pack-ligne' + (deja ? ' importe' : '') });
var texte = elt('div');
texte.appendChild(elt('b', { textContent: pack.name }));
if (deja) {
texte.appendChild(elt('span', { className: 'tag ok', textContent: 'deja importe' }));
}
if (pack.status !== 'verified') {
texte.appendChild(elt('span', { className: 'tag warn', textContent: 'a valider' }));
}
@@ -1077,18 +1436,27 @@ function ouvrirCataloguePacks() {
texte.appendChild(elt('div', { className: 'plugin', textContent: pack.plugin + ' | ' + pack.services.length + ' sondes' }));
ligne.appendChild(texte);
var actions = elt('div', { className: 'barre' });
actions.appendChild(elt('button', {
type: 'button', className: 'small', textContent: 'Sondes par defaut',
onclick: function () { importerPack(pack.id, false); }
}));
actions.appendChild(elt('button', {
type: 'button', className: 'small', textContent: 'Toutes les sondes',
onclick: function () { importerPack(pack.id, true); }
}));
if (!deja) {
actions.appendChild(elt('button', {
type: 'button', className: 'small', textContent: 'Sondes par defaut',
onclick: function () { importerPack(pack.id, false); }
}));
actions.appendChild(elt('button', {
type: 'button', className: 'small', textContent: 'Toutes les sondes',
onclick: function () { importerPack(pack.id, true); }
}));
}
ligne.appendChild(actions);
resultats.appendChild(ligne);
});
if (!packs.length) resultats.appendChild(elt('p', { className: 'lede', textContent: 'Aucun pack ne correspond.' }));
if (!packs.length) {
resultats.appendChild(elt('p', {
className: 'lede',
textContent: montrerImportes
? 'Aucun pack ne correspond.'
: 'Aucun pack a importer ne correspond.'
}));
}
}
function filtrer() {
@@ -1111,24 +1479,25 @@ function ouvrirCataloguePacks() {
}
function importerPack(id, tout) {
fetch('/api/packs/' + id + '/projet' + (tout ? '?tout=1' : ''))
.then(function (r) { return r.json(); })
.then(function (fragment) {
var ignores = [];
['commands', 'service_templates', 'host_templates'].forEach(function (cle) {
var existants = {};
projet[cle].forEach(function (o) { existants[o.name] = true; });
fragment[cle].forEach(function (o) {
if (existants[o.name]) { ignores.push(o.name); return; }
projet[cle].push(o);
});
});
fermerModale();
selection = { type: 'htpl', index: Math.max(0, projet.host_templates.length - 1) };
sauver(); rendre();
if (ignores.length) notifier(ignores.length + ' objet(s) deja present(s) ont ete ignores.', 'attention');
else notifier('Pack importe dans le projet.', 'succes');
});
// La fusion est faite par le serveur : calendriers, perimetres, groupes
// d'hotes et prerequis compris. Une liste d'objets tenue ici finirait par
// en oublier — c'est exactement ce qui est arrive.
appelJSON('/api/packs/' + id + '/fusionner', {
method: 'POST',
body: JSON.stringify({ project: projet, tout: !!tout })
}).then(function (donnees) {
projet = donnees.project;
fermerModale();
selection = { type: 'htpl', index: Math.max(0, projet.host_templates.length - 1) };
sauver(); rendre();
if (donnees.ignores && donnees.ignores.length) {
notifier(donnees.ignores.length + ' objet(s) deja present(s) ont ete ignores.', 'attention');
} else {
notifier('Pack importe : modeles, groupe, calendrier, perimetre et prerequis.', 'succes');
}
}).catch(function (erreur) {
notifier('Import impossible : ' + erreur.message, 'erreur');
});
}
// ------------------------------------------------------------------ actions
@@ -1193,6 +1562,10 @@ document.addEventListener('keydown', function (e) {
});
window.notifier = notifier;
// Lecture du projet en cours, pour le test d'interface et le diagnostic depuis
// la console. Une fonction plutot qu'une variable : le projet est remplace a
// chaque ouverture ou import.
window.projetCourant = function () { return projet; };
rendre();
+11
View File
@@ -593,3 +593,14 @@ pre.code {
@media (max-width: 900px) {
.bloc-ligne { grid-template-columns: 1fr 1fr; }
}
/* Packs deja dans le projet : visibles a la demande, sans action possible. */
.note-masques {
display: flex;
align-items: center;
gap: 8px;
color: var(--ink-dim);
font-size: 12.5px;
margin-bottom: 10px;
}
.pack-ligne.importe { opacity: 0.55; }
+3 -2
View File
@@ -1,15 +1,16 @@
{% extends "base.html" %}
{% block title %}Enclume — Générateur de configuration CLAPI pour Centreon{% endblock %}
{% block title %}Forge Centreon — Générateur de configuration pour Centreon avec CLAPI{% endblock %}
{% block body %}
<div class="accueil">
<section class="manchette">
<h2>Créez votre configuration Centreon, repartez avec le CLAPI</h2>
<p>Commandes de contrôle, modèles de service, modèles d'hôte : construisez-les dans votre
navigateur, à partir de zéro ou d'un des {{ pack_count }} packs du catalogue. Enclume produit
navigateur, à partir de zéro ou d'un des {{ pack_count }} packs du catalogue. Forge Centreon produit
les fichiers à jouer sur votre central — que vous relisez avant de les exécuter.</p>
<div class="barre">
<a class="btn primaire" href="/editeur">Ouvrir l'éditeur</a>
<a class="btn" href="/aide/snmp">Installer SNMP</a>
<a class="btn" href="#fonctionnement">Comment ça marche</a>
</div>
<p class="petit">Sans inscription. Rien n'est installé. Projet indépendant de Centreon SAS.</p>
+5 -4
View File
@@ -3,10 +3,10 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}Enclume — Générateur de configuration CLAPI pour Centreon{% endblock %}</title>
<title>{% block title %}Forge Centreon — Générateur de configuration pour Centreon avec CLAPI{% endblock %}</title>
<meta name="description" content="Créez vos commandes de contrôle, modèles de service et modèles d'hôte Centreon, et repartez avec le code CLAPI prêt à jouer sur votre central. Gratuit, sans inscription.">
<link rel="canonical" href="{{ request.url_root }}">
<meta property="og:title" content="Enclume — Générateur de configuration CLAPI pour Centreon">
<meta property="og:title" content="Forge Centreon — Générateur de configuration pour Centreon avec CLAPI">
<meta property="og:description" content="Créez vos commandes, modèles de service et modèles d'hôte, repartez avec le code CLAPI.">
<meta property="og:type" content="website">
<link rel="icon" href="{{ url_for('static', filename='enclume.svg') }}" type="image/svg+xml">
@@ -14,14 +14,15 @@
</head>
<body>
<header class="topbar">
<h1><a href="/">Enclume</a></h1>
<span class="meta">Générateur de configuration CLAPI pour Centreon</span>
<h1><a href="/">Forge Centreon</a></h1>
<span class="meta">Générateur de configuration pour Centreon avec CLAPI</span>
<span class="version">{{ version }}</span>
</header>
{% block body %}{% endblock %}
<footer class="pied">
<span>Projet indépendant, sans lien avec Centreon SAS. Centreon est une marque déposée de son propriétaire.</span>
<span class="grow"></span>
<a href="/aide/snmp">Installer SNMP</a>
<a href="/mentions">Mentions légales</a>
<a href="{{ depot }}">Code source</a>
<a href="{{ depot }}/src/branch/main/CONTRIBUTING.md">Contribuer</a>
+143
View File
@@ -0,0 +1,143 @@
{% extends "base.html" %}
{% block title %}Installer et sécuriser SNMP — Forge Centreon{% endblock %}
{% block body %}
<div class="accueil texte">
<h2>Installer et sécuriser SNMP</h2>
<p>La plupart des packs du catalogue interrogent leurs équipements en SNMP. Cette page
donne, par système, une configuration de départ qui fonctionne et qui ne laisse pas votre
parc ouvert au premier venu.</p>
<div class="notice">
<b>Deux règles avant de commencer</b>
<p>SNMP v1 et v2c transportent la communauté <b>en clair</b> sur le réseau : quiconque
écoute peut la lire et interroger l'équipement. Préférez la <b>version 3</b> partout où
elle est disponible.</p>
<p style="margin-top:8px">Si vous restez en v2c — souvent le cas sur du matériel ancien —
restreignez au moins l'accès à l'adresse du collecteur et n'autorisez que la lecture.</p>
</div>
<h3>Debian et Ubuntu</h3>
<pre class="code">apt install snmpd</pre>
<p>Remplacez le contenu de <code>/etc/snmp/snmpd.conf</code> par ceci, en v3 :</p>
<pre class="code"># N'ecoute que sur l'interface d'administration, jamais sur toutes
agentaddress udp:10.0.4.20:161
# Ce que le compte a le droit de lire : tout l'arbre standard, rien d'autre
view lecture included .1.3.6.1.2.1
view lecture included .1.3.6.1.4.1
# Compte de supervision, lecture seule, sur la vue ci-dessus
rouser centreon authPriv -V lecture
# Informations d'inventaire, facultatives mais utiles
sysLocation Salle serveur, baie A3
sysContact [email protected]</pre>
<p>Le compte lui-même se crée service arrêté, la directive étant déplacée au démarrage
vers un fichier de persistance :</p>
<pre class="code">systemctl stop snmpd
echo 'createUser centreon SHA-256 "MotDePasseAuth" AES "MotDePasseChiffrement"' >> /etc/snmp/snmpd.conf
systemctl start snmpd</pre>
<div class="notice">
<b>Le piège classique</b>
<p>Après démarrage, la ligne <code>createUser</code> disparaît de
<code>/etc/snmp/snmpd.conf</code> : net-snmp la déplace dans
<code>/var/lib/snmp/snmpd.conf</code> sous forme chiffrée. C'est normal. Ne la remettez
pas, vous créeriez un doublon.</p>
</div>
<p>En v2c, si la version 3 n'est pas envisageable :</p>
<pre class="code">agentaddress udp:10.0.4.20:161
# Lecture seule, et uniquement depuis le collecteur
rocommunity UneChaineLongueEtAleatoire 10.0.4.10 -V lecture</pre>
<h3>RHEL, Alma et Rocky</h3>
<pre class="code">dnf install net-snmp net-snmp-utils</pre>
<p>Le fichier de configuration est au même endroit et la syntaxe identique. La différence
est le pare-feu :</p>
<pre class="code">firewall-cmd --permanent --add-rich-rule='rule family="ipv4" \
source address="10.0.4.10/32" port port="161" protocol="udp" accept'
firewall-cmd --reload
systemctl enable --now snmpd</pre>
<p>Sur Debian et Ubuntu, l'équivalent avec ufw :</p>
<pre class="code">ufw allow from 10.0.4.10 to any port 161 proto udp</pre>
<h3>Windows</h3>
<p>Le service SNMP de Windows ne connaît que la v2c, et Microsoft le considère comme
obsolète. Il reste utilisable, mais pour un parc Windows important, les packs
<b>NSClient++</b> du catalogue sont un meilleur choix.</p>
<pre class="code"># Windows 10, 11, Server 2019 et suivants
Add-WindowsCapability -Online -Name "SNMP.Client~~~~0.0.1.0"
# Serveurs plus anciens
Install-WindowsFeature SNMP-Service -IncludeManagementTools</pre>
<p>La configuration se fait dans la base de registre. Communauté en lecture seule, et
restriction au seul collecteur :</p>
<pre class="code">$base = "HKLM:\SYSTEM\CurrentControlSet\Services\SNMP\Parameters"
# 4 = lecture seule. Ne jamais utiliser 8, qui autorise l'ecriture.
New-ItemProperty -Path "$base\ValidCommunities" -Name "UneChaineLongueEtAleatoire" `
-Value 4 -PropertyType DWord -Force
# Seul le collecteur a le droit d'interroger
New-ItemProperty -Path "$base\PermittedManagers" -Name "1" `
-Value "10.0.4.10" -PropertyType String -Force
Restart-Service SNMP</pre>
<p>Puis le pare-feu :</p>
<pre class="code">New-NetFirewallRule -DisplayName "SNMP depuis le collecteur" -Direction Inbound `
-Protocol UDP -LocalPort 161 -RemoteAddress 10.0.4.10 -Action Allow</pre>
<h3>Équipements réseau</h3>
<p>La logique est la même partout : un compte ou une communauté en lecture seule, une
liste d'accès limitée au collecteur, et la version 3 quand le matériel la gère.</p>
<pre class="code"># Cisco IOS, en v3
snmp-server view lecture iso included
snmp-server group SUPERVISION v3 priv read lecture access 20
snmp-server user centreon SUPERVISION v3 auth sha MotDePasseAuth priv aes 128 MotDePasseChiffrement
access-list 20 permit 10.0.4.10</pre>
<pre class="code"># Cisco IOS, en v2c
access-list 20 permit 10.0.4.10
snmp-server community UneChaineLongueEtAleatoire RO 20</pre>
<p>Sur pfSense, OPNsense, FortiGate, Stormshield et la plupart des interfaces web,
l'écran SNMP propose les mêmes notions : communauté ou utilisateur v3, interface
d'écoute, et adresses autorisées. Renseignez toujours la dernière.</p>
<h3>Vérifier depuis le collecteur</h3>
<p>Avant de déployer quoi que ce soit, assurez-vous que le collecteur obtient une réponse.
Une configuration Centreon parfaite ne sert à rien si le port est fermé.</p>
<pre class="code"># v3
snmpwalk -v3 -l authPriv -u centreon -a SHA-256 -A "MotDePasseAuth" \
-x AES -X "MotDePasseChiffrement" 10.0.4.20 sysDescr
# v2c
snmpwalk -v2c -c UneChaineLongueEtAleatoire 10.0.4.20 sysDescr</pre>
<p>Une réponse contenant la description du système signifie que tout est en place. Un
silence vient du pare-feu ou de l'adresse d'écoute ; un refus d'authentification, du
compte ou de la communauté.</p>
<div class="notice">
<b>Ce que Forge Centreon attend de vous ensuite</b>
<p>Les packs SNMP posent la version et la communauté sur le modèle d'hôte, dans les
réglages du projet. En version 3, laissez la communauté vide et passez les options
d'authentification par la macro <code>SNMPEXTRAOPTIONS</code> du modèle d'hôte.</p>
</div>
<p style="margin-top:24px"><a class="btn" href="/editeur">Retour à l'éditeur</a></p>
</div>
{% endblock %}
+2 -2
View File
@@ -1,5 +1,5 @@
{% extends "base.html" %}
{% block title %}Mentions légales — Enclume{% endblock %}
{% block title %}Mentions légales — Forge Centreon{% endblock %}
{% block body %}
<div class="accueil texte">
@@ -13,7 +13,7 @@
<p>{{ hebergeur or "Non renseigné — définir ENCLUME_HEBERGEUR." }}</p>
<h3>Marques</h3>
<p>Centreon est une marque déposée de Centreon SAS. Enclume est un projet indépendant, sans
<p>Centreon est une marque déposée de Centreon SAS. Forge Centreon est un projet indépendant, sans
lien ni affiliation avec cette société. Les noms de constructeurs et d'éditeurs cités dans le
catalogue appartiennent à leurs propriétaires respectifs.</p>
+1 -1
View File
@@ -1,5 +1,5 @@
{% extends "base.html" %}
{% block title %}Moderation — Enclume{% endblock %}
{% block title %}Moderation — Forge Centreon{% endblock %}
{% block body %}
<div class="wrap-moderation">
{% if not connecte %}
+57
View File
@@ -121,6 +121,11 @@ def create_app() -> Flask:
verifies=sum(1 for p in cat.packs.values() if p.status == "verified"),
)
@app.get("/aide/snmp")
def guide_snmp() -> str:
"""Installer et securiser SNMP, par systeme."""
return render_template("guide-snmp.html")
@app.get("/mentions")
def mentions() -> str:
return render_template(
@@ -252,6 +257,58 @@ def create_app() -> Flask:
payload = request.get_json(force=True, silent=True) or {}
return jsonify(generate(payload.get("project", payload)))
@app.get("/api/fuseaux")
def api_fuseaux() -> Response:
"""Fuseaux horaires connus : la saisie libre menait a des erreurs muettes."""
from .model import fuseaux_horaires
return jsonify(fuseaux_horaires())
@app.get("/api/commandes-usuelles")
def api_commandes_usuelles() -> Response:
"""Commandes de verification livrees par Centreon."""
return jsonify(
[
{"nom": "check_centreon_ping", "description": "Ping, avec seuils de perte et de latence"},
{"nom": "check_host_alive", "description": "Ping simplifie, disponibilite de l'hote"},
{"nom": "check-host-alive", "description": "Variante historique de check_host_alive"},
{"nom": "check_centreon_dummy", "description": "Etat fixe, pour un hote passif"},
{"nom": "check_centreon_snmp_value", "description": "Valeur SNMP, pour un hote sans ping"},
]
)
@app.get("/api/valeurs-standards")
def api_valeurs_standards() -> Response:
"""Valeurs livrees par Centreon, proposees plutot que saisies.
Chaque champ libre est une occasion de faute de frappe qui ne se voit
qu'au moment du deploiement sur le central.
"""
return jsonify(
{
"modeles_hote": [
"generic-active-host-custom",
"generic-passive-host-custom",
"generic-active-host",
"generic-passive-host",
],
"modeles_service": [
"generic-active-service-custom",
"generic-passive-service-custom",
"generic-active-service",
"generic-passive-service",
],
"versions_snmp": ["1", "2c", "3"],
"repertoires_plugins": [
"/usr/lib/centreon/plugins",
"/usr/lib/nagios/plugins",
"/usr/local/centreon/plugins",
],
"criticites": ["Critique", "Majeure", "Mineure", "Information"],
"collecteurs": ["Central"],
}
)
@app.get("/api/macros-notification")
def api_macros_notification() -> Response:
"""Les macros proposees dans l'editeur de blocs."""
+2
View File
@@ -8,3 +8,5 @@ Flask-SQLAlchemy>=3.1,<4.0
SQLAlchemy>=2.0,<3.0
alembic>=1.13,<2.0
psycopg[binary]>=3.1,<4.0
# Base des fuseaux horaires : absente des images slim, la liste serait vide.
tzdata>=2024.1
+128 -1
View File
@@ -29,10 +29,39 @@ const dom = new JSDOM(html, {
const { window } = dom;
// Reponses minimales mais de la bonne forme, comme celles du serveur.
// Ce que renverrait le serveur pour une fusion : le pack apporte bien plus que
// des commandes et des modeles.
const PROJET_FUSIONNE = {
name: 'Essai', centreon_version: '25.10', prefix: '', plugins_dir: '/usr/lib/centreon/plugins',
poller: 'Central', apply_config: true, notif_dir: '/usr/share/centreon/notifications',
commands: [{ name: 'App-Essai-Cpu', type: 'check', line: '$USER1$/check', comment: '' }],
service_templates: [], hosts: [],
host_templates: [{ name: 'App-Essai-custom', alias: 'Essai', parents: [], macros: [],
perimetre: 'Essai', check_command: '', check_command_args: '',
snmp_version: '', snmp_community: '', timezone: '' }],
groupes_hotes: [{ name: 'HG-App-Essai', alias: 'Essai' }],
calendriers: [{ name: 'Heures-Ouvrees', alias: '8h-18h', jours: { monday: '08:00-18:00' } }],
perimetres: [{ name: 'Essai', description: '', calendrier: 'Heures-Ouvrees', contacts: [],
groupe: 'CG-App-Essai', options_hote: 'd,u,r', options_service: 'w,c,r',
intervalle: 30, application: '', responsable: '', procedure: '',
criticite: 'Majeure', impact: 'Essai', couleur: '#2f6f9f',
sujet_hote: '', sujet_service: '', blocs_hote: [], blocs_service: [] }],
prerequis: { paquets_debian: ['libwww-perl'], paquets_rhel: [], verifications: [], notes: '' },
};
const reponses = {
'/api/packs': [],
'/api/packs': [
{ id: 'app-essai', name: 'Essai', category: 'applications', category_label: 'Applications',
status: 'verified', plugin: 'essai.pl', description: 'Pack d essai',
host_template: 'App-Essai-custom', services: [] },
],
'/api/generer': { summary: {}, issues: [], files: { 'deploy.clapi': '' } },
'/api/projets': [],
'/api/packs/app-essai/fusionner': { project: PROJET_FUSIONNE, ignores: [] },
'/api/valeurs-standards': {},
'/api/fuseaux': ['Europe/Paris'],
'/api/commandes-usuelles': [{ nom: 'check_centreon_ping', description: 'Ping' }],
'/api/macros-notification': [],
};
window.fetch = (url) => Promise.resolve({
ok: true,
@@ -90,8 +119,106 @@ if (erreurs.length === 0) {
}
}
// L'import d'un pack doit apporter tout ce que le serveur renvoie, pas
// seulement les commandes et les modeles.
try {
document.getElementById('btn-pack').click();
await new Promise((r) => setTimeout(r, 30));
const importer = [...document.querySelectorAll('#modal-corps button')]
.find((b) => b.textContent === 'Sondes par defaut');
if (!importer) {
erreurs.push('aucun bouton d import dans le catalogue');
} else {
importer.click();
await new Promise((r) => setTimeout(r, 40));
const projet = window.projetCourant();
for (const [cle, libelle] of [
['groupes_hotes', "groupe d'hotes"],
['calendriers', 'calendrier'],
['perimetres', 'perimetre'],
]) {
if (!projet[cle] || projet[cle].length === 0) {
erreurs.push(`l import d un pack n apporte pas le ${libelle}`);
}
}
if (!projet.prerequis || !projet.prerequis.paquets_debian.length) {
erreurs.push('l import d un pack n apporte pas les prerequis');
}
}
} catch (erreur) {
erreurs.push('import d un pack : ' + erreur.message);
}
// Un pack deja dans le projet ne doit plus etre proposable a l'import.
try {
window.eval("projetCourant().host_templates.push({ name: 'App-Essai-custom', macros: [], parents: [] });");
document.getElementById('btn-pack').click();
await new Promise((r) => setTimeout(r, 30));
const corps = document.getElementById('modal-corps');
const boutons = [...corps.querySelectorAll('button')].map((b) => b.textContent);
if (boutons.includes('Sondes par defaut')) {
erreurs.push('un pack deja importe reste proposable');
}
if (!corps.textContent.includes('deja dans le projet')) {
erreurs.push('le masquage des packs importes n est pas signale');
}
// Affiches a la demande, ils restent sans action : les reimporter n'aurait
// aucun effet, et un bouton inerte ferait douter l'utilisateur.
const afficher = [...corps.querySelectorAll('button')]
.find((b) => b.textContent === 'Les afficher');
if (!afficher) {
erreurs.push('aucun moyen d afficher les packs masques');
} else {
afficher.click();
await new Promise((r) => setTimeout(r, 30));
const apres = [...corps.querySelectorAll('button')].map((b) => b.textContent);
if (apres.includes('Sondes par defaut')) {
erreurs.push('un pack deja importe redevient proposable une fois affiche');
}
if (!corps.textContent.includes('deja importe')) {
erreurs.push('un pack affiche n est pas signale comme deja importe');
}
}
document.querySelector('[data-fermer-modal]').click();
} catch (erreur) {
erreurs.push('catalogue de packs : ' + erreur.message);
}
// Un perimetre cree apres un import doit reprendre le calendrier du projet.
try {
const ajouts = [...rail.querySelectorAll('button')].filter((b) => b.textContent === '+');
ajouts[ajouts.length - 1].click(); // dernier groupe du rail : perimetres
await new Promise((r) => setTimeout(r, 20));
const projet = window.projetCourant();
const dernier = projet.perimetres[projet.perimetres.length - 1];
if (projet.calendriers.length && !dernier.calendrier) {
erreurs.push('un perimetre neuf ne reprend pas le calendrier du projet');
}
} catch (erreur) {
erreurs.push('creation d un perimetre : ' + erreur.message);
}
// Un champ sans valeur ne doit jamais afficher le mot « undefined ».
for (const entree of rail.querySelectorAll('.rail-item')) {
principal.innerHTML = '';
entree.click();
const champs = [...principal.querySelectorAll('input, textarea, select')];
const fautifs = champs.filter((c) => String(c.value).includes('undefined'));
if (fautifs.length) {
erreurs.push(
`${entree.textContent.trim()} : ${fautifs.length} champ(s) affichent undefined`
);
break;
}
}
// Les notifications doivent s'afficher, avec leur type.
try {
// Les actions precedentes ont pu en laisser : on part d'une zone vide.
const zoneExistante = document.getElementById('notifications');
if (zoneExistante) zoneExistante.innerHTML = '';
window.eval("notifier('essai de reussite', 'succes'); notifier('essai d erreur', 'erreur');");
const zone = document.getElementById('notifications');
if (!zone || zone.children.length !== 2) {
+105
View File
@@ -208,3 +208,108 @@ def test_rollback_supprime_les_groupes_d_hotes():
projet = Project.from_dict({"groupes_hotes": [{"name": "HG-Essai"}]})
lignes = [o.import_line() for o in build_plan(projet).rollback_ops]
assert "HG;DEL;HG-Essai" in lignes
def test_chaque_pack_livre_son_groupe_d_hotes():
"""Un utilisateur qui importe un pack doit recevoir une configuration complete."""
from enclume.packs import pack_to_project
catalogue = Catalog("catalog")
sans = [p.id for p in catalogue.packs.values() if not p.groupe_hote]
assert not sans, f"packs sans groupe d'hotes : {sans}"
projet = pack_to_project(catalogue.get("app-mysql"))
assert [g.name for g in projet.groupes_hotes] == ["HG-App-DB-MySQL"]
lignes = [o.import_line() for o in build_plan(projet).ops if o.obj == "HG"]
assert lignes == ["HG;ADD;HG-App-DB-MySQL;MySQL / MariaDB"]
def test_commande_et_fuseau_sur_l_hote():
"""La commande de verification et le fuseau appartiennent a l'hote."""
projet = Project.from_dict(
{
"hosts": [
{
"name": "srv-01",
"address": "10.0.4.1",
"check_command": "check_centreon_ping",
"check_command_args": "!3!200,20%!400,50%",
"timezone": "Europe/Paris",
}
]
}
)
lignes = [o.import_line() for o in build_plan(projet).ops if o.obj == "HOST"]
assert "HOST;setparam;srv-01;check_command;check_centreon_ping" in lignes
assert "HOST;setparam;srv-01;check_command_arguments;!3!200,20%!400,50%" in lignes
assert "HOST;setparam;srv-01;timezone;Europe/Paris" in lignes
def test_fuseau_horaire_errone_refuse():
"""Une faute de frappe sur un fuseau ne se verrait qu'a l'execution."""
from enclume.model import fuseaux_horaires, validate
if not fuseaux_horaires():
return # base de fuseaux absente de la machine
projet = Project.from_dict(
{"hosts": [{"name": "srv", "address": "10.0.0.1", "timezone": "Europe/Pariss"}]}
)
erreurs = [i["message"] for i in validate(projet) if i["level"] == "error"]
assert any("fuseau horaire inconnu" in m for m in erreurs)
def test_les_fuseaux_sont_exposes():
client = create_app().test_client()
fuseaux = client.get("/api/fuseaux").get_json()
assert "Europe/Paris" in fuseaux
commandes = [c["nom"] for c in client.get("/api/commandes-usuelles").get_json()]
assert "check_centreon_ping" in commandes
def test_guide_snmp_accessible_et_complet():
"""Une page d'aide qui n'aborde pas la securite ferait plus de mal que de bien."""
page = create_app().test_client().get("/aide/snmp").data.decode()
for systeme in ("Debian", "RHEL", "Windows", "Cisco"):
assert systeme in page, systeme
# Les points de securite qui distinguent une configuration tenable.
for notion in ("authPriv", "rocommunity", "PermittedManagers", "snmpwalk", "firewall-cmd"):
assert notion in page, notion
# La lecture seule, jamais l'ecriture.
assert "Ne jamais utiliser 8" in page
def test_valeurs_standards_exposees():
"""Les listes proposees remplacent la saisie libre : elles doivent exister."""
valeurs = create_app().test_client().get("/api/valeurs-standards").get_json()
assert "generic-active-host-custom" in valeurs["modeles_hote"]
assert "generic-active-service-custom" in valeurs["modeles_service"]
assert valeurs["versions_snmp"] == ["1", "2c", "3"]
assert "/usr/lib/centreon/plugins" in valeurs["repertoires_plugins"]
assert "Critique" in valeurs["criticites"]
def test_nom_affiche_et_baseline():
"""Le nom affiche est « Forge Centreon » ; le projet et les images restent « Enclume »."""
page = create_app().test_client().get("/").data.decode()
assert "Forge Centreon" in page
assert "Générateur de configuration pour Centreon avec CLAPI" in page
# La mention d'independance devient d'autant plus necessaire.
assert "Centreon SAS" in page
def test_l_editeur_utilise_la_route_de_fusion():
"""Garde-fou contre une correction qui n'a pas ete appliquee.
L'import d'un pack a laisse deux versions durant, une ancienne fonction qui
ne recopiait que trois listes : le remplacement avait echoue en silence, et
aucun test n'empruntait ce chemin.
"""
from pathlib import Path
script = Path("enclume/static/editeur.js").read_text(encoding="utf-8")
assert "/fusionner" in script, "l'import n'appelle pas la route de fusion"
assert "'service_templates', 'host_templates'" not in script, "l'ancien import subsiste"
+100 -9
View File
@@ -397,25 +397,48 @@ def test_import_d_un_pack_rattache_ses_modeles():
projet = pack_to_project(Catalog("catalog").get("app-ldap"))
perimetre = projet.perimetres[0]
assert perimetre.calendrier == "24x7"
assert perimetre.calendrier == "TP-App-LDAP-24x7"
assert perimetre.groupe == "CG-App-LDAP"
assert perimetre.criticite == "Critique"
assert projet.host_templates[0].perimetre == perimetre.name
assert all(s.perimetre == perimetre.name for s in projet.service_templates)
def test_les_calendriers_livres_par_centreon_ne_sont_pas_recrees():
"""24x7 existe des l'installation : TP;ADD echouerait sur un objet existant."""
def test_chaque_pack_apporte_son_propre_calendrier():
"""Modifier les plages d'un pack ne doit pas toucher celles de tout le central."""
from enclume.catalog import Catalog
from enclume.packs import pack_to_project
projet = pack_to_project(Catalog("catalog").get("app-ldap"))
assert projet.calendriers == []
assert projet.perimetres[0].calendrier == "24x7"
calendrier = projet.calendriers[0]
# Un calendrier qui n'est pas livre, lui, doit etre cree.
assert calendrier.name == "TP-App-LDAP-24x7"
assert calendrier.creer is True
assert len(calendrier.jours) == 7
assert projet.perimetres[0].calendrier == calendrier.name
lignes = [o.import_line() for o in build_plan(projet).ops if o.obj == "TP"]
assert lignes[0].startswith("TP;ADD;TP-App-LDAP-24x7;")
assert any("monday;00:00-24:00" in ligne for ligne in lignes)
# Une imprimante ne reveille personne la nuit : cinq jours ouvres.
imprimante = pack_to_project(Catalog("catalog").get("hw-printer-rfc3805"))
assert [c.name for c in imprimante.calendriers] == ["Heures-Ouvrees"]
assert imprimante.calendriers[0].name == "TP-HW-Printer-RFC3805-Heures-Ouvrees"
assert len(imprimante.calendriers[0].jours) == 5
def test_le_calendrier_d_un_pack_suit_le_prefixe():
"""Comme les autres objets du projet, il porte le prefixe demande."""
from enclume.catalog import Catalog
from enclume.packs import pack_to_project
projet = pack_to_project(Catalog("catalog").get("app-apache"))
projet.prefix = "ACME-"
lignes = [o.import_line() for o in build_plan(projet).ops]
assert any(ligne.startswith("TP;ADD;ACME-TP-App-Apache-24x7;") for ligne in lignes)
periode = next(ligne for ligne in lignes if "notification_period" in ligne)
assert periode.endswith(";ACME-TP-App-Apache-24x7")
def test_un_pack_importe_produit_le_cablage_complet():
@@ -431,7 +454,7 @@ def test_un_pack_importe_produit_le_cablage_complet():
for ligne in lignes
)
assert any("STPL;setcontactgroup;" in ligne for ligne in lignes)
assert any("notification_period;24x7" in ligne for ligne in lignes)
assert any("notification_period;TP-App-DB-MySQL-24x7" in ligne for ligne in lignes)
def test_la_fusion_d_un_pack_apporte_tout(app):
@@ -457,7 +480,12 @@ def test_la_fusion_d_un_pack_apporte_tout(app):
).get_json()["project"]
assert len(suite["perimetres"]) == 2
assert [c["name"] for c in suite["calendriers"]] == ["Heures-Ouvrees"]
# MySQL apporte 24x7, reference mais non recree ; l'imprimante son propre
# calendrier, qui sera cree.
assert [c["name"] for c in suite["calendriers"]] == [
"TP-App-DB-MySQL-24x7",
"TP-HW-Printer-RFC3805-Heures-Ouvrees",
]
assert len(suite["host_templates"]) == 2
@@ -475,3 +503,66 @@ def test_la_fusion_signale_les_doublons(app):
def test_fusion_d_un_pack_inconnu(app):
reponse = app.test_client().post("/api/packs/inexistant/fusionner", json={"project": {}})
assert reponse.status_code == 404
def test_un_calendrier_du_central_est_reference_sans_etre_recree():
"""Quand l'utilisateur vise un calendrier existant, TP;ADD echouerait dessus."""
projet = Project.from_dict(
{
"calendriers": [
{
"name": "24x7",
"alias": "Livre par Centreon",
"jours": {"monday": "00:00-24:00"},
"creer": False,
}
],
"perimetres": [{"name": "Systeme", "calendrier": "24x7", "contacts": ["hcornet"]}],
"prefix": "ACME-",
}
)
plan = build_plan(projet)
assert not [o for o in plan.ops if o.obj == "TP"]
assert not [o for o in plan.rollback_ops if o.obj == "TP"]
# Il porte le nom du central, donc sans prefixe.
periode = next(
o.import_line() for o in plan.ops if "hostnotifperiod" in o.import_line()
)
assert periode.endswith(";24x7")
def test_un_calendrier_du_central_peut_etre_force():
"""Une installation peut avoir perdu ses calendriers par defaut."""
projet = Project.from_dict(
{"calendriers": [{"name": "24x7", "jours": {"monday": "00:00-24:00"}, "creer": True}]}
)
lignes = [o.import_line() for o in build_plan(projet).ops if o.obj == "TP"]
assert lignes[0].startswith("TP;ADD;24x7;")
assert "TP;setparam;24x7;monday;00:00-24:00" in lignes
def test_un_perimetre_sans_calendrier_retombe_sur_celui_du_central():
"""Plutot que de ne jamais notifier, il vise 24x7 — et l'avertissement le dit."""
projet = Project.from_dict(
{"perimetres": [{"name": "Sans calendrier", "calendrier": "", "contacts": ["hcornet"]}]}
)
assert projet.perimetres[0].calendrier == "24x7"
messages = [i["message"] for i in validate(projet)]
assert any("n'est pas dans le projet" in m for m in messages)
def test_chaque_perimetre_de_pack_a_son_calendrier():
"""Sur les 52 packs, aucun perimetre ne doit pointer dans le vide."""
from enclume.catalog import Catalog
from enclume.packs import pack_to_project
manquants = []
for pack in Catalog("catalog").packs.values():
projet = pack_to_project(pack)
connus = {c.name for c in projet.calendriers}
for perimetre in projet.perimetres:
if not perimetre.calendrier or perimetre.calendrier not in connus:
manquants.append((pack.id, perimetre.calendrier))
assert not manquants, manquants