cloud-init-dev team mailing list archive
-
cloud-init-dev team
-
Mailing list archive
-
Message #06793
[Merge] ~harald-jensas/cloud-init:bug/1806014 into cloud-init:master
Harald Jensås has proposed merging ~harald-jensas/cloud-init:bug/1806014 into cloud-init:master with ~harald-jensas/cloud-init:bug/1847517 as a prerequisite.
Requested reviews:
cloud-init Commiters (cloud-init-dev)
Related bugs:
Bug #1696476 in cloud-init: "Identification of e24cloud platform as using Ec2 datasource"
https://bugs.launchpad.net/cloud-init/+bug/1696476
Bug #1806014 in cloud-init: "[Centos] IPV6_AUTOCONF=no when using dhcp6"
https://bugs.launchpad.net/cloud-init/+bug/1806014
Bug #1847517 in cloud-init: "cloudinit/net/sysconfig.py write incorrect config for dhcp-stateless openstack subnets"
https://bugs.launchpad.net/cloud-init/+bug/1847517
For more details, see:
https://code.launchpad.net/~harald-jensas/cloud-init/+git/cloud-init/+merge/374138
--
Your team cloud-init Commiters is requested to review the proposed merge of ~harald-jensas/cloud-init:bug/1806014 into cloud-init:master.
diff --git a/cloudinit/net/netplan.py b/cloudinit/net/netplan.py
index e54a34e..afed089 100644
--- a/cloudinit/net/netplan.py
+++ b/cloudinit/net/netplan.py
@@ -52,6 +52,7 @@ def _extract_addresses(config, entry, ifname):
'netmask': 64,
'type': 'static'}],
'type: physical'
+ 'accept-ra': 'true'
}
An entry dictionary looks like:
@@ -84,6 +85,7 @@ def _extract_addresses(config, entry, ifname):
nameservers = []
searchdomains = []
subnets = config.get('subnets', [])
+ accept_ra = config.get('accept-ra', False)
if subnets is None:
subnets = []
for subnet in subnets:
@@ -144,6 +146,8 @@ def _extract_addresses(config, entry, ifname):
ns = entry.get('nameservers', {})
ns.update({'search': searchdomains})
entry.update({'nameservers': ns})
+ if util.is_true(accept_ra):
+ entry.update({'accept-ra': True})
def _extract_bond_slaves_by_name(interfaces, entry, bond_master):
diff --git a/cloudinit/net/network_state.py b/cloudinit/net/network_state.py
index c0c415d..4123c27 100644
--- a/cloudinit/net/network_state.py
+++ b/cloudinit/net/network_state.py
@@ -22,7 +22,8 @@ NETWORK_STATE_REQUIRED_KEYS = {
}
NETWORK_V2_KEY_FILTER = [
'addresses', 'dhcp4', 'dhcp6', 'gateway4', 'gateway6', 'interfaces',
- 'match', 'mtu', 'nameservers', 'renderer', 'set-name', 'wakeonlan'
+ 'match', 'mtu', 'nameservers', 'renderer', 'set-name', 'wakeonlan',
+ 'accept-ra'
]
NET_CONFIG_TO_V2 = {
@@ -340,7 +341,8 @@ class NetworkStateInterpreter(object):
'name': 'eth0',
'subnets': [
{'type': 'dhcp4'}
- ]
+ ],
+ 'accept-ra': 'true'
}
'''
@@ -370,6 +372,7 @@ class NetworkStateInterpreter(object):
'address': None,
'gateway': None,
'subnets': subnets,
+ 'accept-ra': command.get('accept-ra')
})
self._network_state['interfaces'].update({command.get('name'): iface})
self.dump_network_state()
@@ -613,6 +616,7 @@ class NetworkStateInterpreter(object):
driver: ixgbe
set-name: lom1
dhcp6: true
+ accept-ra: true
switchports:
match:
name: enp2*
@@ -641,7 +645,7 @@ class NetworkStateInterpreter(object):
driver = match.get('driver', None)
if driver:
phy_cmd['params'] = {'driver': driver}
- for key in ['mtu', 'match', 'wakeonlan']:
+ for key in ['mtu', 'match', 'wakeonlan', 'accept-ra']:
if key in cfg:
phy_cmd[key] = cfg[key]
diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py
index 4e65676..39b94b8 100644
--- a/cloudinit/net/sysconfig.py
+++ b/cloudinit/net/sysconfig.py
@@ -333,6 +333,8 @@ class Renderer(renderer.Renderer):
if old_key == 'mac_address' and iface['type'] != 'physical':
continue
iface_cfg[new_key] = old_value
+ if iface.get('accept-ra', False):
+ iface_cfg['IPV6_FORCE_ACCEPT_RA'] = True
@classmethod
def _render_subnets(cls, iface_cfg, subnets, has_default_route):
@@ -343,11 +345,16 @@ class Renderer(renderer.Renderer):
for i, subnet in enumerate(subnets, start=len(iface_cfg.children)):
mtu_key = 'MTU'
subnet_type = subnet.get('type')
- if subnet_type == 'dhcp6' or subnet_type == 'ipv6_dhcpv6-stateful':
+ if subnet_type == 'dhcp6':
# TODO need to set BOOTPROTO to dhcp6 on SUSE
iface_cfg['IPV6INIT'] = True
# Configure network settings using DHCPv6
iface_cfg['DHCPV6C'] = True
+ elif subnet_type == 'ipv6_dhcpv6-stateful':
+ iface_cfg['IPV6INIT'] = True
+ # Configure network settings using DHCPv6
+ iface_cfg['DHCPV6C'] = True
+ iface_cfg['IPV6_FORCE_ACCEPT_RA'] = True
elif subnet_type == 'ipv6_dhcpv6-stateless':
iface_cfg['IPV6INIT'] = True
# Configure network settings using SLAAC from RAs
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
index f5a9cae..b7adb78 100644
--- a/tests/unittests/test_net.py
+++ b/tests/unittests/test_net.py
@@ -1034,26 +1034,74 @@ NETWORK_CONFIGS = {
},
'dhcpv6_only': {
'expected_eni': textwrap.dedent("""\
- auto lo
- iface lo inet loopback
+ auto lo
+ iface lo inet loopback
- auto iface0
- iface iface0 inet6 dhcp
+ auto iface0
+ iface iface0 inet6 dhcp
+ """).rstrip(' '),
+ 'expected_netplan': textwrap.dedent("""
+ network:
+ version: 2
+ ethernets:
+ iface0:
+ dhcp6: true
+ """).rstrip(' '),
+ 'yaml': textwrap.dedent("""\
+ version: 1
+ config:
+ - type: 'physical'
+ name: 'iface0'
+ subnets:
+ - {'type': 'dhcp6'}
+ """).rstrip(' '),
+ 'expected_sysconfig': {
+ 'ifcfg-iface0': textwrap.dedent("""\
+ BOOTPROTO=none
+ DEVICE=iface0
+ DHCPV6C=yes
+ IPV6INIT=yes
+ DEVICE=iface0
+ NM_CONTROLLED=no
+ ONBOOT=yes
+ STARTMODE=auto
+ TYPE=Ethernet
+ USERCTL=no
+ """),
+ },
+ },
+ 'dhcpv6_accept_ra': {
+ 'expected_eni': textwrap.dedent("""\
+ auto lo
+ iface lo inet loopback
+
+ auto iface0
+ iface iface0 inet6 dhcp
""").rstrip(' '),
+ # TODO: Validate expected_netplan
'expected_netplan': textwrap.dedent("""
network:
version: 2
ethernets:
iface0:
+ accept-ra: true
dhcp6: true
""").rstrip(' '),
- 'yaml': textwrap.dedent("""\
+ 'yaml_v1': textwrap.dedent("""\
version: 1
config:
- type: 'physical'
name: 'iface0'
subnets:
- {'type': 'dhcp6'}
+ accept-ra: 'true'
+ """).rstrip(' '),
+ 'yaml_v2': textwrap.dedent("""\
+ version: 2
+ ethernets:
+ iface0:
+ dhcp6: true
+ accept-ra: 'true'
""").rstrip(' '),
'expected_sysconfig': {
'ifcfg-iface0': textwrap.dedent("""\
@@ -1061,13 +1109,14 @@ NETWORK_CONFIGS = {
DEVICE=iface0
DHCPV6C=yes
IPV6INIT=yes
+ IPV6_FORCE_ACCEPT_RA=yes
DEVICE=iface0
NM_CONTROLLED=no
ONBOOT=yes
STARTMODE=auto
TYPE=Ethernet
USERCTL=no
- """),
+ """),
},
},
'dhcpv6_stateless': {
@@ -1137,6 +1186,7 @@ NETWORK_CONFIGS = {
DEVICE=iface0
DHCPV6C=yes
IPV6INIT=yes
+ IPV6_FORCE_ACCEPT_RA=yes
DEVICE=iface0
NM_CONTROLLED=no
ONBOOT=yes
@@ -2857,6 +2907,20 @@ USERCTL=no
self._compare_files_to_expected(entry[self.expected_name], found)
self._assert_headers(found)
+ def test_dhcpv6_accept_ra_config_v1(self):
+ entry = NETWORK_CONFIGS['dhcpv6_accept_ra']
+ found = self._render_and_read(network_config=yaml.load(
+ entry['yaml_v1']))
+ self._compare_files_to_expected(entry[self.expected_name], found)
+ self._assert_headers(found)
+
+ def test_dhcpv6_accept_ra_config_v2(self):
+ entry = NETWORK_CONFIGS['dhcpv6_accept_ra']
+ found = self._render_and_read(network_config=yaml.load(
+ entry['yaml_v2']))
+ self._compare_files_to_expected(entry[self.expected_name], found)
+ self._assert_headers(found)
+
def test_dhcpv6_stateless_config(self):
entry = NETWORK_CONFIGS['dhcpv6_stateless']
found = self._render_and_read(network_config=yaml.load(entry['yaml']))
@@ -3918,6 +3982,14 @@ class TestNetplanRoundTrip(CiTestCase):
entry['expected_netplan'].splitlines(),
files['/etc/netplan/50-cloud-init.yaml'].splitlines())
+ def testsimple_render_dhcpv6_accept_ra(self):
+ entry = NETWORK_CONFIGS['dhcpv6_accept_ra']
+ files = self._render_and_read(network_config=yaml.load(
+ entry['yaml_v1']))
+ self.assertEqual(
+ entry['expected_netplan'].splitlines(),
+ files['/etc/netplan/50-cloud-init.yaml'].splitlines())
+
def testsimple_render_all(self):
entry = NETWORK_CONFIGS['all']
files = self._render_and_read(network_config=yaml.load(entry['yaml']))