Journal Code Python en BDD avec Canopsis

Posté par (page perso) . Licence CC by-sa
Tags :
6
27
jan.
2016

1. Introduction

Avant de rentrer dans le vif du sujet, une petite présentation de Canopsis s'impose.

Canopsis Logo

Il s'agit d'une solution d'hypervision sous licence AGPL3, capable d'agréger de nombreuses sources de données afin de les présenter à l'utilisateur, et de lui permettre d'interagir avec de manière standardisée et cohérente.

L'architecture du projet, grossièrement simplifiée, se compose des éléments suivants :

  • des connecteurs récupèrent les données depuis différentes sources (Nagios/Shinken/Icinga/…, jMeter, Sikuli, BDD type SQL, API REST, …), et les envoient sur un bus de données sous forme d'événement standardisé
  • des moteurs consomment les événements afin de les traiter et de les stocker de manière cohérente en base de données
  • une API REST fournit un accès à ces données
  • un application web complètement personnalisable permet à l'utilisateur de construire ses vues et de décider comment afficher, valoriser et interagir avec ces données

Les parties moteurs et API REST sont développées en Python, et c'est ce qui va nous intéresser dans cet article.

2. Charger le code dynamiquement

Du travail est en cours sur ce projet afin de généraliser la modularité du projet.

Actuellement, un moteur se présente comme un daemon, et s'implémente en surclassant une classe de base abstraite afin d'implémenter certaines méthodes.

C'est certes simple, mais pas suffisamment souple car cela ne permet pas de bien découper le projet quand les fonctionnalités s'additionnent, on se retrouve ainsi avec un paquet python engines qui fait un peu fourre tout.

L'idée était donc de rentre tout cela plus modulaire. Et la solution adoptée fut donc de spécifier dans le fichier de configuration l'implémentation des méthodes. La classe de base (que l'on n'a plus besoin de toucher) va charger le code tel qu'il est spécifié dans la configuration.

Un exemple vaut mieux qu'un long discours.

Avec ce fichier de configuration :

[engine:myengine]

event_processing=canopsis.myfeature.process.event_processing

Le moteur saura aller chercher la fonction event_processing dans le paquet python canopsis.myfeature.process, et l'implémentation se résume à ceci :

def event_processing(event, **_):
    # do something with event

Ce système permet donc de mieux découper le code, chaque fonctionnalité apporte ses propres implémentations pour chaque aspect du projet.

Cela repose notamment sur un petit utilitaire :

from canopsis.common.utils import lookup

event_processing = lookup('canopsis.myfeature.process.event_processing')

Nous visons a démocratiser dans le projet ce genre d'usage, toujours pour une meilleure découpe, et une meilleure maintenabilité.

3. Le vif du sujet (enfin)

En parcourant un peu le web, je tombe sur un article en particulier.

TL;DR: cela présente le mécanisme qui permet d'agrémenter le système d'import de Python avec de nouvelles fonctionnalités (ici un import depuis un dépôt Github).

Bon, fonctionnalité un peu risquée dans le cas où le code dépend du bon vouloir d'un inconnu à ne pas supprimer/casser son code.

MAIS, le mécanisme présenté peut avoir d'autres usages, c'est donc notre cas.

Ici, il est utilisé afin de stocker du code dans une base de données :

  • document MongoDB
  • entrée dans une table SQL
  • … (avec le système de storage, nous sommes capable de développer un driver pour n'importe quelle base de données)

Ce qui permet ainsi de stocker le code des moteurs (et autres à l'avenir) dans MongoDB actuellement :

{
    "_id": "myfeature",
    "src": "def event_processing(event, **_):\n    # do something with event\n"
}

Et de le référencer dans la configuration :

[engine:myengine]

event_processing=canopsis.pyloader.myfeature.event_processing

Après cela, nous serons en mesure d'écrire un schéma JSON décrivant le document en base, et ce dernier sera utilisé par l'application web pour générer automatiquement un modèle, utilisable pour faire un listing des morceaux de code présent en base.

L'édition du code pourra ainsi se faire depuis l'application web de Canopsis, même si ce n'est pas l'objectif premier, cela permettra de modifier à l'exécution le traitement des données, par le biais de l'API REST.

On peut même imaginer une sorte de pastebin contenant diverses implémentations, qu'il suffira d'injecter pour tester avant de considérer un merge.

4. Conclusion

Cette fonctionnalité, simple mais efficace, est intégrée à un plus gros chantier (de migration du code utilisant l'ancienne API pour les moteurs, à la nouvelle API plus dynamique), et ne sera donc pas disponible tout de suite.

En attendant, on peut toujours suivre l'avancée du projet sur notre Gitlab.

  • # Puissant… et dangereux

    Posté par (page perso) . Évalué à 6.

    Prévoyez peut-être un truc genre signature de code avec une clé + vérification, afin de ne pas permettre l'exécution d'un code qui aurait été malicieusement introduit dans la base de données.

    Python 3 - Apprendre à programmer en Python avec PyZo et Jupyter Notebook → https://www.dunod.com/sciences-techniques/python-3

    • [^] # Re: Puissant… et dangereux

      Posté par (page perso) . Évalué à 2.

      Effectivement c'est une idée à creuser, heureusement que pour le moment la problématique ne se pose pas car Canopsis est généralement installé sur des infra interne où les utilisateurs n'ont aucun intérêt à injecter du code malicieux (m'enfin, on sait jamais).

      De toutes façons, d'autres critères doivent prévenir l'exécution du code (absence de TU ou ceux ci ne passent pas ?).

  • # canopsis

    Posté par . Évalué à 3.

    Je ne connaissais pas canopsis. Si je comprends bien c'est une alternative au combo ElasticSearch/Logstash/Kibana qui avait déjà était présenté ici ?

    N'hésite surtout pas à faire un journal voir une dépêche sur le sujet :)

    Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

    • [^] # Re: canopsis

      Posté par . Évalué à 2.

      ou TICK
      ou Grafana + Graphite|Elasticsearch|Cloudwatch|Prometheus|InfluxDB

      • [^] # Re: canopsis

        Posté par (page perso) . Évalué à 2.

        Dans Canopsis il y a toute une partie événementielle que n'ont pas ses solutions.

        Quand j'écris qu'on récupère des données depuis les sources type Nagios/Shinken/Icinga/… c'est donc les checks, les downtimes, les ack, etc…

        Et du coup quand j'écris qu'on peut interagir avec depuis l'application web, c'est qu'on propose une vue (personnalisable comme tout le reste) qui permet d'unifier tout ça (donc de poser des ACK, des downtimes, de requalifier la criticité des alarmes, et même de faire de la déclaration de ticket dans des outils tierces type iTop).

        De plus, on fournit des éléments permettant de faire de la root cause analysis avec des outils tels que les sélecteurs ou les topologies (en cours d'amélioration d'ailleurs).

        Je garde dans un coin l'idée de faire une dépêche pour parler de tout ça plus en détail ;)

        Merci pour les retours en tout cas, je ne connaissais pas TICK ni Prometheus.

  • # Utilité

    Posté par . Évalué à 4.

    Je ne comprends pas très bien l'utilité.
    L'objectif est-il de permettre à l'utilisateur de fournir son propre bout de code ? De déployer une mise à jour du code sans avoir à changer le socle ? …

    Si c'est vraiment juste pour modulariser le projet, il y atout de même d'autres façon de faire AMHA (même si je ne suis pas spécialiste de python). Déjà en utilisant de la composition plutôt qu'une hiérarchie de classe.

    Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

    • [^] # Re: Utilité

      Posté par . Évalué à 1.

      Je partage.
      Il est tout à fait possible d'appliquer un principe d'inversion de contrôle par exemple avec de l'injection de dépendances.

    • [^] # Re: Utilité

      Posté par (page perso) . Évalué à 1.

      En réalisant cela, on a pensé à deux usages :

      • ce que j'ai exposé comme une sorte de pastebin, en gros un répertoire de code disponible pour tout utilisateur (il récupère ainsi le code et l'insère en base via l'UI)
      • lieu de stockage pour le code généré par les schémas JSON (une idée qui nous trotte dans la tête depuis un moment sans que quoi que ce soit ne soit encore mis en oeuvre pour)

      Certes cela permet également à l'utilisateur de fournir son propre code, et donc de le mettre également à jour sans changer le socle comme tu dis, mais ce n'est qu'une conséquence.

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.