Support more bond options

In order to enable user to flexibly control the network transmission
over the bonded interface, support all the bond options which are
currently supported by NetworkManager.

Signed-off-by: Wen Liang <liangwen12year@gmail.com>
This commit is contained in:
Wen Liang 2022-02-02 07:57:20 -05:00 committed by Till Maas
parent fde69e0758
commit 59be618857
8 changed files with 851 additions and 12 deletions

144
README.md
View file

@ -692,19 +692,149 @@ SSL certificates and keys must be deployed on the host prior to running the role
### `bond`
The `bond` setting configures the options of bonded interfaces
(type `bond`). It supports the following options:
The `bond` setting configures the options of bonded interfaces (type `bond`).
See the [kernel documentation for
bonding](https://www.kernel.org/doc/Documentation/networking/bonding.txt) or
your distribution `nmcli` documentation for valid values. It supports the
following options:
- `mode`
Bonding mode. See the
[kernel documentation](https://www.kernel.org/doc/Documentation/networking/bonding.txt)
or your distribution `nmcli` documentation for valid values.
NetworkManager defaults to `balance-rr`.
Bonding mode. The possible values are `balance-rr` (default), `active-backup`,
`balance-xor`, `broadcast`, `802.3ad`, `balance-tlb`, or `balance-alb`.
- `ad_actor_sys_prio`
In `802.3ad` bonding mode, this specifies the system priority. The valid range is
1 - 65535.
- `ad_actor_system`
In `802.3ad` bonding mode, this specifies the system mac-address for the actor in
protocol packet exchanges (LACPDUs).
- `ad_select`
This option specifies the 802.3ad aggregation selection logic to use. The possible
values are: `stable`, `bandwidth`, `count`.
- `ad_user_port_key`
In `802.3ad` bonding mode, this defines the upper 10 bits of the port key. The
allowed range for the value is 0 - 1023.
- `all_ports_active`
`all_slaves_active` in kernel and NetworkManager. The boolean value `False` drops
the duplicate frames (received on inactive ports) and the boolean value `True`
delivers the duplicate frames.
- `arp_all_targets`
This option specifies the quantity of arp_ip_targets that must be reachable in
order for the ARP monitor to consider a port as being up. The possible values are
`any` or `all`.
- `arp_interval`
This option specifies the ARP link monitoring frequency in milliseconds. A value of
0 disables ARP monitoring.
- `arp_validate`
In any mode that supports arp monitoring, this option specifies whether or not ARP
probes and replies should be validated. Or for link monitoring purposes, whether
non-ARP traffic should be filtered (disregarded). The possible values are: `none`,
`active`, `backup`, `all`, `filter`, `filter_active`, `filter_backup`.
- `arp_ip_target`
When `arp_interval` is enabled, this option specifies the IP addresses to use as
ARP monitoring peers.
- `downdelay`
The time to wait (in milliseconds) before disabling a port after a link failure
has been detected.
- `fail_over_mac`
This option specifies the policy to select the MAC address for the bond interface
in active-backup mode. The possible values are: `none` (default), `active`,
`follow`.
- `lacp_rate`
In `802.3ad` bonding mode, this option defines the rate in which we requst link
partner to transmit LACPDU packets. The possible values are: `slow`, `fast`.
- `lp_interval`
This option specifies the number of seconds between instances where the bonding
driver sends learning packets to each ports peer switch.
- `miimon`
Sets the MII link monitoring interval (in milliseconds)
Sets the MII link monitoring interval (in milliseconds).
- `min_links`
This option specifies the minimum number of links that must be active before
asserting the carrier.
- `num_grat_arp`
This option specify the number of peer notifications (gratuitious ARPs) to be
issued after a failover event. The allowed range for the value is 0 - 255.
- `packets_per_port`
In `balance-rr` bonding mode, this option specifies the number of packets allowed
for a port in network transmission before moving to the next one. The allowed
range for the value is 0 - 65535.
- `peer_notif_delay`
This option specifies the delay (in milliseconds) between each peer notification
when they are issued after a failover event.
- `primary`
This option defines the primary device.
- `primary_reselect`
This option specifies the reselection policy for the primary port. The possible
values are: `always`, `better`, `failure`.
- `resend_igmp`
This option specifies the number of IGMP membership reports to be issued after a
failover event. The allowed range for the value is 0 - 255.
- `tlb_dynamic_lb`
This option specifies if dynamic shuffling of flows is enabled in tlb mode. The
boolean value `True` enables the flow shuffling while the boolean value `False`
disables it.
- `updelay`
This option specifies the time (in milliseconds) to wait before enabling a port
after a link recovery has been detected.
- `use_carrier`
This options specifies whether or not miimon should use MII or ETHTOOL ioctls
versus netif_carrier_ok() to determine the link sattus. The boolean value `True`
enables the use of netif_carrier_ok() while the boolean value `False` uses MII or
ETHTOOL ioctls instead.
- `xmit_hash_policy`
This option specifies the transmit hash policy to use for port selection, the
possible values are: `layer2`, `layer3+4`, `layer2+3`, `encap2+3`, `encap3+4`,
`vlan+srcmac`.
Examples of Options
-------------------

51
examples/bond_options.yml Normal file
View file

@ -0,0 +1,51 @@
# SPDX-License-Identifier: BSD-3-Clause
---
- hosts: network-test
vars:
network_connections:
# Specify the bond profile
- name: bond0
state: up
type: bond
interface_name: bond0
# ip configuration (optional)
ip:
address:
- "192.0.2.24/24"
- "2001:db8::23/64"
bond:
mode: 802.3ad
ad_actor_sys_prio: 65535
ad_actor_system: 00:00:5e:00:53:5d
ad_select: stable
ad_user_port_key: 1023
all_ports_active: True
arp_all_targets: all
downdelay: 0
lacp_rate: slow
lp_interval: 128
miimon: 110
min_links: 0
num_grat_arp: 64
peer_notif_delay: 220
primary_reselect: better
resend_igmp: 225
updelay: 0
use_carrier: True
xmit_hash_policy: encap2+3
# add an ethernet profile to the bond
- name: member1
state: up
type: ethernet
interface_name: eth1
controller: bond0
# add a second ethernet profile to the bond
- name: member2
state: up
type: ethernet
interface_name: eth2
controller: bond0
roles:
- linux-system-roles.network
...

View file

@ -867,8 +867,14 @@ class NMUtil:
s_con.set_property(NM.SETTING_CONNECTION_TYPE, NM.SETTING_BOND_SETTING_NAME)
s_bond = self.connection_ensure_setting(con, NM.SettingBond)
s_bond.add_option("mode", connection["bond"]["mode"])
if connection["bond"]["miimon"] is not None:
s_bond.add_option("miimon", str(connection["bond"]["miimon"]))
for option, value in connection["bond"].items():
if value is None:
continue
if option in ["all_ports_active", "use_carrier", "tlb_dynamic_lb"]:
value = int(value)
if option in ["all_ports_active", "packets_per_port"]:
option = option.replace("port", "slave")
s_bond.add_option(option, str(value))
elif connection["type"] == "team":
s_con.set_property(NM.SETTING_CONNECTION_TYPE, NM.SETTING_TEAM_SETTING_NAME)
elif connection["type"] == "dummy":

View file

@ -1158,15 +1158,204 @@ class ArgValidator_DictBond(ArgValidatorDict):
name="bond",
nested=[
ArgValidatorStr("mode", enum_values=ArgValidator_DictBond.VALID_MODES),
ArgValidatorNum(
"ad_actor_sys_prio", val_min=1, val_max=65535, default_value=None
),
ArgValidatorMac("ad_actor_system"),
ArgValidatorStr(
"ad_select", enum_values=["stable", "bandwidth", "count"]
),
ArgValidatorNum(
"ad_user_port_key", val_min=0, val_max=1023, default_value=None
),
ArgValidatorBool("all_ports_active", default_value=None),
ArgValidatorStr("arp_all_targets", enum_values=["any", "all"]),
ArgValidatorNum(
"arp_interval", val_min=0, val_max=1000000, default_value=None
),
ArgValidatorStr(
"arp_validate",
enum_values=[
"none",
"active",
"backup",
"all",
"filter",
"filter_active",
"filter_backup",
],
),
ArgValidatorStr("arp_ip_target"),
ArgValidatorNum(
"downdelay", val_min=0, val_max=1000000, default_value=None
),
ArgValidatorStr(
"fail_over_mac", enum_values=["none", "active", "follow"]
),
ArgValidatorStr("lacp_rate", enum_values=["slow", "fast"]),
ArgValidatorNum(
"lp_interval", val_min=1, val_max=1000000, default_value=None
),
ArgValidatorNum(
"miimon", val_min=0, val_max=1000000, default_value=None
),
ArgValidatorNum(
"min_links", val_min=0, val_max=1000000, default_value=None
),
ArgValidatorNum(
"num_grat_arp", val_min=0, val_max=255, default_value=None
),
ArgValidatorNum(
"packets_per_port", val_min=0, val_max=65535, default_value=None
),
ArgValidatorNum(
"peer_notif_delay", val_min=0, val_max=1000000, default_value=None
),
ArgValidatorStr("primary"),
ArgValidatorStr(
"primary_reselect", enum_values=["always", "better", "failure"]
),
ArgValidatorNum(
"resend_igmp", val_min=0, val_max=255, default_value=None
),
ArgValidatorBool("tlb_dynamic_lb", default_value=None),
ArgValidatorNum(
"updelay", val_min=0, val_max=1000000, default_value=None
),
ArgValidatorBool("use_carrier", default_value=None),
ArgValidatorStr(
"xmit_hash_policy",
enum_values=[
"layer2",
"layer3+4",
"layer2+3",
"encap2+3",
"encap3+4",
"vlan+srcmac",
],
),
],
default_value=ArgValidator.MISSING,
)
def _validate_post(self, value, name, result):
AD_OPTIONS = [
"ad_actor_sys_prio",
"ad_actor_system",
"ad_user_port_key",
"lacp_rate",
]
ARP_OPTIONS = ["arp_interval", "arp_ip_target", "arp_validate"]
ARP_ONLY_MODE = ["balance-rr", "active-backup", "balance-xor", "broadcast"]
if result["mode"] != "802.3ad":
for option in AD_OPTIONS:
if result[option] is not None:
raise ValidationError(
name,
"the bond option {0} is only valid with mode 802.3ad".format(
option
),
)
if result["packets_per_port"] is not None and result["mode"] != "balance-rr":
raise ValidationError(
name,
"the bond option packets_per_port is only valid with mode balance-rr",
)
if result["mode"] not in ARP_ONLY_MODE:
for option in ARP_OPTIONS:
if result[option] is not None:
raise ValidationError(
name,
"the bond option {0} is only valid with mode balance-rr, active-backup, balance-xor or broadcast".format(
option
),
)
if result["tlb_dynamic_lb"] is not None and result["mode"] not in [
"balance-tlb",
"balance-alb",
]:
raise ValidationError(
name,
"the bond option tlb_dynamic_lb is only valid with mode balance-tlb or balance-alb",
)
if result["primary"] is not None and result["mode"] not in [
"active-backup",
"balance-tlb",
"balance-alb",
]:
raise ValidationError(
name,
"the bond option primary is only valid with mode active-backup, balance-tlb, balance-alb",
)
if (
result["updelay"] is not None or result["downdelay"] is not None
) and not result["miimon"]:
raise ValidationError(
name,
"the bond option downdelay or updelay is only valid with miimon enabled",
)
if result["peer_notif_delay"] is not None:
if not result["miimon"] or result["peer_notif_delay"] % result["miimon"]:
raise ValidationError(
name,
"the bond option peer_notif_delay needs miimon enabled and must be miimon multiple",
)
if result["arp_interval"]:
raise ValidationError(
name,
"the bond option peer_notif_delay needs arp_interval disabled",
)
if result["arp_ip_target"]:
if not result["arp_interval"]:
raise ValidationError(
name,
"the bond option arp_ip_target requires arp_interval to be set",
)
if result["arp_interval"]:
if not result["arp_ip_target"]:
raise ValidationError(
name,
"the bond option arp_interval requires arp_ip_target to be set",
)
return result
def get_default_bond(self):
return {"mode": ArgValidator_DictBond.VALID_MODES[0], "miimon": None}
return {
"mode": ArgValidator_DictBond.VALID_MODES[0],
"ad_actor_sys_prio": None,
"ad_actor_system": None,
"ad_select": None,
"ad_user_port_key": None,
"all_ports_active": None,
"arp_all_targets": None,
"arp_interval": None,
"arp_ip_target": None,
"arp_validate": None,
"downdelay": None,
"fail_over_mac": None,
"lacp_rate": None,
"lp_interval": None,
"miimon": None,
"min_links": None,
"num_grat_arp": None,
"packets_per_port": None,
"peer_notif_delay": None,
"primary": None,
"primary_reselect": None,
"resend_igmp": None,
"tlb_dynamic_lb": None,
"updelay": None,
"use_carrier": None,
"xmit_hash_policy": None,
}
class ArgValidator_DictInfiniband(ArgValidatorDict):
@ -1889,6 +2078,12 @@ class ArgValidator_ListConnections(ArgValidatorList):
"not a controller "
"type by '%s'" % (connection["controller"], c["type"]),
)
if connection["type"] == "infiniband":
if c["type"] == "bond" and c["bond"]["mode"] != "active_backup":
raise ValidationError(
name + "[" + str(idx) + "].controller",
"bond only supports infiniband ports in active-backup mode",
)
if connection["port_type"] is None:
connection["port_type"] = c["type"]
elif connection["port_type"] != c["type"]:
@ -2083,6 +2278,28 @@ class ArgValidator_ListConnections(ArgValidatorList):
"match.path is not supported by the running version of "
"NetworkManger.",
)
if "bond" in connection:
if mode == self.VALIDATE_ONE_MODE_INITSCRIPTS:
for option in connection["bond"]:
if connection["bond"][option] is not None and option not in [
"mode",
"miimon",
]:
raise ValidationError.from_connection(
idx,
"initscripts only supports the mode and miimon bond "
"options. All the other bond options are not supported by "
"initscripts.",
)
# the `peer_notif_delay` bond option was supported in NM since NM 1.30
if connection["bond"]["peer_notif_delay"]:
if not hasattr(Util.NM(), "SETTING_BOND_OPTION_PEER_NOTIF_DELAY"):
raise ValidationError.from_connection(
idx,
"the bond option peer_notif_delay is not supported in "
"NetworkManger until NM 1.30",
)
self.validate_route_tables(connection, idx)

View file

@ -67,6 +67,7 @@ ibution_major_version | int < 9",
EXTRA_RUN_CONDITION: "ansible_distribution != 'RedHat' or\n ansible_distr\
ibution_major_version | int < 9",
},
"playbooks/tests_bond_options.yml": {},
"playbooks/tests_eth_dns_support.yml": {},
"playbooks/tests_dummy.yml": {},
"playbooks/tests_ipv6_disabled.yml": {

View file

@ -0,0 +1,178 @@
# SPDX-License-Identifier: BSD-3-Clause
---
- hosts: all
vars:
controller_profile: bond0
controller_device: nm-bond
port1_profile: bond0.0
dhcp_interface1: test1
port2_profile: bond0.1
dhcp_interface2: test2
tasks:
- name: "INIT Prepare setup"
debug:
msg: "##################################################"
- import_tasks: tasks/create_test_interfaces_with_dhcp.yml
- import_tasks: tasks/assert_device_present.yml
vars:
interface: "{{ dhcp_interface1 }}"
- import_tasks: tasks/assert_device_present.yml
vars:
interface: "{{ dhcp_interface2 }}"
- block:
- name: "TEST Add Bond with 2 ports"
debug:
msg: "##################################################"
- name: Configure the bond options
import_role:
name: linux-system-roles.network
vars:
network_connections:
# Create a bond controller
- name: "{{ controller_profile }}"
state: up
type: bond
interface_name: "{{ controller_device }}"
bond:
mode: 802.3ad
ad_actor_sys_prio: 65535
ad_actor_system: 00:00:5e:00:53:5d
ad_select: stable
ad_user_port_key: 1023
all_ports_active: True
arp_all_targets: all
downdelay: 0
lacp_rate: slow
lp_interval: 128
miimon: 110
min_links: 0
num_grat_arp: 64
primary_reselect: better
resend_igmp: 225
updelay: 0
use_carrier: True
xmit_hash_policy: encap2+3
# add an ethernet to the bond
- name: "{{ port1_profile }}"
state: up
type: ethernet
interface_name: "{{ dhcp_interface1 }}"
controller: "{{ controller_profile }}"
# add a second ethernet to the bond
- name: "{{ port2_profile }}"
state: up
type: ethernet
interface_name: "{{ dhcp_interface2 }}"
controller: "{{ controller_profile }}"
- import_tasks: tasks/assert_device_present.yml
vars:
interface: "{{ controller_device }}"
- include_tasks: tasks/assert_profile_present.yml
vars:
profile: "{{ item }}"
loop:
- "{{ controller_profile }}"
- "{{ port1_profile }}"
- "{{ port2_profile }}"
- command: cat
/sys/class/net/{{ controller_device }}/bonding/'{{ item.key }}'
name: "** TEST check bond settings"
register: result
until: "'{{ item.value }}' in result.stdout"
loop:
- { key: 'mode', value: '802.3ad'}
- { key: 'ad_actor_sys_prio', value: '65535'}
- { key: 'ad_actor_system', value: '00:00:5e:00:53:5d'}
- { key: 'ad_select', value: 'stable'}
- { key: 'ad_user_port_key', value: '1023'}
- { key: 'all_slaves_active', value: '1'}
- { key: 'arp_all_targets', value: 'all'}
- { key: 'downdelay', value: '0'}
- { key: 'lacp_rate', value: 'slow'}
- { key: 'lp_interval', value: '128'}
- { key: 'miimon', value: '110'}
- { key: 'num_grat_arp', value: '64'}
- { key: 'resend_igmp', value: '225'}
- { key: 'updelay', value: '0'}
- { key: 'use_carrier', value: '1'}
- { key: 'xmit_hash_policy', value: 'encap2+3'}
- command: ip -4 a s {{ controller_device }}
name: "** TEST check IPv4"
register: result
until: "'192.0.2' in result.stdout"
retries: 20
delay: 2
- command: ip -6 a s {{ controller_device }}
name: "** TEST check IPv6"
register: result
until: "'2001' in result.stdout"
retries: 20
delay: 2
- name: Reconfigure the bond options
import_role:
name: linux-system-roles.network
vars:
network_connections:
# Create a bond controller
- name: "{{ controller_profile }}"
state: up
type: bond
interface_name: "{{ controller_device }}"
bond:
mode: active-backup
arp_interval: 60
arp_ip_target: 192.0.2.128
arp_validate: none
primary: "{{ dhcp_interface1 }}"
- command: cat
/sys/class/net/{{ controller_device }}/bonding/'{{ item.key }}'
name: "** TEST check bond settings"
register: result
until: "'{{ item.value }}' in result.stdout"
loop:
- { key: 'mode', value: 'active-backup'}
- { key: 'arp_interval', value: '60'}
- { key: 'arp_ip_target', value: '192.0.2.128'}
- { key: 'arp_validate', value: 'none'}
- { key: 'primary', value: '{{ dhcp_interface1 }}'}
- command: ip -4 a s {{ controller_device }}
name: "** TEST check IPv4"
register: result
until: "'192.0.2' in result.stdout"
retries: 20
delay: 2
- command: ip -6 a s {{ controller_device }}
name: "** TEST check IPv6"
register: result
until: "'2001' in result.stdout"
retries: 20
delay: 2
always:
- block:
- name: Import network role
import_role:
name: linux-system-roles.network
vars:
network_connections:
- name: "{{ port2_profile }}"
persistent_state: absent
state: down
- name: "{{ port1_profile }}"
persistent_state: absent
state: down
- name: "{{ controller_profile }}"
persistent_state: absent
state: down
ignore_errors: true
- command: ip link del {{ controller_device }}
ignore_errors: true
- import_tasks: tasks/remove_test_interfaces_with_dhcp.yml
tags:
- "tests::cleanup"

View file

@ -0,0 +1,20 @@
# SPDX-License-Identifier: BSD-3-Clause
# This file was generated by ensure_provider_tests.py
---
# set network provider and gather facts
- hosts: all
name: Run playbook 'playbooks/tests_bond_options.yml' with nm as provider
tasks:
- include_tasks: tasks/el_repo_setup.yml
- name: Set network provider to 'nm'
set_fact:
network_provider: nm
tags:
- always
# The test requires or should run with NetworkManager, therefore it cannot run
# on RHEL/CentOS 6
- import_playbook: playbooks/tests_bond_options.yml
when:
- ansible_distribution_major_version != '6'

View file

@ -1737,7 +1737,34 @@ class TestValidator(Python26CompatTestCase):
{
"actions": ["present", "up"],
"autoconnect": True,
"bond": {"mode": "balance-rr", "miimon": None},
"bond": {
"mode": "balance-rr",
"ad_actor_sys_prio": None,
"ad_actor_system": None,
"ad_select": None,
"ad_user_port_key": None,
"all_ports_active": None,
"arp_all_targets": None,
"arp_interval": None,
"arp_ip_target": None,
"arp_validate": None,
"downdelay": None,
"fail_over_mac": None,
"lacp_rate": None,
"lp_interval": None,
"miimon": None,
"min_links": None,
"num_grat_arp": None,
"packets_per_port": None,
"peer_notif_delay": None,
"primary": None,
"primary_reselect": None,
"resend_igmp": None,
"tlb_dynamic_lb": None,
"updelay": None,
"use_carrier": None,
"xmit_hash_policy": None,
},
"check_iface_exists": True,
"ethernet": ETHERNET_DEFAULTS,
"ethtool": ETHTOOL_DEFAULTS,
@ -1788,7 +1815,34 @@ class TestValidator(Python26CompatTestCase):
{
"actions": ["present", "up"],
"autoconnect": True,
"bond": {"mode": "active-backup", "miimon": None},
"bond": {
"mode": "active-backup",
"ad_actor_sys_prio": None,
"ad_actor_system": None,
"ad_select": None,
"ad_user_port_key": None,
"all_ports_active": None,
"arp_all_targets": None,
"arp_interval": None,
"arp_ip_target": None,
"arp_validate": None,
"downdelay": None,
"fail_over_mac": None,
"lacp_rate": None,
"lp_interval": None,
"miimon": None,
"min_links": None,
"num_grat_arp": None,
"packets_per_port": None,
"peer_notif_delay": None,
"primary": None,
"primary_reselect": None,
"resend_igmp": None,
"tlb_dynamic_lb": None,
"updelay": None,
"use_carrier": None,
"xmit_hash_policy": None,
},
"check_iface_exists": True,
"ethernet": ETHERNET_DEFAULTS,
"ethtool": ETHTOOL_DEFAULTS,
@ -4312,6 +4366,188 @@ class TestValidatorRouteTable(Python26CompatTestCase):
)
class TestValidatorDictBond(Python26CompatTestCase):
def setUp(self):
self.validator = network_lsr.argument_validator.ArgValidator_ListConnections()
self.test_connections = [
{
"name": "bond0",
"type": "bond",
"bond": {
"mode": "balance-rr",
},
},
]
def test_invalid_bond_option_ad(self):
"""
Test the ad bond option restrictions
"""
self.test_connections[0]["bond"]["ad_actor_sys_prio"] = 65535
self.assertRaisesRegex(
ValidationError,
"the bond option ad_actor_sys_prio is only valid with mode 802.3ad",
self.validator.validate,
self.test_connections,
)
self.test_connections[0]["bond"]["mode"] = "802.3ad"
self.validator.validate(self.test_connections)
def test_invalid_bond_option_packets_per_port(self):
"""
Test the packets_per_port bond option restrictions
"""
self.test_connections[0]["bond"]["mode"] = "802.3ad"
self.test_connections[0]["bond"]["packets_per_port"] = 2
self.assertRaisesRegex(
ValidationError,
"the bond option packets_per_port is only valid with mode balance-rr",
self.validator.validate,
self.test_connections,
)
self.test_connections[0]["bond"]["mode"] = "balance-rr"
self.validator.validate(self.test_connections)
def test_invalid_bond_option_arp(self):
"""
Test the arp bond option restrictions
"""
self.test_connections[0]["bond"]["mode"] = "802.3ad"
self.test_connections[0]["bond"]["arp_interval"] = 2
self.test_connections[0]["bond"]["arp_ip_target"] = "198.51.100.3"
self.assertRaisesRegex(
ValidationError,
"the bond option arp_interval is only valid with mode balance-rr, active-backup, balance-xor or broadcast",
self.validator.validate,
self.test_connections,
)
self.test_connections[0]["bond"]["mode"] = "balance-rr"
self.validator.validate(self.test_connections)
def test_invalid_bond_option_tlb_dynamic_lb(self):
"""
Test the tlb_dynamic_lb bond option restrictions
"""
self.test_connections[0]["bond"]["tlb_dynamic_lb"] = True
self.assertRaisesRegex(
ValidationError,
"the bond option tlb_dynamic_lb is only valid with mode balance-tlb or balance-alb",
self.validator.validate,
self.test_connections,
)
self.test_connections[0]["bond"]["mode"] = "balance-tlb"
self.validator.validate(self.test_connections)
def test_invalid_bond_option_primary(self):
"""
Test the primary bond option restrictions
"""
self.test_connections[0]["bond"]["primary"] = "bond0.0"
self.assertRaisesRegex(
ValidationError,
"the bond option primary is only valid with mode active-backup, balance-tlb, balance-alb",
self.validator.validate,
self.test_connections,
)
self.test_connections[0]["bond"]["mode"] = "balance-tlb"
self.validator.validate(self.test_connections)
def test_invalid_bond_option_downdelay_updelay(self):
"""
Test the downdelay or updelay bond option restrictions
"""
self.test_connections[0]["bond"]["downdelay"] = 5
self.assertRaisesRegex(
ValidationError,
"the bond option downdelay or updelay is only valid with miimon enabled",
self.validator.validate,
self.test_connections,
)
self.test_connections[0]["bond"]["miimon"] = 110
self.validator.validate(self.test_connections)
def test_invalid_bond_option_peer_notif_delay(self):
"""
Test the peer_notif_delay bond option restrictions
"""
self.test_connections[0]["bond"]["miimon"] = 110
self.test_connections[0]["bond"]["peer_notif_delay"] = 222
self.assertRaisesRegex(
ValidationError,
"the bond option peer_notif_delay needs miimon enabled and must be miimon multiple",
self.validator.validate,
self.test_connections,
)
self.test_connections[0]["bond"]["peer_notif_delay"] = 220
self.test_connections[0]["bond"]["arp_interval"] = 110
self.assertRaisesRegex(
ValidationError,
"the bond option peer_notif_delay needs arp_interval disabled",
self.validator.validate,
self.test_connections,
)
self.test_connections[0]["bond"]["arp_interval"] = 0
self.validator.validate(self.test_connections)
def test_invalid_bond_option_peer_arp_ip_target_arp_interval(self):
"""
Test the arp_ip_target or arp_interval bond option restrictions
"""
self.test_connections[0]["bond"]["arp_interval"] = 4
self.assertRaisesRegex(
ValidationError,
"the bond option arp_interval requires arp_ip_target to be set",
self.validator.validate,
self.test_connections,
)
self.test_connections[0]["bond"]["arp_ip_target"] = "198.51.100.3"
self.test_connections[0]["bond"]["arp_interval"] = 0
self.assertRaisesRegex(
ValidationError,
"the bond option arp_ip_target requires arp_interval to be set",
self.validator.validate,
self.test_connections,
)
self.test_connections[0]["bond"]["arp_interval"] = 4
self.validator.validate(self.test_connections)
def test_invalid_bond_option_infiniband_port(self):
"""
Test that bond only supports infiniband ports in active-backup mode
"""
test_connections_with_infiniband_port = [
{
"name": "bond0",
"type": "bond",
"bond": {
"mode": "balance-rr",
},
},
{
"name": "bond0.0",
"type": "infiniband",
"controller": "bond0",
},
{
"name": "bond0.1",
"type": "infiniband",
"controller": "bond0",
},
]
self.assertRaisesRegex(
ValidationError,
"bond only supports infiniband ports in active-backup mode",
self.validator.validate,
test_connections_with_infiniband_port,
)
self.test_connections[0]["bond"]["mode"] = "active-backup"
self.validator.validate(self.test_connections)
class TestSysUtils(unittest.TestCase):
def test_link_read_permaddress(self):
self.assertEqual(SysUtil._link_read_permaddress("lo"), "00:00:00:00:00:00")