From 001f81b8237b2af1c886e5bbb8651c7ebbdf6935 Mon Sep 17 00:00:00 2001 From: Jack Adolph Date: Thu, 29 Oct 2020 19:17:46 +1100 Subject: [PATCH] Fix static IPv6 support for initscripts provider Use the correct parameter names for declaring static IPV6 connections for the initscripts provider. Also, add integration and unit tests to cover this. Signed-off-by: Jack Adolph Signed-off-by: Till Maas --- library/network_connections.py | 6 +- tests/playbooks/tests_ipv6.yml | 94 +++++++++++++++++++++++ tests/tests_ipv6_initscripts.yml | 13 ++++ tests/tests_ipv6_nm.yml | 19 +++++ tests/unit/test_network_connections.py | 101 +++++++++++++++++++++++++ 5 files changed, 231 insertions(+), 2 deletions(-) create mode 100644 tests/playbooks/tests_ipv6.yml create mode 100644 tests/tests_ipv6_initscripts.yml create mode 100644 tests/tests_ipv6_nm.yml diff --git a/library/network_connections.py b/library/network_connections.py index dc30ae8..6eb1581 100644 --- a/library/network_connections.py +++ b/library/network_connections.py @@ -479,9 +479,11 @@ class IfcfgUtil: else: ifcfg["IPV6INIT"] = "no" if addrs6: - ifcfg["IPVADDR"] = addrs6[0]["address"] + "/" + str(addrs6[0]["prefix"]) + ifcfg["IPV6ADDR"] = ( + addrs6[0]["address"] + "/" + str(addrs6[0]["prefix"]) + ) if len(addrs6) > 1: - ifcfg["IPVADDR_SECONDARIES"] = " ".join( + ifcfg["IPV6ADDR_SECONDARIES"] = " ".join( [a["address"] + "/" + str(a["prefix"]) for a in addrs6[1:]] ) if ip["gateway6"] is not None: diff --git a/tests/playbooks/tests_ipv6.yml b/tests/playbooks/tests_ipv6.yml new file mode 100644 index 0000000..98d98d1 --- /dev/null +++ b/tests/playbooks/tests_ipv6.yml @@ -0,0 +1,94 @@ +# SPDX-License-Identifier: BSD-3-Clause +--- +- hosts: all + vars: + type: veth + interface: veth0 + tasks: + - include_tasks: tasks/show_interfaces.yml + - include_tasks: tasks/manage_test_interface.yml + vars: + state: present + - name: Set up gateway ip on veth peer + shell: | + ip netns add ns1 + ip link set peer{{ interface }} netns ns1 + ip netns exec ns1 ip -6 addr add 2001:db8::1/32 dev peer{{ interface }} + ip netns exec ns1 ip link set peer{{ interface }} up + when: + # netns not available on RHEL/CentOS 6 + - ansible_distribution_major_version != '6' + - block: + - name: >- + TEST: I can configure an interface with static ipv6 config + debug: + msg: "##################################################" + - import_role: + name: linux-system-roles.network + vars: + network_connections: + - name: "{{ interface }}" + type: ethernet + state: up + ip: + dhcp4: false + auto6: false + address: + - "2001:db8::2/32" + - "2001:db8::3/32" + - "2001:db8::4/32" + gateway6: "2001:db8::1" + - include_tasks: tasks/assert_device_present.yml + - include_tasks: tasks/assert_profile_present.yml + vars: + profile: "{{ interface }}" + - name: Get ip address information + command: "ip addr show {{ interface }}" + register: ip_addr + - name: + debug: + var: ip_addr.stdout + - name: Assert ipv6 addresses are correctly set + assert: + that: + - >- + 'inet6 2001:db8::2/32' in ip_addr.stdout + - >- + 'inet6 2001:db8::3/32' in ip_addr.stdout + - >- + 'inet6 2001:db8::4/32' in ip_addr.stdout + - name: Get ipv6 routes + command: "ip -6 route" + register: ipv6_route + - name: + debug: + var: ipv6_route.stdout + - name: Assert default ipv6 route is set + assert: + that: + - >- + "default via 2001:db8::1 dev {{ interface }}" + in ipv6_route.stdout + - name: Test gateway can be pinged + command: ping6 -c1 2001:db8::1 + when: + - ansible_distribution_major_version != '6' + always: + - name: "TEARDOWN: remove profiles." + debug: + msg: "##################################################" + - import_role: + name: linux-system-roles.network + vars: + network_connections: + - name: "{{ interface }}" + persistent_state: absent + state: down + ignore_errors: true + - include_tasks: tasks/manage_test_interface.yml + vars: + state: absent + - name: Clean up namespace + command: ip netns delete ns1 + when: + - ansible_distribution_major_version != '6' diff --git a/tests/tests_ipv6_initscripts.yml b/tests/tests_ipv6_initscripts.yml new file mode 100644 index 0000000..736a8e0 --- /dev/null +++ b/tests/tests_ipv6_initscripts.yml @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: BSD-3-Clause +# This file was generated by ensure_provider_tests.py +--- +- hosts: all + name: Run playbook 'playbooks/tests_ipv6.yml' with initscripts as provider + tasks: + - name: Set network provider to 'initscripts' + set_fact: + network_provider: initscripts + tags: + - always + +- import_playbook: playbooks/tests_ipv6.yml diff --git a/tests/tests_ipv6_nm.yml b/tests/tests_ipv6_nm.yml new file mode 100644 index 0000000..f186912 --- /dev/null +++ b/tests/tests_ipv6_nm.yml @@ -0,0 +1,19 @@ +# 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_ipv6.yml' with nm as provider + tasks: + - 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_ipv6.yml + when: + - ansible_distribution_major_version != '6' diff --git a/tests/unit/test_network_connections.py b/tests/unit/test_network_connections.py index 847f18f..b14e7b3 100644 --- a/tests/unit/test_network_connections.py +++ b/tests/unit/test_network_connections.py @@ -751,6 +751,107 @@ class TestValidator(unittest.TestCase): ], ) + def test_ipv6_static(self): + self.maxDiff = None + self.do_connections_validate( + [ + { + "actions": ["present", "up"], + "autoconnect": True, + "check_iface_exists": True, + "ethernet": ETHERNET_DEFAULTS, + "ethtool": ETHTOOL_DEFAULTS, + "force_state_change": None, + "ignore_errors": None, + "interface_name": "prod1", + "ip": { + "gateway6": "2001:db8::1", + "gateway4": None, + "route_metric4": None, + "auto6": False, + "ipv6_disabled": False, + "dhcp4": False, + "address": [ + { + "address": "2001:db8::2", + "family": socket.AF_INET6, + "prefix": 32, + }, + { + "address": "2001:db8::3", + "family": socket.AF_INET6, + "prefix": 32, + }, + { + "address": "2001:db8::4", + "family": socket.AF_INET6, + "prefix": 32, + }, + ], + "route_append_only": False, + "rule_append_only": False, + "route": [], + "dns": [], + "dns_options": [], + "dns_search": [], + "route_metric6": None, + "dhcp4_send_hostname": None, + }, + "mac": None, + "controller": None, + "ieee802_1x": None, + "wireless": None, + "mtu": None, + "name": "prod1", + "parent": None, + "persistent_state": "present", + "port_type": None, + "state": "up", + "type": "ethernet", + "wait": None, + "zone": None, + } + ], + [ + { + "name": "prod1", + "state": "up", + "type": "ethernet", + "ip": { + "dhcp4": "no", + "auto6": "no", + "address": [ + "2001:db8::2/32", + "2001:db8::3/32", + "2001:db8::4/32", + ], + "gateway6": "2001:db8::1", + }, + } + ], + initscripts_dict_expected=[ + { + "ifcfg": { + "BOOTPROTO": "none", + "IPV6INIT": "yes", + "IPV6_AUTOCONF": "no", + "IPV6ADDR": "2001:db8::2/32", + "IPV6ADDR_SECONDARIES": "2001:db8::3/32 2001:db8::4/32", + "IPV6_DEFAULTGW": "2001:db8::1", + "NM_CONTROLLED": "no", + "ONBOOT": "yes", + "TYPE": "Ethernet", + "DEVICE": "prod1", + }, + "keys": None, + "route": None, + "route6": None, + "rule": None, + "rule6": None, + } + ], + ) + def test_routes(self): self.maxDiff = None self.do_connections_validate(