This role helps with managing libvirt networks from Ansible variables. For example, it allows to create,
modify and delete NAT based networks, routed networks, isolated networks, bridged networks and direct (MacVTap)
connections with variable libvirt_networks
. This variable is defined as a list where each
list item is a dictionary of parameters that will be passed to module jm1.libvirt.net_xml
from
collection jm1.libvirt
. For example, to create a NAT based network
named nat
with the system libvirt daemon (on the Ansible controller), define variable libvirt_networks
in
group_vars
or host_vars
as such:
# connect from Ansible controller to local libvirt daemon
ansible_connection: local
libvirt_networks:
- acl: allow
autostart: true
xml: |
<network>
<name>nat</name>
<bridge name="virbr-nat-0"/>
<forward mode="nat"/>
<ip address="192.168.123.1" netmask="255.255.255.0">
<dhcp>
<range start="192.168.123.100" end="192.168.123.254"/>
</dhcp>
</ip>
</network>
When this role is executed, it will pass each item of the libvirt_networks
list one after another as parameters to
module jm1.libvirt.net_xml
from collection jm1.libvirt
1. If a libvirt network with the same name already exists, it will be updated if
necessary.
If a list item does not contain key autostart
or if its set to true
then module community.libvirt.virt_net
from collection community.libvirt
will be used to mark that
network to be started automatically when the libvirt daemon starts.
If a list item contains key acl
then the capability to create TUN/TAP devices aka cap_net_admin+ep
will be added to
qemu-bridge-helper
and QEMU's config file /etc/qemu/bridge.conf
(on Debian, Fedora and Ubuntu)
or /etc/qemu-kvm/bridge.conf
(on CentOS or Red Hat Enterprise Linux) will be edited to allow or deny access to bridges
(created by qemu-bridge-helper
and implicitly invoked from libvirt daemon) for unprivileged users
2.
At the end the same module will be used to stop and restart libvirt networks automatically to apply pending changes at runtime.
If any list item in libvirt_networks
has its key state
set to absent
then module jm1.libvirt.net_xml
will be used to stop (destroy) and delete (undefine) this network. Any line in QEMU's config file
/etc/qemu/bridge.conf
or /etc/qemu-kvm/bridge.conf
which lists the bridge name of an absent
libvirt
network will be removed to revoke access to bridges for unprivileged users 2.
Tested OS images
- Cloud image (
amd64
) of Debian 10 (Buster) - Cloud image (
amd64
) of Debian 11 (Bullseye) - Cloud image (
amd64
) of Debian 12 (Bookworm) - Cloud image (
amd64
) of Debian 13 (Trixie) - Cloud image (
amd64
) of CentOS 7 (Core) - Cloud image (
amd64
) of CentOS 8 (Stream) - Cloud image (
amd64
) of CentOS 9 (Stream) - Cloud image (
amd64
) of Fedora Cloud Base 40 - Cloud image (
amd64
) of Ubuntu 18.04 LTS (Bionic Beaver) - Cloud image (
amd64
) of Ubuntu 20.04 LTS (Focal Fossa) - Cloud image (
amd64
) of Ubuntu 22.04 LTS (Jammy Jellyfish) - Cloud image (
amd64
) of Ubuntu 24.04 LTS (Noble Numbat)
Available on Ansible Galaxy in Collection jm1.cloudy.
This role uses module(s) from collections community.general
, community.libvirt
and jm1.libvirt
. To install these collections you may follow the steps
described in README.md
using the provided requirements.yml
.
Name | Default value | Required | Description |
---|---|---|---|
distribution_id |
depends on operating system | false | List which uniquely identifies a distribution release, e.g. [ 'Debian', '10' ] for Debian 10 (Buster) |
libvirt_networks |
[] |
false | List of parameter dictionaries for module jm1.libvirt.net_xml from collection jm1.libvirt 2 3 1 4 |
libvirt_uri |
qemu:///system |
false | libvirt connection uri |
None.
- hosts: all
become: true # connection to system libvirt daemon requires root privileges
vars:
# Variables are listed here for convenience and illustration.
# In a production setup, variables would be defined e.g. in
# group_vars and/or host_vars of an Ansible inventory.
# Ref.:
# https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html
# https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html
# connect from Ansible controller to local libvirt daemon
ansible_connection: local
libvirt_networks:
- acl: allow
autostart: true
xml: |
<network>
<name>nat</name>
<bridge name="virbr-nat-0"/>
<forward mode="nat"/>
<ip address="192.168.123.1" netmask="255.255.255.0">
<dhcp>
<range start="192.168.123.100" end="192.168.123.254"/>
</dhcp>
</ip>
</network>
roles:
- name: Setup libvirt virtual networks
role: jm1.cloudy.libvirt_networks
tags: ["jm1.cloudy.libvirt_networks"]
For complete examples on how to use this role, refer to hosts lvrt-lcl-session
and lvrt-lcl-system
from the provided
examples inventory. The top-level README.md
describes how these hosts can be
provisioned with playbook playbooks/site.yml
.
For instructions on how to run Ansible playbooks have look at Ansible's Getting Started Guide.
GNU General Public License v3.0 or later
See LICENSE.md to see the full text.
Jakob Meng @jm1 (github, galaxy, web)
Footnotes
-
If a list item does not contain key
uri
then it will be initialized from Ansible variableslibvirt_uri
. ↩ ↩2 -
Each list item in
libvirt_networks
can have an optional keyacl
which specifies whether unprivileged users do have access to bridges created byqemu-bridge-helper
(implicitly invoked from libvirt daemon). Valid values foracl
areallow
anddeny
. Ifacl
is present, then a line will be added to/etc/qemu/bridge.conf
or/etc/qemu-kvm/bridge.conf
to allow or deny access to QEMU bridges for unprivileged users. Details can be found inroles/libvirt_networks/tasks/main.yml
. Ifstate
of a list item isabsent
and keyacl
is present, then any line in/etc/qemu/bridge.conf
or/etc/qemu-kvm/bridge.conf
which lists the libvirt network will be removed to revoke access to bridges for unprivileged users. ↩ ↩2 ↩3 -
If key
autostart
is present in a list item and it evaluates totrue
, then modulecommunity.libvirt.virt_net
from collectioncommunity.libvirt
will be used to mark that network to be started automatically when the libvirt daemon starts. ↩ -
If key
xml
is present in a list item, then it will be passed unchanged tojm1.libvirt.net_xml
. Ifxml
is not present butxml_file
is present in a list item, then the file path stored inxml_file
will be read with Ansible'slookup('template', item.xml_file)
plugin and passed as parameterxml
to modulejm1.libvirt.net_xml
. If bothxml
andxml_var
are not present in a list item but keyxml_var
is, then the variable named byxml_var
will be read with Ansible'slookup('vars', item.xml_var)
plugin and passed as parameterxml
to modulejm1.libvirt.net_xml
. ↩