cloud-init/SOURCES/ci-Explicit-set-IPV6_AUTOCO...

296 lines
12 KiB
Diff

From 5ded09d5acf4d653fe2cbd54814f53063d265489 Mon Sep 17 00:00:00 2001
From: Eduardo Otubo <otubo@redhat.com>
Date: Thu, 29 Oct 2020 15:05:42 +0100
Subject: [PATCH 1/3] Explicit set IPV6_AUTOCONF and IPV6_FORCE_ACCEPT_RA on
static6 (#634)
RH-Author: Eduardo Terrell Ferrari Otubo (eterrell)
RH-MergeRequest: 13: [RHEL-8.4.0] Add support for ipv6_autoconf on cloud-init-20.3
RH-Commit: [1/1] 41e61c35893f4487981a1ad31f9f97a9a740b397 (eterrell/cloud-init)
RH-Bugzilla: 1889635
commit b46e4a8cff667c8441622089cf7d57aeb88220cd
Author: Eduardo Otubo <otubo@redhat.com>
Date: Thu Oct 29 15:05:42 2020 +0100
Explicit set IPV6_AUTOCONF and IPV6_FORCE_ACCEPT_RA on static6 (#634)
The static and static6 subnet types for network_data.json were
being ignored by the Openstack handler, this would cause the code to
break and not function properly.
As of today, if a static6 configuration is chosen, the interface will
still eventually be available to receive router advertisements or be set
from NetworkManager to wait for them and cycle the interface in negative
case.
It is safe to assume that if the interface is manually configured to use
static ipv6 address, there's no need to wait for router advertisements.
This patch will set automatically IPV6_AUTOCONF and IPV6_FORCE_ACCEPT_RA
both to "no" in this case.
This patch fixes the specific behavior only for RHEL flavor and
sysconfig renderer. It also introduces new unit tests for the specific
case as well as adjusts some existent tests to be compatible with the
new options. This patch also addresses this problem by assigning the
appropriate subnet type for each case on the openstack handler.
rhbz: #1889635
rhbz: #1889635
Signed-off-by: Eduardo Otubo otubo@redhat.com
Signed-off-by: Eduardo Otubo otubo@redhat.com
---
cloudinit/net/network_state.py | 3 +-
cloudinit/net/sysconfig.py | 4 +
cloudinit/sources/helpers/openstack.py | 8 +-
tests/unittests/test_distros/test_netconfig.py | 2 +
tests/unittests/test_net.py | 100 +++++++++++++++++++++++++
5 files changed, 115 insertions(+), 2 deletions(-)
diff --git a/cloudinit/net/network_state.py b/cloudinit/net/network_state.py
index b2f7d31..d9e7fd5 100644
--- a/cloudinit/net/network_state.py
+++ b/cloudinit/net/network_state.py
@@ -820,7 +820,8 @@ def _normalize_subnet(subnet):
if subnet.get('type') in ('static', 'static6'):
normal_subnet.update(
- _normalize_net_keys(normal_subnet, address_keys=('address',)))
+ _normalize_net_keys(normal_subnet, address_keys=(
+ 'address', 'ip_address',)))
normal_subnet['routes'] = [_normalize_route(r)
for r in subnet.get('routes', [])]
diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py
index af093dd..c078898 100644
--- a/cloudinit/net/sysconfig.py
+++ b/cloudinit/net/sysconfig.py
@@ -451,6 +451,10 @@ class Renderer(renderer.Renderer):
iface_cfg[mtu_key] = subnet['mtu']
else:
iface_cfg[mtu_key] = subnet['mtu']
+
+ if subnet_is_ipv6(subnet) and flavor == 'rhel':
+ iface_cfg['IPV6_FORCE_ACCEPT_RA'] = False
+ iface_cfg['IPV6_AUTOCONF'] = False
elif subnet_type == 'manual':
if flavor == 'suse':
LOG.debug('Unknown subnet type setting "%s"', subnet_type)
diff --git a/cloudinit/sources/helpers/openstack.py b/cloudinit/sources/helpers/openstack.py
index 65e020c..3e6365f 100644
--- a/cloudinit/sources/helpers/openstack.py
+++ b/cloudinit/sources/helpers/openstack.py
@@ -602,11 +602,17 @@ def convert_net_json(network_json=None, known_macs=None):
elif network['type'] in ['ipv6_slaac', 'ipv6_dhcpv6-stateless',
'ipv6_dhcpv6-stateful']:
subnet.update({'type': network['type']})
- elif network['type'] in ['ipv4', 'ipv6']:
+ elif network['type'] in ['ipv4', 'static']:
subnet.update({
'type': 'static',
'address': network.get('ip_address'),
})
+ elif network['type'] in ['ipv6', 'static6']:
+ cfg.update({'accept-ra': False})
+ subnet.update({
+ 'type': 'static6',
+ 'address': network.get('ip_address'),
+ })
# Enable accept_ra for stateful and legacy ipv6_dhcp types
if network['type'] in ['ipv6_dhcpv6-stateful', 'ipv6_dhcp']:
diff --git a/tests/unittests/test_distros/test_netconfig.py b/tests/unittests/test_distros/test_netconfig.py
index 8d7b09c..f9fc3a1 100644
--- a/tests/unittests/test_distros/test_netconfig.py
+++ b/tests/unittests/test_distros/test_netconfig.py
@@ -514,7 +514,9 @@ class TestNetCfgDistroRedhat(TestNetCfgDistroBase):
DEVICE=eth0
IPV6ADDR=2607:f0d0:1002:0011::2/64
IPV6INIT=yes
+ IPV6_AUTOCONF=no
IPV6_DEFAULTGW=2607:f0d0:1002:0011::1
+ IPV6_FORCE_ACCEPT_RA=no
NM_CONTROLLED=no
ONBOOT=yes
TYPE=Ethernet
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
index 9985a97..d7a7a65 100644
--- a/tests/unittests/test_net.py
+++ b/tests/unittests/test_net.py
@@ -750,7 +750,9 @@ IPADDR=172.19.1.34
IPV6ADDR=2001:DB8::10/64
IPV6ADDR_SECONDARIES="2001:DB9::10/64 2001:DB10::10/64"
IPV6INIT=yes
+IPV6_AUTOCONF=no
IPV6_DEFAULTGW=2001:DB8::1
+IPV6_FORCE_ACCEPT_RA=no
NETMASK=255.255.252.0
ONBOOT=yes
TYPE=Ethernet
@@ -1022,6 +1024,8 @@ NETWORK_CONFIGS = {
IPADDR=192.168.14.2
IPV6ADDR=2001:1::1/64
IPV6INIT=yes
+ IPV6_AUTOCONF=no
+ IPV6_FORCE_ACCEPT_RA=no
NETMASK=255.255.255.0
ONBOOT=yes
TYPE=Ethernet
@@ -1247,6 +1251,33 @@ NETWORK_CONFIGS = {
"""),
},
},
+ 'static6': {
+ 'yaml': textwrap.dedent("""\
+ version: 1
+ config:
+ - type: 'physical'
+ name: 'iface0'
+ accept-ra: 'no'
+ subnets:
+ - type: 'static6'
+ address: 2001:1::1/64
+ """).rstrip(' '),
+ 'expected_sysconfig_rhel': {
+ 'ifcfg-iface0': textwrap.dedent("""\
+ BOOTPROTO=none
+ DEVICE=iface0
+ IPV6ADDR=2001:1::1/64
+ IPV6INIT=yes
+ IPV6_AUTOCONF=no
+ IPV6_FORCE_ACCEPT_RA=no
+ DEVICE=iface0
+ NM_CONTROLLED=no
+ ONBOOT=yes
+ TYPE=Ethernet
+ USERCTL=no
+ """),
+ },
+ },
'dhcpv6_stateless': {
'expected_eni': textwrap.dedent("""\
auto lo
@@ -1636,6 +1667,8 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true
IPADDR=192.168.14.2
IPV6ADDR=2001:1::1/64
IPV6INIT=yes
+ IPV6_AUTOCONF=no
+ IPV6_FORCE_ACCEPT_RA=no
IPV6_DEFAULTGW=2001:4800:78ff:1b::1
MACADDR=bb:bb:bb:bb:bb:aa
NETMASK=255.255.255.0
@@ -2158,6 +2191,8 @@ iface bond0 inet6 static
IPADDR1=192.168.1.2
IPV6ADDR=2001:1::1/92
IPV6INIT=yes
+ IPV6_AUTOCONF=no
+ IPV6_FORCE_ACCEPT_RA=no
MTU=9000
NETMASK=255.255.255.0
NETMASK1=255.255.255.0
@@ -2259,6 +2294,8 @@ iface bond0 inet6 static
IPADDR1=192.168.1.2
IPV6ADDR=2001:1::bbbb/96
IPV6INIT=yes
+ IPV6_AUTOCONF=no
+ IPV6_FORCE_ACCEPT_RA=no
IPV6_DEFAULTGW=2001:1::1
MTU=2222
NETMASK=255.255.255.0
@@ -2341,6 +2378,9 @@ iface bond0 inet6 static
HWADDR=52:54:00:12:34:00
IPV6ADDR=2001:1::100/96
IPV6INIT=yes
+ IPV6_AUTOCONF=no
+ IPV6_FORCE_ACCEPT_RA=no
+ NM_CONTROLLED=no
ONBOOT=yes
TYPE=Ethernet
USERCTL=no
@@ -2352,6 +2392,9 @@ iface bond0 inet6 static
HWADDR=52:54:00:12:34:01
IPV6ADDR=2001:1::101/96
IPV6INIT=yes
+ IPV6_AUTOCONF=no
+ IPV6_FORCE_ACCEPT_RA=no
+ NM_CONTROLLED=no
ONBOOT=yes
TYPE=Ethernet
USERCTL=no
@@ -3151,6 +3194,61 @@ USERCTL=no
self._compare_files_to_expected(entry[self.expected_name], found)
self._assert_headers(found)
+ def test_stattic6_from_json(self):
+ net_json = {
+ "services": [{"type": "dns", "address": "172.19.0.12"}],
+ "networks": [{
+ "network_id": "dacd568d-5be6-4786-91fe-750c374b78b4",
+ "type": "ipv4", "netmask": "255.255.252.0",
+ "link": "tap1a81968a-79",
+ "routes": [{
+ "netmask": "0.0.0.0",
+ "network": "0.0.0.0",
+ "gateway": "172.19.3.254",
+ }, {
+ "netmask": "0.0.0.0", # A second default gateway
+ "network": "0.0.0.0",
+ "gateway": "172.20.3.254",
+ }],
+ "ip_address": "172.19.1.34", "id": "network0"
+ }, {
+ "network_id": "mgmt",
+ "netmask": "ffff:ffff:ffff:ffff::",
+ "link": "interface1",
+ "mode": "link-local",
+ "routes": [],
+ "ip_address": "fe80::c096:67ff:fe5c:6e84",
+ "type": "static6",
+ "id": "network1",
+ "services": [],
+ "accept-ra": "false"
+ }],
+ "links": [
+ {
+ "ethernet_mac_address": "fa:16:3e:ed:9a:59",
+ "mtu": None, "type": "bridge", "id":
+ "tap1a81968a-79",
+ "vif_id": "1a81968a-797a-400f-8a80-567f997eb93f"
+ },
+ ],
+ }
+ macs = {'fa:16:3e:ed:9a:59': 'eth0'}
+ render_dir = self.tmp_dir()
+ network_cfg = openstack.convert_net_json(net_json, known_macs=macs)
+ ns = network_state.parse_net_config_data(network_cfg,
+ skip_broken=False)
+ renderer = self._get_renderer()
+ with self.assertRaises(ValueError):
+ renderer.render_network_state(ns, target=render_dir)
+ self.assertEqual([], os.listdir(render_dir))
+
+ def test_static6_from_yaml(self):
+ entry = NETWORK_CONFIGS['static6']
+ found = self._render_and_read(network_config=yaml.load(
+ entry['yaml']))
+ self._compare_files_to_expected(entry[self.expected_name], found)
+ self._assert_headers(found)
+
def test_dhcpv6_reject_ra_config_v2(self):
entry = NETWORK_CONFIGS['dhcpv6_reject_ra']
found = self._render_and_read(network_config=yaml.load(
@@ -3268,6 +3366,8 @@ USERCTL=no
IPADDR=192.168.42.100
IPV6ADDR=2001:db8::100/32
IPV6INIT=yes
+ IPV6_AUTOCONF=no
+ IPV6_FORCE_ACCEPT_RA=no
IPV6_DEFAULTGW=2001:db8::1
NETMASK=255.255.255.0
NM_CONTROLLED=no
--
1.8.3.1