Mon CV

Gestion des compatibilités processeur 32 ou 64 bits sous Munki

2 octobre 2013

J’utilise Munki (dont je vous ai déjà parlé de l’installation) pour gérer les déploiements d’applications sur le parc de Macs de mon entreprise. C’est une solution robuste, bien documentée, qui dispose d’une communauté assez active.
Mon parc est un peu hétérogène (vous allez comprendre l’impact sur la problématique) : j’ai des machines un peu anciennes (quelques Mac Mini et MacBook Pro avec processeur Intel Core Duo) et la version de l’OS n’est pas uniforme (certains postes sont installés en 10.6 et d’autres en 10.8).

Du coup, ce qui devait arriver arriva, je me retrouve avec des problèmes de compatibilité 64 bits sur certaines applications.

Cas pratique : sans y prêter attention, je déploie via Munki une mise à jour récente de XMind (version 3.3.1) sur l’ensemble du parc.
Badaboum ! Pour certains postes l’application n’est pas compatible. J’aurais du le lire, car c’est écrit noir sur blanc :

System requirements: Mac OS X 10.6.x Snow Leopard and later, with a 64-bit processor.

J’avais déjà eu des soucis de versions d’applications non compatibles avec certaines versions d’OS X, mais pas en fonction du processeur. Par analogie, je commence donc par me lancer dans l’utilisation d’une condition (ConditionalItems) dans le plist associée à l’application dans le repository de Munki. La documentation est claire.

Je réimporte dans Munki une version antérieure de XMind (avec la commande sudo /usr/local/munki/munkiimport), à laquelle j’associe la condition suivante, dans le fichier /votre_emplacement_du_repository_munki/pkgsinfo/XMind-3.2.plist :

...
<key>supported_architectures</key>
<array>
	<string>i386</string>
</array>
...

Et j’ajoute la condition suivante à la version 3.3.1 de Xmind (/votre_emplacement_du_repository_munki/pkgsinfo/XMind-3.3.1.plist) :

...
<key>supported_architectures</key>
<array>
	<string>x86_64</string>
</array>
...

Quelques tests plus tard … je m’aperçois que le comportement n’est pas tout à fait celui que je voulais. Sur un MacBook aluminium 13 pouces, doté d’un processeur Intel Core 2 Duo, par exemple, c’est la version ancienne (v. 3.2) qui a été installée, alors que le processeur est effectivement un processeur 64 bits, comme l’indique la documentation d’Apple. Evidemment, ça fonctionne mais je trouve ça curieux, et je n’ai donc pas pu m’empêcher de creuser le problème.

La réponse se trouve aussi dans la documentation d’Apple : un noyau 64 bits diffère d’un processeur 64 bits.

Faisons le test dans un Terminal sur la machine en question :

  • uname -m va renvoyer i386 si le noyau de l’OS est en 32 bits et x86_64 s’il est en 64 bits. Devinez la suite : sur cette machine j’obtiens i386 donc un noyau 32 bits.
  •  maintenant faisons un petit sysctl -n hw.cpu64bit_capable dans notre Terminal. Résultat : 1. Notre processeur est donc bien compatible 64 bits (ce que l’on avait appris plus haut dans la documentation d’Apple).

Déduction rapide : la condition supported_architectures proposée par Munki ne tient pas compte du processeur mais du noyau de l’OS. En l’occurrence, sur cette machine, il y a bien un processeur 64 bits, mais une version OS 10.6, qui tourne en standard en 32 bits.

Il faut donc trouver une alternative qui permette de réellement travailler en fonction du processeur. Quelques recherches dans la documentation de Munki, je trouve un début de solution : depuis la version 0.8.2 des munkitools, Munki gère la possibilité d’appliquer des conditions sur des variables générées par un script. Ça correspond grosso modo à mon besoin.

Il faut d’abord créer un dossier conditions et lui appliquer les bons droits :

sudo mkdir -p /usr/local/munki/conditions
sudo chown -R root:wheel /usr/local/munki/conditions
sudo chmod -R 755 /usr/local/munki/conditions

Tous les scripts interprétables positionnés dans ce dossier seront automatiquement lancés par la commande /usr/local/munki/managedsoftwareupdate lors d’une mise à jour, que ce soit en ligne de commande ou via l’interface graphique de Munki.

Je vais donc utiliser cette approche pour créer une clé hw_cpu64bit_capable que je pourrais ensuite exploiter. Il y a un exemple assez clair sur le wiki de Munki.

Pour créer le script

sudo nano /usr/local/munki/conditions/hw_cpu64bit_capable.sh

Voici mon script. Il est assez documenté pour que vous puissiez comprendre comment il bosse.
Collez-le dans nano :

#!/bin/sh
# 
# Ce script rends disponible la valeur de la commande '/usr/sbin/sysctl -n hw.cpu64bit_capable'
# comme 'hw_cpu64bit_capable' pour une utilisation avec les condtional_items de Munki
# hw_cpu64bit_capable = 1 > processeur compatible 64 bits
# hw_cpu64bit_capable = 0 > processeur compatible 32 bits
#
## <key>condition</key>
## <string>hw_cpu64bit_capable == 1</string>
#
# Merci à Greg pour le script dont je me suis inspiré | https://groups.google.com/forum/#!msg/munki-dev/nvzlCYxro8U/A1D5WLEVMNIJ

IFS=$'\n'

if [ `whoami` != 'root' ]
	then
	echo "Ce script doit être utilisé par le compte root. Utilisez sudo."
	exit 1
fi

# Obtenons la valeur de `/usr/sbin/sysctl -n hw.cpu64bit_capable`
CPU64BIT_CAPABLE=`/usr/sbin/sysctl -n hw.cpu64bit_capable`

# Création d'un fichier temporaire contenant la liste des fichiers ManagedInstall.plist (MCX | /private/var/root/Library/Preferences/ManagedInstalls.plist | /Library/Preferences/ManagedInstalls.plist)
LISTE_PLIST=$(mktemp /tmp/list-plist-munki.XXXXX)

# Lecture de l'emplace ManagedInstallDir depuis les différents fichiers ManagedInstall.plist trouvés et stockage dans notre fichier temporaire LISTE_PLIST
if [ -f /Library/Managed\ Preferences/ManagedInstalls.plist ] 
	then
	/usr/bin/defaults read /Library/Managed\ Preferences/ManagedInstalls ManagedInstallDir > /dev/null 2>&1
	[ $? -eq 0 ] && MANAGEDINSTALLDIR=$(/usr/bin/defaults read /Library/Managed\ Preferences/ManagedInstalls ManagedInstallDir) && echo $MANAGEDINSTALLDIR >> $LISTE_PLIST
fi
if [ -f /private/var/root/Library/Preferences/ManagedInstalls.plist ] 
	then
	/usr/bin/defaults read /private/var/root/Library/Preferences/ManagedInstalls ManagedInstallDir > /dev/null 2>&1
	[ $? -eq 0 ] && MANAGEDINSTALLDIR=$(/usr/bin/defaults read /private/var/root/Library/Preferences/ManagedInstalls ManagedInstallDir) && echo $MANAGEDINSTALLDIR >> $LISTE_PLIST
fi
if [ -f /Library/Preferences/ManagedInstalls.plist ] 
	then
	/usr/bin/defaults read /Library/Preferences/ManagedInstalls ManagedInstallDir > /dev/null 2>&1
	[ $? -eq 0 ] && MANAGEDINSTALLDIR=$(/usr/bin/defaults read /Library/Preferences/ManagedInstalls ManagedInstallDir) && echo $MANAGEDINSTALLDIR >> $LISTE_PLIST
fi

# Dédoublonnage des emplacements
sort -u ${LISTE_PLIST} > ${LISTE_PLIST}.new ; mv ${LISTE_PLIST}.new ${LISTE_PLIST}

# Pour chaque emplacement trouvé ...
cat $LISTE_PLIST | \
while read DIR_PLIST
do
	# Emplacement du fichier "ConditionalItems.plist" 
	# (la commande 'defaults' travaille sans extension '.plist')
	PLIST_LOC="${DIR_PLIST}/ConditionalItems"

	# Modification de l'entrée 'hw_cpu64bit_capable'
	[ $CPU64BIT_CAPABLE -eq 1 ] && sudo /usr/bin/defaults write "${PLIST_LOC}" hw_cpu64bit_capable -int 1
	[ $CPU64BIT_CAPABLE -ne 1 ] && sudo /usr/bin/defaults write "${PLIST_LOC}" hw_cpu64bit_capable -int 0

	# Comme la commande 'defaults' sort sur un plist binaire, nous le convertissons en XML. 
	sudo /usr/bin/plutil -convert xml1 "${PLIST_LOC}.plist"
	sudo chmod 755 "${PLIST_LOC}.plist"

done < $LISTE_PLIST

rm $LISTE_PLIST

exit 0

Quittez nano avec [CTRL] + X puis Yes et [Entrée].

N’oubliez pas de rendre le script exécutable

sudo chmod +x /usr/local/munki/conditions/hw_cpu64bit_capable.sh

Vous pouvez le lancer manuellement pour vérifier qu’il fonctionne correctement :

sudo /usr/local/munki/conditions/hw_cpu64bit_capable.sh

Vous devriez trouver dans votre dossier /Library/Managed Installs/ un nouveau fichier ConditionalItems.plist qui contiendra la clé nécessaire.

 

Il ne vous reste plus qu’à créer un petit package pour déployer cela sur tous vos postes : vous disposez maintenant d’une condition supplémentaire exploitable. J’ai choisi de gérer cela directement dans les installable_condition des pkginfo relatifs aux applications (voici la documentation).

  • Pour les processeurs 32 bits, ce sera donc la version 3.2 de XMind que je vais déployer, à laquelle j’associe la condition suivante, dans le fichier /votre_emplacement_du_repository_munki/pkgsinfo/XMind-3.2.plist :
    ...
    	<key>installable_condition</key>
    	<string>hw_cpu64bit_capable == 0</string>
    ...
  • Pour les processeurs 64 bits, ce sera donc la version 3.3.1 de XMind que je vais déployer, avec la condition suivante (dans le fichier /votre_emplacement_du_repository_munki/pkgsinfo/XMind-3.3.1.plist) :
    ...
    	<key>installable_condition</key>
    	<string>hw_cpu64bit_capable == 1</string>
    ...

 

Vous pouvez aussi choisir d’appliquer vos conditions directement au niveau du manifest, mais la structure du XML ne sera pas tout à fait la même.

Posted in Apple et MacintoshTags: