diff --git a/releasenotes/notes/ipv6-address-mode-option-c85242d337d9e0d9.yaml b/releasenotes/notes/ipv6-address-mode-option-c85242d337d9e0d9.yaml new file mode 100644 index 000000000..b87ae93b3 --- /dev/null +++ b/releasenotes/notes/ipv6-address-mode-option-c85242d337d9e0d9.yaml @@ -0,0 +1,12 @@ +--- +features: + - | + The IPv6 addressing mode is now configurable for the undercloud + provisioning network. The option ``ipv6_address_mode`` (default: + ``dhpcv6-stateless``) in undercloud.conf is used to control the addressing + mode. Possible values: + + - **dhpcv6-stateless**: Address configuration using RA and optional + information using DHCPv6. + - **dhcpv6-stateful**: Address configuration and optional information + using DHCPv6. diff --git a/tripleoclient/config/undercloud.py b/tripleoclient/config/undercloud.py index 6d3d4bc5d..28392c81c 100644 --- a/tripleoclient/config/undercloud.py +++ b/tripleoclient/config/undercloud.py @@ -346,6 +346,19 @@ class UndercloudConfig(StandaloneConfig): 'values is: %s') % ' '.join(constants.ADDITIONAL_ARCHITECTURES)) ), + cfg.StrOpt('ipv6_address_mode', + default='dhcpv6-stateless', + choices=[ + ('dhcpv6-stateless', 'Address configuration using ' + 'RA and optional information ' + 'using DHCPv6.'), + ('dhcpv6-stateful', 'Address configuration and ' + 'optional information using ' + 'DHCPv6.') + ], + help=(_('IPv6 address configuration mode for the ' + 'undercloud provisioning network.')) + ), ] return self.sort_opts(_base_opts + _opts) diff --git a/tripleoclient/tests/config/test_config_undercloud.py b/tripleoclient/tests/config/test_config_undercloud.py index 2b911c16b..b60ca2b85 100644 --- a/tripleoclient/tests/config/test_config_undercloud.py +++ b/tripleoclient/tests/config/test_config_undercloud.py @@ -50,6 +50,7 @@ class TestUndercloudConfig(base.TestCase): 'inspection_interface', 'inspection_runbench', 'ipa_otp', + 'ipv6_address_mode', 'ipxe_enabled', 'local_interface', 'local_ip', @@ -115,6 +116,7 @@ class TestUndercloudConfig(base.TestCase): 'inspection_interface', 'inspection_runbench', 'ipa_otp', + 'ipv6_address_mode', 'ipxe_enabled', 'local_interface', 'local_ip', diff --git a/tripleoclient/tests/v1/undercloud/test_config.py b/tripleoclient/tests/v1/undercloud/test_config.py index f58989edd..a1ba431f1 100644 --- a/tripleoclient/tests/v1/undercloud/test_config.py +++ b/tripleoclient/tests/v1/undercloud/test_config.py @@ -175,7 +175,9 @@ class TestNetworkSettings(base.TestCase): 'DnsNameServers': ['10.10.10.10', '10.10.10.11'], 'HostRoutes': [], 'NetworkCidr': '192.168.24.0/24', - 'NetworkGateway': '192.168.24.1'}}} + 'NetworkGateway': '192.168.24.1'}}, + 'UndercloudCtlplaneIPv6AddressMode': 'dhcpv6-stateless', + } self.assertEqual(expected, env) def test_ipv6_control_plane(self): @@ -221,7 +223,9 @@ class TestNetworkSettings(base.TestCase): 'fd12:3456:789a:1::6'], 'HostRoutes': [], 'NetworkCidr': 'fd12:3456:789a:1::/64', - 'NetworkGateway': 'fd12:3456:789a:1::1'}}} + 'NetworkGateway': 'fd12:3456:789a:1::1'}}, + 'UndercloudCtlplaneIPv6AddressMode': 'dhcpv6-stateless', + } self.assertEqual(expected, env) def test_nameserver_toomany_fail(self): @@ -295,7 +299,9 @@ class TestNetworkSettings(base.TestCase): 'DnsNameServers': ['10.10.10.10', '10.10.10.11'], 'HostRoutes': [], 'NetworkCidr': '192.168.24.0/24', - 'NetworkGateway': '192.168.24.1'}}} + 'NetworkGateway': '192.168.24.1'}}, + 'UndercloudCtlplaneIPv6AddressMode': 'dhcpv6-stateless', + } self.assertEqual(expected, env) def test_ignore_dhcp_start_end_if_default_but_cidr_not_default(self): @@ -323,7 +329,9 @@ class TestNetworkSettings(base.TestCase): 'DnsNameServers': ['10.10.10.10', '10.10.10.11'], 'HostRoutes': [], 'NetworkCidr': '192.168.10.0/24', - 'NetworkGateway': '192.168.10.1'}}} + 'NetworkGateway': '192.168.10.1'}}, + 'UndercloudCtlplaneIPv6AddressMode': 'dhcpv6-stateless', + } self.assertEqual(expected, env) def test_dhcp_exclude(self): @@ -355,7 +363,9 @@ class TestNetworkSettings(base.TestCase): 'DnsNameServers': ['10.10.10.10', '10.10.10.11'], 'HostRoutes': [], 'NetworkCidr': '192.168.10.0/24', - 'NetworkGateway': '192.168.10.1'}}} + 'NetworkGateway': '192.168.10.1'}}, + 'UndercloudCtlplaneIPv6AddressMode': 'dhcpv6-stateless', + } self.assertEqual(expected, env) def test_no_dhcp_start_no_dhcp_end(self): @@ -382,7 +392,9 @@ class TestNetworkSettings(base.TestCase): 'DnsNameServers': ['10.10.10.10', '10.10.10.11'], 'HostRoutes': [], 'NetworkCidr': '192.168.24.0/24', - 'NetworkGateway': '192.168.24.1'}}} + 'NetworkGateway': '192.168.24.1'}}, + 'UndercloudCtlplaneIPv6AddressMode': 'dhcpv6-stateless', + } self.assertEqual(expected, env) def test_dhcp_start_no_dhcp_end(self): @@ -409,7 +421,9 @@ class TestNetworkSettings(base.TestCase): 'DnsNameServers': ['10.10.10.10', '10.10.10.11'], 'HostRoutes': [], 'NetworkCidr': '192.168.24.0/24', - 'NetworkGateway': '192.168.24.1'}} + 'NetworkGateway': '192.168.24.1'}, + }, + 'UndercloudCtlplaneIPv6AddressMode': 'dhcpv6-stateless', } self.assertEqual(expected, env) @@ -437,7 +451,9 @@ class TestNetworkSettings(base.TestCase): 'DnsNameServers': ['10.10.10.10', '10.10.10.11'], 'HostRoutes': [], 'NetworkCidr': '192.168.24.0/24', - 'NetworkGateway': '192.168.24.1'}} + 'NetworkGateway': '192.168.24.1'}, + }, + 'UndercloudCtlplaneIPv6AddressMode': 'dhcpv6-stateless', } self.assertEqual(expected, env) @@ -527,7 +543,8 @@ class TestNetworkSettings(base.TestCase): 'HostRoutes': [], 'NetworkCidr': '192.168.20.0/24', 'NetworkGateway': '192.168.20.254'} - } + }, + 'UndercloudCtlplaneIPv6AddressMode': 'dhcpv6-stateless', } self.assertEqual(expected, env) @@ -603,7 +620,8 @@ class TestNetworkSettings(base.TestCase): 'HostRoutes': [], 'NetworkCidr': '192.168.20.0/24', 'NetworkGateway': '192.168.20.254'} - } + }, + 'UndercloudCtlplaneIPv6AddressMode': 'dhcpv6-stateless', } self.assertEqual(expected, env) @@ -654,7 +672,8 @@ class TestNetworkSettings(base.TestCase): 'HostRoutes': [], 'NetworkCidr': '192.168.10.0/24', 'NetworkGateway': '192.168.10.254'} - } + }, + 'UndercloudCtlplaneIPv6AddressMode': 'dhcpv6-stateless', } self.assertEqual(expected, env) @@ -707,7 +726,8 @@ class TestNetworkSettings(base.TestCase): 'HostRoutes': [], 'NetworkCidr': '192.168.10.0/24', 'NetworkGateway': '192.168.10.222'} - } + }, + 'UndercloudCtlplaneIPv6AddressMode': 'dhcpv6-stateless', } self.assertEqual(expected, env) @@ -795,7 +815,8 @@ class TestNetworkSettings(base.TestCase): 'nexthop': '192.168.20.254'}], 'NetworkCidr': '192.168.20.0/24', 'NetworkGateway': '192.168.20.254'} - } + }, + 'UndercloudCtlplaneIPv6AddressMode': 'dhcpv6-stateless' } self.assertEqual(expected, env) diff --git a/tripleoclient/v1/undercloud_config.py b/tripleoclient/v1/undercloud_config.py index 7de0f20a8..504c97bb7 100644 --- a/tripleoclient/v1/undercloud_config.py +++ b/tripleoclient/v1/undercloud_config.py @@ -331,6 +331,7 @@ def _process_network_args(env): env['IronicInspectorSubnets'] = _generate_inspection_subnets() env['ControlPlaneStaticRoutes'] = _generate_subnets_static_routes() env['UndercloudCtlplaneSubnets'] = {} + env['UndercloudCtlplaneIPv6AddressMode'] = CONF['ipv6_address_mode'] for subnet in CONF.subnets: s = CONF.get(subnet) env['UndercloudCtlplaneSubnets'][subnet] = {