csmart / ansible-role-virt-infra

Define and manage guests and networks on a KVM host with Ansible
GNU General Public License v3.0
67 stars 48 forks source link

add support for network config via cloud-init #47

Closed csmart closed 3 years ago

csmart commented 3 years ago

This patchset enables support for basic network configuration v2 using cloud-init. Currently only ethernet devices are supported (not bonds, bridges or VLANs).

For details, see the cloud-init documentation: https://cloudinit.readthedocs.io/en/latest/topics/network-config-format-v2.html

As not all distros may support this, in order to activate network config please enable the following variable:

virt_infra_network_config: true

The network config is then populated with new optional network configuration options for each VM's network interfaces, including:

It is worth noting that none of the new options are actually required, but here is an example:

virt_infra_networks:

The network config format requires specifying a network device to configure which matches the actual interface. Unfortunately, there's no way to always know that, as some distros will enable persistent names and others won't.

For example, if we say "eth0" but the interfaces are actually "ens0" instead, then the config will still be written to eth0 and therefore not apply to ens0.

The solution to this is to rename the interface, so that it will match, however in order to ensre we pick the exact interface we must match on MAC address.

So, if a MAC address is not specified for the interface, this change also adds a way to ensure that VMs can use network config reliably by deterministically generating MAC addresses. As an ugly hack, it does this based on the interface's place in the list of networks (loop.index0), plus the standard random_mac method based on inventory hostname, e.g.

'{{ network.mac | default(('52:54:' + ("%02d" | format(loop.index0) |string)) | random_mac(seed=inventory_hostname)) }}'

If you have a better way to do this, I gladly accept patches!

Finally, the config must have a valid entry, it cannot be a blank file and it cannot just have boilerplate like this:

version: 2 ethernets:

Furthermore, if we have a MAC address specified then it must match a real interface on the box. Hence we generate them in the config if not specified and ensure the VM gets the same addresses on the same interfaces.

If either of these requirements are not met, cloud-init crashes and fails to read any other config so the VM fails to boot successfully.