Vagrant-Libvirt sur Apple Silicon (M1 et M2)

Vagrant-Libvirt sur Apple Silicon (M1 et M2)

Salut à tous ! 👋

Aujourd’hui, je vais partager mon retour d’expérience sur l’installation du plugin Vagrant-libvirt sur un Macbook Air M2. Je vais être honnête avec vous : ça n’a pas été de tout repos. J’ai rencontré un gros problème en chemin : les Macbook et leurs architectures processeur ARM64 ne sont pas encore officiellement supportés par Hashicorp Vagrant et son plugin Vagrant-libvirt. Pour trouver une solution et faire fonctionner tout ça, j’ai dû sacrifier quelques heures de sommeil, quelques repas et sorties au cinéma. 😅 Mon homelab faisant tourner libvirt/kvm est important pour moi, car c’est sur lui que j’excerce en créant des VMs pour écrire des articles et partager mes expériences. Dans cet article, je vais essayer de vous expliquer la procédure d’installation étape par étape. Si vous êtes dans la même situation que moi, j’espère que ça vous sera utile !

Je tiens à préciser que [Hashicorp Vagrant][hv] et son plugin [Vagrant-libvirt][vl] sont codés en Ruby, et que je n’ai aucune expérience dans ce langage de programmation et son écosystème. Cela signifie qu’il est possible que certaines étapes de ma procédure soient bancales ou incomplètes. Si vous êtes un expert en Ruby et que vous repérez des erreurs ou des manques dans mon article, n’hésitez pas à me le faire savoir ! En outre, si vous repérez des erreurs ou des imprécisions, je me ferai un plaisir de les corriger afin de rendre cette article le plus qualitatif et intelligible possible pour d’autres personnes dans la même situation que moi.

Bon à savoir avant de commencer

Je vais partager avec vous une procédure que j’ai écrite et testée sur mon setup personnel. J’utilise un MacBook Air M2 et j’ai installé macOS Ventura 13.1. Je tiens à préciser que j’ai toujours les dernières mises à jour et que mes paquets brew sont à jour aussi. Et enfin, 2 petits détails qui ont leurs importances :

  1. Je ne suis pas sur ZSH mais sur le bon vieux BASH
  2. Aucun logiciel de virtualisation n’est présent sur ma machine (virtualbox, parallels, etc…)

Donc si vous avez un setup similaire, ça devrait bien fonctionner pour vous aussi !

Prérequis

  1. Avant de passer à l’installation il va nous falloir installer via brew les paquets suivants:
brew install libvirt qemu gnupg
  1. Clonez les 3 repositories github à l’endroit de votre choix ! Pour ma part, c’est dans ~/.vagrant.
mkdir ~/.vagrant
pushd ~/.vagrant
    git clone https://github.com/hashicorp/vagrant-spec.git hashicorp/vagrant-spec \
        && git -C ./hashicorp/vagrant-spec checkout 259c55e
    git clone -b v2.3.4 https://github.com/hashicorp/vagrant.git hashicorp/vagrant
    git clone -b 0.11.2 https://github.com/vagrant-libvirt/vagrant-libvirt.git vagrant-libvirt/vagrant-libvirt
popd
  1. Installer Ruby Version Manager (RVM)

Do NOT use the system Ruby - use a Ruby version manager like rvm or chruby By the Hashicorp team! 👮‍♂️

# Dans un premier temps, installez les clés GPG utilisées pour vérifier le paquet d'installation
curl -sSL https://rvm.io/mpapis.asc | gpg --import -
curl -sSL https://rvm.io/pkuczynski.asc | gpg --import -
# Installe la version stable de RVM avec Ruby
curl -sSL https://get.rvm.io | bash -s stable --ruby
# Dans mon cas, je suis sur un shell bash et non zsh,
# je copie donc cette ligne dans mon ~/.bash_profile
echo '[ -f ~/.profile ] && source ~/.profile' >> ~/.bash_profile \
    && source ~/.bash_profile
# Et enfin créez un environnement virtuel Ruby en version 3.1.x
rvm install 3.1.3

Installation

Comme je l’ai mentionné au début de l’article, HashiCorp Vagrant et son plugin Vagrant-libvirt ne supportent pas officiellement les Apple Silicon (M1 et M2) et leur architecture ARM64. Seul la version AMD64 de Hashicorp Vagrant nous est proposé en téléchargement depuis le repo officiel, et non Rossetta2 ne fera pas l’affaire 😡 !. Pour rendre Hashicorp Vagrant, Vagrant-libvirt et Vagrant-spec compatibles avec l’architecture ARM64, nous allons devoir compiler les sources que nous avons préalablement clonées. Dans la suite de cette section, je vais vous expliquer comment faire.

Vagrant-spec

À noté que vagrant-spec est une dépendance clé de vagrant !

  1. Rendez-vous dans votre répertoire ~/.vagrant/hashicorp/vagrant-spec que vous venez de cloner et assurez-vous d’avoir fait un checkout sur le commit ID 259c55e. Ensuite, fixez la version de la dépendance grpc à 1.47.0, qu’est à ce jour la seule version récente compatible avec ruby-3.x.
sed -i ' ' '26 s/$/  spec.add_dependency "grpc", "= 1.47.0"\n/' vagrant-spec.gemspec
sed -i ' ' '27 s/$/  spec.add_dependency "grpc-tools", "= 1.41"\n/' vagrant-spec.gemspec
  1. Créer le Gemset 3.1.3@vagrant-spec !

    Un gemset est comme un environnement virtuel qui permet de séparer les différentes versions de gems (bibliothèques logicielles) utilisées par une application Ruby.

rvm use ruby-3.1.3@vagrant-spec --create
  1. Installez tous les gems nécessaires à l’application
bundle install
  1. Maintenant, passons à la prochaine étape : transformons ça en un gem que nous utiliserons lors de l’installation de vagrant. Si on laisse vagrant s’en occuper tout seul en lançant bundle install, on risque de se retrouver dans une situation où le processus va échouer. En effet, il va essayer d’installer une version de grpc qui n’est pas égale à 1.47.0, et on se rappelle que cette version n’est pas compatible avec notre version de ruby 3.1.3 ! Pour éviter ce genre de désagrément, mieux vaut prendre les devants et faire en sorte que tout soit en ordre dès le départ.
bundle exec rake build

Le gem généré se trouvera ici: pkg/vagrant-spec-0.0.1.gem, nous-y reviendrons dans 1 minute.

Vagrant

  1. Rendez-vous dans votre repository ~/.vagrant/hashicorp/vagrant fraichement cloné et assurez-vous d’avoir checkout sur v2.3.4 puis fixer la version de la dépendance grpc à 1.47.0, pour les mêmes raisons que je vous ai mentionnées plus haut.
sed -i '' '23 s/"grpc"$/"grpc", "= 1.47.0"\n/g' vagrant.gemspec
  1. Créer le Gemset 3.1.3@vagrant !
rvm use ruby-3.1.3@vagrant --create
  1. Installer le gem de vagrant-spec précédemment généré
bundle exec gem install ../vagrant-spec/pkg/vagrant-spec-0.0.1.gem

Ne paniquez pas les amis, si vous rencontrez l'erreur suivante, pas de souci ! On a tous été là. Il est possible que cette erreur soit liée à une configuration particulière de votre environnement, mais on va se sortir de là ensemble. Suivons simplement les étapes suivantes et tout ira bien.

Could not find gem 'grpc-tools (= 1.41)' in locally installed gems.
Run `bundle install` to install missing gems.
  1. Installons ensuite les gems nécessaires à l’application
bundle install

Bonne nouvelle ! À ce stade, vagrant est opérationnel. Si vous lancez la commande ci-dessous, vous devriez voir s’afficher la page d’aide de vagrant lui-même. Essayez-le, c’est rassurant de voir que tout fonctionne comme prévu après toutes les manips qu’on vient de faire.

bundle exec vagrant help

Ne paniquez pas les amis, si vous rencontrez l'erreur suivante, pas de souci ! Exécutez la commande `bundle exec vagrant plugin update` si l'erreur ci-dessous apparaît avant de retenter la commande présenter à l'étape `4`.

Error message given during initialization: Unable to resolve dependency: user requested 'vagrant-hostmanager (= 1.8.9)'

Cela devrait vous donner une idée de toutes les commandes et les options disponibles pour utiliser vagrant.

Voilà qui est fait, revenons à ~/.vagrant/hashicorp/vagrant un peu plus tard dans la procédure…

Vagrant-libvirt

Et hop, c’est parti ! Maintenant que nous avons un vagrant qui fonctionne, compilé directement pour et depuis une architecture ARM64, passons à l’installation de son plugin vagrant-libvirt. C’est la prochaine étape logique après avoir réussi à faire fonctionner vagrant, l’utilisation de plugin vient compléter les fonctionnalités de base de vagrant. Il est temps de continuer à avancer dans notre projet.

  1. Rendez-vous dans votre repository ~/.vagrant/vagrant-libvirt/vagrant-libvirt assurez-vous d’avoir checkout sur 0.11.2 puis fixer la version de la dépendance grpc à 1.47.0.
sed -i ' ' '28 s/$/  s.add_runtime_dependency "grpc", "= 1.47.0"\n/' vagrant-libvirt.gemspec
sed -i ' ' '29 s/$/  s.add_runtime_dependency "grpc-tools", "= 1.41"\n/' vagrant-libvirt.gemspec
  1. Toujours en étant dans le gemset 3.1.3@vagrant, installez le bundle vagrant-libvirt
bundle install
  1. Transformons ça en un gem que nous utiliserons lors de l’installation en tant que plugin vagrant.
bundle exec rake build

Le gem généré se trouvera ici: pkg/vagrant-libvirt-0.11.2.gem, nous-y reviendrons dans 1 minute.

Installer vagrant-libvirt en tant que plugin de vagrant

Vous êtes toujours là avec moi ? Tout s’est déroulé sans problème ? Cool continuons… 😛

  1. Bon bah lançons les dernières commandes tant attendu
pushd ~/.vagrant/hashicorp/vagrant
    # Installer le plugin depuis le gem précédemment généré
    rvm 3.1.3@vagrant do bundle exec vagrant plugin install ~/.vagrant/vagrant-libvirt/vagrant-libvirt/pkg/vagrant-libvirt-0.11.2.gem
    # Vérifions que tout s'est bien déroulé, listons les plugins installés et voyant si notre petit est présent.
    rvm 3.1.3@vagrant do bundle exec vagrant plugin list
popd

Félicitations, vous êtes un vrai champion voilà vagrant-libvirt et prêt à vous rendre de fiers service ! Je suis fier de vous, si si c’est vrai 🙃 Cela montre que vous avez été patient et persévérant (et accessoirement que mon article vous plaît :D) !

Configuration de l’environnement utilisateur

Maintenant que nous y sommes, vous avez peut-être remarqué que lorsque vous ouvrez un nouveau shell en dehors d’un contexte de Gemset RVM, l’exécution de la commande vagrant génère une erreur.

C’est normal, car RVM ne gère pas les contexts de manière permanente. Il est donc nécessaire de l’initialiser à chaque ouverture de shell avec rvm use 3.1.3@vagrant et se rendre dans le dossier ~/.vagrant/hashicorp/vagrant avant d’executer la commande bundle exec vagrant <action> [options] si vous souhaitez continuer à utiliser vagrant.

Qu’on se le disent, c’est très embétant ! D’autant plus que notre répertoire de travail dans lequel se trouve notre Vagrantfile n’est certainement pas dans ~/.vagrant/hashicorp/vagrant, et je n’ose même pas évoquer l’autocompletion que l’on perd ! Bref, on peut mieux faire et c’est ce que je propose de faire maintenant. :)

Rester dans votre répertoire projet pour faire appel à la commande vagrant

  1. Ouvrez votre fichier ~/.bashrc et ajouter ces lignes.
function vagrant() {
    # Pour commencer, récupérez le chemin du répertoire de projet courant où se
    # trouve le Vagrantfile et passez-le à VAGRANT_CWD
    local current_project_directory=$(pwd)
    # Désactiver les messages d'avertissement indiquant que le chemin de
    # l'exécutable vagrant n'est pas dans notre $PATH
    local rvm_silence_path_mismatch_check_flag=1
    # Pour poursuivre, déplacez-vous dans le dossier où se trouve vagrant pour
    # que l'appel à la commande vagrant puisse réussir
    pushd ~/.vagrant/hashicorp/vagrant >/dev/null
        # Finalement, exécutez vagrant en lui transmettant les arguments supplémentaires `$@`
        # founir à l'appel de la commande hv() tout en définissant la variable d'environnement
        # VAGRANT_CWD sur $current_project_directory pour que vagrant sache où il se trouve.
        # https://developer.hashicorp.com/vagrant/docs/other/environmental-variables#vagrant_cwd
        VAGRANT_CWD=$current_project_directory \
            VAGRANT_INSTALLER_ENV="silent" \
            rvm 3.1.3@vagrant do bundle exec vagrant $@
    popd >/dev/null
}
  1. Demander l’ajout de l’autocompletion à votre ~/.bashrc
pushd ~/.vagrant/hashicorp/vagrant
    rvm 3.1.3@vagrant do bundle exec vagrant autocomplete install
popd

Enfin, pour que tous ces changements soient pris en compte, éxecutez la commande source ~/.bashrc pour mettre à jour votre environnement.

  1. Allez dans votre répertoire projet pour tester que tout fonctionne comme prévu avant de me laisser un commentaire. Cela me permettra de savoir si cette solution fonctionne pour vous et si vous avez des remarques pour améliorer cette méthode.
cd /chemin/du/répertoire/projet
vagrant help
vagrant status
vagrant up
vagrant status
vagrant destroy

Envoy !

Rafraîchis la page si la section des commentaires ci-dessous ne s'affiche pas correctement !
(Win) Ctrl+Shift+R ou (Mac) Cmd+Shift+R

Qui suis-je ?

Babacar TALL

Babacar TALL

Je suis un Cloud Architect et DevOps Microsoft Azure (+15 ans d’expérience) avec une longue expérience de développeur. Au cours de mon expérience, j’ai contribué à la mise en place, à l’exploitation et à la maintenance de programmes et …

En savoir plus