Review Devices (ticket: #170)

En cours de rédaction.

Refonte de la gestion des composants pour les rendre inventoriables avec gestion financière et gestion de stock, permettre leur association sur d'autres éléments que les ordinateurs.

2 idées en parallèles :
  1. revoir les gestion des composants actuels et permettre de les lier à d'autres éléments. Les composants restant des éléments simples.
  2. permettre la définition de sous-éléments : des ordinateurs comme sous-éléments d'un ordinateur (gestion des serveurs lames ou VMs), des matériels réseaux comme sous éléments de matériel réseau (gestion des modules des switchs...)

Gestion des sous-éléments

L'idée et de considérer qu'un ordinateur ou un matériel réseau peut contenir d'autres ordinateurs ou matériels réseaux.
Pour cela il faut donc ajouter une notion de lien parent / enfant. Une fois en place, il faut revoir tous les affichages des éléments qui peuvent être regroupés (ports réseaux...)

  • Définition possible du parent d'un élément ou des fils d'un élément via un onglet spécifique (Chassis)
  • Les VMs sont une problématique spécifique qui ne rentre pas dans ce cadre là car la liaison entre hôte et VM est "virtuelle" et non physique.
  • Sur différents onglets (Composants, ports réseaux, VMs, tickets, problèmes, historique, noms réseaux... ?) il faut pouvoir permettre l'affichage des éléments du matériel lui même ainsi que de la fusion de l'élément et de ces fils.
    • Sélection simple via une préférence d'affichage comme actuellement pour les ports réseaux ou autre système arborescent
  • Voir la gestion du TCO : calcul de l'arborescence et de l'élément unique doit être possible
  • Les impacts sur le moteur de recherche seront minimes (ajout du parent, ?)
  • Pas de limitation prévue sur le niveau de hiérarchie (sous-élément de sous-élément)

Web: Parmi les idées, afin de gérer une récursivité "sans fin" dans les sous-éléments, nous pourrions jeter un œil du côté des "Nested Set Model": http://en.wikipedia.org/wiki/Nested_set_model. Mais si on commence à se pencher sur ce modèle, il faudrait l'envisager pour l'ensemble des tables "tree" car cela permettrait de supprimer leurs champs sons_cache et ancestors_cache ; les requêtes de l'ensemble des parents et des enfants sont directes dans ce modèle.

MoYo : pourquoi pas étudier l'application de cela pour des hiérarchies de GLPI mais il faut dans un premier temps faire simple pour cette notion de sous-éléments. L'idée de base étant simplement de pouvoir définir des sous-éléments de types identiques : des sous éléments réseaux à un élément réseau et des sous-ordinateurs à des ordinateurs, la gestion hiérarchique actuelle devrait suffir. Ce genre de problématique devrait faire l'objet d'un autre chantier pour ne pas interférer avec la problématique initiale de ce chantier : Nested_Set_Model

Refonte de la gestion des composants

La partie spécification a été transférée dans le ticket #4366.

Pourquoi ne pas gérer les éléments connectés (écran, imprimante et téléphone) de la même manière ?
En fait, certains composants externes sont "connectés" à l'ordinateur (disque dur, carte son, carte réseau ...). Inversement, certains écrans LCD ou certains téléphones font partie des composants des ordinateurs (carte modem ou contrôleur d'autocom). Je me demande si nous ne devrions pas uniformiser les périphériques en regroupant les composants et les éléments connectés.

Gonéri> Dans ce cas, on s'approche de l'organisation que je présente plus bas. Des éléments et des interconnexions. Savoir si le composant est intégré dans un autre devrait être une propriété du premier. Par exemple, un laptop avec une webcam USB intégré (laptop3 ? USB ? webcam[inside laptop3]). Je pense que le modèle peut s'étendre à l'ensemble des composants (devices, components), par exemple pour un disque USB ou dans un équipement SAN. Mais je crois que ça correspond a ce que présente Damien plus tard avec le "Nested Set Model".
Effectivement, c'était mon idée initiale. Mais il faut pousser la réflexion beaucoup plus loin. Car sinon, nous risquons d'avoir des problèmes de performance : les Nested Set Models ne le sont pas lorsqu'il s'agit d'ajouter un élément dans l'arbre.

complément de discussion non validé

Web : attention ! Contrairement à une cartouche, lorsqu'un composant est retiré d'un équipement, il peut être remis dans le stock pour éventuellement être réutilisé ailleurs. Je propose de créer une classe "Usage" ou quelque chose d'approchant, qui recenserait, pour un composant donné sa date d'installation et d'extraction d'un composant.
La table aurait plusieurs champs :
  • componenttype : type du composant ;
  • components_id : index du composant ;
  • itemtype : type de l'item dans lequel le composant est installé ;
  • items_id : index de l'item dans lequel le composant est installé ;
  • start : date d'installation du composant dans l'item ;
  • end : date de retrait du composant dans l'item.
    Gonéri : Une cartouche peut être retirée d'une imprimante pour être utilisée sur une autre machine (et on peut la tracer lorsqu'elle a un numéro de série).
Dans ce cas, ce ne serait plus Component qui hériterait de CommonDBRelation, mais cette nouvelle classe Usage.
La nouvelle représentation logique serait :
  • ComponentItem est une classe de composant (carte graphique trucmuche du bidule, processeur machin de untel ...) ;
  • Component (classe héritée de CommonDBChild sur un ComponentItem) est un composant physique (instance de ComponentItem) ;
  • Usage (classe héritée de CommonDBRelation) est l'installation à un instant t dans un Item d'un Component donné.

MoYo : je pense que la classe Usage complique le tout. Ce qui est souhaité en terme d'inventaire c'est d'avoir la vision à un instant t. La vie d'un composant serait visible dans l'historique de celui-ci. Mais avant de partir sur le modèle de données il faut réfléchir aux règles de gestion. On pourra après mettre en place le modèle de données le plus simple possible pour répondre au problème (simplicité du modèle -> gain en perf)

Web : effectivement, si l'inventaire se réduit à l'instant t, alors la classe Usage est superflue. Donc, voici la représentation que je propose :
  • ComponentItem est une classe de composant (carte graphique trucmuche du bidule, processeur machin de untel ...) ;
  • Component (classe héritée de CommonDBRelation reliant un Item et le ComponentItem) est un composant physique (instance de ComponentItem) ;
    Je peux essayer de faire un premier prototype en ce sens.

MoYo : avant de faire un proto, je pense qu'il faut qu'on finisse les spécifications complètes des 2 chantiers (c'est un peu le fouilli d'ailleurs... je vais essayer de faire du ménage). Une fois qu'elles seront validées on pourra se lancer.

Discussions Nouveaux champs

Web : je propose la création de deux classes intermédiaires Component (dont hériteraient Cartridge et Item_Devices) et ComponentItem (classe ancêtre de CartridgeItem et CommonDevice). Ces deux classes centraliseraient la création et la gestion de composants "en stock" : gestion des dates d'entrée et de sortie du stock, des InfoCom, de alertes en cas de rupture de stock ...
Dans la foulée, il faudrait renommer CommonDevice en DeviceItem (DeviceProcessorItem, DeviceProcessorMemory ...) et Item_Devices en Device (DeviceProcessor, DeviceMemory ...).
+MoYo : pour le moment je ne serai pas pour mélanger Cartouches et Composants vu que ce sont vraiment 2 éléments différents avec des mécanismes de gestion différents. Il sera plus simples qu'ils vivent leur vie chacun de leur côté pour le moment. A terme si les règles métiers des 2 éléments sont vraiment les mêmes on factorisera à ce moment là (ca mérite quelques versions de stabilisation et de retours avant). Sinon dans le même esprit il y a les consommables...

  • Web : je propose d'ajouter un champs busid aux composants de type USB, PCI, AGP, PCIe ... Ce champs correspondrait à l'identifiant PCI ou à l'identifiant USB du composant. C'est la seule information constante entre les différents OS pour une carte PCI ou un périphérique USB donné (c'est celle dont se servent les OS pour savoir à quel périphérique ils ont à faire). À terme, cela pourrait être utile pour éviter la duplication des composants entre Windows XP, Windows Seven, Linux, BSD ...
  • Gonéri : il y a deux notions en général, l'ID du matériel (USBID ou PCIID pour PCI, AGP, PCIe, ...) et l'adresse (BUSID) qui correspond à l'emplacement de l'équipement (ID du slot PCI, ID sur la chaîne USB).
    Les ID de matériel sont listés dans deux bases de données, usb.ids et pci.ids (Sur une Debian, les deux DB sont disponibles ici /usr/share/misc/pci.ids et là /usr/share/misc/usb.ids). Ces bases de données contiennent un ID fabriquant, un ID de produit et un sous ID. Un fabriquant peut avoir plusieurs ID qui lui appartiennent dans cette liste. Une information qui n'apparait pas dans ces DB est la classe des équipements qui est aussi importante pour par exemple dire que ce truc là que je ne connais pas, c'est une carte son (lsusb -vvv). A mon avis, il est intéressant de décomposer ces {USB,PCI}ID dans la DB afin de pouvoir rapidement, via une requête SQL, indiquer la classe de l'équipement dans le cas de l'USB et le fabriquant. Je pense qu'il est aussi intéressant d'un point de vu support de pouvoir stocker le nom du driver, même si ça peut être fait dans FusionInventory.
    Pour information, voici les informations qui sont remontées aujourd'hui sur ces éléments par FI : https://metacpan.org/module/FusionInventory::Agent::Task::Inventory::Inventory#CONTROLLERS , https://metacpan.org/module/FusionInventory::Agent::Task::Inventory::Inventory#USBDEVICES

web : effectivement, il peut y avoir confusion avec le bus ID d'une carte PCI sur un bus PCI. Mais cet ID ne se situe pas au niveau du DeviceItem (type générique de la carte, concerné par ma proposition précédente), mais au niveau du lien entre le DeviceItem et l'ordinateur ou l'équipement. J'ai proposé le nom busid pour éviter de multiplier les champs car certains types d'équipements (carte réseau, carte son ...) sont disponible en USB et en PCI, voire en Firewire (disques durs). Mais je suis beaucoup moins au point sur ce sujet : existe-t-il des fw_id à l'instar de pci_id et usb_id ? J'ai oublié l'ajout d'un mécanisme pour fournir l'ensemble des ID de fabricant à chaque fabricant (classe Manufacturer). Mais peut-être n'est-ce pas le propos de cette page.

Discussion diverses

Web : je propose la création de deux classes intermédiaires Component (dont hériteraient Cartridge et Item_Devices) et ComponentItem (classe ancêtre de CartridgeItem et CommonDevice). Ces deux classes centraliseraient la création et la gestion de composants "en stock" : gestion des dates d'entrée et de sortie du stock, des InfoCom, de alertes en cas de rupture de stock ...
Dans la foulée, il faudrait renommer CommonDevice en DeviceItem (DeviceProcessorItem, DeviceProcessorMemory ...) et Item_Devices en Device (DeviceProcessor, DeviceMemory ...).
+MoYo : pour le moment je ne serai pas pour mélanger Cartouches et Composants vu que ce sont vraiment 2 éléments différents avec des mécanismes de gestion différents. Il sera plus simples qu'ils vivent leur vie chacun de leur côté pour le moment. A terme si les règles métiers des 2 éléments sont vraiment les mêmes on factorisera à ce moment là (ca mérite quelques versions de stabilisation et de retours avant). Sinon dans le même esprit il y a les consommables...

Web : peut-être serait-il bon de faire également hériter Cartridge de CommonDBRelation afin de profiter des mécanismes de CommonDBRelation and CommonDBChild improvement. Si ce point est entériné, alors il y aurait moins d'obstacle au point précédent (création des classes Component et ComponentItem).

MoYo : dans un premier temps il faut se focaliser sur les composants et uniquement cette partie. On verra dans un second temps une extension de cette partie si besoin.

Web : j'ai du mal à comprendre comment fonctionnera la recherche avec les sous-éléments. Par exemple, il existera des switchs où les ports réseaux sont directements intégrés au switch et d'autres où les ports réseaux seront attachés à un module du switch (ie. : sous-switch). Il en va de même avec la recherche des logiciels contenus sur une machine, en ce y compris ceux contenus dans les machines virtuelles qui tournent sur cette machine. J'ai même vu un ordinateur équipé d'une carte réseau qui fait office de switch ... Cette hiérarchie est parfaitement justifiée. Mais elle risque de poser problème dans la recherche globale : à moins de faire des unions dans les SELECT en tenant compte des cas avec imbrications exotiques ... C'est pour cela que je proposais de changer de modèle pour la gestion de la hiérarchie en utilisant, par exemple, des Nested Set Model. Mais il existe d'autres modèles qui pourraient représenter cette hiérarchie beaucoup plus flexible.
Mais peut-être y a-t-il deux chantiers différents : d'une part la refonte des composants ; d'autre part la possibilité d'avoir des sous-items ?

MoYo : Oui c'est bien 2 chantiers différents même si complémentaires. Sur la recherche je ne vois pas trop le problème. Si tu cherche un logiciel ce que tu veux c'est la VMs et non la machine contenant la VMs. Tu pourra remonter au contenant une fois sur la VMs. Idem pour les ports, tu recherche un port tu trouve le module auquel appartient le port et tu as sur ce module l'information de contenance te permettant de savoir qu'il est dans tel switch sur lequel tu peux alors te déplacer si tu veux avoir une vu globale.


  • Web : je propose d'ajouter un champs busid aux composants de type USB, PCI, AGP, PCIe ... Ce champs correspondrait à l'identifiant PCI ou à l'identifiant USB du composant. C'est la seule information constante entre les différents OS pour une carte PCI ou un périphérique USB donné (c'est celle dont se servent les OS pour savoir à quel périphérique ils ont à faire). À terme, cela pourrait être utile pour éviter la duplication des composants entre Windows XP, Windows Seven, Linux, BSD ...
  • Gonéri : il y a deux notions en général, l'ID du matériel (USBID ou PCIID pour PCI, AGP, PCIe, ...) et l'adresse (BUSID) qui correspond à l'emplacement de l'équipement (ID du slot PCI, ID sur la chaîne USB).
    Les ID de matériel sont listés dans deux bases de données, usb.ids et pci.ids (Sur une Debian, les deux DB sont disponibles ici /usr/share/misc/pci.ids et là /usr/share/misc/usb.ids). Ces bases de données contiennent un ID fabriquant, un ID de produit et un sous ID. Un fabriquant peut avoir plusieurs ID qui lui appartiennent dans cette liste. Une information qui n'apparait pas dans ces DB est la classe des équipements qui est aussi importante pour par exemple dire que ce truc là que je ne connais pas, c'est une carte son (lsusb -vvv). A mon avis, il est intéressant de décomposer ces {USB,PCI}ID dans la DB afin de pouvoir rapidement, via une requête SQL, indiquer la classe de l'équipement dans le cas de l'USB et le fabriquant. Je pense qu'il est aussi intéressant d'un point de vu support de pouvoir stocker le nom du driver, même si ça peut être fait dans FusionInventory.
    Pour information, voici les informations qui sont remontées aujourd'hui sur ces éléments par FI : https://metacpan.org/module/FusionInventory::Agent::Task::Inventory::Inventory#CONTROLLERS , https://metacpan.org/module/FusionInventory::Agent::Task::Inventory::Inventory#USBDEVICES

web : effectivement, il peut y avoir confusion avec le bus ID d'une carte PCI sur un bus PCI. Mais cet ID ne se situe pas au niveau du DeviceItem (type générique de la carte, concerné par ma proposition précédente), mais au niveau du lien entre le DeviceItem et l'ordinateur ou l'équipement. J'ai proposé le nom busid pour éviter de multiplier les champs car certains types d'équipements (carte réseau, carte son ...) sont disponible en USB et en PCI, voire en Firewire (disques durs). Mais je suis beaucoup moins au point sur ce sujet : existe-t-il des fw_id à l'instar de pci_id et usb_id ? J'ai oublié l'ajout d'un mécanisme pour fournir l'ensemble des ID de fabricant à chaque fabricant (classe Manufacturer). Mais peut-être n'est-ce pas le propos de cette page.

Web : attention ! Contrairement à une cartouche, lorsqu'un composant est retiré d'un équipement, il peut être remis dans le stock pour éventuellement être réutilisé ailleurs. Je propose de créer une classe "Usage" ou quelque chose d'approchant, qui recenserait, pour un composant donné sa date d'installation et d'extraction d'un composant.
La table aurait plusieurs champs :
  • componenttype : type du composant ;
  • components_id : index du composant ;
  • itemtype : type de l'item dans lequel le composant est installé ;
  • items_id : index de l'item dans lequel le composant est installé ;
  • start : date d'installation du composant dans l'item ;
  • end : date de retrait du composant dans l'item.
    Gonéri : Une cartouche peut être retirée d'une imprimante pour être utilisée sur une autre machine (et on peut la tracer lorsqu'elle a un numéro de série).
Dans ce cas, ce ne serait plus Component qui hériterait de CommonDBRelation, mais cette nouvelle classe Usage.
La nouvelle représentation logique serait :
  • ComponentItem est une classe de composant (carte graphique trucmuche du bidule, processeur machin de untel ...) ;
  • Component (classe héritée de CommonDBChild sur un ComponentItem) est un composant physique (instance de ComponentItem) ;
  • Usage (classe héritée de CommonDBRelation) est l'installation à un instant t dans un Item d'un Component donné.

MoYo : je pense que la classe Usage complique le tout. Ce qui est souhaité en terme d'inventaire c'est d'avoir la vision à un instant t. La vie d'un composant serait visible dans l'historique de celui-ci. Mais avant de partir sur le modèle de données il faut réfléchir aux règles de gestion. On pourra après mettre en place le modèle de données le plus simple possible pour répondre au problème (simplicité du modèle -> gain en perf)

Web : effectivement, si l'inventaire se réduit à l'instant t, alors la classe Usage est superflue. Donc, voici la représentation que je propose :
  • ComponentItem est une classe de composant (carte graphique trucmuche du bidule, processeur machin de untel ...) ;
  • Component (classe héritée de CommonDBRelation reliant un Item et le ComponentItem) est un composant physique (instance de ComponentItem) ;
    Je peux essayer de faire un premier prototype en ce sens.

MoYo : avant de faire un proto, je pense qu'il faut qu'on finisse les spécifications complètes des 2 chantiers (c'est un peu le fouilli d'ailleurs... je vais essayer de faire du ménage). Une fois qu'elles seront validées on pourra se lancer.

Gonéri : Avis surement hors-sujet car je ne connais pas assez le modèle de données de GLPI et que j'ai un point de vu exterieur. (Vous pouvez virer ce paragraphe si il est hors-sujet :)). Mon avis est qu'on devrait avoir un élément de base réutilisé partout (Ordinateur, Cartouche, Equipement réseau, etc) et il devrait pouvoir avoir être lié avec d'autres élément de base avec une définition de la relation. La distinction composant/élément est à mon avis un peu arbitraire. On a des champs commons partout (fabriquant, date de mise en service, nom, etc). Il serait ainsi possible de pouvoir créer des nouveaux élements, par exemple, Onduleur, Climatisation, etc. Par exemple :
  • L'onduleur a (connecteur 1, électrique) est lié à l'ordinateur b (connecteur 1, électrique) via le lien XXX (cable électrique).
  • L'onduleur a (connecteur 5, USB) est lié à l'ordinateur b (connecteur 4, USB) via le lien XXX (cable USB).
  • La carte PCI c (connecteur 3, slot PCI) est lié à l'ordinateur b (connecteur 5, slot PCI) via le lien YYY (driver, vitesse du bus, etc).

MoYo : ce n'est effectivement pas le sujet de ce chantier mais pourrait faire l'objet d'un autre chantier de refonte complète du modèle qui engendrerai des gros problèmes de perfs à mon avis. Mais toutes les idées sont étudiables.


Web: Parmi les idées, afin de gérer une récursivité "sans fin" dans les sous-éléments, nous pourrions jeter un oeil du côté des Nested Set Model. Mais si on commence à se pencher sur ce modèle, il faudrait l'envisager pour l'ensemble des tables "tree" car cela permettrait de supprimer leurs champs sons_cache et ancestors_cache ; les requêtes de l'ensemble des parents et des enfants sont directes dans ce modèle.

MoYo : pourquoi pas étudier l'application de cela pour des hierarchies de GLPI mais il faut dans un premier temps faire simple pour cette notion de sous-éléments. L'idée de base étant simplement de pouvoir définir des sous-éléments de types identiques : des sous éléments réseaux à un élément réseau et des sous-ordinateurs à des ordinateurs, la gestion hiérarchique actuelle devrait suffir. Ce genre de problématique devrait faire l'objet d'un autre chantier pour ne pas interférer avec la problématique initiale de ce chantier.

Web : cf. commentaire ci-dessus sur l'évolution du modèle de gestion des hiérarchies (Nested Set Model). J'ai l'impression que la structure hiérarchique actuelle, très naturelle, est très rapide et efficace lors de l'ajout d'un élément. Mais lors de l'interrogation de la base de donnée, elle présente quelques limitations (notamment sur les sous-éléments) et impose des requètes SQL complexes (cf. classe Search avec les CommonDBTM::getSearchOptionsToAdd). Inversement, nous pourrions migrer la gestion des arborescences sur un système un petit peu plus complexe lors de l'ajout d'éléments, mais beaucoup plus efficace et pratique lors de l'interrogation de la base de donnée.

MoYo : effectivement ce n'est peut-être pas idéal actuellement mais pour savoir quel modèle est le mieux il faut poser sur la table tous les problèmes et solutions. Personnellement vu de loin j'ai l'impression que cela engendrera énormément de complexité à l'ajout d'élement vu que les ID changeront tout le temps donc modifications des id des éléments liés (historiques...). Il y a peut-être des solutions pour rendre cela plus efficace mais il faut bien tout spécifier. Sur la recherche je ne vois pas trop ce que ca améliorera à par les recherches du genre ON / NOT IN. Le reste sera toujours aussi complexe d'après moi. Mais je me trompe peut-être aussi. L'ouverture du chantier parallèle est très bien et permettra de montrer l'intérêt de la nouvelle solution.

Gonéri : C'est jouable avec MySQL ? “Queries using nested sets can be expected to be faster than queries using a stored procedure to traverse an adjacency list, and so are the faster option for databases which lack native recursive query constructs, such as MySQL.[4] However, recursive SQL queries can be expected to perform comparably for 'find immediate descendants' queries, and much faster for other depth search queries, and so are the faster option for databases which provide them, such as PostgreSQL,[5] Oracle,[6] and Microsoft SQL Server.[7]”

Web : si mon anglais n'est pas trop rouillé, ils précisent justement que c'est la méthode la plus rapide sur MySQL qui manque de mécanisme de recherche récursive, par opposition à PostgreSQL, Oracle ... Pour un exemple d'instanciation sur MySQL : http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/.

web : En fait, en poussant ma reflexion plus loin, je pense que nous gagnerions à définir une classe "Nested Set Model" qui engloberait tous les composants d'un ordinateur (ou d'un élément générique) par arborescence (Ordinateur -> BUS PCI -> Carte réseau -> Port réseau -> ...). Chaque ligne de cette base de donnée contiendrait : <items_id, itemtype> (identifiant du composant) + <left, right> (les élément du Nested Set Model). Dans la foulée, une machine virtuelle serait également une noeud de cette arbre. Et je suis sûr que les possibilités offertes par un tel mécanisme permettraient d'aller encore plus loin ...