From 034778b6a8bb0740f0b157f1b105c2e6c0c25712 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Harald=20Jens=C3=A5s?= Date: Mon, 11 Mar 2019 19:23:25 +0100 Subject: [PATCH] Undercloud - support ctlplane subnet host routes Add new option 'host_routes' to the subnet definitions for the ctlplane network in undercloud.conf. Routes defined for the local subnet will be appended to the THT parameter 'ControlPlaneStaticRoutes'. The net-config template for the undercloud will ensure these routes are configured on the undercloud. Routes are also added to UndercloudCtlplaneSubnets parameter used by the undercloud to create the ctlplane network and subnets. In THT change: I46b7c7175f542ad4d375a20f133c05064e7b7222 this new data is used so that the host routes are configured for the neutron ctlplane subnets. Related-Bug: #1819464 Change-Id: I692fcc4a494b2cda1911814a53a0c6ec2f99f807 --- ...oud-conf-host-routes-7084bf696020c39e.yaml | 11 ++ tripleoclient/config/undercloud.py | 16 +++ .../tests/config/test_config_undercloud.py | 1 + .../tests/v1/undercloud/test_config.py | 104 +++++++++++++++++- tripleoclient/v1/undercloud_config.py | 5 + 5 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/ctlplane-undercloud-conf-host-routes-7084bf696020c39e.yaml diff --git a/releasenotes/notes/ctlplane-undercloud-conf-host-routes-7084bf696020c39e.yaml b/releasenotes/notes/ctlplane-undercloud-conf-host-routes-7084bf696020c39e.yaml new file mode 100644 index 000000000..53f8785a1 --- /dev/null +++ b/releasenotes/notes/ctlplane-undercloud-conf-host-routes-7084bf696020c39e.yaml @@ -0,0 +1,11 @@ +--- +features: + - | + A new option ``host_routes`` are now available for subnet defenitions in + ``undercloud.conf``. + + - Host routes specified for the *local_subnet* will be added to + the routing table on the Undercloud. + - Host routes for all subnets are passed to tripleo-heat-templates so that + the *host_routes* property of the ctlplane subnets are set accordingly + when installing the Undercloud. diff --git a/tripleoclient/config/undercloud.py b/tripleoclient/config/undercloud.py index 2bb9bf0c3..8030bc5d7 100644 --- a/tripleoclient/config/undercloud.py +++ b/tripleoclient/config/undercloud.py @@ -47,6 +47,10 @@ GATEWAY_HELP_STR = _( 'on this network.') MASQUERADE_HELP_STR = _( 'The network will be masqueraded for external access.') +HOST_ROUTES_HELP_STR = _( + 'Host routes for the Neutron-managed subnet for the Overcloud instances ' + 'on this network. The host routes on the local_subnet will also be ' + 'configured on the undercloud.') # Deprecated options _deprecated_opt_network_gateway = [cfg.DeprecatedOpt( @@ -370,6 +374,13 @@ class UndercloudConfig(StandaloneConfig): cfg.BoolOpt('masquerade', default=False, help=MASQUERADE_HELP_STR), + cfg.ListOpt('host_routes', + item_type=cfg.types.Dict(bounds=True), + bounds=True, + default=[], + sample_default=('[{destination: 10.10.10.0, ' + 'nexthop: 192.168.24.1}]'), + help=HOST_ROUTES_HELP_STR), ] return self.sort_opts(_subnets_opts) @@ -393,6 +404,11 @@ class UndercloudConfig(StandaloneConfig): cfg.BoolOpt('masquerade', default=False, help=MASQUERADE_HELP_STR), + cfg.ListOpt('host_routes', + item_type=cfg.types.Dict(bounds=True), + bounds=True, + default=[], + help=HOST_ROUTES_HELP_STR), ] return self.sort_opts(_subnets_opts) diff --git a/tripleoclient/tests/config/test_config_undercloud.py b/tripleoclient/tests/config/test_config_undercloud.py index 6957f016a..293c2a551 100644 --- a/tripleoclient/tests/config/test_config_undercloud.py +++ b/tripleoclient/tests/config/test_config_undercloud.py @@ -147,6 +147,7 @@ class TestUndercloudConfig(base.TestCase): 'dhcp_exclude', 'dhcp_start', 'gateway', + 'host_routes', 'inspection_iprange', 'masquerade'] diff --git a/tripleoclient/tests/v1/undercloud/test_config.py b/tripleoclient/tests/v1/undercloud/test_config.py index 83c48e2dd..4a46d47ed 100644 --- a/tripleoclient/tests/v1/undercloud/test_config.py +++ b/tripleoclient/tests/v1/undercloud/test_config.py @@ -141,7 +141,10 @@ class TestNetworkSettings(base.TestCase): cfg.ListOpt('dhcp_exclude'), cfg.StrOpt('inspection_iprange'), cfg.StrOpt('gateway'), - cfg.BoolOpt('masquerade')] + cfg.BoolOpt('masquerade'), + cfg.ListOpt('host_routes', + item_type=cfg.types.Dict(bounds=True), + bounds=True,)] self.conf.register_opts(self.opts, group=self.grp0) self.grp1 = cfg.OptGroup(name='subnet1', title='subnet1') self.grp2 = cfg.OptGroup(name='subnet2', title='subnet2') @@ -152,6 +155,7 @@ class TestNetworkSettings(base.TestCase): inspection_iprange='192.168.24.100,192.168.24.120', gateway='192.168.24.1', masquerade=False, + host_routes=[], group='ctlplane-subnet') def test_default(self): @@ -170,6 +174,7 @@ class TestNetworkSettings(base.TestCase): 'ctlplane-subnet': { 'AllocationPools': [ {'start': '192.168.24.5', 'end': '192.168.24.24'}], + 'HostRoutes': [], 'NetworkCidr': '192.168.24.0/24', 'NetworkGateway': '192.168.24.1'}}} self.assertEqual(expected, env) @@ -203,6 +208,7 @@ class TestNetworkSettings(base.TestCase): 'AllocationPools': [ {'start': '192.168.24.4', 'end': '192.168.24.99'}, {'start': '192.168.24.121', 'end': '192.168.24.254'}], + 'HostRoutes': [], 'NetworkCidr': '192.168.24.0/24', 'NetworkGateway': '192.168.24.1'}}} self.assertEqual(expected, env) @@ -228,6 +234,7 @@ class TestNetworkSettings(base.TestCase): 'AllocationPools': [ {'start': '192.168.10.2', 'end': '192.168.10.99'}, {'start': '192.168.10.121', 'end': '192.168.10.254'}], + 'HostRoutes': [], 'NetworkCidr': '192.168.10.0/24', 'NetworkGateway': '192.168.10.1'}}} self.assertEqual(expected, env) @@ -257,6 +264,7 @@ class TestNetworkSettings(base.TestCase): {'start': '192.168.10.51', 'end': '192.168.10.79'}, {'start': '192.168.10.90', 'end': '192.168.10.99'}, {'start': '192.168.10.121', 'end': '192.168.10.254'}], + 'HostRoutes': [], 'NetworkCidr': '192.168.10.0/24', 'NetworkGateway': '192.168.10.1'}}} self.assertEqual(expected, env) @@ -281,6 +289,7 @@ class TestNetworkSettings(base.TestCase): 'AllocationPools': [ {'start': '192.168.24.4', 'end': '192.168.24.99'}, {'start': '192.168.24.121', 'end': '192.168.24.254'}], + 'HostRoutes': [], 'NetworkCidr': '192.168.24.0/24', 'NetworkGateway': '192.168.24.1'}}} self.assertEqual(expected, env) @@ -305,6 +314,7 @@ class TestNetworkSettings(base.TestCase): 'AllocationPools': [ {'start': '192.168.24.10', 'end': '192.168.24.99'}, {'start': '192.168.24.121', 'end': '192.168.24.254'}], + 'HostRoutes': [], 'NetworkCidr': '192.168.24.0/24', 'NetworkGateway': '192.168.24.1'}} } @@ -330,6 +340,7 @@ class TestNetworkSettings(base.TestCase): 'AllocationPools': [ {'start': '192.168.24.4', 'end': '192.168.24.99'}, {'start': '192.168.24.121', 'end': '192.168.24.220'}], + 'HostRoutes': [], 'NetworkCidr': '192.168.24.0/24', 'NetworkGateway': '192.168.24.1'}} } @@ -347,6 +358,7 @@ class TestNetworkSettings(base.TestCase): dhcp_exclude=[], inspection_iprange='192.168.10.100,192.168.10.189', gateway='192.168.10.254', + host_routes=[], masquerade=True, group='subnet1') self.conf.config(cidr='192.168.20.0/24', @@ -355,6 +367,7 @@ class TestNetworkSettings(base.TestCase): dhcp_exclude=[], inspection_iprange='192.168.20.100,192.168.20.189', gateway='192.168.20.254', + host_routes=[], masquerade=True, group='subnet2') env = {} @@ -393,16 +406,19 @@ class TestNetworkSettings(base.TestCase): 'ctlplane-subnet': { 'AllocationPools': [ {'start': '192.168.24.5', 'end': '192.168.24.24'}], + 'HostRoutes': [], 'NetworkCidr': '192.168.24.0/24', 'NetworkGateway': '192.168.24.1'}, 'subnet1': { 'AllocationPools': [ {'start': '192.168.10.10', 'end': '192.168.10.99'}], + 'HostRoutes': [], 'NetworkCidr': '192.168.10.0/24', 'NetworkGateway': '192.168.10.254'}, 'subnet2': { 'AllocationPools': [ {'start': '192.168.20.10', 'end': '192.168.20.99'}], + 'HostRoutes': [], 'NetworkCidr': '192.168.20.0/24', 'NetworkGateway': '192.168.20.254'} } @@ -419,6 +435,7 @@ class TestNetworkSettings(base.TestCase): dhcp_exclude=[], inspection_iprange='192.168.10.100,192.168.10.189', gateway='192.168.10.254', + host_routes=[], group='subnet1') self.conf.config(cidr='192.168.20.0/24', dhcp_start='192.168.20.10', @@ -426,6 +443,7 @@ class TestNetworkSettings(base.TestCase): dhcp_exclude=[], inspection_iprange='192.168.20.100,192.168.20.189', gateway='192.168.20.254', + host_routes=[], group='subnet2') env = {} undercloud_config._process_network_args(env) @@ -454,16 +472,19 @@ class TestNetworkSettings(base.TestCase): 'ctlplane-subnet': { 'AllocationPools': [ {'start': '192.168.24.5', 'end': '192.168.24.24'}], + 'HostRoutes': [], 'NetworkCidr': '192.168.24.0/24', 'NetworkGateway': '192.168.24.1'}, 'subnet1': { 'AllocationPools': [ {'start': '192.168.10.10', 'end': '192.168.10.99'}], + 'HostRoutes': [], 'NetworkCidr': '192.168.10.0/24', 'NetworkGateway': '192.168.10.254'}, 'subnet2': { 'AllocationPools': [ {'start': '192.168.20.10', 'end': '192.168.20.99'}], + 'HostRoutes': [], 'NetworkCidr': '192.168.20.0/24', 'NetworkGateway': '192.168.20.254'} } @@ -477,6 +498,7 @@ class TestNetworkSettings(base.TestCase): dhcp_exclude=[], inspection_iprange='192.168.10.200,192.168.10.254', gateway='192.168.10.254', + host_routes=[], masquerade=False, group='subnet1') env = {} @@ -501,11 +523,13 @@ class TestNetworkSettings(base.TestCase): 'ctlplane-subnet': { 'AllocationPools': [ {'start': '192.168.24.5', 'end': '192.168.24.24'}], + 'HostRoutes': [], 'NetworkCidr': '192.168.24.0/24', 'NetworkGateway': '192.168.24.1'}, 'subnet1': { 'AllocationPools': [ {'start': '192.168.10.1', 'end': '192.168.10.199'}], + 'HostRoutes': [], 'NetworkCidr': '192.168.10.0/24', 'NetworkGateway': '192.168.10.254'} } @@ -519,6 +543,7 @@ class TestNetworkSettings(base.TestCase): dhcp_exclude=[], inspection_iprange='192.168.10.100,192.168.10.199', gateway='192.168.10.222', + host_routes=[], masquerade=False, group='subnet1') env = {} @@ -543,6 +568,7 @@ class TestNetworkSettings(base.TestCase): 'ctlplane-subnet': { 'AllocationPools': [ {'start': '192.168.24.5', 'end': '192.168.24.24'}], + 'HostRoutes': [], 'NetworkCidr': '192.168.24.0/24', 'NetworkGateway': '192.168.24.1'}, 'subnet1': { @@ -550,12 +576,88 @@ class TestNetworkSettings(base.TestCase): {'start': '192.168.10.1', 'end': '192.168.10.99'}, {'start': '192.168.10.200', 'end': '192.168.10.221'}, {'start': '192.168.10.223', 'end': '192.168.10.254'}], + 'HostRoutes': [], 'NetworkCidr': '192.168.10.0/24', 'NetworkGateway': '192.168.10.222'} } } self.assertEqual(expected, env) + def test_additional_host_routes(self): + self.conf.config(subnets=['ctlplane-subnet', 'subnet1', 'subnet2']) + self.conf.config(host_routes=[{'destination': '10.10.10.254/32', + 'nexthop': '192.168.24.1'}], + group='ctlplane-subnet') + self.conf.register_opts(self.opts, group=self.grp1) + self.conf.register_opts(self.opts, group=self.grp2) + self.conf.config(cidr='192.168.10.0/24', + dhcp_start='192.168.10.10', + dhcp_end='192.168.10.99', + dhcp_exclude=[], + inspection_iprange='192.168.10.100,192.168.10.189', + gateway='192.168.10.254', + host_routes=[{'destination': '10.10.10.254/32', + 'nexthop': '192.168.10.254'}], + group='subnet1') + self.conf.config(cidr='192.168.20.0/24', + dhcp_start='192.168.20.10', + dhcp_end='192.168.20.99', + dhcp_exclude=[], + inspection_iprange='192.168.20.100,192.168.20.189', + gateway='192.168.20.254', + host_routes=[{'destination': '10.10.10.254/32', + 'nexthop': '192.168.20.254'}], + group='subnet2') + env = {} + undercloud_config._process_network_args(env) + expected = { + 'ControlPlaneStaticRoutes': [ + {'ip_netmask': '192.168.10.0/24', 'next_hop': '192.168.24.1'}, + {'ip_netmask': '192.168.20.0/24', 'next_hop': '192.168.24.1'}, + {'ip_netmask': '10.10.10.254/32', 'next_hop': '192.168.24.1'}], + 'DnsServers': '', + 'IronicInspectorSubnets': [ + {'gateway': '192.168.24.1', + 'ip_range': '192.168.24.100,192.168.24.120', + 'netmask': '255.255.255.0', + 'tag': 'ctlplane-subnet'}, + {'gateway': '192.168.10.254', + 'ip_range': '192.168.10.100,192.168.10.189', + 'netmask': '255.255.255.0', + 'tag': 'subnet1'}, + {'gateway': '192.168.20.254', + 'ip_range': '192.168.20.100,192.168.20.189', + 'netmask': '255.255.255.0', + 'tag': 'subnet2'} + ], + 'MasqueradeNetworks': {}, + 'UndercloudCtlplaneSubnets': { + # The ctlplane-subnet subnet have defaults + 'ctlplane-subnet': { + 'AllocationPools': [ + {'start': '192.168.24.5', 'end': '192.168.24.24'}], + 'HostRoutes': [{'destination': '10.10.10.254/32', + 'nexthop': '192.168.24.1'}], + 'NetworkCidr': '192.168.24.0/24', + 'NetworkGateway': '192.168.24.1'}, + 'subnet1': { + 'AllocationPools': [ + {'start': '192.168.10.10', 'end': '192.168.10.99'}], + 'HostRoutes': [{'destination': '10.10.10.254/32', + 'nexthop': '192.168.10.254'}], + 'NetworkCidr': '192.168.10.0/24', + 'NetworkGateway': '192.168.10.254'}, + 'subnet2': { + 'AllocationPools': [ + {'start': '192.168.20.10', 'end': '192.168.20.99'}], + 'HostRoutes': [{'destination': '10.10.10.254/32', + 'nexthop': '192.168.20.254'}], + 'NetworkCidr': '192.168.20.0/24', + 'NetworkGateway': '192.168.20.254'} + } + } + self.assertEqual(expected, env) + class TestTLSSettings(base.TestCase): def test_public_host_with_ip_should_give_ip_endpoint_environment(self): diff --git a/tripleoclient/v1/undercloud_config.py b/tripleoclient/v1/undercloud_config.py index f379364e3..8868a4ad7 100644 --- a/tripleoclient/v1/undercloud_config.py +++ b/tripleoclient/v1/undercloud_config.py @@ -78,6 +78,7 @@ PARAMETER_MAPPING = { SUBNET_PARAMETER_MAPPING = { 'cidr': 'NetworkCidr', 'gateway': 'NetworkGateway', + 'host_routes': 'HostRoutes' } THT_HOME = os.environ.get('THT_HOME', @@ -237,6 +238,10 @@ def _generate_subnets_static_routes(): continue s = CONF.get(subnet) env_list.append({'ip_netmask': s.cidr, 'next_hop': local_router}) + for route in CONF.get(CONF.local_subnet).host_routes: + env_list.append({'ip_netmask': route['destination'], + 'next_hop': route['nexthop']}) + return env_list