library: Change ethtool features to use underscores

Ethtool features should use underscores instead of dashes. A
warning shows in case dashes used, and it fails if underscore and dashes are
mixed. Unit tests and integration tests have been added. Since nm already
needed underscores, the string processing that was made in nm_provider is now
unneeded and therefore removed.
This commit is contained in:
Elvira Garcia Ruiz 2020-05-10 19:19:49 +02:00 committed by Till Maas
parent 3fc15de068
commit ef20874f4d
8 changed files with 400 additions and 137 deletions

View file

@ -357,57 +357,57 @@ kernel and device, changing some features might not be supported.
```yaml
ethtool:
features:
esp-hw-offload: yes|no # optional
esp-tx-csum-hw-offload: yes|no # optional
fcoe-mtu: yes|no # optional
esp_hw_offload: yes|no # optional
esp_tx_csum_hw_offload: yes|no # optional
fcoe_mtu: yes|no # optional
gro: yes|no # optional
gso: yes|no # optional
highdma: yes|no # optional
hw-tc-offload: yes|no # optional
l2-fwd-offload: yes|no # optional
hw_tc_offload: yes|no # optional
l2_fwd_offload: yes|no # optional
loopback: yes|no # optional
lro: yes|no # optional
ntuple: yes|no # optional
rx: yes|no # optional
rx-all: yes|no # optional
rx-fcs: yes|no # optional
rx-gro-hw: yes|no # optional
rx-udp_tunnel-port-offload: yes|no # optional
rx-vlan-filter: yes|no # optional
rx-vlan-stag-filter: yes|no # optional
rx-vlan-stag-hw-parse: yes|no # optional
rx_all: yes|no # optional
rx_fcs: yes|no # optional
rx_gro_hw: yes|no # optional
rx_udp_tunnel_port_offload: yes|no # optional
rx_vlan_filter: yes|no # optional
rx_vlan_stag_filter: yes|no # optional
rx_vlan_stag_hw_parse: yes|no # optional
rxhash: yes|no # optional
rxvlan: yes|no # optional
sg: yes|no # optional
tls-hw-record: yes|no # optional
tls-hw-tx-offload: yes|no # optional
tls_hw_record: yes|no # optional
tls_hw_tx_offload: yes|no # optional
tso: yes|no # optional
tx: yes|no # optional
tx-checksum-fcoe-crc: yes|no # optional
tx-checksum-ip-generic: yes|no # optional
tx-checksum-ipv4: yes|no # optional
tx-checksum-ipv6: yes|no # optional
tx-checksum-sctp: yes|no # optional
tx-esp-segmentation: yes|no # optional
tx-fcoe-segmentation: yes|no # optional
tx-gre-csum-segmentation: yes|no # optional
tx-gre-segmentation: yes|no # optional
tx-gso-partial: yes|no # optional
tx-gso-robust: yes|no # optional
tx-ipxip4-segmentation: yes|no # optional
tx-ipxip6-segmentation: yes|no # optional
tx-nocache-copy: yes|no # optional
tx-scatter-gather: yes|no # optional
tx-scatter-gather-fraglist: yes|no # optional
tx-sctp-segmentation: yes|no # optional
tx-tcp-ecn-segmentation: yes|no # optional
tx-tcp-mangleid-segmentation: yes|no # optional
tx-tcp-segmentation: yes|no # optional
tx-tcp6-segmentation: yes|no # optional
tx-udp-segmentation: yes|no # optional
tx-udp_tnl-csum-segmentation: yes|no # optional
tx-udp_tnl-segmentation: yes|no # optional
tx-vlan-stag-hw-insert: yes|no # optional
tx_checksum_fcoe_crc: yes|no # optional
tx_checksum_ip_generic: yes|no # optional
tx_checksum_ipv4: yes|no # optional
tx_checksum_ipv6: yes|no # optional
tx_checksum_sctp: yes|no # optional
tx_esp_segmentation: yes|no # optional
tx_fcoe_segmentation: yes|no # optional
tx_gre_csum_segmentation: yes|no # optional
tx_gre_segmentation: yes|no # optional
tx_gso_partial: yes|no # optional
tx_gso_robust: yes|no # optional
tx_ipxip4_segmentation: yes|no # optional
tx_ipxip6_segmentation: yes|no # optional
tx_nocache_copy: yes|no # optional
tx_scatter_gather: yes|no # optional
tx_scatter_gather_fraglist: yes|no # optional
tx_sctp_segmentation: yes|no # optional
tx_tcp_ecn_segmentation: yes|no # optional
tx_tcp_mangleid_segmentation: yes|no # optional
tx_tcp_segmentation: yes|no # optional
tx_tcp6_segmentation: yes|no # optional
tx_udp_segmentation: yes|no # optional
tx_udp_tnl_csum_segmentation: yes|no # optional
tx_udp_tnl_segmentation: yes|no # optional
tx_vlan_stag_hw_insert: yes|no # optional
txvlan: yes|no # optional
```

View file

@ -16,4 +16,4 @@
features:
gro: "no"
gso: "yes"
tx-sctp-segmentation: "no"
tx_sctp_segmentation: "no"

View file

@ -369,6 +369,7 @@ class IfcfgUtil:
ethtool_features = connection["ethtool"]["features"]
configured_features = []
for feature, setting in ethtool_features.items():
feature = feature.replace("_", "-")
value = ""
if setting:
value = "on"

View file

@ -199,6 +199,12 @@ class ArgValidatorBool(ArgValidator):
raise ValidationError(name, "must be an boolean but is '%s'" % (value))
class ArgValidatorDeprecated:
def __init__(self, name, deprecated_by):
self.name = name
self.deprecated_by = deprecated_by
class ArgValidatorDict(ArgValidator):
def __init__(
self,
@ -222,26 +228,33 @@ class ArgValidatorDict(ArgValidator):
items = list(value.items())
except AttributeError:
raise ValidationError(name, "invalid content is not a dictionary")
for (k, v) in items:
if k in seen_keys:
raise ValidationError(name, "duplicate key '%s'" % (k))
seen_keys.add(k)
validator = self.nested.get(k, None)
if validator is None:
raise ValidationError(name, "invalid key '%s'" % (k))
for (setting, value) in items:
try:
vv = validator._validate(v, name + "." + k)
validator = self.nested[setting]
except KeyError:
raise ValidationError(name, "invalid key '%s'" % (setting))
if isinstance(validator, ArgValidatorDeprecated):
setting = validator.deprecated_by
validator = self.nested.get(setting, None)
if setting in seen_keys:
raise ValidationError(name, "duplicate key '%s'" % (setting))
seen_keys.add(setting)
try:
validated_value = validator._validate(value, name + "." + setting)
except ValidationError as e:
raise ValidationError(e.name, e.error_message)
result[k] = vv
for (k, v) in self.nested.items():
if k in seen_keys:
result[setting] = validated_value
for (setting, validator) in self.nested.items():
if setting in seen_keys or isinstance(validator, ArgValidatorDeprecated):
continue
if v.required:
raise ValidationError(name, "missing required key '%s'" % (k))
vv = v.get_default_value()
if not self.all_missing_during_validate and vv is not ArgValidator.MISSING:
result[k] = vv
if validator.required:
raise ValidationError(name, "missing required key '%s'" % (setting))
default_value = validator.get_default_value()
if (
not self.all_missing_during_validate
and default_value is not ArgValidator.MISSING
):
result[setting] = default_value
return result
@ -549,62 +562,174 @@ class ArgValidator_DictEthtoolFeatures(ArgValidatorDict):
self,
name="features",
nested=[
ArgValidatorBool("esp-hw-offload", default_value=None),
ArgValidatorBool("esp-tx-csum-hw-offload", default_value=None),
ArgValidatorBool("fcoe-mtu", default_value=None),
ArgValidatorBool("esp_hw_offload", default_value=None),
ArgValidatorDeprecated(
"esp-hw-offload", deprecated_by="esp_hw_offload"
),
ArgValidatorBool("esp_tx_csum_hw_offload", default_value=None),
ArgValidatorDeprecated(
"esp-tx-csum-hw-offload", deprecated_by="esp_tx_csum_hw_offload",
),
ArgValidatorBool("fcoe_mtu", default_value=None),
ArgValidatorDeprecated("fcoe-mtu", deprecated_by="fcoe_mtu"),
ArgValidatorBool("gro", default_value=None),
ArgValidatorBool("gso", default_value=None),
ArgValidatorBool("highdma", default_value=None),
ArgValidatorBool("hw-tc-offload", default_value=None),
ArgValidatorBool("l2-fwd-offload", default_value=None),
ArgValidatorBool("hw_tc_offload", default_value=None),
ArgValidatorDeprecated("hw-tc-offload", deprecated_by="hw_tc_offload"),
ArgValidatorBool("l2_fwd_offload", default_value=None),
ArgValidatorDeprecated(
"l2-fwd-offload", deprecated_by="l2_fwd_offload"
),
ArgValidatorBool("loopback", default_value=None),
ArgValidatorBool("lro", default_value=None),
ArgValidatorBool("ntuple", default_value=None),
ArgValidatorBool("rx", default_value=None),
ArgValidatorBool("rxhash", default_value=None),
ArgValidatorBool("rxvlan", default_value=None),
ArgValidatorBool("rx-all", default_value=None),
ArgValidatorBool("rx-fcs", default_value=None),
ArgValidatorBool("rx-gro-hw", default_value=None),
ArgValidatorBool("rx-udp_tunnel-port-offload", default_value=None),
ArgValidatorBool("rx-vlan-filter", default_value=None),
ArgValidatorBool("rx-vlan-stag-filter", default_value=None),
ArgValidatorBool("rx-vlan-stag-hw-parse", default_value=None),
ArgValidatorBool("rx_all", default_value=None),
ArgValidatorDeprecated("rx-all", deprecated_by="rx_all"),
ArgValidatorBool("rx_fcs", default_value=None),
ArgValidatorDeprecated("rx-fcs", deprecated_by="rx_fcs"),
ArgValidatorBool("rx_gro_hw", default_value=None),
ArgValidatorDeprecated("rx-gro-hw", deprecated_by="rx_gro_hw"),
ArgValidatorBool("rx_udp_tunnel_port_offload", default_value=None),
ArgValidatorDeprecated(
"rx-udp_tunnel-port-offload",
deprecated_by="rx_udp_tunnel_port_offload",
),
ArgValidatorBool("rx_vlan_filter", default_value=None),
ArgValidatorDeprecated(
"rx-vlan-filter", deprecated_by="rx_vlan_filter"
),
ArgValidatorBool("rx_vlan_stag_filter", default_value=None),
ArgValidatorDeprecated(
"rx-vlan-stag-filter", deprecated_by="rx_vlan_stag_filter",
),
ArgValidatorBool("rx_vlan_stag_hw_parse", default_value=None),
ArgValidatorDeprecated(
"rx-vlan-stag-hw-parse", deprecated_by="rx_vlan_stag_hw_parse",
),
ArgValidatorBool("sg", default_value=None),
ArgValidatorBool("tls-hw-record", default_value=None),
ArgValidatorBool("tls-hw-tx-offload", default_value=None),
ArgValidatorBool("tls_hw_record", default_value=None),
ArgValidatorDeprecated("tls-hw-record", deprecated_by="tls_hw_record"),
ArgValidatorBool("tls_hw_tx_offload", default_value=None),
ArgValidatorDeprecated(
"tls-hw-tx-offload", deprecated_by="tls_hw_tx_offload",
),
ArgValidatorBool("tso", default_value=None),
ArgValidatorBool("tx", default_value=None),
ArgValidatorBool("txvlan", default_value=None),
ArgValidatorBool("tx-checksum-fcoe-crc", default_value=None),
ArgValidatorBool("tx-checksum-ipv4", default_value=None),
ArgValidatorBool("tx-checksum-ipv6", default_value=None),
ArgValidatorBool("tx-checksum-ip-generic", default_value=None),
ArgValidatorBool("tx-checksum-sctp", default_value=None),
ArgValidatorBool("tx-esp-segmentation", default_value=None),
ArgValidatorBool("tx-fcoe-segmentation", default_value=None),
ArgValidatorBool("tx-gre-csum-segmentation", default_value=None),
ArgValidatorBool("tx-gre-segmentation", default_value=None),
ArgValidatorBool("tx-gso-partial", default_value=None),
ArgValidatorBool("tx-gso-robust", default_value=None),
ArgValidatorBool("tx-ipxip4-segmentation", default_value=None),
ArgValidatorBool("tx-ipxip6-segmentation", default_value=None),
ArgValidatorBool("tx-nocache-copy", default_value=None),
ArgValidatorBool("tx-scatter-gather", default_value=None),
ArgValidatorBool("tx-scatter-gather-fraglist", default_value=None),
ArgValidatorBool("tx-sctp-segmentation", default_value=None),
ArgValidatorBool("tx-tcp6-segmentation", default_value=None),
ArgValidatorBool("tx-tcp-ecn-segmentation", default_value=None),
ArgValidatorBool("tx-tcp-mangleid-segmentation", default_value=None),
ArgValidatorBool("tx-tcp-segmentation", default_value=None),
ArgValidatorBool("tx-udp-segmentation", default_value=None),
ArgValidatorBool("tx-udp_tnl-csum-segmentation", default_value=None),
ArgValidatorBool("tx-udp_tnl-segmentation", default_value=None),
ArgValidatorBool("tx-vlan-stag-hw-insert", default_value=None),
ArgValidatorBool("tx_checksum_fcoe_crc", default_value=None),
ArgValidatorDeprecated(
"tx-checksum-fcoe-crc", deprecated_by="tx_checksum_fcoe_crc",
),
ArgValidatorBool("tx_checksum_ipv4", default_value=None),
ArgValidatorDeprecated(
"tx-checksum-ipv4", deprecated_by="tx_checksum_ipv4",
),
ArgValidatorBool("tx_checksum_ipv6", default_value=None),
ArgValidatorDeprecated(
"tx-checksum-ipv6", deprecated_by="tx_checksum_ipv6",
),
ArgValidatorBool("tx_checksum_ip_generic", default_value=None),
ArgValidatorDeprecated(
"tx-checksum-ip-generic", deprecated_by="tx_checksum_ip_generic",
),
ArgValidatorBool("tx_checksum_sctp", default_value=None),
ArgValidatorDeprecated(
"tx-checksum-sctp", deprecated_by="tx_checksum_sctp",
),
ArgValidatorBool("tx_esp_segmentation", default_value=None),
ArgValidatorDeprecated(
"tx-esp-segmentation", deprecated_by="tx_esp_segmentation",
),
ArgValidatorBool("tx_fcoe_segmentation", default_value=None),
ArgValidatorDeprecated(
"tx-fcoe-segmentation", deprecated_by="tx_fcoe_segmentation",
),
ArgValidatorBool("tx_gre_csum_segmentation", default_value=None),
ArgValidatorDeprecated(
"tx-gre-csum-segmentation",
deprecated_by="tx_gre_csum_segmentation",
),
ArgValidatorBool("tx_gre_segmentation", default_value=None),
ArgValidatorDeprecated(
"tx-gre-segmentation", deprecated_by="tx_gre_segmentation",
),
ArgValidatorBool("tx_gso_partial", default_value=None),
ArgValidatorDeprecated(
"tx-gso-partial", deprecated_by="tx_gso_partial"
),
ArgValidatorBool("tx_gso_robust", default_value=None),
ArgValidatorDeprecated("tx-gso-robust", deprecated_by="tx_gso_robust"),
ArgValidatorBool("tx_ipxip4_segmentation", default_value=None),
ArgValidatorDeprecated(
"tx-ipxip4-segmentation", deprecated_by="tx_ipxip4_segmentation",
),
ArgValidatorBool("tx_ipxip6_segmentation", default_value=None),
ArgValidatorDeprecated(
"tx-ipxip6-segmentation", deprecated_by="tx_ipxip6_segmentation",
),
ArgValidatorBool("tx_nocache_copy", default_value=None),
ArgValidatorDeprecated(
"tx-nocache-copy", deprecated_by="tx_nocache_copy",
),
ArgValidatorBool("tx_scatter_gather", default_value=None),
ArgValidatorDeprecated(
"tx-scatter-gather", deprecated_by="tx_scatter_gather",
),
ArgValidatorBool("tx_scatter_gather_fraglist", default_value=None),
ArgValidatorDeprecated(
"tx-scatter-gather-fraglist",
deprecated_by="tx_scatter_gather_fraglist",
),
ArgValidatorBool("tx_sctp_segmentation", default_value=None),
ArgValidatorDeprecated(
"tx-sctp-segmentation", deprecated_by="tx_sctp_segmentation",
),
ArgValidatorBool("tx_tcp6_segmentation", default_value=None),
ArgValidatorDeprecated(
"tx-tcp6-segmentation", deprecated_by="tx_tcp6_segmentation",
),
ArgValidatorBool("tx_tcp_ecn_segmentation", default_value=None),
ArgValidatorDeprecated(
"tx-tcp-ecn-segmentation", deprecated_by="tx_tcp_ecn_segmentation",
),
ArgValidatorBool("tx_tcp_mangleid_segmentation", default_value=None),
ArgValidatorDeprecated(
"tx-tcp-mangleid-segmentation",
deprecated_by="tx_tcp_mangleid_segmentation",
),
ArgValidatorBool("tx_tcp_segmentation", default_value=None),
ArgValidatorDeprecated(
"tx-tcp-segmentation", deprecated_by="tx_tcp_segmentation",
),
ArgValidatorBool("tx_udp_segmentation", default_value=None),
ArgValidatorDeprecated(
"tx-udp-segmentation", deprecated_by="tx_udp_segmentation",
),
ArgValidatorBool("tx_udp_tnl_csum_segmentation", default_value=None),
ArgValidatorDeprecated(
"tx-udp_tnl-csum-segmentation",
deprecated_by="tx_udp_tnl_csum_segmentation",
),
ArgValidatorBool("tx_udp_tnl_segmentation", default_value=None),
ArgValidatorDeprecated(
"tx-udp_tnl-segmentation", deprecated_by="tx_udp_tnl_segmentation",
),
ArgValidatorBool("tx_vlan_stag_hw_insert", default_value=None),
ArgValidatorDeprecated(
"tx-vlan-stag-hw-insert", deprecated_by="tx_vlan_stag_hw_insert",
),
],
)
self.default_value = dict(
[(k, v.default_value) for k, v in self.nested.items()]
[
(name, validator.default_value)
for name, validator in self.nested.items()
if not isinstance(validator, ArgValidatorDeprecated)
]
)

View file

@ -17,7 +17,7 @@ def get_nm_ethtool_feature(name):
:rtype: str
"""
name = ETHTOOL_FEATURE_PREFIX + name.upper().replace("-", "_")
name = ETHTOOL_FEATURE_PREFIX + name.upper()
feature = getattr(Util.NM(), name, None)
return feature

View file

@ -79,6 +79,72 @@
- >-
'tx-tcp-segmentation: off' in
ethtool_features.stdout_lines | map('trim')
- name: >-
TEST: I can enable tx_tcp_segmentation (using underscores).
debug:
msg: "##################################################"
- import_role:
name: linux-system-roles.network
vars:
network_connections:
- name: "{{ interface }}"
state: up
type: ethernet
ip:
dhcp4: "no"
auto6: "no"
ethtool:
features:
tx_tcp_segmentation: "yes"
- name: Get current device features
command: "ethtool --show-features {{ interface }}"
register: ethtool_features
- name:
debug:
var: ethtool_features.stdout_lines
- name: Assert device features
assert:
that:
- >-
'tx-tcp-segmentation: on' in
ethtool_features.stdout_lines | map('trim')
- name: I cannot change tx_tcp_segmentation and tx-tcp-segmentation at
the same time.
block:
- name: >-
TEST: Change feature with both underscores and dashes.
debug:
msg: "##################################################"
- network_connections:
provider: "{{ network_provider | mandatory }}"
connections:
- name: "{{ interface }}"
state: up
type: ethernet
ip:
dhcp4: "no"
auto6: "no"
ethtool:
features:
tx_tcp_segmentation: "no"
tx-tcp-segmentation: "no"
register: __network_connections_result
rescue:
- name: Show network_connections result
debug:
var: __network_connections_result
- assert:
that:
- '{{ "fatal error: configuration error:
connections[0].ethtool.features: duplicate key
''tx_tcp_segmentation''" in
__network_connections_result.msg }}'
always:
- name: Check failure
debug:
var: __network_connections_result
- assert:
that: "{{ __network_connections_result.failed == true }}"
- name: "TEST: I can reset features to their original value."
debug:
msg: "##################################################"

View file

@ -8,6 +8,7 @@ import pprint as pprint_
import socket
import sys
import unittest
import copy
TESTS_BASEDIR = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(1, os.path.join(TESTS_BASEDIR, "../..", "library"))
@ -69,57 +70,57 @@ VALIDATE_ONE_MODE_INITSCRIPTS = ARGS_CONNECTIONS.VALIDATE_ONE_MODE_INITSCRIPTS
VALIDATE_ONE_MODE_NM = ARGS_CONNECTIONS.VALIDATE_ONE_MODE_NM
ETHTOOL_FEATURES_DEFAULTS = {
"esp-hw-offload": None,
"esp-tx-csum-hw-offload": None,
"fcoe-mtu": None,
"esp_hw_offload": None,
"esp_tx_csum_hw_offload": None,
"fcoe_mtu": None,
"gro": None,
"gso": None,
"highdma": None,
"hw-tc-offload": None,
"l2-fwd-offload": None,
"hw_tc_offload": None,
"l2_fwd_offload": None,
"loopback": None,
"lro": None,
"ntuple": None,
"rx": None,
"rx-all": None,
"rx-fcs": None,
"rx-gro-hw": None,
"rx-udp_tunnel-port-offload": None,
"rx-vlan-filter": None,
"rx-vlan-stag-filter": None,
"rx-vlan-stag-hw-parse": None,
"rx_all": None,
"rx_fcs": None,
"rx_gro_hw": None,
"rx_udp_tunnel_port_offload": None,
"rx_vlan_filter": None,
"rx_vlan_stag_filter": None,
"rx_vlan_stag_hw_parse": None,
"rxhash": None,
"rxvlan": None,
"sg": None,
"tls-hw-record": None,
"tls-hw-tx-offload": None,
"tls_hw_record": None,
"tls_hw_tx_offload": None,
"tso": None,
"tx": None,
"tx-checksum-fcoe-crc": None,
"tx-checksum-ip-generic": None,
"tx-checksum-ipv4": None,
"tx-checksum-ipv6": None,
"tx-checksum-sctp": None,
"tx-esp-segmentation": None,
"tx-fcoe-segmentation": None,
"tx-gre-csum-segmentation": None,
"tx-gre-segmentation": None,
"tx-gso-partial": None,
"tx-gso-robust": None,
"tx-ipxip4-segmentation": None,
"tx-ipxip6-segmentation": None,
"tx-nocache-copy": None,
"tx-scatter-gather": None,
"tx-scatter-gather-fraglist": None,
"tx-sctp-segmentation": None,
"tx-tcp-ecn-segmentation": None,
"tx-tcp-mangleid-segmentation": None,
"tx-tcp-segmentation": None,
"tx-tcp6-segmentation": None,
"tx-udp-segmentation": None,
"tx-udp_tnl-csum-segmentation": None,
"tx-udp_tnl-segmentation": None,
"tx-vlan-stag-hw-insert": None,
"tx_checksum_fcoe_crc": None,
"tx_checksum_ip_generic": None,
"tx_checksum_ipv4": None,
"tx_checksum_ipv6": None,
"tx_checksum_sctp": None,
"tx_esp_segmentation": None,
"tx_fcoe_segmentation": None,
"tx_gre_csum_segmentation": None,
"tx_gre_segmentation": None,
"tx_gso_partial": None,
"tx_gso_robust": None,
"tx_ipxip4_segmentation": None,
"tx_ipxip6_segmentation": None,
"tx_nocache_copy": None,
"tx_scatter_gather": None,
"tx_scatter_gather_fraglist": None,
"tx_sctp_segmentation": None,
"tx_tcp_ecn_segmentation": None,
"tx_tcp_mangleid_segmentation": None,
"tx_tcp_segmentation": None,
"tx_tcp6_segmentation": None,
"tx_udp_segmentation": None,
"tx_udp_tnl_csum_segmentation": None,
"tx_udp_tnl_segmentation": None,
"tx_vlan_stag_hw_insert": None,
"txvlan": None,
}
@ -2475,6 +2476,76 @@ class TestValidator(unittest.TestCase):
},
)
def _test_ethtool_changes(self, input_features, expected_features):
"""
When passing a dictionary 'input_features' with each feature and their
value to change, and a dictionary 'expected_features' with the expected
result in the configuration, the expected and resulting connection are
created and validated.
"""
custom_ethtool_features = copy.deepcopy(ETHTOOL_FEATURES_DEFAULTS)
custom_ethtool_features.update(expected_features)
expected_ethtool = {"features": custom_ethtool_features}
input_connection = {
"ethtool": {"features": input_features},
"name": "5",
"persistent_state": "present",
"type": "ethernet",
}
expected_connection = {
"actions": ["present"],
"ethtool": expected_ethtool,
"interface_name": "5",
"persistent_state": "present",
"state": None,
"type": "ethernet",
}
self.check_one_connection_with_defaults(input_connection, expected_connection)
def test_set_ethtool_feature(self):
"""
When passing the name of an non-deprecated ethtool feature, their
current version is updated.
"""
input_features = {"tx_tcp_segmentation": "yes"}
expected_feature_changes = {"tx_tcp_segmentation": True}
self._test_ethtool_changes(input_features, expected_feature_changes)
def test_set_deprecated_ethtool_feature(self):
"""
When passing a deprecated name, their current version is updated.
"""
input_features = {"tx-tcp-segmentation": "yes"}
expected_feature_changes = {"tx_tcp_segmentation": True}
self._test_ethtool_changes(input_features, expected_feature_changes)
def test_invalid_ethtool_settings(self):
"""
When both the deprecated and current version of a feature are stated,
a Validation Error is raised.
"""
input_features = {"tx-tcp-segmentation": "yes", "tx_tcp_segmentation": "yes"}
features_validator = (
network_lsr.argument_validator.ArgValidator_DictEthtoolFeatures()
)
self.assertValidationError(features_validator, input_features)
def test_deprecated_ethtool_names(self):
"""
Test that for each validator in
ArgValidator_DictEthtoolFeatures.nested there is another non-deprecated
validator that has the name from the deprecated_by attribute"
"""
validators = (
network_lsr.argument_validator.ArgValidator_DictEthtoolFeatures().nested
)
for name, validator in validators.items():
if isinstance(
validator, network_lsr.argument_validator.ArgValidatorDeprecated
):
assert validator.deprecated_by in validators.keys()
@my_test_skipIf(nmutil is None, "no support for NM (libnm via pygobject)")
class TestNM(unittest.TestCase):

View file

@ -27,5 +27,5 @@ with mock.patch.dict("sys.modules", {"gi": mock.Mock(), "gi.repository": mock.Mo
def test_get_nm_ethtool_feature():
""" Test get_nm_ethtool_feature() """
with mock.patch.object(nm_provider.Util, "NM") as nm_mock:
nm_feature = nm_provider.get_nm_ethtool_feature("esp-hw-offload")
nm_feature = nm_provider.get_nm_ethtool_feature("esp_hw_offload")
assert nm_feature == nm_mock.return_value.ETHTOOL_OPTNAME_FEATURE_ESP_HW_OFFLOAD