Use Vagrant with libvirt unsupported boxes

Use Vagrant with libvirt unsupported boxes

Vagrant is an excellent tool for building and maintaining virtual development environments with plenty of configurations options and plugins for extending capabilities.

One of the major issues I found with Vagrant is the lack of libvirt supported boxes. Why? Because vagrant uses VirtualBox as its default provider. Vagrant boxes can be found in VagrantCloud or the popular website.

Enough with the Vagrant introduction. If you are here then that means you already have a pretty good idea about Vagrant. Let us cut to the chase. How to use existing VirtualBox images to work with libvirt or KVM?

Before getting into the configuration I assume you have already configured the vagrant,libvirt,qemu and KVM in your machine.

Installation of libvirt plugin can be found in the official vagrant-libvirt GitHub repository.

Then the next step is to install the awesome vagrant-mutate plugin.

On Fedora/RedHat/CentOS

$ yum install qemu-img libvirt-devel rubygem-ruby-libvirt ruby-devel redhat-rpm-config
$ vagrant plugin install vagrant-mutate

On Debian or Ubuntu derivatives

$ apt-get install qemu-utils libvirt-dev ruby-dev

On ArchLinux

$ pacman -S qemu
$ vagrant plugin install vagrant-mutate

you will see a similar output to this.

Now if you haven’t downloaded the Vagrant box, now is the time to download it. I have selected the Laravel/homestead box which I am using for Laravel development:

$ vagrant box add --provider virtualbox laravel/homestead
$ vagrant box list
laravel/homestead (virtualbox, 5.1.0)

Now the box is downloaded, it is pretty straightforward to convert it:

$ vagrant mutate laravel/homestead libvirt
Converting laravel/homestead from virtualbox to libvirt.
The box laravel/homestead (libvirt) is now ready to use.

This is the real magic. Now you have a libvirt supported Vagrant box:

$ vagrant box list
laravel/homestead (libvirt, 5.1.0)
laravel/homestead (virtualbox, 5.1.0)

If you have multiple providers, which means if you have downloaded boxes for e.g VirtualBox and KVM. You must specify the provider to use for input using the — input-provider option:

$ vagrant box list

Let us convert VirtualBox image to KVM, since we have our converted libvirt image we should specify virtualbox as our input image:

$ vagrant mutate --input-provider=virtualbox laravel/homestead kvm

If you see errors similar to below, that means Vagrant does not have the properly installed nokogiri plugin:

Traceback (most recent call last):
 9: from /opt/vagrant/embedded/gems/gems/vagrant-2.0.2/bin/vagrant:151:in `<main>'
 8: from /opt/vagrant/embedded/gems/gems/vagrant-2.0.2/lib/vagrant/environment.rb:269:in `cli'
 7: from /opt/vagrant/embedded/gems/gems/vagrant-2.0.2/lib/vagrant/cli.rb:46:in `execute'
 6: from /home/gamunu/.vagrant.d/gems/2.5.0/gems/vagrant-mutate-1.2.0/lib/vagrant-mutate/mutate.rb:47:in `execute'
 5: from /home/gamunu/.vagrant.d/gems/2.5.0/gems/vagrant-mutate-1.2.0/lib/vagrant-mutate/box_loader.rb:21:in `prepare_for_output'
 4: from /home/gamunu/.vagrant.d/gems/2.5.0/gems/vagrant-mutate-1.2.0/lib/vagrant-mutate/box_loader.rb:144:in `create_box'
 3: from /home/gamunu/.vagrant.d/gems/2.5.0/gems/vagrant-mutate-1.2.0/lib/vagrant-mutate/box_loader.rb:144:in `require_relative'
 2: from /home/gamunu/.vagrant.d/gems/2.5.0/gems/vagrant-mutate-1.2.0/lib/vagrant-mutate/box/kvm.rb:2:in `<top (required)>'
 1: from /usr/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
/usr/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require': cannot load such file -- nokogiri (LoadError)

Installed nokogiri as a Vagrant plugin and re-ran the command:

$ vagrant plugin install nokogiri
Fetching: mini_portile2-2.3.0.gem (100%)
Fetching: nokogiri-1.8.2.gem (100%)
Building native extensions. This could take a while...
Installed the plugin 'nokogiri (1.8.2)'!
$ vagrant mutate --input-provider=virtualbox laravel/homestead kvm
Converting laravel/homestead from virtualbox to kvm.
The box laravel/homestead (kvm) is now ready to use.

Now we have two additional boxes which support KVM and libvirt:

$ vagrant box list
laravel/homestead (kvm, 5.1.0)
laravel/homestead (libvirt, 5.1.0)
laravel/homestead (virtualbox, 5.1.0)

Now, these new boxes are ready to use. Use vagrant init to create a basic Vagrantfile and change the box name of the file to our converted box:

$ cat Vagrantfile
... = "laravel/homestead"

If you are running upstream Vagrant you need to always specify the provider which you want to use.

$ vagrant up --provider=libvirt