From ef20874f4d9846d54d19e6d0eca2024db7d84ca0 Mon Sep 17 00:00:00 2001 From: Elvira Garcia Ruiz Date: Sun, 10 May 2020 19:19:49 +0200 Subject: [PATCH] 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. --- README.md | 78 +++--- examples/ethtool_features.yml | 2 +- library/network_connections.py | 1 + .../network_lsr/argument_validator.py | 237 +++++++++++++----- module_utils/network_lsr/nm_provider.py | 2 +- tests/playbooks/tests_ethtool_features.yml | 66 +++++ tests/unit/test_network_connections.py | 149 ++++++++--- tests/unit/test_nm_provider.py | 2 +- 8 files changed, 400 insertions(+), 137 deletions(-) diff --git a/README.md b/README.md index fa7929d..f753fa9 100644 --- a/README.md +++ b/README.md @@ -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 ``` diff --git a/examples/ethtool_features.yml b/examples/ethtool_features.yml index d8842c2..c580f89 100644 --- a/examples/ethtool_features.yml +++ b/examples/ethtool_features.yml @@ -16,4 +16,4 @@ features: gro: "no" gso: "yes" - tx-sctp-segmentation: "no" + tx_sctp_segmentation: "no" diff --git a/library/network_connections.py b/library/network_connections.py index 217a178..1935f70 100644 --- a/library/network_connections.py +++ b/library/network_connections.py @@ -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" diff --git a/module_utils/network_lsr/argument_validator.py b/module_utils/network_lsr/argument_validator.py index 06dc58d..f82e740 100644 --- a/module_utils/network_lsr/argument_validator.py +++ b/module_utils/network_lsr/argument_validator.py @@ -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) + ] ) diff --git a/module_utils/network_lsr/nm_provider.py b/module_utils/network_lsr/nm_provider.py index 9f9b028..c59330e 100644 --- a/module_utils/network_lsr/nm_provider.py +++ b/module_utils/network_lsr/nm_provider.py @@ -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 diff --git a/tests/playbooks/tests_ethtool_features.yml b/tests/playbooks/tests_ethtool_features.yml index bdaddb0..76b0f8a 100644 --- a/tests/playbooks/tests_ethtool_features.yml +++ b/tests/playbooks/tests_ethtool_features.yml @@ -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: "##################################################" diff --git a/tests/unit/test_network_connections.py b/tests/unit/test_network_connections.py index 939f4f2..3ec9520 100755 --- a/tests/unit/test_network_connections.py +++ b/tests/unit/test_network_connections.py @@ -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): diff --git a/tests/unit/test_nm_provider.py b/tests/unit/test_nm_provider.py index 0a2679a..c8fd4eb 100644 --- a/tests/unit/test_nm_provider.py +++ b/tests/unit/test_nm_provider.py @@ -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