Fedora-Fr - Communauté francophone Fedora - Linux

Planet de Fedora-Fr : la communauté francophone autour de la distribution Linux Fedora

A propos

Cette page est actualisée toutes les heures.

Cette page est une sélection de blogs autour de Fedora. Fedora-Fr.org décline toute responsabilité au sujet des propos tenus par les auteurs des blogs de ce planet. Leurs propos sont leur entière responsabilité.

Le contenu de ce planet appartient à leurs auteurs respectifs. Merci de consulter leur blogs pour obtenir les licences respectives.

Mot-clefs : Système

Participation au Kernel et Embedded recipes 2018

Charles-Antoine Couret

Cela faisait quelques années que je souhaitais participer à l'évènement parisien Kernel recipes (et au tout nouveau Embedded recipes). Des évènements annuels se déroulement en semaine à la fin septembre. Cette année c'est du 24 au 28 septembre dans les locaux parisiens de Mozilla.

Ce sont des conférences en anglais très techniques sur le noyau Linux et les systèmes embarqués à base de Logiciel Libre. Et c'est remarquable d'avoir cela en France de manière régulière, d'autant plus que chaque année de grands noms font le déplacement.

Grâce à mon employeur Essensium / Mind je vais pouvoir y assister en guise de veille et formation sur mon temps de travail. Je les remercie de m'en donner l'opportunité. Ce sera également l'occasion pour faire coucou à mes connaissances de la région.

En plus de cela j'effectuerai une conférence sur la mise à jour des systèmes embarqués avec swupdate le lundi 24 septembre à 15h. Je relayerais la vidéo de la conférence et la diapo quand ce sera disponible. Il y a je crois une retranscription en direct.

Si le domaine vous intéresse vous pouvez visionner les précédentes éditions. Comme toujours, bon courage et merci aux organisateurs.

La sécurité, l'obsolescence et la maintenance des systèmes embarqués

Charles-Antoine Couret

Il est assez banal de dire que de plus en plus d'équipements modernes sont connectés au réseau. Cela apporte de nouvelles fonctionnalités, la possibilité d'améliorer le produit même une fois vendu par des mises à jour mais aussi des problèmes de confidentialité et de sécurité.

Les systèmes embarqués sont particulièrement concernés par ces problématiques, que les industriels traitent parfois mal et dont les consommateurs sont rarement dans le vrai également.

C'est de cette problématique dont on va parler.

Obsolescence programmée ?

Ce terme revient souvent dans ce genre de discussions. Que l'abandon du support d'un produit, comme par exemple l'absence d'une mise à jour Android, ou que justement la mise à jour de trop rend le système trop lent (cas de certains iPhone) serait une pratique digne de l'obsolescence programmée.

Globalement c'est faux. L'obsolescence programmée est une pratique supposée où un constructeur fragilise **volontairement** son produit afin de nécessiter un remplacement régulier pour augmenter ses ventes.

Le mot clé est donc l'aspect volontaire. Qui est difficile en réalité à constater. Et certains oublient aussi l'aspect de l'équilibre entre le prix et la qualité. Un produit bas de gamme va minimiser la qualité des matériaux par exemple pour que cela coûte moins cher au client. Il est donc normal que le produit dure moins longtemps. Cette question du compromis dans la réalisation du produit est l'essence même du travail d'un ingénieur et de la création de différentes gammes de produits, on ne peut assimiler cela à de l'obsolescence programmée qui consiste en un sabotage.

Je ne vais pas m'étendre beaucoup sur le sujet, il y a trois articles de blog (ici, et là-bas) qui traitent bien de la question de l'obsolescence programmée qui reste une pratique à priori confidentielle. Mais le célèbre reportage d'Arte sur le sujet a mis en lumière cette pratique avec de mauvais exemples et certains le voient du coup... partout.

En tout cas on ne m'a jamais demandé de saboter mon propre produit, et aucun de mes collègues ou connaissances non plus. ;-)" class="smiley Par contre il arrive que certains bogues ne soient jamais corrigés, faute de temps ou de ressources financières pour les traiter.

De la question du progrès logiciel

Certains produits, comme nos ordinateurs ou téléphones portables, peuvent vivre des années sans problèmes. Et ces outils à usage assez génériques peuvent exécuter du logiciel conçu bien après la réalisation du produit.

Mon ordinateur portable personnel actuel date de 2011, il est passé de Fedora 16 à 27, de Windows 7 à 10, de Firefox 7 à Firefox 56, de GNOME 3.0 à GNOME 3.26, de Linux 3.1 à Linux 4.14, etc.

Ce sont des millions de lignes de code ajoutées depuis, le Web a beaucoup grossi entre temps avec du JavaScript devenu omniprésent et des sites devenant de plus en plus des applications complètes. Le contenu multimédia salourdit, passant du 720p à 4K pour les vidéos ou les photos. Le chiffrement s'est généralisé également dans les communications ou le stockage.

J'ai constaté peu à peu un ralentissement de ma machine, la consommation de la mémoire a monté (j'ai du rajouter 4 Gio récemment) alors que mon usage, fondamentalement n'a pas changé.

Ce phénomène n'a rien de nouveau, cela suit la loi de Wirth.

C'est un phénomène naturel. Les logiciels évoluent pour ajouter des fonctionnalités (pour répondre à des besoins des utilisateurs). Il est impossible de proposer du logiciel plus moderne tout en espérant une consommation en ressource identique indéfiniment. Soit il faut utiliser un produit qui n'évoluera plus fonctionnellement (cas de beaucoup d'outils simples et légers), ou alors il faudrait beaucoup de ressources financières et humaines pour maintenir plusieurs déclinaisons du logiciel dans le temps. Ce que l'on abordera plus tard.

Ce que la loi de Wirth n'explique pas ou mal, c'est que l'évolution du matériel se produit de manière globale, mais localement un produit a un matériel plutôt figé. Si le matériel évolue mais que les logiciels n'exploitent pas cette puissance supplémentaire, ce serait du gâchis. Donc la consommation des programmes évoluent pour bénéficier de ces ressources disponibles. Et forcément cela se fait au détriment des machines qui accusent d'un certain âge. Cela est encore plus visible sur les téléphones qui ont fait un saut de performances spectaculaire en très peu d'années.

Certains veulent exploiter la machine le plus longtemps possible (donc disons 10-15 ans) tout en bénéficiant de ces évolutions. Ce n'est pas possible sans concession. Il faut faire des choix, en payant cher des produits pour les maintenir longtemps, en renonçant partiellement à ce progrès, en changeant de machine ou renoncer à des usages. Typiquement, aller sur le Web avec une machine de 2002 doit être possible, mais cela ne doit pas être une expérience très agréable en dehors de quelques sites très légers.

Et pour un téléphone bas de gamme, conçu pour être tout juste capable de lancer les applications populaires de l'époque, ne peut pas soutenir la charge d'une mise à jour des dites applications sur le long terme.

Et après toute cette explication, comment associer cela à de l'obsolescence programmée alors que cette lourdeur progressive provient de logiciels extérieurs à la conception du matériel ? Ce n'est pas Intel qui a rendu Firefox plus lourd avec le temps. :-)" class="smiley

La sécurité

La sécurité est devenue depuis quelques années un sujet de premier plan pour tout un nouveau panel de produits. Avec une connexion accessible depuis Internet, il devient possible d'essayer d'infiltrer ces produits qui peuvent être accessibles non stop pendant des années et sans maintenance active (il n'y a pas un administrateur système pour surveiller le réseau domestique d'un particulier).

Du coup, pour combler les failles, il devient nécessaire de mettre à jour le produit. Parfois changer l'outil interne, ou le protocole employé (le MD5 n'est plus un moyen fiable pour vérifier l'intégrité d'un fichier ou d'un certificat).

Du coup pour améliorer la sécurité, on doit les faire évoluer. Ce qui peut nous faire revenir sur le point précédent où le logiciel devient trop lourd pour le matériel considéré ce qui rend compliqué la conciliation des deux.

L'autre problème est... le coût. Quand on achète un produit type téléphone, un réfrigérateur connecté, un modem ou autre, nous achetons le produit à un prix fixe, parfois très dérisoire car très bas de gamme. Sauf que d'assurer une maintenance sur 10-15 ans, cela coûte très cher. Car il devient nécessaire de maintenir plusieurs versions du logiciel (suivant l'âge du matériel et de ses successeurs à maintenir), de tester chaque mise à jour sur chaque produit, tester son déploiement, corriger les éventuels ratés auprès des clients, communiquer auprès d'eux (manuels explicatifs, mise à jour d'un site Web possiblement en plusieurs langues, courriers / courriels envoyés en nombre).

Admettons que pour maintenir un modèle d'un téléphone portable pendant 15 ans il faut une équipe de 10 personnes à temps plein (ce qui n'est pas irréaliste car cela demande beaucoup de travail pour corriger la moindre faille ou les bogues découverts, sachant que le logiciel dépend également du lieu vendu pour des raisons de contraintes légales). En admettant qu'ils ne sont pas mal payés (et qu'il leur faut du matériel adéquat), cela peut revenir par employé à un coût annuel pour l'employeur d'environ 100 000€. Donc 1 million d'euros par an. Sachant qu'un modèle lambda d'un téléphone peut être vendu auprès du million d'unités au total, cela reviendrait a un coût de 10-15 millions d'euros rien que pour la maintenance une fois le produit vendu. Pour des téléphones à 100€, cela représente 10% du budget global du produit ! Ce n'est clairement pas négligeable. Et je ne parle pas des cas de produits moins vendus qui méritent pourtant la même maintenance.

Le Libre comme solution ?

Certains pensent qu'un produit embarqué, s'il est fait avec du logiciel libre, il est aisé de le maintenir pour proposer des mises à jour du produit pendant des années après l'abandon par son constructeur. La réalité est plus complexe.

Pour les projets assez puissants pour accueillir un système d'exploitation Linux (cas des téléphones par exemple), le système est rarement compilé de zéro à la main. Pour gagner du temps, il existe des solutions comme Yocto ou buildroot (et ses déclinaisons OpenWRT ou ptxdist) pour compiler l'ensemble des logiciels (dont le noyau) pour notre système afin d'obtenir une image qu'on pourra installer sur la cible. Je les présenterais dans un autre article.

Seulement, chaque processeur ou plateforme a ses spécificités. C'est pourquoi, les concepteurs des puces (Qualcomm, Texas Instrument, Broadcom, Freescale / NXP et autres) fournissent les solutions citées plus haut avec les changements nécessaires pour exploiter la plateforme. Très souvent le noyau Linux et le chargeur de démarrage U-Boot accueillent une grande liste de correctifs maison (plusieurs centaines).

Cela est bien, car nous n'avons pas à développer nous même les pilotes pour exploiter les fonctions du processeur (notamment pour la couche graphique) et dans l'essentiel cela reste du code libre. Cependant ces correctifs sont gros et souvent… mal réalisés. Faute de temps et de ressources, les constructeurs ne cherchent pas à concevoir des correctifs qui finiront dans le projet officiel. Leur but est que cela fonctionne avec le noyau fourni aux développeurs / intégrateurs. Du coup nous nous retrouvons avec un noyau et un chargeur de démarrage figé, car Linux évolue très vite et il est très difficile de porter ces correctifs pour une autre version. Et comme cela est trop souvent trop mal fait (utilisation d'une pile logicielle différente que celle du noyau pour une fonction donnée, comme le SPI ou le réseau par exemple, code spaghetti avec lien fort entre le tronc commun et leur pilote, etc.) il est difficilement imaginable de porter cela sur le noyau officiel directement.

Pas mal de personnes essayent pourtant de porter le nécessaire sur le noyau officiel. Mais cela demande beaucoup de temps (aujourd'hui le support du téléphone N900 est quasiment complet, mais il aura fallu 8 ans après sa sortie !) et c'est souvent au prix de fonctionnalités partielles (performances graphiques ou réseaux plus faibles, gestion de l'énergie douteuse). Sans collaboration du fondeur, c'est une tâche globalement vouée à l'échec étant donné le rythme de sortie des composants. Puis le fabricant de la puce bosse déjà sur la plateforme suivante. Ils n'ont pas le temps, ni l'envie, de s'attarder sur un produit qui n'a plus d'avenir.

Et même dans le cas où ce serait possible, il y a des sacs de nœuds dans l'architecture du système. Si vous souhaitez profiter par exemple des dernières tablettes Wacom sur votre machine, il faudra un noyau récent. En admettant que vous avez un noyau LTS un peu ancien comme la 3.4, il faudra rétro-porter cette fonctionnalité. Cela signifie récupérer le pilote mais souvent d'autres commits sur le sous-systèmes des périphériques entrées. Mais le noyau ne fait pas tout, il faut également que l'interface graphique propose de quoi configurer et exploiter le matériel. Donc par exemple en récupérant du travail effectué sur les versions récentes de GTK+ et de GNOME. Cela peut donc représenter beaucoup de travail, sur beaucoup de composants, et il faudra tester bien sûr du bon fonctionnement, de la sécurité et de la maintenance de tout ceci.

Bref, l'aspect libre peut aider bien sûr à maintenir un produit plus longtemps. D'ailleurs les initiatives du genre OpenWRT, CyanogenMod / LineageOS permettent de maintenir à jour certains produits embarqués plus longtemps que le support officiel du constructeur. Mais cela se fait souvent au détriment de certaines fonctionnalités matérielles.

Solutions ?

Je pense que la solution ne peut se passer de l'aide des industriels, qui eux-mêmes ne peuvent pas se permettre à un coût fixe d'une maintenance complexe sur une très longue durée. Imposer légalement une durée minimale de support conduirait à une hausse de prix d'achat inévitable de tous ces biens.

Une autre solution serait d'évoluer vers une tarification en tant que service. À savoir payer pour une durée de maintenance souhaitée. Si l'utilisateur souhaite 10 ans de maintenance, il le pourra, au prix d'un abonnement ajusté en conséquence. Je pense que c'est la seule solution, notamment pour les produits vendus à un volume moyen ou faible, d'avoir une maintenance dans le temps à la hauteur, sans rendre le produits inutilisable ou trop cher à l'achat.

La solution libre et gratuite me semble difficilement possible. Il suffit de voir qu'aucune distribution purement communautaire gratuite pour x86 n'arrive à gérer une maintenance de plus de 5 ans. Pourtant la plateforme est plus simple et plus standard. Donc aller au delà me paraît difficile. Car ce n'est pas une tâche aisée, ni très passionnante. Il faut en effet du savoir faire du matériel et beaucoup de temps.

Après bien entendu, les constructeurs ont leur part à jouer, en s'impliquant d'avantage dans le noyau officiel (qui pourrait lui également avoir une politique plus adaptée à ces besoins, en ayant une API interne plus stable). Il faut également réduire la surface d'attaque au maximum, n'offrir l'accès au réseau que lorsque la plus valu est réelle. Ce genre de décisions aideraient à avoir une meilleure sécurité dans le temps de ces plateformes.

Un processeur qui perd le nord

Charles-Antoine Couret

Retour trois années en arrière quand je me penchais sur la gestion du stockage de masse d'un projet professionnel. C'est toujours avec le fameux processeur 8148 de Texas Instrument, le même projet que pour l'épisode 1.

Le stockage de masse est assuré par une mémoire flash NOR. En réalité l'implémentation n'était pas le principal problème, je vais raconter à nouveau un bogue assez délicat à identifier.

Mais d'abord, contexte !

Contexte

Choix de la mémoire

Donc sur ce projet, comme tout projet avec un système embarqué, se pose la question du stockage du système d'exploitation, des données et de comment charger le tout.

Il y a en général plusieurs possibilités pour un tel système : une mémoire NAND, NOR, une carte SD, une mémoire eMMC (une carte SD soudée), une clé USB voire via Internet. Bien entendu, chaque support a son lot d'avantages et inconvénients, voici pourquoi le NOR a été choisi :

  • Il est très fiable sur la durée (bien plus que les flashs NAND ou les mémoires SD/eMMC) ;
  • Sa lenteur n'était pas impactant pour notre système (c'est en effet de tous la méthode d'accès la plus lente) ;
  • Son espace de stockage (256 Mio) pour son prix était suffisant, sachant que la NOR est plus cher au Gio que les autres dispositifs ;
  • Il est possible d'exécuter le système en place (c'est le mécanisme XIP pour eXecute In Place) ce qui économise de la RAM et simplifie la conception.

Le dernier point est une propriété intéressante. En fait le processeur est capable d'adresser directement dans la mémoire NOR, les instructions machine du genre exécuter la fonction de cette adresse n'a pas besoin d'être chargé en RAM, le processeur peut accéder à cette adresse depuis la NOR et exécuter la dite fonction sans charger le code au préalable.

Préparation

Cependant, la dite technique XIP nécessite d'être précautionneux. Tout d'abord, le processeur au départ n'a pas accès à tout l'espace de stockage que propose notre mémoire.

Car dans le monde ARM (ce qui suit reste plus ou moins valable avec d'autres architectures, potentiellement avec d'autres noms), quand nous appuyons sur le bouton d'alimentation de la carte, l'alimentation démarre le processeur qui lance un petit chargeur de démarrage située dans sa ROM et qui a été conçu par le fabricant de la puce, ici Texas Instrument. Il va initialiser le minimum nécessaire dans le SoC et essayer de charger du code depuis un espace de stockage (notre mémoire NOR bien entendu ici, mais cela peut être par Ethernet, USB, mémoire NAND, carte SD ou autre). Dans notre cas, nous avons configuré (matériellement, en mettant des pins du processeur à 1 et d'autres à 0) de sorte que ce chargeur de démarrage cherche notre système sur la carte SD (car durant le développement, nous avons une carte SD), et si rien n'est trouvé, charger depuis la NOR.

Ce sont des mécanismes assez simples derrière. Pour le démarrage SD, le processeur détecte si une carte est présente, essaye de trouver un fichier nommé MLO dans un système de fichier FAT de la première partition pour le charger. Pour la NOR, il vérifie si les 4 premiers octets (situés à l'adresse 0x08000000) sont non nuls (donc différents de 0xFFFFFFFF ou 0x00000000). Si le chargement est effectué mais que cela n'aboutit sur rien, le processeur sera bloqué. Donc il faut veiller à charger quelque chose de correct.

Et pour charger le code initial (dans notre cas notre propre chargeur de démarrage U-boot, qui chargera Linux, qui chargera le reste des applications), le chargeur de démarrage de Texas Instrument n'a pas besoin de tout charger. Essentiellement car c'est plus simple, mais aussi parce que c'est plus générique, toute mémoire NOR pourra être chargée à priori quelque soit sa taille réelle.

Donc il ne charge que les 4 premiers kiloctets disponibles. Ces premières instructions de U-boot vont servir principalement à initialiser le nécessaire pour accéder au reste de la mémoire NOR, initialiser également la pile, la vitesse du processeur, etc.

C'est pour cela que nous avons le code suivant situé dans les 4 premiers kiloctets. Puis il y a une subtilité technique à prendre en compte. Nous allons changer les paramètres d'accès à la mémoire NOR. Cela se fait par l'écriture sur 7 registres différents dans le processeur. Non seulement nous allons dire au processeur d'activer des lignes d'adresses supplémentaires (permettant l'accès à toute la mémoire disponible), mais en plus nous allons modifier la vitesse d'accès pour améliorer les performances globales.

Les paramètres d'accès à la NOR sont situés dans les registres GPMC (adresses 0x51000060 à 0x51000078). Nous pouvons indiquer au processeur, pour chaque caractéristique du signal pour dialoguer avec la NOR, le nombre de cycles d'horloge nécessaires. Ces valeurs dépendent donc de la vitesse d'un cycle d'horloge et des caractéristiques de la mémoire NOR.

Attention, quand je parle de la vitesse d'un cycle d'horloge, ce n'est pas directement celui du processeur lui même. En général au sein d'un circuit, il y a une chaîne d'horloge qui se met en place pour alimenter chaque sous-système avec une vitesse qui lui convient. Ainsi le réseau, le multimédia, l'USB, le PCIe ou le processeur lui même ont des horloges propres. Ces horloges sont construits à partir de quartz qui générèrent un signal entre 15 et 25 MHz. Ensuite une PLL va amplifier ce signal pour moduler sa vitesse afin d'atteindre parfois plusieurs GHz. Dans notre cas, le quartz OSC0 (à 20 MHz) alimente la DPLL L3 (jusqu'à 220 MHz) qui alimente l'horloge GPMC qui divise par quatre le signal précédent (jusqu'à 55 MHz donc). Je ferais sans doute un article complet sur le sujet des horloges. :-)" class="smiley

Et comme nous allons changer la vitesse d'accès à la mémoire, alors que nous exécutons le code depuis la NOR elle même, vous pouvez deviner un problème. Entre le changement du premier et du dernier registre, les temps d'accès à la NOR ne seront plus cohérents, le système va se bloquer faute de pouvoir lire les instructions suivantes. Du coup il est nécessaire de copier le bout de code qui fait ce changement dans la SRAM (une petite zone de mémoire interne au processeur à l'adresse 0x40400000, qui n'est pas impactée par nos changements) afin de l'exécuter depuis celle-ci avant de revenir exécuter le code dans la NOR une fois l'opération faite.

Cela est fait via les lignes suivantes (l'essentiel du code employé provient du code de Texas Instrument qu'il a fallu adapter à notre cas) :

 /**************************************************************************
  * cpy_nor_gpmc_code: relocates nor gpmc init code into ocmc0 where its
  * safer to execute
  * R2 is loaded wtih size of data to be copied, this should be calculated
  * if we are modifying nor_gpmc_init()
  *************************************************************************/
 .global cpy_nor_gpmc_code
 cpy_nor_gpmc_code:
         stmfd sp!, {r0 - r10}
         /* Copy NOR GPMC init code into SRAM */
         adr r0, nor_gpmc_init     /* get addr of nor gpmc init code */
         mov r2, #640    /* r2 <- copy size(% by 32 bytes:r3-r10 (8) regs used) */
         ldr r1, sram_pc_start     /* r1 <- dest address (passed in) */
         add r2, r2, r0      /* r2 <- source end address */
 next2:
         ldmia   r0!, {r3 - r10}     /* copy from source address r0 */
         stmia   r1!, {r3 - r10}     /* copy to   target address r1 */
         cmp r0, r2          /* until source end address r2 */
         bne next2
         ldmfd sp!, {r0 - r10}
         mov pc, lr          /* back to caller */

Ce code fonctionne comme attendu, les premières cartes venant de la série A fonctionnent tous sans encombres.

Les problèmes arrivent

Quelques mois plus tard, un second jeu de cartes électroniques arrive avec une révision matérielle pour corriger les premiers défauts relevés. Et au bout de quelques heures, nous détectons un problème fondamental : sur certaines de ces cartes, le démarrage depuis la NOR ne fonctionne pas du tout, sur d'autres c'est aléatoire (de 1 fois sur 2 à 1 fois sur 100) et sur un exemplaire, aucun problème.

C'est pourtant, à ce stade, le même code qui est exécuté que sur les premières cartes qui ne bronchent toujours pas dans cet exercice. Notons également que sur ces nouvelles cartes, le démarrage depuis une carte SD ne pose aucun problème. D'ailleurs charger U-boot depuis la carte SD et le reste depuis la NOR ne présente aucun problème non plus.

La première piste est évidemment de vérifier tous mes calculs pour les registres d'accès à la NOR. Nous tombons tous d'accord sur le fait que ces valeurs sont correctes. Nous vérifions également l'ensemble des changements matériels autour du processeur et de la NOR et il n'y a rien. Tout au mieux, le responsable du routage de la carte (celui qui est responsable de transformer les liaisons logiques entre les composants en un circuit avec les pistes dessinées sur le plan final) note une différence de quelques micro/millimètres sur la longueur de ces fils entre les deux versions.

Mais rien de très intéressant, le module n'a pas beaucoup bougé sur ces fonctions et pourtant, le comportement est aléatoire. Nous prenons donc la JTAG pour en savoir plus afin de voir à quel endroit le démarrage échoue. Sur la plupart des modèles, cela tourne autour des registres du Watchdog. Mais si on supprime cette section du code, cela apparaît plus loin. Il semble donc que les échecs se produisent autour d'un certain nombre d'instructions constant depuis le démarrage plutôt que sur une instruction particulière. La JTAG nous montre que à l'instruction de trop, il va charger l'instruction suivante à une adresse délirante avant de retomber sur le vecteur d'exceptions du processeur pour avoir accédé dans une zone mémoire invalide.

Pour essayer d'identifier la cause de l'échec, le concepteur de la carte prend son oscilloscope à bras le corps et fait les mesures pendant que j'exécute le logiciel avec la JTAG pas à pas. Il semble que par moment le processeur fasse des signaux d'accès à la NOR d'environ 10 nanosecondes (oui, nanosecondes) trop courts. Pourtant les valeurs des registres que nous avons indiqué sont bons.

La solution

Une première solution est d'abaisser significativement les performances d'accès à la NOR et cela semble fonctionner. Mais si la NOR n'était pas un soucis niveau performances, nous avons une exigence contractuelle de démarrer l'ensemble du système en moins d'une minute. Et avec ces réglages, ce n'était plus possible. Puis nous ne comprenons toujours pas la cause du problème ce qui est gênant.

Il me faudra près d'une semaine de recherche dans la documentation de Texas Instrument pour comprendre la cause du problème et ainsi comment le résoudre. Je tombe en effet sur l'information suivante (page 1027 du document technique de référence) :

Horloge-boot-NOR.png

Or, si on prend le document de référence condensé page 183, on a :

Horloge-OPP.png

Vous ne voyez pas ? Il y a pourtant une incohérence pour une source d'horloge : la DPLL L3 qui est pour l'OPP 100 de 220 MHz et de l'autre de 200 MHz.

Or, tous mes calculs ont été conçus pour un signal d'entrée de 50 MHz et non de 55 MHz, ce qui donne un temps d'accès par cycle respectivement de 18 à 20 nanosecondes, soit bien sûr 2 nanosecondes d'écart. Quand on sait que la quasi-totalité de la configuration du signal d'accès tourne autour de 4 à 6 cycles par élément du signal, on retombe sur les 10 nanosecondes environ plus court constatés plus haut.

En quoi la documentation / implémentation de Texas Instrument est étrange ? En fait il faut expliquer brièvement ce qu'est un OPP. Un OPP pour OPerating Point est une méthode pour gérer l'énergie. Il consiste à fixer les fréquences maximales des différentes horloges du système par rapport à la tension d'alimentation du processeur. Plus le processeur consomme d'énergie (avec une tension élevée), plus les fréquences peuvent être élevées, mais plus la température peut monter également. En général on utilise le terme Dynamic Voltage Frequency Scaling pour décrire ce mécanisme.

Ce qui est curieux est que lors du démarrage NOR, par défaut, la ROM de Texas Instrument utilise l'OPP100 (celui de base) pour toutes les fréquences... sauf la L3 dont on se sert où c'est un OPP120 qui est employé. Cela n'est pas très cohérent comme choix et c'est ce qui nous a induit en erreur dans les calculs. Dans notre cas, pour éviter d'avoir besoin d'une ventilation active de la chaleur, nous souhaitons avoir une OPP100 durant le fonctionnement de l'appareil.

Pourquoi ce caractère aléatoire ?

Jusqu'ici j'ai expliqué le cadre général, l'origine du bogue a été trouvée, mais je n'ai pas expliqué pourquoi sur certaines cartes cela fonctionne, d'autres pas. Pourtant le code et le problème devrait se manifester partout.

Tout d'abord le démarrage SD fonctionne car dans U-boot, je changeais manuellement la fréquence des différentes horloges pour fixer le tout à l'OPP100 (et pour démarrer certaines horloges pour le processeur multimédia dont j'ai parlé dans le précédent article, chose qui n'est pas fait par le chargeur de démarrage de Texas Instrument). Du coup je supprimais le problème dans ce cas.

Le caractère aléatoire vient des différences minimes entre les différentes cartes. Comme je l'ai dit plus haut, les nouveaux modèles étaient plus sensibles à cause de la longueur des pistes qui avait changé, mais aussi parce que les composants ne sont pas identiques (numéros de série différentes, modèles différents pour les quartz, etc.). Étant donné la différence minime dans les temps d'accès, ces variations mineurs en temps normal peuvent avoir des impacts importants sur la longue.

D'autant que je changeais les fréquences d'horloge peu après la configuration du GPMC. Du coup, certains modèles avaient parfois la possibilité de régler le problème en abaissant la fréquence d'horloge finale en accédant à ces instructions à temps et sans encombre, d'autres pas.

Conclusion

Nous avons pu voir un problème qui survient parfois dans le domaine, des cartes qui se comportent différemment. Cela montre la nécessité de tester chaque modèle même si à priori c'est le même code, le même circuit. Chaque carte est unique. Il est nécessaire de documenter au maximum les petits changements qui peuvent être opérés. une collaboration forte entre l'équipe matérielle et logicielle est également fondamentale, il est probable que la cause n'aurait pas été retrouvée si vite sans cela. Chaque équipe ayant pu apporter des informations cruciales dans la résolution du problème.

Ensuite, bien entendu, la lecture de la documentation est importante, il faut tout vérifier, tout contrôler. Même ce qui paraît évident / logique. Il aurait été aussi appréciable que Texas Instrument choisisse une voie de moindre surprise en adoptant un choix cohérent dans les valeurs initiales de ses fréquences.

Et j'espère que vous aurez appris au sujet du démarrage sur les plateformes ARM et de la gestion des horloges. :)" class="smiley

Une erreur… bien cachée

Charles-Antoine Couret

J'avais dit que je parlerais un peu des systèmes embarqués et de mes aventures dans le milieu. Aujourd'hui je voudrais relater un problème que j'avais dû résoudre au travail et qui n'était pas évident. Le prochain article sera plus générique (et celui d'après à propos d'un autre problème au boulot). Je vais essayer de varier un peu. ;-)" class="smiley

Ce sera sûrement un peu long, et je vais donner mon cheminement intellectuel autour de ce problème. Je respecte la chronologie des éléments dont j'avais connaissance à chaque étape.

Présentation du matériel et contexte

Pour situer un peu, je travaillais sur une plateforme Texas Instrument 8148 qui est un processeur ARM Cortex-A8 couplé avec un processeur M3 et des accélérateurs vidéos / DSP en son sein. Cette plateforme exploitait un noyau Linux 2.6.37 patchée à mort par Texas Instrument pour son processeur.

Le but du jour était d'exploiter le composant TVP5158 de… Texas Instrument encore (ce module a été conçu pour ce processeur en même temps). Pour décrire rapidement, ce composant permet de fusionner jusqu'à 4 flux vidéo analogiques (PAL / NTSC principalement) dans un seul numérisé que le processeur peut exploiter.

En soit le composant avait déjà un pilote fonctionnel pour Linux. Mais cela ne nous convenait pas. En effet, nous utilisons le TVP dans une chaîne de traitement vidéo où on faisait des décodages, redimensionnements, des remplacements d'images ou encore des encodages. Pour faire cela, non seulement il faut de la performance mais il faut aussi utiliser une API plutôt unifiée.

La performance est offerte par les accélérateurs vidéos qui sont dans les co-processeurs du système. On peut les exploiter via un firmware (dont le code source est confidentiel, désolé) et on peut communiquer avec ces accélérateurs via le noyau Linux et l'API OpenMax (OMX). Cette API est standard, éditée par le même groupe et dans les mêmes conditions qu'OpenGL, mais plutôt que de s'occuper de la 3D, il s'occupe des codecs vidéos. C'est souvent la référence libre dans ce domaine, avec GStreamer couplé avec libav.

Cette API est disponible dans le firmware de TI, cela tombe bien. Mais là où cela ce corse c'est pour récupérer des informations. En effet, il faut que durant notre traitement vidéo que nous sachions la résolution détectée par TVP du flux vidéo, et s'il existe (sur les 4 flux, des caméras peuvent être en pannes ou absentes pour diverses raisons).

Et TVP se configure via un bus assez standard et typique I2C qui est assez simple à mettre en place et largement suffisant pour lire / écrire des registres sur un composant. Il est par exemple souvent utilisé dans les cartes mères / graphiques de nos ordinateurs pour les capteurs de températures. Le soucis est que ce bus ne peut être géré par le firmware de TI (pour configurer le flux) et par le noyau Linux (pour récupérer les infos sur le flux pour l'application). Si on fait cela, il y aura conflit et le bus sera inutilisable. Modifier le firmware pour renvoyer les informations à l'espace utilisateur ou que le noyau gère la configuration du flux vidéo est plutôt complexe. Le mieux est d'utiliser un canal de communication existant entre le noyau et le firmware pour faire ceci, le firmware a donc la main sur le bus I2C et le noyau fera ses requêtes a travers lui.

On code

Partie intéressant du travail, coder. Et réfléchir à comment faire aller / revenir les informations voulues. Le noyau et le firmware, comme dans la quasi-totalité des systèmes à processeurs asymétriques, communiquent entre eux par mémoire partagée. Une partie de la RAM est allouée pour les messages, une autre pour les buffers vidéos, etc. Ceci est configurable (avec des limites) dans le code des deux côtés. Bien évidemment, les deux doivent être d'accord sur les adresses de base de chaque fonction, sinon ils ne retrouveront plus leurs petits. Cela est plutôt bien pris en charge par l'environnement de compilation fourni par TI. Vous pouvez consulter l'adressage mémoire entre les deux ici.

Dm8148-ezsdk-sw-arch.png

Bon, et le code alors ? La communication entre ces deux modules se faisant par mémoire partagée, il y a un certain protocole qui a été conçu par TI et qui s'exploite à travers une API maison nommée FVID2. Elle est déjà partiellement implémentée mais pas celle concernant le fameux TVP (qui est pourtant décrite dans l'API en question). J'ai donc écrit un pilote Linux pour combler cela. Aspect amusant, TI à la pointe de la technologie fournissait la doc de cette API dans un document .chm, un vieux format propriétaire dont le seul lecteur sous Linux potable est une application de l'ère de KDE3 : Kchmviewer. Quand je vous dis que l'embarqué c'est moderne !

Mais cela reste un peu moche, l'application en espace utilisateur demande au firmware HDVPSS de configurer le TVP. Mais, pour faire cela, il instancie le pilote interne de TVP du firmware qui ne doit pas être instancié deux fois et dont on ne peut récupérer la référence pour notre API FVID2… J'utilise donc une référence d'un autre composant dont le noyau a la référence (car il l'instancie) et j'envoie mes messages avec, le firmware a été modifié pour comprendre la situation et rediriger le message ensuite à bon port. Je n'avais pas trouvé mieux dans le délai imparti.

Et le bogue arrive… parfois

Et après le code, on teste. Après plusieurs essais difficiles, cela fini par passer. Youhou. Champomy dans les bureaux.

Mais, quand mes collègues vont tester leur application avec mon travail, cela ne fonctionne pas toujours. Le module noyau qui fait les échanges avec le coprocesseur nous signifie que certaines requêtes, en quantité variables, mettent trop de temps à revenir. On était à une moyenne de 1 à 10 échecs par minute (pour 24 requêtes). Mais il arrivait malgré tout que sur 30 minutes / 1 heure cela n'arrive pas, avant de revenir. C'est beaucoup trop problématique, et ce qui est étonnant c'est que mes tests ne présentaient aucune erreur.

Du coup, comme pour toute chaine de communication, on va déboguer étape par étape pour identifier où cela coince. Je précise que la seule section dont je pouvais difficilement déboguer c'est l'échange des messages entre Linux et le firmware qui est assez mal documenté et le code assez obscur en plus d'être gros.

Matériel

Le plus simple à tester, c'est le matériel (recompiler le firmware vidéo pour y ajouter du débogue c'est 40 minutes de compilation, c'est pénible et long, on évite au maximum de le faire). Je vérifie donc que le TVP reçoit les bonnes requêtes et y répond. Le bus I2C étant très simple, un petit oscilloscope sur un fil et on peut rapidement conclure que les signaux sont bons dans les deux sens que la requête échoue ou non à la fin.

Mais je me dis que le temps d'attente côté Linux pour recevoir ce message est trop court, je l'allonge volontairement à un délai absurde comme 30 secondes, cela ne change rien. Soit ça réussi vite, soit au bout des 30 secondes j'ai l'erreur. Pas d'entre deux, pas de hausse ou baisse de ces erreurs.

Du coup on sait que la chaîne d'envoi est bonne, et le matériel aussi, le soucis se situe bien au retour.

Firmware vidéo

Donc forcément je remonte un peu la chaîne côté firmware vidéo et à chaque étape en son sein, l'information est correcte à tous les coups. Comme le soucis n'est pas côté Linux après l'API FVID2, le soucis se situe forcément dans le transfert des messages entre les deux mondes comme on dit. Côté retour uniquement.

Plongeons au cœur de la mémoire

À ce stade là, cela devient assez étrange. Comment cela peut planter de cette manière là ? Jémets quelques hypothèses, manque de place pour l'échange de messages (il y a d'autres messages que ceux du TVP là dedans) ou éventuellement un conflit de lecture / écriture simultanée par les deux sur un même message.

Pendant que je cherchais comment l'ensemble fonctionnait, des collègues m'ont rapporté des informations pertinentes (bah oui, ils continuent de testeur leur travail de leur côté et disent ce qui est pertinent quand ils constatent le problème). Il y a une corrélation entre le nombre de caméras branchées au TVP (et exploitées par notre programme) et la fréquence du bogue. Plus il y a avait de caméras, moins cela plantait. Cela paraît contre intuitif.

J'ai maintenant une idée plus claire de ce qui semble être le cas, mais je dois vérifier. J'essaye de voir donc comment l'échange de message fonctionne, et la fonction que j'appelle a quelques lignes intrigantes dont je copie la boucle intéressante :

while (fctrl->fctrlprms->returnvalue == VPS_FVID2_M3_INIT_VALUE) {
       usleep_range(100, 300);
       if (vps_timeout) {
              do_gettimeofday(&etime);
              td = time_diff(stime, etime);
              if (vps_timeout < td) {
                    VPSSERR("contrl event 0x%x timeout\n",  cmd);
                     return -ETIMEDOUT;
               }
        }
}

En gros, Linux initialise une valeur précise à une adresse précise dans la RAM. Quand le firmware a fini son boulot et renvoie les infos demandés, il signifie au noyau qu'il a fini en changeant la valeur initialisée précédemment. Le noyau regarde sa valeur régulièrement par tranches de 100 à 300 microsecondes pendant 2 secondes maximum.

Et comme par hasard, si je mets dans la boucle un printk de débogue (l'équivalent de printf pour le noyau, pour afficher des chaînes de caractères visibles en espace utilisateur, cette fonction est plutôt grosse), le bogue disparaît. Quelques soient les conditions.

Cela me renforce dans mon hypothèse : nous sommes face à un soucis d'accès à la valeur de cette variable. Le noyau Linux relit la variable depuis le cache ou le registre du processeur qui bien sûr ne change pas (car le processeur n'a pas changé cette valeur, c'est au coprocesseur de le faire !), du coup il voit éternellement la variable comme au départ et il croit que le firmware vidéo ne fout rien. Le printk ou l'activité du système (plus il y a de caméras, moins cela arrive, n'oublions pas) permettant à Linux de bien voir la véritable valeur en la rechargeant depuis la RAM.

Le problème vient du fait que ce genre de vérification ne doit pas se faire directement, surtout que la zone mémoire concernée a été allouée avec "ioremap()".

Il suffit donc de remplacer la ligne

 while (fctrl->fctrlprms->returnvalue == VPS_FVID2_M3_INIT_VALUE) {

Par

 while (ioread32(&fctrl->fctrlprms->returnvalue) == VPS_FVID2_M3_INIT_VALUE) {

Les accès par "ioread*()" mettent des barrières mémoires et indiquent que la variable peut être modifiée de l'extérieur. Obligeant donc une nouvelle lecture de la valeur en toute circonstance.

Conclusion

Je suis tombé sur ce bogue après quelques mois dans la vie active seulement. C'était un défi intéressant, je n'avais pas trouvé cela évident. C'est vraiment le genre de choses que l'on a tendance à oublier, on accorde trop de confiances aux couches d'en dessous (matériel / noyau / compilateur / bibliothèque / langage) qu'on en oublie qu'ils peuvent présenter des problèmes et qu'on doit faire attention en les utilisant.

Après, cela met en évidence un énième bogue / oubli stupide de la part de Texas Instrument (ils en font du code horrible, je vous le dis) qui aurait pu être évité s'ils travaillaient un peu plus avec le noyau officiel. Nul doute qu'avec plus de relecteurs de leur code, quelqu'un l'aurait vu. Mais bon, tant pis, je me suis bien amusé. :-)" class="smiley

Les systèmes embarqués

Charles-Antoine Couret

Cela faisait un moment que je réfléchissais à parler des systèmes embarqués, en particulier autour de Linux. Cela fait quelques temps que je suis dedans, et les ressources francophones étant plutôt rares dans le secteur, j'aimerais partager mon expérience, mes pensées, mes trucs et astuces potentiels.

Bien sûr cela ne remet nullement en cause la communication de l'actualité autour de Fedora. :-)" class="smiley

Pour commencer cette catégorie, je pense qu'il est bon de définir ce que j'entends ici par systèmes embarqués afin que ce soit clair et raconter un peu ma vie sur pourquoi je travaille dedans.

Mon parcours

Mon intérêt pour les systèmes embarqués vient de loin, mais reste flou. Globalement j'ai toujours apprécié manipuler un produit, un objet. Cela s'est confirmé durant mon cursus dans le supérieur, je n'éprouve pas une grande satisfaction à faire tourner mon bout de programme sur un serveur dont j'ignore même sa localisation. Ce besoin de concret est très important pour moi. J'ai toujours été très excité de lancer le résultat de mon travail préliminaire sur une nouvelle carte électronique qui vient de débarquer. Et constater que cela ne fonctionne pas du premier coup bien entendu.

Ensuite, il y a également l'intérêt d'apprendre le fonctionnement de nos ordinateurs. J'ai toujours été fasciné par le fonctionnement des processeurs, de la RAM ou des systèmes d'exploitation. Sans doute l'émerveillement devant leur complexité et l'ingéniosité de leur conception (si on met sous le tapis les horreurs également présentes). Dans ce domaine, il faut connaître les caractéristiques du circuit, du processeur, lire la documentation associée, comprendre l'état de la mémoire, comment l'OS va gérer les entrées/sorties et les processus pour donner accès à la fonction voulue. Impossible de se reposer sur une machine virtuelle ou un interpréteur qui nous cache ces détails (ce qu'ils font à raison, mais cela ne m'intéresse pas).

Enfin, je trouve que c'est un domaine omniprésent. Cela permet de côtoyer de nombreux secteurs d'activités différents comme: télécommunication, aéronautique ou spatial, automobile, agriculture, sécurité bancaire, multimédia, l'électronique, etc. Et comme le produit doit répondre aux contraintes de chaque secteur, il faut étudier, comprendre et analyser les caractéristiques du secteur considéré. Cela permet de varier l'environnement d'étude et donc les choses à en apprendre. Or j'adore apprendre.

Qu'est-ce qu'un système embarqué ?

Cela peut paraître absurde, mais il y a probablement autant de définitions que d'acteurs dans le domaine. D'autant plus qu'avec le temps et l'évolution technique, la définition de ce qui entre ou pas dans ce cadre peut varier. Typiquement, un téléphone aujourd'hui est radicalement différent par rapport aux débuts des années 2000. Pour certains un smartphone n'en est plus un, pour d'autres, cela continue.

Du coup on va dégager les tendances ou les points communs pour le définir. Globalement nous pouvons résumer cela en tout système programmé qui n'est pas d'architecture x86 ou qui présente une contrainte spécifique.

La puissance disponible

La première chose qui vient à l'esprit, ce sont les performances matérielles. Un processeur pas très puissant, voire ancien, peu de RAM ou de stockage et une connectique souvent un peu spéciale pour en tirer parti. Grâce aux progrès de la miniaturisation et de l'économie d'énergie, c'est de moins en moins vrai. Des processeurs tels que les nVidia Tegra TK1/TX1 ne consomment pas grand chose. Pour moins d'une dizaine de watts, et une surface raisonnable, nous avons un couple GPU/CPU pouvant atteindre le TFLOPS en puissance de calcul brut. Qu'on peut facilement épauler de quelques Gio de RAM et de mémoire de stockage.

À titre de comparaison, 1 TFLOPS (en admettant cette unité de mesure comme pertinente, ce qui est discutable) c'est l'ordinateur le plus puissant du monde déclaré (donc pas militaire ou top secret) en 1997. 20 ans après un téléphone ou une voiture en ont un voire plusieurs sur quelques millimètres carré. Nous sommes très loin d'un simple microcontrôleur ou d'un processeur peinant à gérer plusieurs processus à la fois. Cela est également proche de ce qu'on peut retrouver dans un ordinateur personnel normal.

Donc si la puissance disponible est un critère souvent retenu, programmer un microcontrôleur est de fait un système embarqué, il est possible aujourd'hui de faire des systèmes embarqués avec une puissance de calcul très élevée.

Les contraintes d'un système peu puissant c'est qu'il demandera sans doute une économie des ressources, la renonciation à certaines technologies et à certaines fonctionnalités. Ce n'est pas pour rien que le C et le C++ règnent encore en maître dans le domaine, même si Python ou Java prennent de plus en plus de place, grâce justement à l'amélioration des performances.

L'énergie

Pour enchaîner avec le point précédent, nous pouvons relever la consommation énergétique. Tous les systèmes embarqués n'ont pas cette contrainte, mais cela reste assez commun. En effet, un système sur batterie devra faire attention à la consommation énergétique pour limiter l'apport d'énergie (en fréquence comme en puissance) par exemple pour augmenter son autonomie.

Le lien avec la puissance est évidente, malgré les progrès, plus de puissance de calcul demandera plus de ressources électriques. C'est ce qui a limité pendant longtemps la possibilité de faire des systèmes embarqués avec des performances élevées. La mise à disposition de processeurs modernes avec une consommation faible permet le contournement de ce problème mais pas complètement. Cela se vérifie avec l'Internet des Objets qui remet au centre du secteur des processeurs très minimalistes et très peu gourmands pour exécuter uniquement la fonction demandée.

L'énergie va avoir plusieurs contraintes sur le système. Il peut en effet limiter la puissance disponible. Il peut aussi être une contrainte car l'énergie fournie est non fiable. Nous pouvons penser à des systèmes en aéronautique ou aérospatiale dont certains composants ont une puissance électrique allouée maximale et que dans certains cas l'engin peut couper l'alimentation de composants secondaire (par exemple le multimédia à bord des avions).

Il faut donc tenir compte de cela, par exemple certaines communications peuvent être coupées brutalement, le système aussi. Cela a un impact fort sur le design électronique et logiciel. Il faut réfléchir à comment gérer le cas d'une coupure de courant lors d'une mise à jour du système (dans quel état le système va être retrouvé ?). Les fonctions qui doivent être maintenues en vie et d'autres pas. Si ces questions existent pour l'ordinateur personnel, cela reste moins problématique et beaucoup plus rare que dans le cas des systèmes embarqués. On peut en effet présumer que dans les pays développés le réseau électrique est plutôt fiable (ce qui n'est pas sans poser de soucis pour ceux ne vivant pas dans de tels pays mais passons).

L'autonomie

Ici je ne parlerai pas d'autonomie électrique, bien que ce soit liée, mais plutôt d'autonomie en terme d'isolement du système. Un système où l'accès au réseau n'existe pas forcément, où il n'y a pas un technicien disponible pour le réparer en cas de besoin rapidement.

Cela a un impact bien entendu très fort sur le système. Cela signifie que le système doit être robuste aux pannes ou bogues divers. Certains processus devront être très fiables, comme la mise à jour. Si on envoie un nouveau logiciel à un satellite dans l'espace et que cela échoue, le satellite doit rester opérationnel dans tous les cas. On ne va pas envoyer une fusée pour réparer ce genre de choses.

En terme d'architecture du système, il va falloir penser à beaucoup de choses pour minimiser l'intervention humaine. Il faut forcément automatiser le lancement pour que l'application métier soit lancée toute seule. Mais aussi programmer des tâches récurrentes, prévoir des solutions en cas de coupure du réseau ou de l'électricité.

Par exemple, pour que le système soit auto-entretenu dans un tel contexte, il est courant de recourir à un système sans état. Ce type de système fait qu'en cas de redémarrage, la fonction recommence comme si de rien n'était, le système pouvant être en lecture seule. On couple cela avec un watchdog pour que le système redémarre matériellement tout seul si jamais l'application ou le noyau ont planté.

Les entrées/sorties limitées ou spéciales

De part les contraintes énoncées plus haut, il en ressort qu'on n'interagit pas avec un système embarqué comme avec son ordinateur personnel. Il n'y a pas forcément d'écran, encore moins souvent de clavier complet ou de souris. Si écran il y a, c'est souvent du mono applicatif donc sans bureau. Le système doit être minimal, pour économiser en coût de composants, en risque de problèmes matériels ou logiciels et simple d'utilisation pour un utilisateur non formé. En effet il serait malvenue que le distributeur de billet de votre quartier soit complexe à prendre en main ou qu'il tombe en panne régulièrement.

Cela va induire par effet de bords des choix en terme d'interface utilisateur pour présenter le moins de choix possibles d'un coup, en restant clair et complet. Et que tout ceci soit sélectionnable sans difficulté ou ambiguïté pour tous les utilisateurs (comme les personnes âgées ou les handicapées). Ceci explique souvent les interfaces un peu vieillottes avec de gros boutons que ce soit bien visible et clair. Les interfaces riches peuvent être sources de confusion dans ce genre de situations en plus de demander plus de ressources matérielles et de temps de développement.

En terme d'entrées/sorties spécifiques, nous avons ceux du développement et en environnement de production. Pour le développement, comme nous utilisons notre ordinateur, nous devons communiquer avec la bête. Très souvent cela se fait par le réseau (par SSH et NFS), par port série voire USB pour l'accès à la console (quand le SSH n'est pas possible) et JTAG pour déboguer en stoppant le processeur par exemple pour analyser la situation à n'importe quel moment. Parfois pour flasher la JTAG sert encore mais cela est de moins en moins le cas. Il faut souvent jongler avec tout ceci ce qui encombre pas mal le poste de travail.

Les normes et l'environnement

Encore un sujet assez vaste et pourtant au combien important. Les systèmes embarqués sont très souvent employés dans des secteurs industriels où les normes sont omniprésentes pour des raisons de sécurité, de compatibilité, de respect de l'environnement, etc. Et cela n'est pas sans incidence sur le développement.

Des secteurs sont par exemple très très réglementés comme l'aéronautique, le médical, le spatial, l'automobile ou le ferroviaire. Ce sont des secteurs où des défauts peuvent engendrés la perte de vies humaines ou avoir des coûts matériels très important en cas de défaut. Il est impératif de respecter des normes afin de limiter au maximum les risques.

Je vais parler de l'aéronautique, secteur que j'ai pu côtoyer durant deux ans. Tout logiciel (et matériel) embarquant dans un avion doit être certifié conformément aux directives des agences continentales et internationales. Pour être certifié, l'écriture du logiciel doit suivre une procédure précise qui dépend bien sûr de la criticité du système.

En effet, tout système se voit attribué un DAL qui est un niveau d'exigence noté de A à F, plus la note est élevée, plus l'exigence et les limitations seront fortes. Dans tous les cas il faudra documenter le design, rédiger des cahiers de tests et communiquer les résultats. Il faut également facilement faire le lien entre le code / commit et un test ou une exigence du design.

Et là où cela se corse, c'est par exemple des logiciels pour les DAL A ou B, il faut impérativement que tout soit contrôlé. Tout le chemin d'exécution du code, de même que le déterminisme du processeur en dessous. C'est pourquoi il est fréquent d'utiliser des code très léger sur microcontrôleur dans ce cas, on ne peut se fier à la complexité d'un noyau Linux complet sur un processeur x86. La communication avec les autres composants doit être réduite au strict nécessaire, la consommation électrique est plafonnée. Il y a aussi des interdictions plus concrètes comme le respect d'un code couleur pour les interfaces (le rouge est par exemple réservé aux erreurs sévères et strictement définies).

Concernant les normes, il y a aussi les standards comme le bus CAN pour l'automobile ou l'A429 pour laéronautique qui sont incontournables pour interagir avec le reste de l'appareil sans réinventer la roue systématiquement. D'ailleurs l'analyse de ces normes mettent en évidence les contraintes de l'environnement pour expliquer ces choix de design et le maintient de ces normes anciennes sur des systèmes modernes. Cela fera l'objet d'un autre article.

En somme, il faut respecter les contraintes du secteur d'activités qui peuvent être importantes car il y a de fortes responsabilités derrière. Et cela influe forcément le design de l'application et du matériel et de fait du produit qui sera réalisé.

Conclusion

C'est un article un peu long qui se veut être une introduction générale. Par la suite je compte présenter quelques petites choses :

  • Étude d'une norme comme le bus CAN ou A429, qui sont assez simples, et comprendre leur intérêt dans les systèmes actuels et les raisons d'une telle conception ;
  • Présenter des projets liés aux systèmes embarqués comme Yocto, buildroot, U-boot ou le noyau Linux et expliquer le boulot d'un développeur sur ces projets ;
  • Expliquer certaines pratiques industrielles ou technologies dans le secteur, pour comprendre certaines décisions qui peuvent paraître aberrantes mais qui finalement le sont moins. Typiquement pourquoi il est rare qu'Android soit mis à jour décemment sur la plupart des modèles vendus ? Pourquoi il est difficile de faire un OS compatible avec tous les systèmes ARM ?
  • Présenter certains bogues ou designs que j'ai rencontré dans le cadre de mon travail.

Cela s'étendra dans le temps, je ne compte pas tout rédiger maintenant. Les humeurs, les envies, les idées, tout ça.

N'hésitez pas si vous avez des suggestions, des corrections, des questions ou de signifier si cela vous plaît / déplaît. Merci.

Bug OpenSSL - CVE-2014-0160

Alexandre Frandemiche

Heartbleed Bug

Je pense que beaucoup d'entre vous ont vu passer l'info, je me contenterai donc de donner quelques liens permettant de sécuriser son routeur sous OpenWRT et son NAS ReadyNAS !

Bug OpenSSL en question : https://heartbleed.com/

Pour tester son site/url : http://filippo.io/Heartbleed/

Mise à Jour OpenWRT

Rendez-vous dans l'interface d'administration luci dans System -> Software et filtrer sur openssl, on constate la version incriminée, passer sur l'onglet "Available packages (openssl) et installer les 2 mises à jour de openssl-util et libopenssl et le tour est joué !

openwrt-opensslMise à Jour ReadyNAS OS 6

Le plus simple est de se rendre sur ce post et de suivre les instructions : http://www.readynas.com/forum/viewtopic.php?f=65&t=75947&start=15#p423049
En gros, cela revient à éxécuter en root les commandes suivantes : 

Pour vérifier la version actuelle :

dpkg -l | grep openssl

Mettre à jour openssl :
wget http://security.debian.org/debian-security/pool/updates/main/o/openssl/openssl_1.0.1e-2+deb7u5_amd64.deb
dpkg -i openssl_1.0.1e-2+deb7u5_amd64.deb
service apache2 restart
service ssh restart

Vérifier la version à nouveau :

dpkg -l | grep openssl

Ensuite, vous pouvez vous rendre sur l'interface d'administration de votre NAS, dans System -> Settings -> Services, cliquer sur HTTPS , changer le nom et regénérer le certificat !

Par la suite, vous pouvez aussi surpprimer vos clé SSH présent sur votre serveur :

rm /etc/ssh/ssh_host_*.pub
rm /etc/ssh/ssh_host_*
rm /root/.ssh/id_rsa.pub
rm /root/.ssh/id_rsa

Voilà ! Vous êtes tranquille ! ;)" class="smiley ... jusqu'à la prochaine faille :D!

Quand mon utilisateur n'a pas de droits sur un disque USB formaté en extend 2/3/4

Alexandre Frandemiche

Ceci est plus uns note qu'un article mais bon ... ça peut servir à plus d'un !

J'ai eu besoin de monter un disque dur externe formaté en ext2/3/4 avec les droits pour mon utilisateur sous Fedora, voici la procédure à suivre :

  • connecter son disque dur USB
  • ouvrir un terminal et passer en root (ou sudo) :
  • # su -
  • # setfacl -m d:u::rwx,d:g::rwx,d:m:rwx,d:o:rwx /run/media/utilisateur/uuid
  • # setfacl -m u::rwx,g::rwx,m:rwx,o:rwx /run/media/utilisateur/uuid
Et voilà, votre utilisateur à tous les droits sur le disque USB formaté en ext2/3/4 !

Quand l'espace de stockage interne de son périphérique mobile sous CyanogenMod n'est pas suffisant

Alexandre Frandemiche

Ceci est juste une note qui peut en intéresser quelques-uns. J'ai eu sur le Galaxy S2 (i9100P) de ma femme et sur le mien (i9000) qui sont sous CyanogenMod 10.1, des problèmes d'espace de stockage interne, sans pour autant avoir sur mes 2 Go la totalité prise par les applications ou leur données.

En utilisant une application telle que DiskUsage (https://play.google.com/store/apps/details?id=com.google.android.diskusage&hl=fr) on se rend compte qu'effectivement il n'y a plus de place, mais ce qu'il y a d'étonnant c'est que j'avais 2 Go de rempli en ayant que 400 Mo en tout d'utiliser d'après les indications de stockage fournies par CyanogenMod.

Ce qu'il faut savoir c'est qu'en fin de compte dans le répertoire qui contient les applications : /data/ , il y a un répertoire log qui empiète sur cet espace interne et peut, s'il se remplit aboutir au problème précédemment cité.

L'astuce consiste donc à vider le contenu de ce répertoire /data/log/ soit en ligne de commande via le terminal

# rm -Rf /data/log/*

Soit via une selection de ces mêmes fichiers par ES Explorer en mode root, puis les supprimer !

Il paraitrait que la non purge de ces logs via CyanogenMod soit un bug. En attendant, ça permet de garder son appareil fonctionnel, car avec ce soucis, les appareils n'étaient pas très stable.

Installation d'une sonde Nagios pour ESXi

Alexandre Frandemiche

Contexte

Pour des besoins concernant lhébergement que propose ma société, j'ai été amené à gérer un serveur ESXi, du coup, il n'y a pas de raison de ne pas le surveiller, je dirai même que c'est encore plus nécessaire ! On a vite tendance à tomber dans les pièges de la virtualisation qui consistent à charger le serveur avec beaucoup VM s'imaginant que celui-ci augmente ces performances au fur et à mesure de la charge ... :D

Prérequis

Installation des paquets nécessaires

# yum install openssl-devel binutils perl perl-Nagios-Plugin perl-Class-MethodMaker mod_perl libuuid uuid-perl perl-XML-LibXML perl-XML-LibXML-Common

Installation du vSphere SDK Perl

Vous téléchargez le tar.gz : VMware-vSphere-Perl-SDK-5.1.0-780721.x86_64.tar.gz

$ tar xvfz VMware-vSphere-Perl-SDK-5.1.0-780721.x86_64.tar.gz

$ cd vmware-vsphere-cli-distrib

Il y a 2 variables à changer afin de permettre sans encombre l'installation du SDK :

my $httpproxy =0;
my $ftpproxy =0;
par :
my $httpproxy =1;
my $ftpproxy =1;

# ./vmware-install.pl

Problème UUID

Si vous avez encore un soucis d'une dépendance non résolue avec UUID, alors effectuez ceci :

# yum install gcc

$ wget http://search.cpan.org/CPAN/authors/id/C/CF/CFABER/UUID-0.03.tar.gz

$ tar xvfz UUID-0.03.tar.gz

$ cd UUID-0.03

# perl Makefile.PL

# make

# make install

Puis relancez ./vmware-install.pl

Installation du plugin Nagios

Télécharger le plugin ici :http://www.op5.org/community/plugin-inventory/op5-projects/check-esx-plugin

$ cd /usr/local/nagios/libexec/

$ wget http://git.op5.org/git/?p=nagios/op5plugins.git;a=blob_plain;f=check_vmware_api.pl;hb=HEAD

# chown nagios:nagios check_vmware_api.pl

# chmod 755 check_vmware_api.pl

Lançons la commande une première fois et nous obtenons ceci :

$ ./check_vmware_api.pl --help

check_vmware_api.pl 0.7.0

This nagios plugin is free software, and comes with ABSOLUTELY NO WARRANTY.
It may be used, redistributed and/or modified under the terms of the GNU
General Public Licence (see http://www.fsf.org/licensing/licenses/gpl.txt).

VMWare Infrastructure plugin

Usage: check_vmware_api.pl -D <data_center> | -H <host_name> [ -C <cluster_name> ] [ -N <vm_name> ]
    -u <user> -p <pass> | -f <authfile>
    -l <command> [ -s <subcommand> ] [ -T <timeshift> ] [ -i <interval> ]
    [ -x <black_list> ] [ -o <additional_options> ]
    [ -t <timeout> ] [ -w <warn_range> ] [ -c <crit_range> ]
    [ -V ] [ -h ]

 -?, --usage
   Print usage information
 -h, --help
   Print detailed help screen
 -V, --version
   Print version information
 --extra-opts=[section][@file]
   Read options from an ini file. See http://nagiosplugins.org/extra-opts
   for usage and examples.
 -H, --host=<hostname>
   ESX or ESXi hostname.
 -C, --cluster=<clustername>
   ESX or ESXi clustername.
 -D, --datacenter=<DCname>
   Datacenter hostname.
 -N, --name=<vmname>
   Virtual machine name.
 -u, --username=<username>
   Username to connect with.
 -p, --password=<password>
   Password to use with the username.
 -f, --authfile=<path>
   Authentication file with login and password. File syntax :
   username=<login>
   password=<password>
 -w, --warning=THRESHOLD
   Warning threshold. See
   http://nagiosplug.sourceforge.net/developer-guidelines.html#THRESHOLDFORMAT
   for the threshold format.
 -c, --critical=THRESHOLD
   Critical threshold. See
   http://nagiosplug.sourceforge.net/developer-guidelines.html#THRESHOLDFORMAT
   for the threshold format.
 -l, --command=COMMAND
   Specify command type (CPU, MEM, NET, IO, VMFS, RUNTIME, ...)
 -s, --subcommand=SUBCOMMAND
   Specify subcommand
 -S, --sessionfile=SESSIONFILE
   Specify a filename to store sessions for faster authentication
 -x, --exclude=<black_list>
   Specify black list
 -o, --options=<additional_options>
   Specify additional command options (quickstats, ...)
 -T, --timestamp=<timeshift>
   Timeshift in seconds that could fix issues with "Unknown error". Use values like 5, 10, 20, etc
 -i, --interval=<sampling period>
   Sampling Period in seconds. Basic historic intervals: 300, 1800, 7200 or 86400. See config for any changes.
   Supports literval values to autonegotiate interval value: r - realtime interval, h<number> - historical interval specified by position.
   Default value is 20 (realtime). Since cluster does not have realtime stats interval other than 20(default realtime) is mandatory.
 -M, --maxsamples=<max sample count>
   Maximum number of samples to retrieve. Max sample number is ignored for historic intervals.
   Default value is 1 (latest available sample).
 --trace=<level>
   Set verbosity level of vSphere API request/respond trace
 -t, --timeout=INTEGER
   Seconds before plugin times out (default: 30)
 -v, --verbose
   Show details for command-line debugging (can repeat up to 3 times)
Supported commands(^ - blank or not specified parameter, o - options, T - timeshift value, b - blacklist) :
    VM specific :
        * cpu - shows cpu info
            + usage - CPU usage in percentage
            + usagemhz - CPU usage in MHz
            + wait - CPU wait time in ms
            + ready - CPU ready time in ms
            ^ all cpu info(no thresholds)
        * mem - shows mem info
            + usage - mem usage in percentage
            + usagemb - mem usage in MB
            + swap - swap mem usage in MB
            + swapin - swapin mem usage in MB
            + swapout - swapout mem usage in MB
            + overhead - additional mem used by VM Server in MB
            + overall - overall mem used by VM Server in MB
            + active - active mem usage in MB
            + memctl - mem used by VM memory control driver(vmmemctl) that controls ballooning
            ^ all mem info(except overall and no thresholds)
        * net - shows net info
            + usage - overall network usage in KBps(Kilobytes per Second)
            + receive - receive in KBps(Kilobytes per Second)
            + send - send in KBps(Kilobytes per Second)
            ^ all net info(except usage and no thresholds)
        * io - shows disk I/O info
            + usage - overall disk usage in MB/s
            + read - read latency in ms (totalReadLatency.average)
            + write - write latency in ms (totalWriteLatency.average)
            ^ all disk io info(no thresholds)
        * runtime - shows runtime info
            + con - connection state
            + cpu - allocated CPU in MHz
            + mem - allocated mem in MB
            + state - virtual machine state (UP, DOWN, SUSPENDED)
            + status - overall object status (gray/green/red/yellow)
            + consoleconnections - console connections to VM
            + guest - guest OS status, needs VMware Tools
            + tools - VMWare Tools status
            + issues - all issues for the host
            ^ all runtime info(except con and no thresholds)
    Host specific :
        * cpu - shows cpu info
            + usage - CPU usage in percentage
                o quickstats - switch for query either PerfCounter values or Runtime info
            + usagemhz - CPU usage in MHz
                o quickstats - switch for query either PerfCounter values or Runtime info
            ^ all cpu info
                o quickstats - switch for query either PerfCounter values or Runtime info
        * mem - shows mem info
            + usage - mem usage in percentage
                o quickstats - switch for query either PerfCounter values or Runtime info
            + usagemb - mem usage in MB
                o quickstats - switch for query either PerfCounter values or Runtime info
            + swap - swap mem usage in MB
                o listvm - turn on/off output list of swapping VM's
            + overhead - additional mem used by VM Server in MB
            + overall - overall mem used by VM Server in MB
            + memctl - mem used by VM memory control driver(vmmemctl) that controls ballooning
                o listvm - turn on/off output list of ballooning VM's
            ^ all mem info(except overall and no thresholds)
        * net - shows net info
            + usage - overall network usage in KBps(Kilobytes per Second)
            + receive - receive in KBps(Kilobytes per Second)
            + send - send in KBps(Kilobytes per Second)
            + nic - makes sure all active NICs are plugged in
            ^ all net info(except usage and no thresholds)
        * io - shows disk io info
            + aborted - aborted commands count
            + resets - bus resets count
            + read - read latency in ms (totalReadLatency.average)
            + write - write latency in ms (totalWriteLatency.average)
            + kernel - kernel latency in ms
            + device - device latency in ms
            + queue - queue latency in ms
            ^ all disk io info
        * vmfs - shows Datastore info
            + (name) - free space info for datastore with name (name)
                o used - output used space instead of free
                o breif - list only alerting volumes
                o regexp - whether to treat name as regexp
                o blacklistregexp - whether to treat blacklist as regexp
                b - blacklist VMFS's
                T (value) - timeshift to detemine if we need to refresh
            ^ all datastore info
                o used - output used space instead of free
                o breif - list only alerting volumes
                o blacklistregexp - whether to treat blacklist as regexp
                b - blacklist VMFS's
                T (value) - timeshift to detemine if we need to refresh
        * runtime - shows runtime info
            + con - connection state
            + health - checks cpu/storage/memory/sensor status
                o listitems - list all available sensors(use for listing purpose only)
                o blackregexpflag - whether to treat blacklist as regexp
                b - blacklist status objects
            + storagehealth - storage status check
                o blackregexpflag - whether to treat blacklist as regexp
                b - blacklist status objects
            + temperature - temperature sensors
                o blackregexpflag - whether to treat blacklist as regexp
                b - blacklist status objects
            + sensor - threshold specified sensor
            + maintenance - shows whether host is in maintenance mode
            + list(vm) - list of VMWare machines and their statuses
            + status - overall object status (gray/green/red/yellow)
            + issues - all issues for the host
                b - blacklist issues
            ^ all runtime info(health, storagehealth, temperature and sensor are represented as one value and no thresholds)
        * service - shows Host service info
            + (names) - check the state of one or several services specified by (names), syntax for (names):<service1>,<service2>,...,<serviceN>
            ^ show all services
        * storage - shows Host storage info
            + adapter - list bus adapters
                b - blacklist adapters
            + lun - list SCSI logical units
                b - blacklist LUN's
            + path - list logical unit paths
                b - blacklist paths
            ^ show all storage info
        * uptime - shows Host uptime
                o quickstats - switch for query either PerfCounter values or Runtime info
        * device - shows Host specific device info
            + cd/dvd - list vm's with attached cd/dvd drives
                o listall - list all available devices(use for listing purpose only)
    DC specific :
        * cpu - shows cpu info
            + usage - CPU usage in percentage
                o quickstats - switch for query either PerfCounter values or Runtime info
            + usagemhz - CPU usage in MHz
                o quickstats - switch for query either PerfCounter values or Runtime info
            ^ all cpu info
                o quickstats - switch for query either PerfCounter values or Runtime info
        * mem - shows mem info
            + usage - mem usage in percentage
                o quickstats - switch for query either PerfCounter values or Runtime info
            + usagemb - mem usage in MB
                o quickstats - switch for query either PerfCounter values or Runtime info
            + swap - swap mem usage in MB
            + overhead - additional mem used by VM Server in MB
            + overall - overall mem used by VM Server in MB
            + memctl - mem used by VM memory control driver(vmmemctl) that controls ballooning
            ^ all mem info(except overall and no thresholds)
        * net - shows net info
            + usage - overall network usage in KBps(Kilobytes per Second)
            + receive - receive in KBps(Kilobytes per Second)
            + send - send in KBps(Kilobytes per Second)
            ^ all net info(except usage and no thresholds)
        * io - shows disk io info
            + aborted - aborted commands count
            + resets - bus resets count
            + read - read latency in ms (totalReadLatency.average)
            + write - write latency in ms (totalWriteLatency.average)
            + kernel - kernel latency in ms
            + device - device latency in ms
            + queue - queue latency in ms
            ^ all disk io info
        * vmfs - shows Datastore info
            + (name) - free space info for datastore with name (name)
                o used - output used space instead of free
                o breif - list only alerting volumes
                o regexp - whether to treat name as regexp
                o blacklistregexp - whether to treat blacklist as regexp
                b - blacklist VMFS's
                T (value) - timeshift to detemine if we need to refresh
            ^ all datastore info
                o used - output used space instead of free
                o breif - list only alerting volumes
                o blacklistregexp - whether to treat blacklist as regexp
                b - blacklist VMFS's
                T (value) - timeshift to detemine if we need to refresh
        * runtime - shows runtime info
            + list(vm) - list of VMWare machines and their statuses
            + listhost - list of VMWare esx host servers and their statuses
            + listcluster - list of VMWare clusters and their statuses
            + tools - VMWare Tools status
                b - blacklist VM's
            + status - overall object status (gray/green/red/yellow)
            + issues - all issues for the host
                b - blacklist issues
            ^ all runtime info(except cluster and tools and no thresholds)
        * recommendations - shows recommendations for cluster
            + (name) - recommendations for cluster with name (name)
            ^ all clusters recommendations
    Cluster specific :
        * cpu - shows cpu info
            + usage - CPU usage in percentage
            + usagemhz - CPU usage in MHz
            ^ all cpu info
        * mem - shows mem info
            + usage - mem usage in percentage
            + usagemb - mem usage in MB
            + swap - swap mem usage in MB
                o listvm - turn on/off output list of swapping VM's
            + memctl - mem used by VM memory control driver(vmmemctl) that controls ballooning
                o listvm - turn on/off output list of ballooning VM's
            ^ all mem info(plus overhead and no thresholds)
        * cluster - shows cluster services info
            + effectivecpu - total available cpu resources of all hosts within cluster
            + effectivemem - total amount of machine memory of all hosts in the cluster
            + failover - VMWare HA number of failures that can be tolerated
            + cpufainess - fairness of distributed cpu resource allocation
            + memfainess - fairness of distributed mem resource allocation
            ^ only effectivecpu and effectivemem values for cluster services
        * runtime - shows runtime info
            + list(vm) - list of VMWare machines in cluster and their statuses
            + listhost - list of VMWare esx host servers in cluster and their statuses
            + status - overall cluster status (gray/green/red/yellow)
            + issues - all issues for the cluster
                b - blacklist issues
            ^ all cluster runtime info
        * vmfs - shows Datastore info
            + (name) - free space info for datastore with name (name)
                o used - output used space instead of free
                o breif - list only alerting volumes
                o regexp - whether to treat name as regexp
                o blacklistregexp - whether to treat blacklist as regexp
                b - blacklist VMFS's
                T (value) - timeshift to detemine if we need to refresh
            ^ all datastore info
                o used - output used space instead of free
                o breif - list only alerting volumes
                o blacklistregexp - whether to treat blacklist as regexp
                b - blacklist VMFS's
                T (value) - timeshift to detemine if we need to refresh


Copyright (c) 2008 op5


Après un test rapide, nous obtenons une erreur de ce type :
CHECK_VMWARE_API.PL CRITICAL - Server version unavailable at ...
La vérification du certificat pose problème, si vous ne voulez pas le passer en paramètre, utiliser cette option :
--no-certificate-checking
ou rajoutez ceci au début du script perl :
$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;

Configuration de Nagios

Nous allons stocker les identifiants de connexions de l'ESXi dans le fichiers etc/resource.cfg qui ne doit pas être accessible via les CGI

$USER09$=username
$USER10$=password

Ensuite reste à configurer les commandes :

# 'check_esx_cpu' command definition

define command{
        command_name check_esx_cpu
        command_line $USER1$/check_vmware_api.pl -H $HOSTADDRESS$ -u $USER09$ -p $USER10$ -l cpu -s usage -w $ARG1$ -c $ARG2$
        }
 
# 'check_esx_mem' command definition
define command{
        command_name check_esx_mem
        command_line $USER1$/check_vmware_api.pl -H $HOSTADDRESS$ -u $USER09$ -p $USER10$ -l mem -s usage -w $ARG1$ -c $ARG2$
        }
 
# 'check_esx_net' command definition
define command{
        command_name check_esx_net
        command_line $USER1$/check_vmware_api.pl -H $HOSTADDRESS$ -u $USER09$ -p $USER10$ -l net -s usage -w $ARG1$ -c $ARG2$
        }
 
# 'check_esx_runtime' command definition
define command{
        command_name check_esx_runtime
        command_line $USER1$/check_vmware_api.pl -H $HOSTADDRESS$ -u $USER09$ -p $USER10$ -l runtime -s status
        }
 
# 'check_esx_ioread' command definition
define command{
        command_name check_esx_ioread
        command_line $USER1$/check_vmware_api.pl -H $HOSTADDRESS$ -u $USER09$ -p $USER10$ -l io -s read -w $ARG1$ -c $ARG2$
        }
 
# 'check_esx_iowrite' command definition
define command{
        command_name check_esx_iowrite
        command_line $USER1$/check_vmware_api.pl -H $HOSTADDRESS$ -u $USER09$ -p $USER10$ -l io -s write -w $ARG1$ -c $ARG2$
        }

Puis la traditionnelle configuration :

define host{

    use              generic-host
    host_name    myesx1
    alias             myesx1
    address        XXX.XXX.XXX.XXX
}

Et la définition des services :
 


define service{
        use                                  generic-service
        host_name                        myesx1
        service_description            ESXi CPU Load
        check_command                check_esx_cpu!80!90
        }
 
define service{
        use                                  generic-service
        host_name                        myesx1
        service_description            ESXi Memory usage
        check_command                check_esx_mem!80!90
        }
 
define service{
        use                                  generic-service
        host_name                        myesx1
        service_description            ESXi Network usage
        check_command                check_esx_net!102400!204800
        }
 
define service{
        use                                  generic-service
        host_name                        myesx1
        service_description            ESXi Runtime status
        check_command                check_esx_runtime
        }
 
define service{
        use                                 generic-service
        host_name                       myesx1
        service_description           ESXi IO read
        check_command               check_esx_ioread!40!90
        }
 
define service{
        use                                 generic-service
        host_name                       myesx1
        service_description           ESXi IO write
        check_command               check_esx_iowrite!40!90
        }

Conclusion

Voilà, le tour est joué, vous avez un début de supervision de votre serveur ESX ! Pour avoir un monitoring plus fin, je vous invite à parcourir cette documentation : http://www.op5.com/how-to/monitoring-vmware-esx-3-x-esxi-vsphere-4-and-vcenter-server

Quand VMware Workstation cherche les sources du kernel ...

Alexandre Frandemiche

Votre VMware Workstation se lance et vous demande le chemin des source de votre kernel, et à chaque mise à jour du noyau, ça sera le cas !

Que faire pour qu'il retrouve ces petits ? soit utiliser une des nombreuses alternatives libres (^^), soit à chaque fois exécuter ce qui suit :

# cp /usr/include/linux/version.h /lib/modules/maversiondemondernierkernel.fc17.x86_64/build/include/linux/

vmware kernel sourceVoilà, mémo à 2 balles, mais j'en avais ras le bol de rechercher dans l'historique de mon terminal !

Authentification SSH par agent sur CentOS/Fedora

Alexandre Frandemiche

Contexte

Lorsque l'on manipule des serveurs sous GNU/Linux, on utilise de manière quasiment exclusive nos si chères et si pratiques/efficaces/magiques commandes en utilisant très souvent le Secure Shell aussi appelé : SSH !

J'ai un serveur qui héberge ce blog entre autre et un NAS chez moi afin d'y entreposer ces indispensables sauvegardes ! Quoi de mieux que de passer par un script pour effectuer les différentes opérations ! Voilà que notre script peut très rapidement avoir besoin de copier un certains nombre de fichiers vers ce NAS via la commande scp par exemple. Tout ceci est parfait mais comment ne pas devoir entrer son mot de passe ou le stocker en clair à l'aide d'une quelconque bidouille ou commande bizarres ? Utiliser un système d'authentification proposé par ce formidable outil !

Prérequis

Tout d'abord vérifions coté serveur que nous disposons bien des paquets nécéssaires et l'autorisation d'authentification par clé RSA :

# yum install openssh-server openssh-client openssh

$ grep RSA /etc/sshd_config RSAAuthentication yes

Que notre serveur SSH est lancé et se lance au démarrage du serveur ( ;)" class="smiley ):

# /etc/init.d/sshd status ou # service sshd status

# chkconfig sshd on

S'il n'est pas démarré, un simple # service sshd start doit suffire !

Fonctionnement

Un schéma vaut mieux qu'une explication :
cle-rsa.pngSource : http://geekfault.org - license Creative Commons

Génération d'une clé RSA ou DSA

Une fois ce qu'il faut d'activé et de configuré côté serveur, nous nous rendons sur le client. C'est sur cette machine que nous ne voulons plus rentrer ce mot de passe si long et compliqué :)" class="smiley

Rendez vous dans votre home de l'utilisateur qui voudra se connecter au serveur SSH sans donner de mot de passe mais en utilisant ce système d'authentification.

$ cd

$ ssh-keygen -t rsa

Generating public/private dsa key pair. Enter file in which to save the key (/home/monuser/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/monuser/.ssh/id_rsa. Your public key has been saved in /home/monuser/.ssh/id_rsa.pub. The key fingerprint is: 8f:80:d8:c5:3d:9s:0b:10:66:42:9c:84:45:a1:d0:14 monuser@monserveur

Nos clés se trouvent en théorie dans /home/monuser/.ssh/ avec comme nom id_rsa et id_rsa.pub.

Retenez bien la passphrase renseignée car elle nous servira encore ! Elle sert de base à lalgorithme de génération de la clé privée, donc plus elle est compliquée en combinant des chiffres/lettres/ponctuations majuscules/minuscules, mieux c'est !

Sécurisation de la clé privée

Nous allons mettre la clé privée en lecture seule pour le propriétaire de la clé et aucun droit pour les autres utilisateurs :

$ chmod 400 ~/.ssh/id_rsa

Modifier la passphrase

$ chmod u+w ~/.ssh/id_rsa
$ ssh-keygen -p -f ~/.ssh/id_rsa
$ chmod u-w ~/.ssh/id_rsa

Exporter la clé publique

Comme vu ci-dessus, 2 clés ont été générées ; une privée que l'on ne communique pas et une publique que l'on va transférer sur le serveur SSH :

$ cat .ssh/id_rsa.pub | ssh monuser@monserveur \ "cat - >>~/.ssh/authorized_keys"

Votre mot de passe est demandée, normal, vous effectuez l'opération et ensuite on teste en listant le contenu du répertoire home de monuser :

$ ssh monuser@monserveur ls

Là il nous demande la passphrase et affiche le résultat de la commande ls ! Plus de mot de passe ! ... mais une passphrase ... :(" class="smiley

Automatiser le stockage de la clé privée (passphrase)

Démarrer l'agent

Pour cela nous allons utiliser un agent SSH, c'est lui qui va s'occuper de stocker en mémoire la clé privée :

Pour cela nous allons lancer l'agent, puis un shell supplémentaire avec les variables d'environnement qui l'identifient :

$ ssh-agent /bin/bash

Ajouter une clé

Nous fournissons notre clé privée à l'agent via un simple :

$ ssh-add

Qui nous demande une dernière fois la passphrase et le tour est joué !

Vérifions :

$ ssh monuser@monserveur ls

Nous obtenons le résultat de la commande ls sans avoir rentré quoique ce soit !

Supprimer une clé

$ ssh-add -d ~/.ssh/id_rsa

Cubox - Mise à jour du U-boot et installation d'une distribution GNU/Linux

Alexandre Frandemiche

Prérequis

Téléchargements et préparation de la clé USB

Tout d'abord il faut télécharger ces 2 fichiers (disponibles ici : http://download.solid-run.com/pub/solidrun/cubox/installer/ ) : 

cubox-installer-0_1.zip

cubox-installer-0_2.zip

Dézipper cubox-installer-0_2.zip sur une clé USB formaté en fat32 ou ext2, sur laquelle on obtient :

/boot

Ouvrir le cubox-installer-0_1.zip et dézipper u-boot.bin dans /boot de la clé USB.

Installation des prérequis

# yum install minicom

# minicom -s

  • Choose 'Serial port setup'
  • Click A, and fill in serial device - for example /dev/ttyUSB0
  • Click E, and choose 115200 8N1 by click E,Q, then enter
  • Click F to disable Hardware Flow Control
  • If needed, click G to disable Software Flow Control, then enter
  • Now select 'Save setup as dfl'. Next time you run minicom without the '-s' flag, the saved parameters will be used
  • Press exit, leaving configuration and enter console

Une fois fait, plus besoin de le reconfigurer, on peut le lancer directement :
# minicom

Afin de connaitre le ttyUSB à utiliser, il suffit de faire appel à dmesg :

# dmesg | grep ttyUSB

Mise à jour de U-boot

Préparation et lancement

  • Vérifier que minicom est lancé
  • Brancher en microUSB le Cubox avec accès internet + hdmi + cléUSB avec les fichiers téléchargés plus tôt
  • Brancher le Cubox et appuyer sur une flèche ou autre touche du clavier aussitôt. Nous obtenons ceci :B
minicom-uboot
Il y a un  bug concernant mon u-boot, il m'affiche être en 5.4.4 NQ alors que 
CuBox>>version
me retourne 5.4.4_SR1 ... où j'ai loupé un truc (probable).
Bref, du coup on force le "burning boot" ;)" class="smiley :

Clé USB en ext2

CuBox>>if ext2load usb 0:0 0x00200000 /boot/u-boot.bin;
>then run pre_burn;
>sf write 0x00200000 0 0x00080000;
>run post_burn; fi
Si cela ne donne rien :
CuBox>>if ext2load usb 0:1 0x00200000 /boot/u-boot.bin;
>then run pre_burn;
>sf write 0x00200000 0 0x00080000;
>run post_burn; fi

Clé USB en fat32

CuBox>>if fatload usb 0:0 0x00200000 /boot/u-boot.bin;
>then run pre_burn;
>sf write 0x00200000 0 0x00080000;
>run post_burn; fi
Si cela ne donne rien :
CuBox>>if fatload usb 0:1 0x00200000 /boot/u-boot.bin;
>then run pre_burn;
>sf write 0x00200000 0 0x00080000;
>run post_burn; fi
Selon la clé et le port, ca se met à démarrer sur le bon u-boot et force la mise à jour.

Installation de la distribution via Cubox_Installer

Ensuite il ne reste qu'à lancer l'installer et on se laisse porter par la vague ;)" class="smiley Si vous avez peur d'être perdu, il suffit de suivre ceci : http://www.solid-run.com/mw/index.php/CuBox_Installer mais c'est tout de même assez clair et explicite :)" class="smiley !Le plus dur a été fait avant ;)" class="smiley !
Voilà le résultat : 
GeekBox - cuboxEt au niveau écran HDMI : 
GeekBox_XBMC.jpg

Quand rrdtool fait des siennes ... sur CentOS

Alexandre Frandemiche

En souhaitant terminer une installation de Cacti et le coupler à Nagios à l'aide de n2rrd, j'ai dû me préoccuper d'installer des prérequis que sont rrdtool et rrdtool-perl.

Seulement, voilà Un petit yum install rrdtool perl-rrdtool me génère cette erreur :

Loaded plugins: dellsysid, fastestmirror

Loading mirror speeds from cached hostfile

 * base: centos.crazyfrogs.org

 * epel: mir01.syntis.net

 * extras: centos.crazyfrogs.org

 * jpackage-generic: mirror.ibcp.fr

 * jpackage-generic-updates: mirror.ibcp.fr

 * updates: centos.crazyfrogs.org

Setting up Install Process

Resolving Dependencies

--> Running transaction check

---> Package rrdtool-perl.x86_64 0:1.2.27-3.el5 set to be updated

--> Processing Dependency: rrdtool = 1.2.27-3.el5 for package: rrdtool-perl

--> Processing Dependency: librrd.so.2()(64bit) for package: rrdtool-perl

--> Running transaction check

---> Package rrdtool.i386 0:1.2.27-3.el5 set to be updated

---> Package rrdtool-perl.x86_64 0:1.2.27-3.el5 set to be updated

--> Processing Dependency: librrd.so.2()(64bit) for package: rrdtool-perl

--> Finished Dependency Resolution

rrdtool-perl-1.2.27-3.el5.x86_64 from epel has depsolving problems

  --> Missing Dependency: librrd.so.2()(64bit) is needed by package rrdtool-perl-1.2.27-3.el5.x86_64 (epel)

Error: Missing Dependency: librrd.so.2()(64bit) is needed by package rrdtool-perl-1.2.27-3.el5.x86_64 (epel)

Visiblement, déjà installé, il y atout de même un problème ...
En réalité, je mélange ici, le dépôt RPMForge et EPL (pas bien !!!), du coup on désinstalle la version de RPMForge et on installe ceux d'EPEL !
yum remove rrdtool
Puis on relance notre yum install :
yum install rrdtool perl-rrdtool
Et voilà, il y a plus qu'à continuer !

Mise à jour d'ownCloud depuis mon ReadyNas Ultra 4

Alexandre Frandemiche

Version française

Note avant toute migration d'ownCloud

Je ne saurai vous conseiller de faire des sauvegardes à la fois régulièrement mais aussi avant chaque mise à jour ! De plus, il est conseillé de monter de version dans le dernier patch d'ownCloud avant d'upgrader à la version majeur ou mineur du dessus !

Vous l'aurez deviné, j'ai donc migré en 2 étapes, 2 fois la même manipulation d'affilé vu que le plugin ReadyNas que je cite dans ce billet : OwnCloud - Partage de fichiers est en version 4.0.4.

Migration d'ownCloud pour ReadyNas basé sur l'add-on de ReadyNasXtras

Connectez-vous en SSH à votre ReadyNas, si besoin vous pouvez utiliser ce plugin : Enable SSH

Téléchargement et installation

#!/bin/bash

cd /tmp
rm -Rf owncloud*.*
#wget http://mirrors.owncloud.org/releases/owncloud-latest.tar.bz2
wget http://mirrors.owncloud.org/releases/owncloud-4.5.5.tar.bz2
#rm -Rf /usr/share/owncloud_*
mv /usr/share/owncloud/ /usr/share/owncloud_save
#tar -xjf owncloud-latest.tar.bz2
tar -xjf owncloud*.bz2
mv owncloud /usr/share/
chown -R admin:admin /usr/share/owncloud/
cd /usr/share/owncloud/
ln -s /c/.owncloud/data/ data
cp -R ../owncloud_save/config/ ./
cp -R ../owncloud_save/.htaccess ./
cp -Rn ../owncloud_save/apps/ ./
chown -R admin:admin /usr/share/owncloud/
cd /etc/frontview/
apache-ssl -f /etc/frontview/apache/httpd.conf -k restart

Explication

Bon, je vous dois qd même une petite explication, une fois le fichier téléchargé, on sauvegarde l'ancienne instance d'ownCloud afin d'un de sécuriser l'opération et surtout parce quil y a des fichiers de configuration que l'on souhaite récupérer :

3 répertoires et 1 fichier:

  • config
  • data (qui se trouve être un lien symbolique vers /c/.owncloud/data, car me demandez pas pourquoi, mais /c/ est un autre point de montage ayant le plus d'espace ! pourquoi un /c/ et non /home ... ??? merci Netgear !!!)
  • .htaccess
  • apps (contient les plugins éventuellement ajoutés)

Sans ça, vous retrouveriez pas vos petits et surtout, sans le dernier, La planète aurait accès à vos fichiers :D !

Votre nouvelle version est maintenant déployée ! Il ne vous reste plus qu'à vous rendre sur https://mon_ip_ou_mon_dns/owncloud/ et vous connecter !

Migration du client ownCloud en 1.1.1 pour Fedora

Tout d'abord, il faut penser à désactiver ou enlever le dépôt utilisé précédemment :

# vi /etc/yum.repo.d/isv\:ownCloud\:community.repo

...
enabled=1
...

...
enable=0
...

Personnellement, j'ai dû désinstaller owncloud-client et mirall :

# yum remove owncloud-client mirall

Ensuite, même combat que pour la version 1.0.5 du client :

# cd /etc/yum.repos.d/
# wget http://download.opensuse.org/repositories/isv:ownCloud:devel/Fedora_16/isv:ownCloud:devel.repo
# yum install owncloud-client

On se retrouve avec un nouveau dépôt dédié à ce nouveau client ownCloud ... l'histoire ne dit pas comment le repository va évoluer, quid de la prochaine version ?

Pour le client mobile android, une reconfiguration peut être nécessaire après le passage à la 4.5.1 d'ownCloud.

Bilan 4.5.1 d'ownCloud

J'avoue être réellement conquis ! Avec cette mise à jour, les quelques bugs comme la déconnexion qui ne fonctionnait pas sur linterface web, ou une synchronisation via cette même interface qui était limite. Là on à vraiment l'impression d'un outil plus abouti et toujours si prometteur ! Seule ombre au tableau, l'"Instant Upload" qui fonctionnait bien avant à l'air de vouloir faire des siennes ... à vérifié car le client Android m'indique bien que le fichier à été téléversé ! :)" class="smiley !

Je pense attaquer le reste maintenant que l'installation et la mise à jour sont fiables :)" class="smiley ! J'ai commencé d'ailleurs à utiliser les modules d'édition de fichier texte ou LibreOffice :)" class="smiley C'est très très sympa !

English Version

Notes before ownCloud update

At first, make backup !!!! Daily or weekly, and before update ! On the ownCloud website, it advice to update all patches before upgrade to the new version.

So, has you supppose, I updates in 2 steps with the same way because ReadyNas add-on that I use in this article : OwnCloud - Partage de fichiers is in 4.0.4 version.

OwnCloud update on ReadyNas based on ReadyNasXtras's add-on

Connect with SSH to your ReadyNas, for that you need this plugin : Enable SSH

Download and installation

#!/bin/bash

cd /tmp
rm -Rf owncloud*.*
#wget http://mirrors.owncloud.org/releases/owncloud-latest.tar.bz2
wget http://mirrors.owncloud.org/releases/owncloud-4.5.5.tar.bz2
#rm -Rf /usr/share/owncloud_*
mv /usr/share/owncloud/ /usr/share/owncloud_save
#tar -xjf owncloud-latest.tar.bz2
tar -xjf owncloud*.bz2
mv owncloud /usr/share/
chown -R admin:admin /usr/share/owncloud/
cd /usr/share/owncloud/
ln -s /c/.owncloud/data/ data
cp -R ../owncloud_save/config/ ./
cp -R ../owncloud_save/.htaccess ./
cp -Rn ../owncloud_save/apps/ ./
chown -R admin:admin /usr/share/owncloud/
cd /etc/frontview/
apache-ssl -f /etc/frontview/apache/httpd.conf -k restart

Explanation

So, I give you some explanation, after the download of the last version (maybe, the link is not good and you have to update to link to the version you want, each time), we save the old ownCloud instance to secure our operation ;)" class="smiley and also because there are some configuration files which we want to keep :

3 folders and 1 file :

  • config
  • data (which is a symbolic link to /c/.owncloud/data,I don't know why, but /c/ is an other mounted point with more space (all HDD added in the nas)! Why a /c/ and not an /home directory like under linux... ??? thanks Netgear !!!)
  • .htaccess (for secure access)
  • apps (contains owncloud add-on)

Less that, you lose all you specific configuration ... it would be bad :/

so your new ownCloud version is up to date ! Go to https://my_ip_or_my_dns/owncloud/ and connect you !

Update sync client ownCloud in the 1.1.1 version on Fedora

So you have to disable or remove the old repository :

# vi /etc/yum.repo.d/isv\:ownCloud\:community.repo

...
enabled=1
...

...
enable=0
...

In my case, I have to remove owncloud-client and mirall :

# yum remove owncloud-client mirall

then, same way for install version 1.0.5 of sync-client :

# cd /etc/yum.repos.d/
# wget http://download.opensuse.org/repositories/isv:ownCloud:devel/Fedora_16/isv:ownCloud:devel.repo
# yum install owncloud-client

It works, you have only one last thing : configure it ;)" class="smiley !

for the android client cell, just a new configuration may be necessary when you'll be in 4.5.1 of ownCloud server.

Resume ownCloud 4.5.1

I'm very exited about this program ! And after this last update, many bugs are fix, like this one about the logout on the website ! It seems really a good job and on all sync-client too (InstantUpload works fine on my Android, etc ...)

Have fun !

OwnCloud - Partage de fichiers

Alexandre Frandemiche

Et si ... et si enfin je quittais (un peu) Google ???

Cela fait longtemps que je rêve de disposer du tout synchronisé ! Google l'a fait !

Au départ, je ne voulais pas réellement y mettre le doigt, mais avec un Samsung Galaxy S2 sous Android, puis CyanogenMod 10 maintenant, il faut avouer que c'est très tentant, et j'ai craqué ! C'est trop facile ...

Pourtant à la lecture de l'article de Dada, je me suis dis, mince, ça doit maintenant pouvoir se faire ! Surtout que j'ai un ReadyNas Ultra 4 chez moi !

J'avais tenté il y a quelque temps Tonido, mais le client Android est une horreur et je n'ai jamais eu le temps d'aller voir plus loin ... Là j'ai gouté à ownCloud ! Attention, c'est très prometteur !!!!

Installation sur ReadyNas Ultra 4

Je me suis simplifié la vie en achetant la module ownCloud fournis par un membre de la communauté Netgear ReadyNas. Facile, rapide, on participe en finançant à hauteur de 2€, on va pas chipoter !

Et voilà, c'est partie, ownCloud tourne sur mon serveur :

owncloud_readynasIl faut préciser que ownCloud nécessite une version récente de php, du coup j'ai aussi acheté le module PHP que fournit ReadyNasXtra. Il reste à cliquer sur

Access your ownCloud

Et nous voilà sur l'interface de connexion d'ownCloud puis voici le vif du sujet :

owncloud_start

Installation du client pour ma Fedora

Étant en version 4.0.X et non 4.5 à l'heure actuelle, il faut le client ownCloud en version 1.0.5 et non la toute dernière 1.1.1 (plus d'informations sur le site)

Pour Fedora, dans la version 4.0 d'ownCloud, nous disposons d'un dépôt !

# cd /etc/yum.repos.d/
# wget http://download.opensuse.org/repositories/isv:ownCloud:community/Fedora_16/isv:ownCloud:community.repo
# yum install owncloud-client

Il ne reste qu'à le lancer manuellement ou au démarrage de la session :

$ gnome-session-properties

Vous ajoutez votre entrée en précisant owncloud comme commande et le tour est joué !

Je ne vous ferez pas l'affront de vous expliquer comment remplir les différents (3) paramètres que sont l'url, le nom d'utilisateur et le mot de passe :)" class="smiley ! Surtout que le menu administration en bas à gauche dans l'interface web d'ownCloud donne tout ce qu'il faut !

Installation du client pour ma CyanogenMod

Une fois de plus, c'est extrêmement simple, Vous recherchez owncloud sur le market et je vous laisse deviner la suite ! Même combat que pour le client PC !

Vous pouvez configurer le compte dans les paramètres de CyanogenMod/Android dans la partie compte, ownCloud est proposé ! Je rajoute un fichier sur mon PC dans le répertoire partagé ownCloud et voici le résultat
:

owncloud_android

Ce fichier (ma tronche) est bien sur ma Fedora, ou l'inverse ... :D owncloud_fedora

Rapide bilan

C'est beau n'est-ce pas ? Bon il reste encore à faire avec les calendriers, les contacts, etc ... J'ai testé l'"Instant Upload" qui permet d'automatiquement uploader téléverser vos photos fraichement prises avec votre téléphone, ça fonctionne très bien !

Génial pour les sauvegardes ! Par contre, je ne vois pas mes répertoire dans l'interface web ... c'est bizarre. J'ai fais joujou rapidement, donc je ne peux pas encore faire un vrai retour, il faut que je creuse, mais une chose est sûre, ça donne clairement envie dapprofondir le sujet et c'est très prometteur ! J'ai hâte de me pencher sur la mise à jour 4.5.1, et voir comment faire avec le module ReadyNas ... les derniers clients apporteront surement plus de possibilités également !

Bref, je suis très agréablement surpris ! Tellement que ça me donne une idée d'article pour Muffin !

Migration Fedora 15 à Fedora 16 via preupgrade

Alexandre Frandemiche

fedora-16.jpgVoilà, après quelques semaines, je me décide enfin à passer à Fedora 16 ! Au vu des nouveautés je n'ai pas pu attendre plus longtemps ! (Notamment tout ce qui touche à la virtualisation ;) )

Seulement voilà, quelques petits problèmes sont apparus lors de cette mise à jour ... c'est rare, mais ca arrive !

Voici la procédure à suivre, si après le preupgrade,, vous arrivez sur un écran "Oh no! ..." ou "Oh mince! ...

Changement uid et gid

Tout d'abord il faut éditer 2 fichiers, dans lequel nous allons remplacer les uid de notre (nos) utilisateur(s), le tout avec les droits root :

# vi /etc/passwd
# vi /etc/group

J'ai passé mon uid de 500 à 1000. Rappel pour vi : i pour insérer, /monuser pour rechercher la chaine monuser, [echap]wq pour enregistrer et quitter et [echap]q! pour quitter sans enregistrer.

Ensuite :

# find / -gid 500 -exec chgrp -h 1000 {} \; # find / -uid 500 -exec chown -h 1000 {} \;

Enfin on change le propriétaire de /home/monuser :

# chown -Rf 1000 /home/monuser

Voilà, en théorie, plus de problèmes au niveau des droits ...

Problème avec Gnome

J'ai été contraints de supprimer l'ensemble des extensions :

# yum remove gnome-shell-extension*

Par sécurité, j'ai aussi enlevé le driver propriétaire Nvidia :

# yum remove *nvidia*

Après tout cela, j'avais toujours cette erreur.

# yum reinstall gnome-shell

Et voilà, je peux enfin me connecter !
Fedora 16 me voilà !

CentOS + Tomcat + beaucoup d'ouvertures de fichiers = java.net.SocketException: Too many open files

Alexandre Frandemiche

ExceptionTout est dans le titre !!! Comme d'habitude, c'est plus un pense-bête qu'un véritable article ... si ça peut aider ...

J'ai eu une surprise ce matin sur un serveur client de constater cette erreur :

java.net.SocketException: Too many open files


C'est un serveur sous CentOS 5.5 hébergeant un serveur MySQL, un serveur tomcat avec plusieurs Webapps, un serveur Apache et enfin un serveur propriétaire qui utilise pas mal de socket et a une base de donnée en interne ...

Cocktail génial pour visiblement dépasser la limite par défaut du système s'élevant à 1024 que l'on obtient en faisant un :

ulimit -n

Il y a 2 valeurs possibles à modifier, celle présente dans le fichier /proc/sys/fs/file-max par défaut, celle-ci est assez élevée (plus de 64000). Au besoin il faut modifier la ligne suivante :

...

fs.file-max = 64000

...

Si (comme tel était mon cas) la valeur de ce fichier est plus élevée, il reste à ajouter une entrée au fichier /etc/security/limits.conf :

user         -          nofile          8192

ou

@group         -          nofile          8192

La première colonne désigne l'utilisateur ou le groupe (grâce à @) ou encore n'importe qui grâce à *.
La seconde colonne, on détermine si la limite est soft ou hard, ou les 2 grâce à -.
La troisième colonne indique sur quel paramètre cette configuration s'exécute, ici nofile correspond au paramètre open files retourné par ulimit.
Enfin la dernière colonne indique la valeur.
Dans mon cas, j'ai rajouté :

@tomcat         -          nofile          8192
optitime           -          nofile          8192

Il est indiqué sur la documentation Red Hat de redémarrer le serveur pour que cela prenne effet. La solution peut consister à relancer le ou les services concernés ainsi que les sessions utilisateurs.

Voilà, en espérant que ça puisse aider et surtout m'éviter de rechercher cette information à nouveau ;) !