URL: https://linuxfr.org/users/toremilac/journaux/ecrire-une-petite-interface-utilisateur-ipmitool-en-1h-avec-whiptail Title: Ecrire une petite interface utilisateur ipmitool en 1h avec whiptail Authors: toremilaC Date: 2023年08月01日T14:49:09+02:00 License: CC By-SA Tags: whiptail et ipmi Score: 26 Bonjour, ce matin j'avais besoin d'adresser des commandes ipmi à plusieurs hôtes pour pouvoir, notamment, paramétrer l'hôte pour qu'il démarre dans les options de BIOS, qu'il boote en PXE, qu'il démarre ou s'éteigne aussi, tout simplement. Et j'avais besoin de me simplifier la vie pour lancer ces commandes sur un grand nombre d'hôte. Chercher dans l'historique des commandes, remplacer le nom d'hôte devient vite non satisfaisant. Ecrire un script shell, pourquoi pas; oh et puis pourquoi ne pas regarder comment faire simplement une petite interface utilisateur en shell ?! # Les commandes ipmitool utiles # Les commandes ipmitool qui m'étaient utiles sont les suivantes (en notant `monhote` le nom de l'hôte ciblé ) : - **Aller dans les paramètres de BIOS au prochain boot** : `ipmitool -I lanplus -H imonhote -U root -P PASSWORD chassis bootparam set bootflag force_bios` - **Partir en boot PXE au prochain boot** : `ipmitool -I lanplus -H imonhote -U root -P PASSWORD chassis bootdev pxe` - **Eteindre le chassis** : `ipmitool -I lanplus -H imonhote -U root -P PASSWORD chassis power off` - **Allumer le chassis** : `ipmitool -I lanplus -H imonhote -U root -P PASSWORD chassis power on` - **Faire un power off/power on** : `ipmitool -I lanplus -H imonhote -U root -P PASSWORD chassis power cycle` - **Faire un power reset quand l'extinction propre ne fonctionne plus** : `ipmitool -I lanplus -H imonhote -U root -P PASSWORD chassis power reset` Ces commandes très pratiques, je vais devoir les répéter pour environ 100 hôtes pour lancer des réinstallations PXE à distance et probablement de temps en temps pour d'autres raisons. # L'interface whiptail # J'ai commencé à regarder ce qu'il existe comme outils pour faire une petite interface. Et puis je suis tombé sur [dialog](https://manpages.debian.org/testing/dialog/dialog.1.en.html) et [whiptail](https://manpages.debian.org/testing/whiptail/whiptail.1.en.html). Je n'ai pas suffisamment creusé pour avoir un avis sur l'un ou l'autres (et d'ailleurs dialog semble avoir eu 2 vies). Les syntaxes m'ont l'air similaires, j'avais whiptail installé sur le serveur d'administration que j'utilisai, je suis partie là dessus. Pour ma petite interface, je vais utiliser une hiérarchie de menu : - une première liste de l'ensemble des hôtes parmi lesquel on peut sélectionner l'hôte cible, on appellera la fonction `select_node $message`, la variable `message` me permettant d'afficher un message arbitraire sur l'interface - une liste de commandes IPMI exécutables sur l'hôte, on appellera la commande `ipmi_menu $selected_node`, la variable `selected_node` étant le nom d'hôte ciblé ## Boucle principale ## Le script bash commence par une fonction principale ```bash # Main loop run=1 message="" while [ $run = 1 ]; do selected_node=`select_node $message` exitstatus=$? if [ $exitstatus = 1 ]; then run=1 message=`ipmi_menu $selected_node` else run=0 fi done ``` ## Menu de sélection de l'hôte ## Pour la sélection de l'hôte, je définis un menu avec `whiptail --menu`. La commande complète est de la forme `whiptail --menu text height width menu-height [tag item]`. Les options à fournir à whiptail (ce qui est appelé *tag item* dans la documentation* sont de la forme "nom de l'option 1" "texte supplémentaire pour l'option 1" "nom de l'option 2" "texte supplémentaire pour l'option 2". J'ai un certain nombre d'hôte à mettre en option, j'utilise un *array* bash pour définir ces options. ```bash function select_node() { local message=1ドル node_list=() for i in {01..68}; do node="kyle$i" node_list[${#node_list[@]}]=$node node_list[${#node_list[@]}]="" done OPTION=$(whiptail --title "IPMI interaction" --menu "Choose a node. Last message : $message" 30 90 10 "${node_list[@]}" 3>&1 1>&2 2>&3) exitstatus=$? if [ $exitstatus = 0 ]; then echo $OPTION return 1 else return 0 fi } ```  Je n'ai pas creusé la raison des redirections `3>&1 1>&2 2>&3`. Je profite de l'affichage de ce menu pour afficher un message arbitraire. Dans mon UI, je revies à ce menu chaque fois que j'ai lancé une commande ipmi et je voulai voir la sortie standard de la dernière commande exécutée. ## Menu d'exécution des commandes ipmi ## Lorsque l'hôte est sélectionné, je lance un menu pour les commandes ipmi : ```bash function run_ipmi { local node=1ドル local cmd=2ドル result=`ipmitool -I lanplus -H i$node -U root -P $ipmipass $cmd` echo $result } function ipmi_menu { local node=1ドル pwr_status=`run_ipmi $node "power status"` options=("Force bios on reboot" "" "Force PXE on reboot" "" "Power cycle" "" "Power reset" "" "Power on" "" "Power off" "") OPTION=$(whiptail --title "IPMI interaction" --menu "Choose an ipmitool for node $node; Pwr: $pwr_status" 30 90 6 "${options[@]}" 3>&1 1>&2 2>&3) exitstatus=$? if [ $exitstatus = 0 ]; then case $OPTION in "Force bios on reboot") echo "Bios on reboot for $node" run_ipmi $node "chassis bootparam set bootflag force_bios" ;; "Force PXE on reboot") echo "PXE on reboot for $node" run_ipmi $node "chassis bootdev pxe" ;; "Power cycle") echo "Power cycle $node" run_ipmi $node "chassis power cycle" ;; "Power on") echo "Power reset $node" run_ipmi $node "chassis power on" ;; "Power off") echo "Power reset $node" run_ipmi $node "chassis power off" ;; "Power reset") echo "Power reset $node" run_ipmi $node "chassis power reset" ;; *) echo "unknown" ;; esac else return 0 fi } ```  Cette fois-ci, je défini explicitement les options pour le menu. Je profite de ce menu pour afficher l'état électrique du châssis. La sortie standard de cette commande est capturée dans la boucle principale qui va afficher le premier menu avec commande message arbitraire cette sortie standard. Et voila, je trouve ce petit script bricolé assez pratique et relativement efficace pour piloter mes hôtes par ipmi.