Skip to content

Commit

Permalink
Add 'auto_gateway' option
Browse files Browse the repository at this point in the history
If enabled, a default route will be configured using the default gateway. If disabled,
the default route will be removed.

If this variable is not specified, the role will use the default behavior of the
`network_provider` selected.

Setting this option to `no` is equivalent to:
- `DEFROUTE = no` in initscripts, or
- `ipv4.never-default/ipv6.never-default yes` in nmcli

Signed-off-by: Jack Adolph <jack.adolph@gmail.com>
  • Loading branch information
jaedolph authored and cathay4t committed Jun 3, 2021
1 parent 6fdac16 commit b368bce
Show file tree
Hide file tree
Showing 7 changed files with 409 additions and 0 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,18 @@ The IP configuration supports the following options:

Manual addressing can be specified via a list of addresses under the `address` option.

- `auto_gateway`

If enabled, a default route will be configured using the default gateway. If disabled,
the default route will be removed.

If this variable is not specified, the role will use the default behavior of the
`network_provider` selected.

Setting this option to `no` is equivalent to:
- `DEFROUTE = no` in initscripts, or
- `ipv4.never-default/ipv6.never-default yes` in nmcli

- `dhcp4`, `auto6`, and `ipv6_disabled`

Also, manual addressing can be specified by setting either `dhcp4` or `auto6`.
Expand Down
15 changes: 15 additions & 0 deletions library/network_connections.py
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,12 @@ def ifcfg_create(
if ip["gateway6"] is not None:
ifcfg["IPV6_DEFAULTGW"] = ip["gateway6"]

if ip["auto_gateway"] is not None:
if ip["auto_gateway"]:
ifcfg["DEFROUTE"] = "yes"
else:
ifcfg["DEFROUTE"] = "no"

route4 = []
route6 = []
for r in ip["route"]:
Expand Down Expand Up @@ -1056,6 +1062,15 @@ def connection_create(self, connections, idx, connection_current=None):
s_ip6.set_property(
NM.SETTING_IP_CONFIG_ROUTE_METRIC, ip["route_metric6"]
)

if ip["auto_gateway"] is not None:
if ip["auto_gateway"]:
s_ip6.set_property(NM.SETTING_IP_CONFIG_NEVER_DEFAULT, False)
s_ip4.set_property(NM.SETTING_IP_CONFIG_NEVER_DEFAULT, False)
else:
s_ip6.set_property(NM.SETTING_IP_CONFIG_NEVER_DEFAULT, True)
s_ip4.set_property(NM.SETTING_IP_CONFIG_NEVER_DEFAULT, True)

for nameserver in ip["dns"]:
if nameserver["family"] == socket.AF_INET6:
s_ip6.add_dns(nameserver["address"])
Expand Down
16 changes: 16 additions & 0 deletions module_utils/network_lsr/argument_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,7 @@ def __init__(self):
nested=ArgValidatorIPAddr("address[?]"),
default_value=list,
),
ArgValidatorBool("auto_gateway", default_value=None),
ArgValidatorList(
"route", nested=ArgValidatorIPRoute("route[?]"), default_value=list
),
Expand Down Expand Up @@ -611,6 +612,7 @@ def __init__(self):
"gateway6": None,
"route_metric6": None,
"address": [],
"auto_gateway": None,
"route": [],
"route_append_only": False,
"rule_append_only": False,
Expand Down Expand Up @@ -665,6 +667,20 @@ def _validate_post(self, value, name, result):
raise ValidationError(
name, "'dhcp4_send_hostname' is only valid if 'dhcp4' is enabled"
)

ipv4_gw_defined = result["gateway4"] is not None
ipv6_gw_defined = result["gateway6"] is not None
dhcp_enabled = result["dhcp4"] or result["auto6"]

if result["auto_gateway"] and not (
ipv4_gw_defined or ipv6_gw_defined or dhcp_enabled
):
raise ValidationError(
name,
"must define 'gateway4', 'gateway6', or use dhcp "
"if 'auto_gateway' is enabled",
)

return result


Expand Down
133 changes: 133 additions & 0 deletions tests/playbooks/tests_auto_gateway.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# 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
- include_tasks: tasks/assert_device_present.yml
- name: >-
TEST: I can configure an interface with auto_gateway enabled
debug:
msg: "##################################################"
- import_role:
name: linux-system-roles.network
vars:
network_connections:
- name: "{{ interface }}"
type: ethernet
state: up
ip:
auto_gateway: yes
dhcp4: no
auto6: no
address:
- "2001:db8::2/64"
- "203.0.113.2/24"
gateway6: "2001:db8::1"
gateway4: "203.0.113.1"
- include_tasks: tasks/assert_device_present.yml
- include_tasks: tasks/assert_profile_present.yml
vars:
profile: "{{ interface }}"
- name: "Show ipv4 routes"
command: "ip route"
register: ipv4_routes
changed_when: false
- name: "Assert default ipv4 route is present"
assert:
that:
- >-
"default via 203.0.113.1 dev {{ interface }}"
in ipv4_routes.stdout
- name: "Get ipv6 routes"
command: "ip -6 route"
register: ipv6_route
changed_when: false
- name: "Assert default ipv6 route is present"
assert:
that:
- >-
"default via 2001:db8::1 dev {{ interface }}"
in ipv6_route.stdout
when: network_provider == "nm"
- 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: >-
TEST: I can configure an interface with auto_gateway disabled
debug:
msg: "##################################################"
- include_tasks: tasks/manage_test_interface.yml
vars:
state: present
- import_role:
name: linux-system-roles.network
vars:
network_connections:
- name: "{{ interface }}"
type: ethernet
state: up
ip:
auto_gateway: no
dhcp4: no
auto6: no
address:
- "2001:db8::2/64"
- "203.0.113.2/24"
gateway6: "2001:db8::1"
gateway4: "203.0.113.1"
- include_tasks: tasks/assert_device_present.yml
- include_tasks: tasks/assert_profile_present.yml
vars:
profile: "{{ interface }}"
- name: "Show ipv4 routes"
command: "ip route"
register: ipv4_routes
changed_when: false
- name: "Assert default ipv4 route is absent"
assert:
that:
- >-
"default via 203.0.113.1 dev {{ interface }}"
not in ipv4_routes.stdout
- name: "Get ipv6 routes"
command: "ip -6 route"
register: ipv6_route
changed_when: false
- name: "Assert default ipv6 route is absent"
assert:
that:
- >-
"default via 2001:db8::1 dev {{ interface }}"
not in ipv6_route.stdout
when: network_provider == "nm"
- 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
15 changes: 15 additions & 0 deletions tests/tests_auto_gateway_initscripts.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# SPDX-License-Identifier: BSD-3-Clause
# This file was generated by ensure_provider_tests.py
---
- hosts: all
name: >
Run playbook 'playbooks/tests_auto_gateway.yml' with
initscripts as provider
tasks:
- name: Set network provider to 'initscripts'
set_fact:
network_provider: initscripts
tags:
- always

- import_playbook: playbooks/tests_auto_gateway.yml
19 changes: 19 additions & 0 deletions tests/tests_auto_gateway_nm.yml
Original file line number Diff line number Diff line change
@@ -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_auto_gateway.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_auto_gateway.yml
when:
- ansible_distribution_major_version != '6'
Loading

0 comments on commit b368bce

Please sign in to comment.