Intégration Magento et SNMP

SNMP est un protocole réseau qui porte sur la supervision des équipements d'une infrastructure. Il est souvent disponible sur les équipements réseaux (routeurs, switchs,...), mais il est également supporté par certains logiciels (tels qu'Asterisk ou Kamailio, pour ne citer qu'eux).

Au niveau système, sous Linux, on trouve une implémentation « de référence » fournie par Net-Snmp (www.net-snmp.org), qui se compose d'un certain nombres d'outils, dont un agent SNMP, snmpd.
L'agent est principalement responsable de deux types d'actions, à savoir la réponse aux requêtes qui lui sont transmises, et l'éventuelle émission d'alertes (traps) lorsque les conditions configurées
l'imposent.

Vu la standardisation de SNMP au travers de nombreuses RFC et l'écosystème actuel qui en découle, il est intéressant de voir comment on peut chercher à intégrer un système de surveillance
portant sur Magento, mais interfacé à SNMP, de sorte dans l'idéal à non seulement surveiller des données techniques, mais également des données métiers pour déceler et faire remonter au plus tôt d'éventuelles anomalies.

Pour ce faire, on considérera en particulier trois aspects :

  • La structuration des données pour les rendre conceptuellement compatibles avec SNMP,
  • L'interfaçage entre SNMPd et Magento proprement dit pour la réponse aux requêtes,
  • Et enfin la remontée d'alertes par trap.

Structuration « SNMP-Friendly » des données issues de Magento

L'écosystème de SNMP propose un modèle d'intégration des données dans une structure
arborescente. Chaque nœud de cette arborescence est identifié par un numéro unique appelé Object
Identifier. Les « sous-arbres » issus du modèle conceptuel sont décrits dans des documents
formalisés appelés MIB. Dans le cas présent, on peut particulièrement s'intéresser à la branche
1.3.6.1.4.1, qui est la branche dédiée aux utilisations des entreprises privées. L'utilisation de cette
branche nécessite d'obtenir auprès de l'IANA un numéro d'entreprise (PEN : Private Enterprise
Number), qui sera en fait le numéro de nœud « racine » que l'on pourra administrer à sa guise.
L'obtention d'un numéro d'entreprise est, au moment de la rédaction de cet article, gratuite.

En se référant à la RFC 2578, qui définit la norme SMIv2 (Structure of Management Information
Version 2), on constate que la représentation de structures telles que des séquences et des tableaux
est possible, et que les nœuds feuilles de l'arborescence peuvent porter des valeurs de différents
types (des entiers, des chaînes de caractères, des timestamps par exemple, mais pas de décimaux).
On en déduit donc que les MIB peuvent supporter la représentation de la plupart des tables utilisées
dans Magento, car la plupart des tables utilisées disposent de clefs primaires « techniques »
constituées de valeurs en auto incrément, ce qui en fait de bons candidats pour avant-dernier
constituant de l'identifiant d'un objet. En revanche, il faut être conscient en particulier de deux
limitations pouvant poser problème : d'une part les décimaux ne sont pas supportés dans la RFC
2578, et d'autre part il existe une limitation de la longueur des chaînes de caractères à 65Ko dans la
théorie, et plus généralement 255 octets dans la pratique. Certes, on pourra s'affranchir dans une
certaine mesure de ces limitations, mais au prix de mise en œuvre de structurations non triviales des
données concernées. On comprend l'existence de ce genre de limitations lorsqu'on se rappelle que le
protocole SNMP a été conçu pour la supervision et l'administration de systèmes opérationnels.

Fort de ces informations, on peut donc envisager une stratégie relativement simple de présentation
des données Magento dans SNMP. Pour toute entreprise utilisant SNMP, on peut par exemple demander à l'IANA l'assignation d'un numéro d'entreprise, et structurer ce numéro pour d'abord
représenter par exemple des subdivisions fonctionnelles relatives aux instances Magento utilisées
(par exemple, les données que l'on souhaitera présenter peuvent être différentes en fonction qu'une
instance soit utilisée plutôt en BO qu'en FO), avant de passer à la présentation des données d'une
instance proprement dite, en créant par exemple une branche pour chaque type d'information
technique ou métier, sachant que les données présentées peuvent être non seulement des données
réelles, mais également des indicateurs (par exemple, un drapeau qui peut s'activer en cas d'erreur).

Lors de mon expérimentation, je suis parti d'un numéro d'OID quelconque non attribué (en
utilisation réelle, on demanderait un PEN à l'IANA), que j'ai subdivisé de la manière suivante :


OID.1 : Magento
OID.1.1 : Informations de version
OID.1.1.1 : Numéro de version
OID.1.1.2 : Information de version
OID.1.2 : Mappage de core_config_data
OID.1.2.x : un enregistrement de core_config_data, idenfié par config_id
OID.1.2.x.1 : config_id
OID.1.2.x.2 : scope
OID.1.2.x.3 : scope_id
OID.1.2.x.4 : path
OID.1.2.x.5 : value
OID.1.3 : Informations relatives au cron
OID.1.3.1 : Dernier schedule_id de la table cron_schedule en succès

Comme on va le voir, il est important de définir et de rendre accessible les nœuds intermédiaires, en
leur attribuant des OID et en les implémentant de la sorte.

Interfaçage entre Snmpd et Magento

L'implémentation d'un agent SNMP complet serait un grand investissement en temps et
maintenance, et serait un développement à part entière, d'autant plus qu'un agent SNMP utilise
usuellement un transport UDP sur le port 161. Il est donc plus intéressant de s'interfacer avec
snmpd, car snmpd prévoit justement des extensions pour ce faire.

En effet, outre le mappage d'un OID spécifique sur une commande, snmpd prévoit le mappage d'une
branche sur une commande spécifique avec une syntaxe qui prévoit le support de trois types
d'opérations :

  • l'opération get : pour la récupération d'une donnée en fonction d'un OID
  • l'opération getnext : pour récupérer l'OID et la donnée qui suit l'OID donné
  • l'opération set : pour configurer la valeur renvoyée par un OID

La présence de l'opération getnext permet d'avoir un lien vers le prochain OID, et permet donc de
parcourir les OID dans l'ordre, et ce de manière automatisée avec des outils tels que snmpwalk.
Le résultat attendu pour les opérations get et getnext sont trois lignes sur la sortie standard, avec
respectivement l'OID concerné, le type de sa valeur, et la valeur proprement dite. En cas d'erreur, il
ne faut rien écrire sur la sortie standard.

En ce qui concerne l'opération set, il ne faut rien écrire sur la sortie standard en cas de succès, mais
il faut indiquer « not-writable » ou « wrong-type ».

Au niveau de Magento, il s'agit donc de créer un wrapper shell pour adapter la syntaxe requise par
SNMP à la syntaxe prévue par php et Mage_Shell_Abstract (ou le shell Symfony en Magento 2),
puis d'implémenter un module de framework pour implémenter les classes principales (notamment
la représentation d'un OID, et l'ensemble des opérations afférantes, la gestion de la logique des
commandes et les réponses de type Object Identifier), puis les classes réalisant les opérations
proprement dites, chacune pour son propre domaine de responsabilité. Reste enfin les tests unitaires,
en particulier sur la classe représentant l'OID. De la sorte, on maximise la facilité la maintenance et
les possibilités d'évolutions du module, puisqu'il suffira en gros de se concentrer sur les nouvelles
fonctionnalités à implémenter pour s'adapter aux évolutions de contexte métier.

Lors de ce développement, j'ai néanmoins rencontré un problème avec snmpd dans une version
livrée avec Ubuntu LTS 14 : en effet, le support de la commande set ne marchait pas correctement
en raison d'une syntaxe qui ne correspondait pas à la documentation. Ce bug est un bug connu qui
n'apparait plus dans la version 5.7.3 livrée avec Ubuntu 15.

Avec le développement réalisé (initialement réalisé pour Magento 1 puis migré vers Magento 2), on
arrive à des résultats d'exemples tels que suit :


./magento snmp:get 1.3.6.1.4.1.50000.1.1.1
.1.3.6.1.4.1.50000.1.1.1
string
2.0.0
./magento snmp:getnext 1.3.6.1.4.1.50000.1.1.1
.1.3.6.1.4.1.50000.1.1.2
string
Community
./magento snmp:get 1.3.6.1.4.1.50000.1.2.19.5
.1.3.6.1.4.1.50000.1.2.19.5
string
tata
./magento snmp:set 1.3.6.1.4.1.50000.1.2.19.5 tutu
./magento snmp:get 1.3.6.1.4.1.50000.1.2.19.5
.1.3.6.1.4.1.50000.1.2.19.5
string
tutu

Et en appel SNMP :


snmpget ­v1 ­cpublic 127.0.0.1 1.3.6.1.4.1.50000.1.1.1
iso.3.6.1.4.1.50000.1.1.1 = STRING: "2.0.0"
snmpgetnext ­v1 ­cpublic 127.0.0.1 1.3.6.1.4.1.50000.1.1.1
iso.3.6.1.4.1.50000.1.1.2 = STRING: "Community"
snmpget ­v1 ­cprivate 127.0.0.1 1.3.6.1.4.1.50000.1.2.19.5
iso.3.6.1.4.1.50000.1.2.19.5 = STRING: "tutu"
snmpset ­v1 ­cprivate 127.0.0.1 1.3.6.1.4.1.50000.1.2.19.5 s toto
iso.3.6.1.4.1.50000.1.2.19.5 = STRING: "toto"
snmpget ­v1 ­cprivate 127.0.0.1 1.3.6.1.4.1.50000.1.2.19.5
iso.3.6.1.4.1.50000.1.2.19.5 = STRING: "toto"

Bien entendu, dans le cadre d'une production réelle, on n'utiliserait pas la version 1, mais la version
3 de SNMP, pour sa gestion de la sécurité renforcée.

Remontée d'alertes

Le mécanisme présenté dans la section précédente montre que l'on peut effectivement arriver à voir
l'état et à configurer certaines valeurs de Magento à travers SNMP. Cependant, ce mécanisme n'est a
priori pas suffisant pour fournir une remontée d'alerte, et ceci est assez embêtant, car PHP
lui-même ne fournit pas en standard d'implémentation des traps (même si des librairies PHP tierces
qui implémentent cette fonctionnalité existent).

Toutefois, snmpd fournit une fonctionnalité qui permet de résoudre ce problème. Snmpd est capable
de monitorer (commande monitor) à intervalles réguliers les valeurs numériques d'OID, afin de voir
si les valeurs rencontrées soulèvent un cas où il faut envoyer un trap ou non. Mieux encore, il est
même possible de surveiller non pas les valeurs en elles-mêmes, mais les différences de valeurs
dans le temps. Une application de cette fonctionnalité est par exemple la surveillance de l'exécution
continue des crons : si dans un OID on place la dernière valeur de schedule_id d'une tâche cronMagento exécutée en succès, on peut chercher à voir si cette valeur croît dans le temps ou non, et on peut ainsi chercher à détecter un cron qui serait en défaut.

J'ai justement implémenté ceci en utilisant snmptrapd comme destinataire des traps SNMP (en v1 et
v2), et en sortant les alertes dans un fichier, j'ai obtenu des alertes tel que suit grâce au monitoring :
monitor -D -I -r 30 CRON .1.3.6.1.4.1.50000.1.3.1 == 0


2016­02­07 09:06:47 localhost [UDP: [127.0.0.1]:41722­>[127.0.0.1]:162]:
iso.3.6.1.2.1.1.3.0 = Timeticks: (3240) 0:00:32.40 iso.3.6.1.6.3.1.1.4.1.0 = OID:
iso.3.6.1.2.1.88.2.0.1 iso.3.6.1.2.1.88.2.1.1.0 = STRING: "CRON" iso.3.6.1.2.1.88.2.1.2.0 =
"" iso.3.6.1.2.1.88.2.1.3.0 = "" iso.3.6.1.2.1.88.2.1.4.0 = OID: iso.3.6.1.4.1.50000.1.3.1
iso.3.6.1.2.1.88.2.1.5.0 = INTEGER: 5
2016­02­07 09:42:47 192.168.3.131(via UDP: [127.0.0.1]:34709­>[127.0.0.1]:162) TRAP, SNMP v1,
community public
iso.3.6.1.2.1.88.2 Enterprise Specific Trap (1) Uptime: 0:36:31.58
iso.3.6.1.2.1.88.2.1.1.0 = STRING: "CRON" iso.3.6.1.2.1.88.2.1.2.0 = ""
iso.3.6.1.2.1.88.2.1.3.0 = "" iso.3.6.1.2.1.88.2.1.4.0 = OID: iso.3.6.1.4.1.50000.1.3.1
iso.3.6.1.2.1.88.2.1.5.0 = INTEGER: 6
2016­02­07 09:42:47 localhost [UDP: [127.0.0.1]:41722­>[127.0.0.1]:162]:
iso.3.6.1.2.1.1.3.0 = Timeticks: (219158) 0:36:31.58 iso.3.6.1.6.3.1.1.4.1.0 = OID:
iso.3.6.1.2.1.88.2.0.1 iso.3.6.1.2.1.88.2.1.1.0 = STRING: "CRON" iso.3.6.1.2.1.88.2.1.2.0 =
"" iso.3.6.1.2.1.88.2.1.3.0 = "" iso.3.6.1.2.1.88.2.1.4.0 = OID: iso.3.6.1.4.1.50000.1.3.1
iso.3.6.1.2.1.88.2.1.5.0 = INTEGER: 6
2016­02­07 09:44:47 192.168.3.131(via UDP: [127.0.0.1]:34709­>[127.0.0.1]:162) TRAP, SNMP v1,
community public
iso.3.6.1.2.1.88.2 Enterprise Specific Trap (1) Uptime: 0:38:31.58
iso.3.6.1.2.1.88.2.1.1.0 = STRING: "CRON" iso.3.6.1.2.1.88.2.1.2.0 = ""
iso.3.6.1.2.1.88.2.1.3.0 = "" iso.3.6.1.2.1.88.2.1.4.0 = OID: iso.3.6.1.4.1.50000.1.3.1
iso.3.6.1.2.1.88.2.1.5.0 = INTEGER: 7
2016­02­07 09:44:47 localhost [UDP: [127.0.0.1]:41722­>[127.0.0.1]:162]:
iso.3.6.1.2.1.1.3.0 = Timeticks: (231158) 0:38:31.58 iso.3.6.1.6.3.1.1.4.1.0 = OID:
iso.3.6.1.2.1.88.2.0.1 iso.3.6.1.2.1.88.2.1.1.0 = STRING: "CRON" iso.3.6.1.2.1.88.2.1.2.0 =
"" iso.3.6.1.2.1.88.2.1.3.0 = "" iso.3.6.1.2.1.88.2.1.4.0 = OID: iso.3.6.1.4.1.50000.1.3.1
iso.3.6.1.2.1.88.2.1.5.0 = INTEGER: 7

Dans cet exemple, j'ai fait artificiellement augmenter la valeur du dernier succès de tâche via la base
de données. On constate qu'initialement la valeur était 5. Elle n'a pas augmenté lors de la prochaine
vérification, ce qui a déclenché les deux premiers trap (snmpv1 et v2), sans déclencher de trap
supplémentaire jusqu'à ce que j'ai incrémenté la valeur : la situation est donc redevenue normale, ce
qui a réactivé la possibilité de lancer des traps. La valeur n'a de nouveau pas évolué entre deux
vérifications, ce qui a déclenché l'alerte sur la valeur 6, et j'ai ensuite immédiatement incrémenté
l'ID. On comprend donc qu'il faut, lorsque la fréquence de vérification est de 1 minute, au
maximum 2 minutes pour que le système détecte la non progression de la valeur et lance un
nouveau trap.

On voit donc qu'il n'y a pas besoin d'implémenter d'autres mécanismes au niveau de Magento pour
déclencher des traps, si ce n'est la remontée des informations par SNMP. Certes, ce système procure
l'inconvénient qu'il faille scruter périodiquement les valeurs, mais a pour avantage d'être facile à
mettre en œuvre.

Conclusion

En conclusion, on voit qu'il est possible d'interfacer Magento et SNMP, au travers d'une conception
de MIB adaptée au cas pratique, et de l'utilisation de snmpd pour s'affranchir du développement de
la couche SNMP en elle même. Ceci permet non seulement de récupérer des valeurs systèmes, mais
également des valeurs métiers, ainsi que si nécessaire, permet de faire certains ajustements de
configuration. De part les fonctionnalités prodiguées par snmpd, on a constaté qu'il est même
possible de faire remonter des alertes issues de Magento. Ce type de développement rentre donc
dans une certaine mesure dans l'esprit du mouvement Devops, qui vise justement à assurer une
meilleure cohésion entre développeurs et les administrateurs.

Enregistrer

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.