Merge "Allow DNS server configuration for kubernetes"

This commit is contained in:
Zuul 2019-01-24 18:20:19 +00:00 committed by Gerrit Code Review
commit 4d62be583e
8 changed files with 251 additions and 24 deletions

View File

@ -29,4 +29,5 @@ from configutilities.common.utils import validate_address # noqa: F401
from configutilities.common.utils import ip_version_to_string # noqa: F401
from configutilities.common.utils import lag_mode_to_str # noqa: F401
from configutilities.common.utils import validate_openstack_password # noqa: F401
from configutilities.common.utils import validate_nameserver_address_str # noqa: F401
from configutilities.common.utils import extract_openstack_password_rules_from_file # noqa: F401

View File

@ -23,6 +23,7 @@ from configutilities.common.utils import is_mtu_valid
from configutilities.common.utils import get_service
from configutilities.common.utils import get_optional
from configutilities.common.utils import validate_address_str
from configutilities.common.utils import validate_nameserver_address_str
from configutilities.common.exceptions import ConfigFail
from configutilities.common.exceptions import ValidateFail
@ -944,8 +945,25 @@ class ConfigValidator(object):
raise ConfigFail("SDN Configuration is no longer supported")
def validate_dns(self):
if self.conf.has_section('DNS'):
raise ConfigFail("DNS Configuration is no longer supported")
# DNS config is optional
if not self.conf.has_section('DNS'):
return
if self.cgcs_conf is not None:
self.cgcs_conf.add_section('cDNS')
for x in range(0, 3):
if self.conf.has_option('DNS', 'NAMESERVER_' + str(x + 1)):
dns_address_str = self.conf.get('DNS', 'NAMESERVER_' + str(
x + 1))
try:
dns_address = validate_nameserver_address_str(
dns_address_str)
if self.cgcs_conf is not None:
self.cgcs_conf.set('cDNS', 'NAMESERVER_' + str(x + 1),
str(dns_address))
except ValidateFail as e:
raise ConfigFail(
"Invalid DNS NAMESERVER value of %s.\nReason: %s" %
(dns_address_str, e))
def validate_ntp(self):
if self.conf.has_section('NTP'):

View File

@ -28,6 +28,7 @@ from configutilities import validate_network_str
from configutilities import validate_address_str
from configutilities import validate_address
from configutilities import ip_version_to_string
from configutilities import validate_nameserver_address_str
from configutilities import validate_openstack_password
from configutilities import DEFAULT_DOMAIN_NAME
from netaddr import IPNetwork
@ -463,6 +464,10 @@ class ConfigAssistant():
# SDN config
self.enable_sdn = False
# DNS config
self.nameserver_addresses = ["8.8.8.8", "8.8.4.4", ""]
# HTTPS
self.enable_https = False
# Network config
@ -2666,6 +2671,64 @@ class ConfigAssistant():
""" Cluster host interface configuration complete"""
self.cluster_host_interface_configured = True
def get_dns_servers(self):
"""Produce a comma separated list of DNS servers."""
servers = [str(s) for s in self.nameserver_addresses if s]
return ",".join(servers)
def input_dns_config(self):
"""Allow user to input DNS config and perform validation."""
print("\nDomain Name System (DNS):")
print("-------------------------\n")
print(textwrap.fill(
"Configuring DNS servers accessible through the external "
"OAM network allows domain names to be mapped to IP "
"addresses.", 80))
print(textwrap.fill(
"The configuration of at least one DNS server is mandatory. To "
"skip the configuration of one or more nameservers (1 to 3 are "
"allowed), enter C to continue to the next configuration item.",
80))
print('')
if self.external_oam_subnet.version == 6:
self.nameserver_addresses = ["2001:4860:4860::8888",
"2001:4860:4860::8844", ""]
for server in range(0, len(self.nameserver_addresses)):
while True:
user_input = raw_input(
"Nameserver " + str(server + 1) + " [" +
str(self.nameserver_addresses[server]) + "]: ")
if user_input.lower() == 'q':
raise UserQuit
elif user_input.lower() == 'c':
if server == 0:
print("At least one DNS server is required.")
continue
for x in range(server, len(self.nameserver_addresses)):
self.nameserver_addresses[x] = ""
return
elif user_input == "":
user_input = self.nameserver_addresses[server]
# Pressing enter with a blank default will continue
if user_input == "":
return
try:
try:
ip_input = validate_nameserver_address_str(
user_input, self.external_oam_subnet.version)
except ValidateFail as e:
print('{}'.format(e))
continue
self.nameserver_addresses[server] = ip_input
break
except (AddrFormatError, ValueError):
print("Invalid address - please enter a valid IPv4 "
"address")
def input_authentication_config(self):
"""Allow user to input authentication config and perform validation.
"""
@ -2711,6 +2774,8 @@ class ConfigAssistant():
self.management_interface_configured = True
self.external_oam_interface_configured = True
self.default_pxeboot_config()
if not self.kubernetes:
self.nameserver_addresses = ["", "", ""]
if utils.is_cpe():
self.system_mode = sysinv_constants.SYSTEM_MODE_DUPLEX
@ -2747,6 +2812,8 @@ class ConfigAssistant():
if self.kubernetes:
self.input_cluster_host_config()
self.input_external_oam_config()
if self.kubernetes:
self.input_dns_config()
self.input_authentication_config()
def is_valid_management_multicast_subnet(self, ip_subnet):
@ -3079,6 +3146,19 @@ class ConfigAssistant():
self.external_oam_interface_configured = True
# DNS configuration
if self.kubernetes:
if config.has_section('cDNS'):
self.nameserver_addresses = ["", "", ""]
for x in range(0, len(self.nameserver_addresses)):
if config.has_option('cDNS',
'NAMESERVER_' + str(x + 1)):
cvalue = config.get('cDNS',
'NAMESERVER_' + str(x + 1))
if cvalue != "NC" and cvalue != "":
self.nameserver_addresses[x] = \
IPAddress(cvalue)
# SDN Network configuration
if config.has_option('cSDN', 'ENABLE_SDN'):
raise ConfigFail("The option ENABLE_SDN is no longer "
@ -3511,6 +3591,18 @@ class ConfigAssistant():
else:
print("External OAM address: " + str(self.external_oam_address_0))
if self.kubernetes:
print("\nDNS Configuration")
print("-----------------")
dns_config = False
for x in range(0, len(self.nameserver_addresses)):
if self.nameserver_addresses[x]:
print("Nameserver " + str(x + 1) + ": " +
str(self.nameserver_addresses[x]))
dns_config = True
if not dns_config:
print("External DNS servers not configured")
if self.region_config:
print("\nRegion Configuration")
print("--------------------")
@ -3796,6 +3888,17 @@ class ConfigAssistant():
f.write("EXTERNAL_OAM_1_ADDRESS=" +
str(self.external_oam_address_1) + "\n")
if self.kubernetes:
# DNS configuration
f.write("\n[cDNS]")
f.write("\n# DNS Configuration\n")
for x in range(0, len(self.nameserver_addresses)):
if self.nameserver_addresses[x]:
f.write("NAMESERVER_" + str(x + 1) + "=" +
str(self.nameserver_addresses[x]) + "\n")
else:
f.write("NAMESERVER_" + str(x + 1) + "=NC" + "\n")
# Network configuration
f.write("\n[cNETWORK]")
f.write("\n# Data Network Configuration\n")
@ -5188,6 +5291,17 @@ class ConfigAssistant():
"required_patches": "N/A"}
client.sysinv.load.create(**patch)
def _populate_dns_config(self, client):
# Retrieve the list of dns servers to get the uuid
dns_list = client.sysinv.idns.list()
dns_record = dns_list[0]
values = {
'nameservers': self.get_dns_servers(),
'action': 'apply'
}
patch = sysinv.dict_to_patch(values)
client.sysinv.idns.update(dns_record.uuid, patch)
def populate_initial_config(self):
"""Populate initial system inventory configuration"""
try:
@ -5195,6 +5309,8 @@ class ConfigAssistant():
self._populate_system_config(client)
self._populate_load_config(client)
self._populate_network_config(client)
if self.kubernetes:
self._populate_dns_config(client)
controller = self._populate_controller_config(client)
# ceph_mon config requires controller host to be created
self._inventory_config_complete_wait(client, controller)

View File

@ -0,0 +1,86 @@
[cSYSTEM]
# System Configuration
SYSTEM_MODE=duplex
TIMEZONE=UTC
[cPXEBOOT]
# PXEBoot Network Support Configuration
PXECONTROLLER_FLOATING_HOSTNAME=pxecontroller
[cMGMT]
# Management Network Configuration
MANAGEMENT_INTERFACE_NAME=eth1
MANAGEMENT_INTERFACE=eth1
MANAGEMENT_MTU=1500
MANAGEMENT_SUBNET=192.168.204.0/24
LAG_MANAGEMENT_INTERFACE=no
CONTROLLER_FLOATING_ADDRESS=192.168.204.2
CONTROLLER_0_ADDRESS=192.168.204.3
CONTROLLER_1_ADDRESS=192.168.204.4
NFS_MANAGEMENT_ADDRESS_1=192.168.204.5
NFS_MANAGEMENT_ADDRESS_2=192.168.204.6
CONTROLLER_FLOATING_HOSTNAME=controller
CONTROLLER_HOSTNAME_PREFIX=controller-
OAMCONTROLLER_FLOATING_HOSTNAME=oamcontroller
DYNAMIC_ADDRESS_ALLOCATION=yes
MANAGEMENT_MULTICAST_SUBNET=239.1.1.0/28
[cINFRA]
# Infrastructure Network Configuration
INFRASTRUCTURE_INTERFACE_NAME=NC
INFRASTRUCTURE_INTERFACE=NC
INFRASTRUCTURE_VLAN=NC
INFRASTRUCTURE_MTU=NC
INFRASTRUCTURE_SUBNET=NC
LAG_INFRASTRUCTURE_INTERFACE=no
INFRASTRUCTURE_BOND_MEMBER_0=NC
INFRASTRUCTURE_BOND_MEMBER_1=NC
INFRASTRUCTURE_BOND_POLICY=NC
CONTROLLER_0_INFRASTRUCTURE_ADDRESS=NC
CONTROLLER_1_INFRASTRUCTURE_ADDRESS=NC
NFS_INFRASTRUCTURE_ADDRESS_1=NC
STORAGE_0_INFRASTRUCTURE_ADDRESS=NC
STORAGE_1_INFRASTRUCTURE_ADDRESS=NC
CONTROLLER_INFRASTRUCTURE_HOSTNAME_SUFFIX=NC
INFRASTRUCTURE_START_ADDRESS=NC
INFRASTRUCTURE_END_ADDRESS=NC
[cCLUSTER]
# Cluster Host Network Configuration
CLUSTER_INTERFACE_NAME=eth1
CLUSTER_INTERFACE=eth1
CLUSTER_VLAN=NC
CLUSTER_MTU=1500
CLUSTER_SUBNET=192.168.206.0/24
LAG_CLUSTER_INTERFACE=no
[cEXT_OAM]
# External OAM Network Configuration
EXTERNAL_OAM_INTERFACE_NAME=eth0
EXTERNAL_OAM_INTERFACE=eth0
EXTERNAL_OAM_VLAN=NC
EXTERNAL_OAM_MTU=1500
LAG_EXTERNAL_OAM_INTERFACE=no
EXTERNAL_OAM_SUBNET=10.10.10.0/24
EXTERNAL_OAM_GATEWAY_ADDRESS=10.10.10.1
EXTERNAL_OAM_FLOATING_ADDRESS=10.10.10.2
EXTERNAL_OAM_0_ADDRESS=10.10.10.3
EXTERNAL_OAM_1_ADDRESS=10.10.10.4
[cDNS]
# DNS Configuration
NAMESERVER_1=1.2.3.4
NAMESERVER_2=5.6.7.8
NAMESERVER_3=NC
[cNETWORK]
# Data Network Configuration
VSWITCH_TYPE=ovs-dpdk
[cSECURITY]
[cREGION]
# Region Configuration
REGION_CONFIG=False
[cAUTHENTICATION]
ADMIN_PASSWORD=Li69nux*

View File

@ -44,6 +44,11 @@ CIDR=10.10.10.0/24
GATEWAY=10.10.10.1
LOGICAL_INTERFACE=LOGICAL_INTERFACE_2
[DNS]
# DNS Configuration
NAMESERVER_1=1.2.3.4
NAMESERVER_2=5.6.7.8
;[PXEBOOT_NETWORK]
;PXEBOOT_CIDR=192.168.203.0/24

View File

@ -19,13 +19,14 @@ import controllerconfig.common.constants as constants
def _test_answerfile(tmpdir, filename,
mock_get_net_device_list,
mock_get_rootfs_node,
compare_results=True):
compare_results=True,
ca_options={}):
""" Test import and generation of answerfile """
mock_get_net_device_list.return_value = \
['eth0', 'eth1', 'eth2']
mock_get_rootfs_node.return_value = '/dev/sda'
assistant = ca.ConfigAssistant()
assistant = ca.ConfigAssistant(**ca_options)
# Create the path to the answerfile
answerfile = os.path.join(
@ -93,3 +94,10 @@ def test_answerfile_region_nuage_vrs(tmpdir):
""" Test import of answerfile with region values for nuage_vrs"""
_test_answerfile(tmpdir, "cgcs_config.region_nuage_vrs")
def test_answerfile_kubernetes(tmpdir):
""" Test import of answerfile with kubernetes values """
_test_answerfile(tmpdir, "cgcs_config.kubernetes",
ca_options={"kubernetes": True})

View File

@ -42,7 +42,7 @@ def _test_system_config(filename):
cr.create_cgcs_config_file(None, system_config, None, None, None, 0,
validate_only=True)
# Validate the region config file.
# Validate the system config file.
# Using onboard validation since the validator's reference version number
# is only set at build-time when validating offboard
validate(system_config, DEFAULT_CONFIG, None, False)
@ -508,14 +508,6 @@ def test_system_config_validation():
with pytest.raises(exceptions.ConfigFail):
validate(system_config, DEFAULT_CONFIG, None, False)
# Test detection of unsupported DNS NAMESERVER
system_config = cr.parse_system_config(simple_systemfile)
system_config.add_section('DNS')
system_config.set('DNS', 'NAMESERVER_1', '8.8.8.8')
with pytest.raises(exceptions.ConfigFail):
cr.create_cgcs_config_file(None, system_config, None, None, None, 0,
validate_only=True)
# Test detection of unsupported NTP NTP_SERVER
system_config = cr.parse_system_config(simple_systemfile)
system_config.add_section('NTP')
@ -606,12 +598,13 @@ def test_pxeboot_range():
validate(system_config, DEFAULT_CONFIG, None, False)
def test_cluster_network():
""" Test import of system_config file for cluster network address """
def test_kubernetes():
""" Test import of system_config file for kubernetes """
# Create the path to the system_config file
systemfile = os.path.join(
os.getcwd(), "controllerconfig/tests/files/", "system_config.cluster")
os.getcwd(), "controllerconfig/tests/files/",
"system_config.kubernetes")
# Test import and generation of answer file
_test_system_config(systemfile)
@ -647,3 +640,10 @@ def test_cluster_network():
validate_only=True)
with pytest.raises(exceptions.ConfigFail):
validate(system_config, DEFAULT_CONFIG, None, False)
# Test absence of optional DNS configuration
system_config = cr.parse_system_config(systemfile)
system_config.remove_section('DNS')
cr.create_cgcs_config_file(None, system_config, None, None, None, 0,
validate_only=True)
validate(system_config, DEFAULT_CONFIG, None, False)

View File

@ -58,15 +58,8 @@ class platform::kubernetes::master::init
# For initial controller install, configure kubernetes from scratch.
$resolv_conf = '/etc/resolv.conf'
# Add a DNS server to allow access to kubernetes repo. This will no longer
# be required once we are using our own internal repo.
file_line { "${resolv_conf} nameserver 8.8.8.8":
path => $resolv_conf,
line => 'nameserver 8.8.8.8',
}
# Configure the master node.
-> file { '/etc/kubernetes/kubeadm.yaml':
file { '/etc/kubernetes/kubeadm.yaml':
ensure => file,
content => template('platform/kubeadm.yaml.erb'),
}