Add support for bonded (LAG) host network interfaces

This is configured by setting the <network>_bond_slaves variable to a list
of network interfaces to act as slaves.
This commit is contained in:
Mark Goddard 2017-08-05 08:50:38 +00:00
parent b9e1243d7d
commit 2afc6fabae
5 changed files with 115 additions and 2 deletions

View File

@ -137,6 +137,11 @@ def net_bridge_ports(context, name, inventory_hostname=None):
return net_attr(context, name, 'bridge_ports', inventory_hostname)
net_bond_mode = _make_attr_filter('bond_mode')
net_bond_slaves = _make_attr_filter('bond_slaves')
net_bond_miimon = _make_attr_filter('bond_miimon')
def _route_obj(route):
"""Return a dict representation of an IP route.
@ -226,14 +231,82 @@ def net_bridge_obj(context, name, inventory_hostname=None):
return interface
@jinja2.contextfilter
def net_bond_obj(context, name, inventory_hostname=None):
"""Return a dict representation of a network bond interface.
The returned dict is compatible with the interfaces_bond_interfaces
variable in the MichaelRigaert.interfaces role.
"""
device = net_interface(context, name, inventory_hostname)
if not device:
raise errors.AnsibleFilterError(
"Network interface for network '%s' on host '%s' not found" %
(name, inventory_hostname))
ip = net_ip(context, name, inventory_hostname)
cidr = net_cidr(context, name, inventory_hostname)
netmask = net_mask(context, name, inventory_hostname)
gateway = net_gateway(context, name, inventory_hostname)
vlan = net_vlan(context, name, inventory_hostname)
mtu = net_mtu(context, name, inventory_hostname)
mode = net_bond_mode(context, name, inventory_hostname)
slaves = net_bond_slaves(context, name, inventory_hostname)
miimon = net_bond_miimon(context, name, inventory_hostname)
routes = net_routes(context, name, inventory_hostname)
if routes:
routes = [_route_obj(route) for route in routes]
interface = {
'device': device,
'address': ip,
'netmask': netmask,
'gateway': gateway,
'vlan': vlan,
'mtu': mtu,
'bond_slaves': slaves,
'bond_mode': mode,
'bond_miimon': miimon,
'route': routes,
'bootproto': 'static',
'onboot': 'yes',
}
interface = {k: v for k, v in interface.items() if v is not None}
return interface
def _net_interface_type(context, name, inventory_hostname):
"""Return a string describing the network interface type.
Possible types include 'ether', 'bridge', 'bond'.
"""
bridge_ports = net_bridge_ports(context, name, inventory_hostname)
bond_slaves = net_bond_slaves(context, name, inventory_hostname)
if bridge_ports is not None and bond_slaves is not None:
raise errors.AnsibleFilterError(
"Network %s on host %s has both bridge ports and bond slaves "
"defined" %
(name,
_get_hostvar(context, 'inventory_hostname', inventory_hostname)))
if bridge_ports is None and bond_slaves is None:
return 'ether'
if bridge_ports is not None:
return 'bridge'
if bond_slaves is not None:
return 'bond'
@jinja2.contextfilter
def net_is_ether(context, name, inventory_hostname=None):
return net_bridge_ports(context, name) is None
return _net_interface_type(context, name, inventory_hostname) == 'ether'
@jinja2.contextfilter
def net_is_bridge(context, name, inventory_hostname=None):
return net_bridge_ports(context, name) is not None
return _net_interface_type(context, name, inventory_hostname) == 'bridge'
@jinja2.contextfilter
def net_is_bond(context, name, inventory_hostname=None):
return _net_interface_type(context, name, inventory_hostname) == 'bond'
@jinja2.contextfilter
@ -251,6 +324,11 @@ def net_select_bridges(context, names):
return [name for name in names if net_is_bridge(context, name)]
@jinja2.contextfilter
def net_select_bonds(context, names):
return [name for name in names if net_is_bond(context, name)]
@jinja2.contextfilter
def net_select_vlans(context, names):
return [name for name in names if net_is_vlan(context, name)]
@ -338,11 +416,14 @@ class FilterModule(object):
'net_routes': net_routes,
'net_interface_obj': net_interface_obj,
'net_bridge_obj': net_bridge_obj,
'net_bond_obj': net_bond_obj,
'net_is_ether': net_is_ether,
'net_is_bridge': net_is_bridge,
'net_is_bond': net_is_bond,
'net_is_vlan': net_is_vlan,
'net_select_ethers': net_select_ethers,
'net_select_bridges': net_select_bridges,
'net_select_bonds': net_select_bonds,
'net_select_vlans': net_select_vlans,
'net_reject_vlans': net_reject_vlans,
'net_configdrive_network_device': net_configdrive_network_device,

View File

@ -6,6 +6,7 @@
vars:
ether_interfaces: "{{ network_interfaces | net_select_ethers | list }}"
bridge_interfaces: "{{ network_interfaces | net_select_bridges | list }}"
bond_interfaces: "{{ network_interfaces | net_select_bonds | list }}"
pre_tasks:
- block:
- name: Validate network interface configuration
@ -23,6 +24,14 @@
{{ item }}. This should be configured via '{{ item }}_interface'.
with_items: "{{ bridge_interfaces }}"
when: "{{ not item | net_interface }}"
- name: Validate bond interface configuration
fail:
msg: >
Bond interface validation failed - no interface configured for
{{ item }}. This should be configured via '{{ item }}_interface'.
with_items: "{{ bond_interfaces }}"
when: "{{ not item | net_interface }}"
tags:
- config-validation
@ -57,6 +66,10 @@
{{ bridge_interfaces |
map('net_bridge_obj') |
list }}
interfaces_bond_interfaces: >
{{ bond_interfaces |
map('net_bond_obj') |
list }}
become: True
- role: MichaelRigart.interfaces

View File

@ -168,6 +168,13 @@ The following attributes are supported:
``bridge_ports``
For bridge interfaces, a list of names of network interfaces to add to the
bridge.
``bond_mode``
For bond interfaces, the bond's mode, e.g. 802.3ad.
``bond_slaves``
For bond interfaces, a list of names of network interfaces to act as slaves
for the bond.
``bond_miimon``
For bond interfaces, the time in milliseconds between MII link monitoring.
In order to provide flexibility in the system's network topology, Kayobe maps
the named networks to logical network roles. A single named network may

View File

@ -5,26 +5,32 @@
# Overcloud provisioning network IP information.
# provision_oc_net_interface:
# provision_oc_net_bridge_ports:
# provision_oc_net_bond_slaves:
# Workload provisioning network IP information.
# provision_wl_net_interface:
# provision_wl_net_bridge_ports:
# provision_wl_net_bond_slaves:
# Internal network IP information.
# internal_net_interface:
# internal_net_bridge_ports:
# internal_net_bond_slaves:
# External network IP information.
# external_net_interface:
# external_net_bridge_ports:
# external_net_bond_slaves:
# Storage network IP information.
# storage_net_interface:
# storage_net_bridge_ports:
# storage_net_bond_slaves:
# Storage management network IP information.
# storage_mgmt_net_interface:
# storage_mgmt_net_bridge_ports:
# storage_mgmt_net_bond_slaves:
###############################################################################
# Dummy variable to allow Ansible to accept this file.

View File

@ -5,26 +5,32 @@
# Overcloud provisioning network IP information.
# provision_oc_net_interface:
# provision_oc_net_bridge_ports:
# provision_oc_net_bond_slaves:
# Workload provisioning network IP information.
# provision_wl_net_interface:
# provision_wl_net_bridge_ports:
# provision_wl_net_bond_slaves:
# Internal network IP information.
# internal_net_interface:
# internal_net_bridge_ports:
# internal_net_bond_slaves:
# External network IP information.
# external_net_interface:
# external_net_bridge_ports:
# external_net_bond_slaves:
# Storage network IP information.
# storage_net_interface:
# storage_net_bridge_ports:
# storage_net_bond_slaves:
# Storage management network IP information.
# storage_mgmt_net_interface:
# storage_mgmt_net_bridge_ports:
# storage_mgmt_net_bond_slaves:
###############################################################################
# Dummy variable to allow Ansible to accept this file.