diff --git a/tripleoclient/config/undercloud.py b/tripleoclient/config/undercloud.py index 817c6c866..6d3d4bc5d 100644 --- a/tripleoclient/config/undercloud.py +++ b/tripleoclient/config/undercloud.py @@ -51,6 +51,10 @@ 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.') +DNS_NAMESERVERS_HELP_STR = _( + 'DNS nameservers for the Neutron-managed subnet for the Overcloud ' + 'instances on this network. If no nameservers are defined for the subnet, ' + 'the nameservers defined for undercloud_nameservers will be used.') # Deprecated options _deprecated_opt_network_gateway = [cfg.DeprecatedOpt( @@ -385,6 +389,9 @@ class UndercloudConfig(StandaloneConfig): sample_default=('[{destination: 10.10.10.0/24, ' 'nexthop: 192.168.24.1}]'), help=HOST_ROUTES_HELP_STR), + cfg.ListOpt('dns_nameservers', + default=constants.CTLPLANE_DNS_NAMESERVERS_DEFAULT, + help=DNS_NAMESERVERS_HELP_STR), ] return self.sort_opts(_subnets_opts) @@ -413,6 +420,9 @@ class UndercloudConfig(StandaloneConfig): bounds=True, default=[], help=HOST_ROUTES_HELP_STR), + cfg.ListOpt('dns_nameservers', + default=constants.CTLPLANE_DNS_NAMESERVERS_DEFAULT, + help=DNS_NAMESERVERS_HELP_STR), ] return self.sort_opts(_subnets_opts) diff --git a/tripleoclient/constants.py b/tripleoclient/constants.py index aa28a8c96..d5a32f156 100644 --- a/tripleoclient/constants.py +++ b/tripleoclient/constants.py @@ -100,6 +100,7 @@ CTLPLANE_DHCP_START_DEFAULT = ['192.168.24.5'] CTLPLANE_DHCP_END_DEFAULT = ['192.168.24.24'] CTLPLANE_INSPECTION_IPRANGE_DEFAULT = '192.168.24.100,192.168.24.120' CTLPLANE_GATEWAY_DEFAULT = '192.168.24.1' +CTLPLANE_DNS_NAMESERVERS_DEFAULT = [] # Ansible parameters used for the actions being # executed during tripleo deploy/upgrade. diff --git a/tripleoclient/tests/config/test_config_undercloud.py b/tripleoclient/tests/config/test_config_undercloud.py index 99ceb1043..2b911c16b 100644 --- a/tripleoclient/tests/config/test_config_undercloud.py +++ b/tripleoclient/tests/config/test_config_undercloud.py @@ -148,6 +148,7 @@ class TestUndercloudConfig(base.TestCase): 'dhcp_end', 'dhcp_exclude', 'dhcp_start', + 'dns_nameservers', 'gateway', 'host_routes', 'inspection_iprange', diff --git a/tripleoclient/tests/v1/undercloud/test_config.py b/tripleoclient/tests/v1/undercloud/test_config.py index db1e37c1e..3fdaf114a 100644 --- a/tripleoclient/tests/v1/undercloud/test_config.py +++ b/tripleoclient/tests/v1/undercloud/test_config.py @@ -131,7 +131,8 @@ class TestNetworkSettings(base.TestCase): fixtures.MockPatch('tripleoclient.utils.load_config')) self.conf.config(local_ip='192.168.24.1/24', undercloud_admin_host='192.168.24.3', - undercloud_public_host='192.168.24.2') + undercloud_public_host='192.168.24.2', + undercloud_nameservers=['10.10.10.10', '10.10.10.11']) # ctlplane network - config group options self.grp0 = cfg.OptGroup(name='ctlplane-subnet', title='ctlplane-subnet') @@ -144,7 +145,8 @@ class TestNetworkSettings(base.TestCase): cfg.BoolOpt('masquerade'), cfg.ListOpt('host_routes', item_type=cfg.types.Dict(bounds=True), - bounds=True,)] + bounds=True,), + cfg.ListOpt('dns_nameservers')] 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') @@ -156,14 +158,15 @@ class TestNetworkSettings(base.TestCase): gateway='192.168.24.1', masquerade=False, host_routes=[], + dns_nameservers=[], group='ctlplane-subnet') def test_default(self): env = {} undercloud_config._process_network_args(env) expected = { + 'DnsServers': '10.10.10.10,10.10.10.11', 'ControlPlaneStaticRoutes': [], - 'DnsServers': '', 'IronicInspectorSubnets': [ {'gateway': '192.168.24.1', 'host_routes': [], @@ -175,6 +178,7 @@ class TestNetworkSettings(base.TestCase): 'ctlplane-subnet': { 'AllocationPools': [ {'start': '192.168.24.5', 'end': '192.168.24.24'}], + 'DnsNameServers': ['10.10.10.10', '10.10.10.11'], 'HostRoutes': [], 'NetworkCidr': '192.168.24.0/24', 'NetworkGateway': '192.168.24.1'}}} @@ -189,6 +193,8 @@ class TestNetworkSettings(base.TestCase): dhcp_start='fd12:3456:789a:1::10', dhcp_end='fd12:3456:789a:1::20', dhcp_exclude=[], + dns_nameservers=['fd12:3456:789a:1::5', + 'fd12:3456:789a:1::6'], inspection_iprange=('fd12:3456:789a:1::30,' 'fd12:3456:789a:1::40'), gateway='fd12:3456:789a:1::1', @@ -203,7 +209,7 @@ class TestNetworkSettings(base.TestCase): 'RedisIPv6': True, 'MysqlIPv6': True, 'ControlPlaneStaticRoutes': [], - 'DnsServers': '', + 'DnsServers': '10.10.10.10,10.10.10.11', 'IronicInspectorSubnets': [ {'gateway': 'fd12:3456:789a:1::1', 'host_routes': [], @@ -216,6 +222,8 @@ class TestNetworkSettings(base.TestCase): 'AllocationPools': [ {'start': 'fd12:3456:789a:1::10', 'end': 'fd12:3456:789a:1::20'}], + 'DnsNameServers': ['fd12:3456:789a:1::5', + 'fd12:3456:789a:1::6'], 'HostRoutes': [], 'NetworkCidr': 'fd12:3456:789a:1::/64', 'NetworkGateway': 'fd12:3456:789a:1::1'}}} @@ -237,8 +245,8 @@ class TestNetworkSettings(base.TestCase): env = {} undercloud_config._process_network_args(env) expected = { + 'DnsServers': '10.10.10.10,10.10.10.11', 'ControlPlaneStaticRoutes': [], - 'DnsServers': '', 'IronicInspectorSubnets': [ {'gateway': '192.168.24.1', 'host_routes': [], @@ -251,6 +259,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'}], + 'DnsNameServers': ['10.10.10.10', '10.10.10.11'], 'HostRoutes': [], 'NetworkCidr': '192.168.24.0/24', 'NetworkGateway': '192.168.24.1'}}} @@ -264,8 +273,8 @@ class TestNetworkSettings(base.TestCase): env = {} undercloud_config._process_network_args(env) expected = { + 'DnsServers': '10.10.10.10,10.10.10.11', 'ControlPlaneStaticRoutes': [], - 'DnsServers': '', 'IronicInspectorSubnets': [ {'gateway': '192.168.10.1', 'host_routes': [], @@ -278,6 +287,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'}], + 'DnsNameServers': ['10.10.10.10', '10.10.10.11'], 'HostRoutes': [], 'NetworkCidr': '192.168.10.0/24', 'NetworkGateway': '192.168.10.1'}}} @@ -293,8 +303,8 @@ class TestNetworkSettings(base.TestCase): env = {} undercloud_config._process_network_args(env) expected = { + 'DnsServers': '10.10.10.10,10.10.10.11', 'ControlPlaneStaticRoutes': [], - 'DnsServers': '', 'IronicInspectorSubnets': [ {'gateway': '192.168.10.1', 'host_routes': [], @@ -309,6 +319,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'}], + 'DnsNameServers': ['10.10.10.10', '10.10.10.11'], 'HostRoutes': [], 'NetworkCidr': '192.168.10.0/24', 'NetworkGateway': '192.168.10.1'}}} @@ -321,8 +332,8 @@ class TestNetworkSettings(base.TestCase): env = {} undercloud_config._process_network_args(env) expected = { + 'DnsServers': '10.10.10.10,10.10.10.11', 'ControlPlaneStaticRoutes': [], - 'DnsServers': '', 'IronicInspectorSubnets': [ {'gateway': '192.168.24.1', 'host_routes': [], @@ -335,6 +346,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'}], + 'DnsNameServers': ['10.10.10.10', '10.10.10.11'], 'HostRoutes': [], 'NetworkCidr': '192.168.24.0/24', 'NetworkGateway': '192.168.24.1'}}} @@ -347,8 +359,8 @@ class TestNetworkSettings(base.TestCase): env = {} undercloud_config._process_network_args(env) expected = { + 'DnsServers': '10.10.10.10,10.10.10.11', 'ControlPlaneStaticRoutes': [], - 'DnsServers': '', 'IronicInspectorSubnets': [ {'gateway': '192.168.24.1', 'host_routes': [], @@ -361,6 +373,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'}], + 'DnsNameServers': ['10.10.10.10', '10.10.10.11'], 'HostRoutes': [], 'NetworkCidr': '192.168.24.0/24', 'NetworkGateway': '192.168.24.1'}} @@ -374,8 +387,8 @@ class TestNetworkSettings(base.TestCase): env = {} undercloud_config._process_network_args(env) expected = { + 'DnsServers': '10.10.10.10,10.10.10.11', 'ControlPlaneStaticRoutes': [], - 'DnsServers': '', 'IronicInspectorSubnets': [ {'gateway': '192.168.24.1', 'host_routes': [], @@ -388,6 +401,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'}], + 'DnsNameServers': ['10.10.10.10', '10.10.10.11'], 'HostRoutes': [], 'NetworkCidr': '192.168.24.0/24', 'NetworkGateway': '192.168.24.1'}} @@ -399,6 +413,7 @@ class TestNetworkSettings(base.TestCase): self.conf.register_opts(self.opts, group=self.grp1) self.conf.register_opts(self.opts, group=self.grp2) self.conf.config(masquerade=True, + dns_nameservers=['10.1.1.100', '10.1.1.101'], group='ctlplane-subnet') self.conf.config(cidr='192.168.10.0/24', dhcp_start='192.168.10.10', @@ -406,6 +421,7 @@ class TestNetworkSettings(base.TestCase): dhcp_exclude=[], inspection_iprange='192.168.10.100,192.168.10.189', gateway='192.168.10.254', + dns_nameservers=['10.2.2.100', '10.2.2.101'], host_routes=[], masquerade=True, group='subnet1') @@ -415,16 +431,17 @@ class TestNetworkSettings(base.TestCase): dhcp_exclude=[], inspection_iprange='192.168.20.100,192.168.20.189', gateway='192.168.20.254', + dns_nameservers=['10.3.3.100', '10.3.3.101'], host_routes=[], masquerade=True, group='subnet2') env = {} undercloud_config._process_network_args(env) expected = { + 'DnsServers': '10.10.10.10,10.10.10.11', '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'}], - 'DnsServers': '', 'IronicInspectorSubnets': [ {'gateway': '192.168.24.1', 'host_routes': [], @@ -457,18 +474,21 @@ class TestNetworkSettings(base.TestCase): 'ctlplane-subnet': { 'AllocationPools': [ {'start': '192.168.24.5', 'end': '192.168.24.24'}], + 'DnsNameServers': ['10.1.1.100', '10.1.1.101'], 'HostRoutes': [], 'NetworkCidr': '192.168.24.0/24', 'NetworkGateway': '192.168.24.1'}, 'subnet1': { 'AllocationPools': [ {'start': '192.168.10.10', 'end': '192.168.10.99'}], + 'DnsNameServers': ['10.2.2.100', '10.2.2.101'], 'HostRoutes': [], 'NetworkCidr': '192.168.10.0/24', 'NetworkGateway': '192.168.10.254'}, 'subnet2': { 'AllocationPools': [ {'start': '192.168.20.10', 'end': '192.168.20.99'}], + 'DnsNameServers': ['10.3.3.100', '10.3.3.101'], 'HostRoutes': [], 'NetworkCidr': '192.168.20.0/24', 'NetworkGateway': '192.168.20.254'} @@ -486,6 +506,7 @@ class TestNetworkSettings(base.TestCase): dhcp_exclude=[], inspection_iprange='192.168.10.100,192.168.10.189', gateway='192.168.10.254', + dns_nameservers=[], host_routes=[], group='subnet1') self.conf.config(cidr='192.168.20.0/24', @@ -494,15 +515,16 @@ class TestNetworkSettings(base.TestCase): dhcp_exclude=[], inspection_iprange='192.168.20.100,192.168.20.189', gateway='192.168.20.254', + dns_nameservers=[], host_routes=[], group='subnet2') env = {} undercloud_config._process_network_args(env) expected = { + 'DnsServers': '10.10.10.10,10.10.10.11', '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'}], - 'DnsServers': '', 'IronicInspectorSubnets': [ {'gateway': '192.168.24.1', 'host_routes': [], @@ -526,18 +548,21 @@ class TestNetworkSettings(base.TestCase): 'ctlplane-subnet': { 'AllocationPools': [ {'start': '192.168.24.5', 'end': '192.168.24.24'}], + 'DnsNameServers': ['10.10.10.10', '10.10.10.11'], 'HostRoutes': [], 'NetworkCidr': '192.168.24.0/24', 'NetworkGateway': '192.168.24.1'}, 'subnet1': { 'AllocationPools': [ {'start': '192.168.10.10', 'end': '192.168.10.99'}], + 'DnsNameServers': ['10.10.10.10', '10.10.10.11'], 'HostRoutes': [], 'NetworkCidr': '192.168.10.0/24', 'NetworkGateway': '192.168.10.254'}, 'subnet2': { 'AllocationPools': [ {'start': '192.168.20.10', 'end': '192.168.20.99'}], + 'DnsNameServers': ['10.10.10.10', '10.10.10.11'], 'HostRoutes': [], 'NetworkCidr': '192.168.20.0/24', 'NetworkGateway': '192.168.20.254'} @@ -552,15 +577,16 @@ class TestNetworkSettings(base.TestCase): dhcp_exclude=[], inspection_iprange='192.168.10.200,192.168.10.254', gateway='192.168.10.254', + dns_nameservers=[], host_routes=[], masquerade=False, group='subnet1') env = {} undercloud_config._process_network_args(env) expected = { + 'DnsServers': '10.10.10.10,10.10.10.11', 'ControlPlaneStaticRoutes': [ {'ip_netmask': '192.168.10.0/24', 'next_hop': '192.168.24.1'}], - 'DnsServers': '', 'IronicInspectorSubnets': [ {'gateway': '192.168.24.1', 'host_routes': [], @@ -579,12 +605,14 @@ class TestNetworkSettings(base.TestCase): 'ctlplane-subnet': { 'AllocationPools': [ {'start': '192.168.24.5', 'end': '192.168.24.24'}], + 'DnsNameServers': ['10.10.10.10', '10.10.10.11'], 'HostRoutes': [], 'NetworkCidr': '192.168.24.0/24', 'NetworkGateway': '192.168.24.1'}, 'subnet1': { 'AllocationPools': [ {'start': '192.168.10.1', 'end': '192.168.10.199'}], + 'DnsNameServers': ['10.10.10.10', '10.10.10.11'], 'HostRoutes': [], 'NetworkCidr': '192.168.10.0/24', 'NetworkGateway': '192.168.10.254'} @@ -599,15 +627,16 @@ class TestNetworkSettings(base.TestCase): dhcp_exclude=[], inspection_iprange='192.168.10.100,192.168.10.199', gateway='192.168.10.222', + dns_nameservers=[], host_routes=[], masquerade=False, group='subnet1') env = {} undercloud_config._process_network_args(env) expected = { + 'DnsServers': '10.10.10.10,10.10.10.11', 'ControlPlaneStaticRoutes': [ {'ip_netmask': '192.168.10.0/24', 'next_hop': '192.168.24.1'}], - 'DnsServers': '', 'IronicInspectorSubnets': [ {'gateway': '192.168.24.1', 'host_routes': [], @@ -626,6 +655,7 @@ class TestNetworkSettings(base.TestCase): 'ctlplane-subnet': { 'AllocationPools': [ {'start': '192.168.24.5', 'end': '192.168.24.24'}], + 'DnsNameServers': ['10.10.10.10', '10.10.10.11'], 'HostRoutes': [], 'NetworkCidr': '192.168.24.0/24', 'NetworkGateway': '192.168.24.1'}, @@ -634,6 +664,7 @@ 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'}], + 'DnsNameServers': ['10.10.10.10', '10.10.10.11'], 'HostRoutes': [], 'NetworkCidr': '192.168.10.0/24', 'NetworkGateway': '192.168.10.222'} @@ -654,6 +685,7 @@ class TestNetworkSettings(base.TestCase): dhcp_exclude=[], inspection_iprange='192.168.10.100,192.168.10.189', gateway='192.168.10.254', + dns_nameservers=[], host_routes=[{'destination': '10.10.10.254/32', 'nexthop': '192.168.10.254'}], group='subnet1') @@ -663,17 +695,18 @@ class TestNetworkSettings(base.TestCase): dhcp_exclude=[], inspection_iprange='192.168.20.100,192.168.20.189', gateway='192.168.20.254', + dns_nameservers=[], host_routes=[{'destination': '10.10.10.254/32', 'nexthop': '192.168.20.254'}], group='subnet2') env = {} undercloud_config._process_network_args(env) expected = { + 'DnsServers': '10.10.10.10,10.10.10.11', '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', 'host_routes': [{'destination': '10.10.10.254/32', @@ -700,6 +733,7 @@ class TestNetworkSettings(base.TestCase): 'ctlplane-subnet': { 'AllocationPools': [ {'start': '192.168.24.5', 'end': '192.168.24.24'}], + 'DnsNameServers': ['10.10.10.10', '10.10.10.11'], 'HostRoutes': [{'destination': '10.10.10.254/32', 'nexthop': '192.168.24.1'}], 'NetworkCidr': '192.168.24.0/24', @@ -707,6 +741,7 @@ class TestNetworkSettings(base.TestCase): 'subnet1': { 'AllocationPools': [ {'start': '192.168.10.10', 'end': '192.168.10.99'}], + 'DnsNameServers': ['10.10.10.10', '10.10.10.11'], 'HostRoutes': [{'destination': '10.10.10.254/32', 'nexthop': '192.168.10.254'}], 'NetworkCidr': '192.168.10.0/24', @@ -714,6 +749,7 @@ class TestNetworkSettings(base.TestCase): 'subnet2': { 'AllocationPools': [ {'start': '192.168.20.10', 'end': '192.168.20.99'}], + 'DnsNameServers': ['10.10.10.10', '10.10.10.11'], 'HostRoutes': [{'destination': '10.10.10.254/32', 'nexthop': '192.168.20.254'}], 'NetworkCidr': '192.168.20.0/24', diff --git a/tripleoclient/v1/undercloud_config.py b/tripleoclient/v1/undercloud_config.py index 4abc6a4a1..746cd3160 100644 --- a/tripleoclient/v1/undercloud_config.py +++ b/tripleoclient/v1/undercloud_config.py @@ -78,7 +78,7 @@ PARAMETER_MAPPING = { SUBNET_PARAMETER_MAPPING = { 'cidr': 'NetworkCidr', 'gateway': 'NetworkGateway', - 'host_routes': 'HostRoutes' + 'host_routes': 'HostRoutes', } THT_HOME = os.environ.get('THT_HOME', @@ -310,6 +310,9 @@ def _calculate_allocation_pools(subnet): CONF.undercloud_admin_host))) ip_set.remove(netaddr.IPNetwork(utils.get_single_ip( CONF.undercloud_public_host))) + # Remove dns nameservers + for addr in subnet.get('dns_nameservers', []): + ip_set.remove(netaddr.IPAddress(addr)) # Remove addresses in the inspection_iprange inspect_start, inspect_end = subnet.get('inspection_iprange').split(',') ip_set.remove(netaddr.IPRange(inspect_start, inspect_end)) @@ -337,6 +340,12 @@ def _process_network_args(env): env['UndercloudCtlplaneSubnets'][subnet] = { 'AllocationPools': _calculate_allocation_pools(s) } + if s.get('dns_nameservers'): + env['UndercloudCtlplaneSubnets'][subnet].update( + {'DnsNameServers': s['dns_nameservers']}) + else: + env['UndercloudCtlplaneSubnets'][subnet].update( + {'DnsNameServers': CONF['undercloud_nameservers']}) for param_key, param_value in SUBNET_PARAMETER_MAPPING.items(): if param_value: env['UndercloudCtlplaneSubnets'][subnet].update( diff --git a/tripleoclient/v1/undercloud_preflight.py b/tripleoclient/v1/undercloud_preflight.py index 35da3cc91..8c40f3429 100644 --- a/tripleoclient/v1/undercloud_preflight.py +++ b/tripleoclient/v1/undercloud_preflight.py @@ -447,6 +447,21 @@ def _validate_deprecetad_now_invalid_parameters(): del deprecate_conf +def _validate_dnsnameservers(s): + ip_version = netaddr.IPNetwork(s['cidr']).version + if s['dns_nameservers']: + nameservers = s['dns_nameservers'] + else: + nameservers = CONF.undercloud_nameservers + + for nameserver in nameservers: + if not netaddr.IPAddress(nameserver).version == ip_version: + message = (_('IP version missmatch. Nameserver {0} is not valid ' + 'for subnet {1}').format(nameserver, s['cidr'])) + LOG.error(message) + raise FailedValidation(message) + + def check(verbose_level, upgrade=False): # Fetch configuration and use its log file param to add logging to a file utils.load_config(CONF, constants.UNDERCLOUD_CONF_PATH) @@ -483,6 +498,7 @@ def check(verbose_level, upgrade=False): _validate_dhcp_range(s, subnet) _checking_status('Inspection range for subnet "%s"' % subnet) _validate_inspection_range(s) + _validate_dnsnameservers(s) _checking_status('IP addresses') _validate_ips() _checking_status('Network interfaces')