summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cloudinit/net/eni.py7
-rw-r--r--cloudinit/net/sysconfig.py7
-rw-r--r--cloudinit/sources/helpers/openstack.py3
-rw-r--r--tests/unittests/test_datasource/test_configdrive.py39
-rw-r--r--tests/unittests/test_net.py88
5 files changed, 141 insertions, 3 deletions
diff --git a/cloudinit/net/eni.py b/cloudinit/net/eni.py
index b129bb62..530922b5 100644
--- a/cloudinit/net/eni.py
+++ b/cloudinit/net/eni.py
@@ -411,8 +411,13 @@ class Renderer(renderer.Renderer):
else:
ipv4_subnet_mtu = subnet.get('mtu')
iface['inet'] = subnet_inet
- if subnet['type'].startswith('dhcp'):
+ if (subnet['type'] == 'dhcp4' or subnet['type'] == 'dhcp6' or
+ subnet['type'] == 'ipv6_dhcpv6-stateful'):
+ # Configure network settings using DHCP or DHCPv6
iface['mode'] = 'dhcp'
+ elif subnet['type'] == 'ipv6_dhcpv6-stateless':
+ # Configure network settings using SLAAC from RAs
+ iface['mode'] = 'auto'
# do not emit multiple 'auto $IFACE' lines as older (precise)
# ifupdown complains
diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py
index 87b548e5..4e656768 100644
--- a/cloudinit/net/sysconfig.py
+++ b/cloudinit/net/sysconfig.py
@@ -343,10 +343,15 @@ 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':
+ if subnet_type == 'dhcp6' or subnet_type == 'ipv6_dhcpv6-stateful':
# 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-stateless':
+ iface_cfg['IPV6INIT'] = True
+ # Configure network settings using SLAAC from RAs
+ iface_cfg['IPV6_AUTOCONF'] = True
elif subnet_type in ['dhcp4', 'dhcp']:
iface_cfg['BOOTPROTO'] = 'dhcp'
elif subnet_type == 'static':
diff --git a/cloudinit/sources/helpers/openstack.py b/cloudinit/sources/helpers/openstack.py
index 8f069115..d1c4601a 100644
--- a/cloudinit/sources/helpers/openstack.py
+++ b/cloudinit/sources/helpers/openstack.py
@@ -585,7 +585,8 @@ def convert_net_json(network_json=None, known_macs=None):
subnet = dict((k, v) for k, v in network.items()
if k in valid_keys['subnet'])
if 'dhcp' in network['type']:
- t = 'dhcp6' if network['type'].startswith('ipv6') else 'dhcp4'
+ t = (network['type'] if network['type'].startswith('ipv6')
+ else 'dhcp4')
subnet.update({
'type': t,
})
diff --git a/tests/unittests/test_datasource/test_configdrive.py b/tests/unittests/test_datasource/test_configdrive.py
index 520c50fe..8c788c1c 100644
--- a/tests/unittests/test_datasource/test_configdrive.py
+++ b/tests/unittests/test_datasource/test_configdrive.py
@@ -499,6 +499,45 @@ class TestNetJson(CiTestCase):
known_macs=KNOWN_MACS)
self.assertEqual(myds.network_config, network_config)
+ def test_network_config_conversion_dhcp6(self):
+ """Test some ipv6 input network json and check the expected
+ conversions."""
+ in_data = {
+ 'links': [
+ {'vif_id': '2ecc7709-b3f7-4448-9580-e1ec32d75bbd',
+ 'ethernet_mac_address': 'fa:16:3e:69:b0:58',
+ 'type': 'ovs', 'mtu': None, 'id': 'tap2ecc7709-b3'},
+ {'vif_id': '2f88d109-5b57-40e6-af32-2472df09dc33',
+ 'ethernet_mac_address': 'fa:16:3e:d4:57:ad',
+ 'type': 'ovs', 'mtu': None, 'id': 'tap2f88d109-5b'},
+ ],
+ 'networks': [
+ {'link': 'tap2ecc7709-b3', 'type': 'ipv6_dhcpv6-stateless',
+ 'network_id': '6d6357ac-0f70-4afa-8bd7-c274cc4ea235',
+ 'id': 'network0'},
+ {'link': 'tap2f88d109-5b', 'type': 'ipv6_dhcpv6-stateful',
+ 'network_id': 'd227a9b3-6960-4d94-8976-ee5788b44f54',
+ 'id': 'network1'},
+ ]
+ }
+ out_data = {
+ 'version': 1,
+ 'config': [
+ {'mac_address': 'fa:16:3e:69:b0:58',
+ 'mtu': None,
+ 'name': 'enp0s1',
+ 'subnets': [{'type': 'ipv6_dhcpv6-stateless'}],
+ 'type': 'physical'},
+ {'mac_address': 'fa:16:3e:d4:57:ad',
+ 'mtu': None,
+ 'name': 'enp0s2',
+ 'subnets': [{'type': 'ipv6_dhcpv6-stateful'}],
+ 'type': 'physical'}
+ ],
+ }
+ conv_data = openstack.convert_net_json(in_data, known_macs=KNOWN_MACS)
+ self.assertEqual(out_data, conv_data)
+
def test_network_config_conversions(self):
"""Tests a bunch of input network json and checks the
expected conversions."""
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
index b6597412..f5a9cae6 100644
--- a/tests/unittests/test_net.py
+++ b/tests/unittests/test_net.py
@@ -1070,6 +1070,82 @@ NETWORK_CONFIGS = {
"""),
},
},
+ 'dhcpv6_stateless': {
+ 'expected_eni': textwrap.dedent("""\
+ auto lo
+ iface lo inet loopback
+
+ auto iface0
+ iface iface0 inet6 auto
+ """).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': 'ipv6_dhcpv6-stateless'}
+ """).rstrip(' '),
+ 'expected_sysconfig': {
+ 'ifcfg-iface0': textwrap.dedent("""\
+ BOOTPROTO=none
+ DEVICE=iface0
+ IPV6_AUTOCONF=yes
+ IPV6INIT=yes
+ DEVICE=iface0
+ NM_CONTROLLED=no
+ ONBOOT=yes
+ STARTMODE=auto
+ TYPE=Ethernet
+ USERCTL=no
+ """),
+ },
+ },
+ 'dhcpv6_stateful': {
+ 'expected_eni': textwrap.dedent("""\
+ auto lo
+ iface lo inet loopback
+
+ 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': 'ipv6_dhcpv6-stateful'}
+ """).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
+ """),
+ },
+ },
'all': {
'expected_eni': ("""\
auto lo
@@ -2781,6 +2857,18 @@ USERCTL=no
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']))
+ self._compare_files_to_expected(entry[self.expected_name], found)
+ self._assert_headers(found)
+
+ def test_dhcpv6_stateful_config(self):
+ entry = NETWORK_CONFIGS['dhcpv6_stateful']
+ 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_check_ifcfg_rh(self):
"""ifcfg-rh plugin is added NetworkManager.conf if conf present."""
render_dir = self.tmp_dir()