published: 25th of October 2017
One of the quirks of Vagrants Virtualbox provider is you cannot configure the IP address of the management interface. It's a core design principal of the project that the management interface IP of a box is configured via DHCP. The Virtualbox provider uses port forwarding with a NAT network to communicate between the Host and the guest box, this behaviour cannot be changed.
In a previous post I installed the vagrant-libvirt provider for use with Vagrant. In this post I will cover how to control the IP address assigned to the Vagrant box management interface when using the vagrant-libvirt provider.
You might ask why you would want to do this. Great question. Having a method to predictably assign an IP address to a Vagrant box is useful for a number of scenarios. I find this most relevant when using provisioning tools such as Ansible and Salt to configure VM's once Vagrant has deployed them. This allows me to use the same inventory files I would normally use and not have to monkey around with the Vagrant provisioner config.
Libvirt comes with a command line tool virsh , we can use this tool to interact and control a hypervisors network, storage etc...
Firstly lets confirm that the vagrant-libvirt network is configured. This is the network that Vagrant VMs will use for their management interfaces.
virsh net-list --all
# output
Name State Autostart Persistent
---------------------------------------------------------
default active yes yes
vagrant-libvirt active yes yes
Libvirt network configurations are xml files stored in the /etc/libvirt/<hypervisor>/networks/ directory. Before we make any modifications lets check the current config of the vagrant-libvirt network.
virsh net-dumpxml vagrant-libvirt
# output
<network ipv6='yes'>
<name>vagrant-libvirt</name>
<uuid>589814cf-fdf7-45c8-87bc-707314b9254d</uuid>
<forward mode='nat'>
<nat>
<port start='1024' end='65535'/>
</nat>
</forward>
<bridge name='virbr1' stp='on' delay='0'/>
<mac address='52:54:00:0e:6d:db'/>
<ip address='192.168.121.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.121.1' end='192.168.121.254'/>
</dhcp>
</ip>
</network>
You can see above that the IP range for the vagrant-libvirt network is 192.168.121.0/24 and the DHCP range is 192.168.121.1 - 254 . This network is mapped to a virtual interface on the host machine called virbr1 .
It is part of the core design of Vagrant that the management interface of a box gets an IP address via DHCP. This means we cannot directly assign an IP address to the management interface, we can however use some tried and true techniques to ensure a box gets the IP address we intend.
Enter the world of DHCP reservations. We can control the MAC address assigned to a Vagrant box's management interface, then use the same MAC address to reserve an IP address in the DHCP Configuration of the vagrant-libvirt network.
Coming up next I will reserve the IP address; 192.168.121.111 for the MAC address; 52:54:00:00:01:01 in the vagrant-libvirt network.
In the Vagrantfile define the MAC address for the box's management network with the management_network_mac parameter under the libvirt domain specific configuration.
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.define "spine01" do |node|
node.vm.hostname = "spine01"
node.vm.box = "CumulusCommunity/cumulus-vx"
node.vm.synced_folder ".", "/vagrant", disabled: true
# Provider-specific configuration
node.vm.provider :libvirt do |domain|
domain.management_network_mac = "52:54:00:00:01:01" # Management interface MAC
end
end
end
Use the virsh tool to add a DHCP reservation to the vagrant-libvirt network.
virsh net-update vagrant-libvirt add-last ip-dhcp-host \
'<host mac="52:54:00:00:01:01" ip="192.168.121.111"/>' \
--live --config --parent-index 0
# output
Updated network vagrant-libvirt persistent config and live state
Confirm that the DHCP reservation was added to the vagrant-libvirt network.
virsh net-dumpxml vagrant-libvirt
# output
<network ipv6='yes'>
<name>vagrant-libvirt</name>
<uuid>589814cf-fdf7-45c8-87bc-707314b9254d</uuid>
<forward mode='nat'>
<nat>
<port start='1024' end='65535'/>
</nat>
</forward>
<bridge name='virbr1' stp='on' delay='0'/>
<mac address='52:54:00:0e:6d:db'/>
<ip address='192.168.121.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.121.1' end='192.168.121.254'/>
<host mac='52:54:00:00:01:01' ip='192.168.121.111'/> # New DHCP reservation
</dhcp>
</ip>
</network>
Use the above Vagrantfile to build a test VM and confirm the intended IP address was assigned.
vagrant up --provider=libvirt
# output
Bringing machine 'spine01' up with 'libvirt' provider...
==> spine01: Creating image (snapshot of base box volume).
==> spine01: Creating domain with the following settings...
..
<snip>
..
==> spine01: Setting hostname...
==> spine01: Configuring and enabling network interfaces...
Login to the box and confirm the intended IP address was assigned to the management interface.
vagrant@spine01:~$ sudo net show int eth0
# output
Name MAC Speed MTU Mode
-- ------ ----------------- ------- ----- ------
UP eth0 52:54:00:00:01:01
1G 1500 Mgmt
IP Details
------------------------- ------------------
IP: 192.168.121.111/24
IP Neighbor(ARP) Entries: 1
From the host shell we can also see the DHCP reservation in the /var/lib/libvirt/dnsmasq/virbr1.status file.
cat /var/lib/libvirt/dnsmasq/virbr1.status
# output
[
{
"ip-address": "192.168.121.111",
"mac-address": "52:54:00:00:01:01",
"hostname": "spine01",
"expiry-time": 1508917500
}
]
There you have it, The Vagrant box received the IP address we intended and all is right with the force.
The virsh tool can also be used to delete a DHCP reservation. Generally I dont do this and re-use the same reservations across many Vagrant environments.
virsh net-update vagrant-libvirt delete ip-dhcp-host \
'<host mac="52:54:00:00:01:01" ip="192.168.121.111"/>' \
--live --config --parent-index 0
# output
Updated network vagrant-libvirt persistent config and live state
Using the libvirt-vagrant provider allows us to predictibly define a box's management IP address. Vagrant is a great tool and using Libvert makes it even greater.
http://wiki.libvirt.org/page/VirtualNetworking
https://github.com/vagrant-libvirt/vagrant-libvirt/issues/409
https://jamielinux.com/docs/libvirt-networking-handbook/appendix/dhcp-host-entries.html