From 3cb6226ff08cac571654466029d5bfca5ea54702 Mon Sep 17 00:00:00 2001 From: "huang.xiangdong" Date: Tue, 19 Feb 2019 11:10:55 +0800 Subject: [PATCH] Support multi DNS server Using comma delimited ipv4 address list to specify multi dns server "8.8.8.8,114.114.114.114". Task: 29465 Story: 2004994 Change-Id: I031247b0cc2ae417f18b2a5b9b3832e78ed9dafd --- .../dcos_centos_v1/templates/dcoscluster.yaml | 2 +- .../templates/kubecluster.yaml | 2 +- magnum/api/controllers/v1/cluster_template.py | 2 +- magnum/api/controllers/v1/types.py | 13 ++++++++++ magnum/common/exception.py | 6 +++++ magnum/common/utils.py | 19 ++++++++++++++ magnum/drivers/common/templates/network.yaml | 5 ++-- .../k8s_coreos_v1/templates/kubecluster.yaml | 2 +- .../templates/kubecluster.yaml | 2 +- .../templates/kubecluster.yaml | 2 +- .../templates/mesoscluster.yaml | 2 +- .../templates/cluster.yaml | 2 +- .../templates/swarmcluster.yaml | 2 +- .../controllers/v1/test_cluster_template.py | 26 ++++++++++++++++++- .../unit/api/controllers/v1/test_types.py | 18 +++++++++++++ ...ort-multi-dns-server-0528be20f0e6aa62.yaml | 6 +++++ 16 files changed, 98 insertions(+), 13 deletions(-) create mode 100644 releasenotes/notes/support-multi-dns-server-0528be20f0e6aa62.yaml diff --git a/contrib/drivers/dcos_centos_v1/templates/dcoscluster.yaml b/contrib/drivers/dcos_centos_v1/templates/dcoscluster.yaml index d413f37694..a521822d7e 100644 --- a/contrib/drivers/dcos_centos_v1/templates/dcoscluster.yaml +++ b/contrib/drivers/dcos_centos_v1/templates/dcoscluster.yaml @@ -67,7 +67,7 @@ parameters: default: 10.0.0.0/24 dns_nameserver: - type: string + type: comma_delimited_list description: address of a dns nameserver reachable in your environment http_proxy: diff --git a/contrib/drivers/k8s_opensuse_v1/templates/kubecluster.yaml b/contrib/drivers/k8s_opensuse_v1/templates/kubecluster.yaml index 19fda3cad2..9109f50a6a 100644 --- a/contrib/drivers/k8s_opensuse_v1/templates/kubecluster.yaml +++ b/contrib/drivers/k8s_opensuse_v1/templates/kubecluster.yaml @@ -31,7 +31,7 @@ parameters: description: flavor to use when booting the server for minions dns_nameserver: - type: string + type: comma_delimited_list description: address of a DNS nameserver reachable in your environment default: 8.8.8.8 diff --git a/magnum/api/controllers/v1/cluster_template.py b/magnum/api/controllers/v1/cluster_template.py index 766bd8f017..4fb16c7c3a 100644 --- a/magnum/api/controllers/v1/cluster_template.py +++ b/magnum/api/controllers/v1/cluster_template.py @@ -61,7 +61,7 @@ class ClusterTemplate(base.APIBase): master_flavor_id = wtypes.StringType(min_length=1, max_length=255) """The flavor of the master node for this ClusterTemplate""" - dns_nameserver = wtypes.IPv4AddressType() + dns_nameserver = types.dns_list """The DNS nameserver address""" keypair_id = wsme.wsattr(wtypes.StringType(min_length=1, max_length=255), diff --git a/magnum/api/controllers/v1/types.py b/magnum/api/controllers/v1/types.py index 9a7955a66f..a80f26a8e5 100644 --- a/magnum/api/controllers/v1/types.py +++ b/magnum/api/controllers/v1/types.py @@ -14,6 +14,7 @@ # under the License. import inspect +import six from oslo_utils import strutils from oslo_utils import uuidutils @@ -25,6 +26,17 @@ from magnum.common import utils from magnum.i18n import _ +class DNSListType(wtypes.UserType): + """A comman delimited dns nameserver list""" + + basetype = six.string_types + name = "dnslist" + + @staticmethod + def validate(value): + return utils.validate_dns(value) + + class MacAddressType(wtypes.UserType): """A simple MAC address type.""" @@ -129,6 +141,7 @@ class MultiType(wtypes.UserType): % {'type': self.types, 'value': type(value)}) +dns_list = DNSListType() macaddress = MacAddressType() uuid = UuidType() name = NameType() diff --git a/magnum/common/exception.py b/magnum/common/exception.py index efe35f9283..4aaf684a46 100755 --- a/magnum/common/exception.py +++ b/magnum/common/exception.py @@ -220,6 +220,12 @@ class InvalidMAC(Invalid): message = _("Expected a MAC address but received %(mac)s.") +class InvalidDNS(Invalid): + message = _( + "Expected a single dns address or comma separated dns list, " + "but received %(dns)s.") + + class ConfigInvalid(Invalid): message = _("Invalid configuration file. %(error_msg)s") diff --git a/magnum/common/utils.py b/magnum/common/utils.py index 2588354dbc..5a1fc424ee 100755 --- a/magnum/common/utils.py +++ b/magnum/common/utils.py @@ -25,6 +25,7 @@ import re import shutil import tempfile +import netaddr from oslo_concurrency import processutils from oslo_log import log as logging from oslo_utils import netutils @@ -115,6 +116,24 @@ def validate_and_normalize_mac(address): return address.lower() +def validate_dns(dns_list): + """Validate a string is a single dns address or comma separated dns list + + :param dns_list: dns_list to be validated + :returns: original dns_list. + :raise: InvalidDNS if dns format is invalid + + """ + dns_nameservers = dns_list.split(',') + try: + for dns in dns_nameservers: + netaddr.IPAddress(dns, version=4, flags=netaddr.INET_PTON) + except netaddr.AddrFormatError: + raise exception.InvalidDNS(dns=dns_list) + else: + return dns_list + + @contextlib.contextmanager def tempdir(**kwargs): tempfile.tempdir = CONF.tempdir diff --git a/magnum/drivers/common/templates/network.yaml b/magnum/drivers/common/templates/network.yaml index 2399ff8308..1ec3370acb 100644 --- a/magnum/drivers/common/templates/network.yaml +++ b/magnum/drivers/common/templates/network.yaml @@ -23,7 +23,7 @@ parameters: default: "" dns_nameserver: - type: string + type: comma_delimited_list description: address of a dns nameserver reachable in your environment external_network: @@ -41,8 +41,7 @@ resources: properties: cidr: {get_param: private_network_cidr} network: {get_resource: private_network} - dns_nameservers: - - {get_param: dns_nameserver} + dns_nameservers: {get_param: dns_nameserver} extrouter: type: Magnum::Optional::Neutron::Router diff --git a/magnum/drivers/k8s_coreos_v1/templates/kubecluster.yaml b/magnum/drivers/k8s_coreos_v1/templates/kubecluster.yaml index d7703bc3dc..3015344371 100644 --- a/magnum/drivers/k8s_coreos_v1/templates/kubecluster.yaml +++ b/magnum/drivers/k8s_coreos_v1/templates/kubecluster.yaml @@ -59,7 +59,7 @@ parameters: admin user password for the Grafana monitoring interface dns_nameserver: - type: string + type: comma_delimited_list description: address of a DNS nameserver reachable in your environment default: 8.8.8.8 diff --git a/magnum/drivers/k8s_fedora_atomic_v1/templates/kubecluster.yaml b/magnum/drivers/k8s_fedora_atomic_v1/templates/kubecluster.yaml index 421e3da01f..bfcb190611 100644 --- a/magnum/drivers/k8s_fedora_atomic_v1/templates/kubecluster.yaml +++ b/magnum/drivers/k8s_fedora_atomic_v1/templates/kubecluster.yaml @@ -54,7 +54,7 @@ parameters: admin user password for the Grafana monitoring interface dns_nameserver: - type: string + type: comma_delimited_list description: address of a DNS nameserver reachable in your environment default: 8.8.8.8 diff --git a/magnum/drivers/k8s_fedora_ironic_v1/templates/kubecluster.yaml b/magnum/drivers/k8s_fedora_ironic_v1/templates/kubecluster.yaml index 653a4892d1..ac865535de 100644 --- a/magnum/drivers/k8s_fedora_ironic_v1/templates/kubecluster.yaml +++ b/magnum/drivers/k8s_fedora_ironic_v1/templates/kubecluster.yaml @@ -58,7 +58,7 @@ parameters: admin user password for the Grafana monitoring interface dns_nameserver: - type: string + type: comma_delimited_list description: address of a dns nameserver reachable in your environment default: 8.8.8.8 diff --git a/magnum/drivers/mesos_ubuntu_v1/templates/mesoscluster.yaml b/magnum/drivers/mesos_ubuntu_v1/templates/mesoscluster.yaml index c2e7798d7e..8e31531da0 100644 --- a/magnum/drivers/mesos_ubuntu_v1/templates/mesoscluster.yaml +++ b/magnum/drivers/mesos_ubuntu_v1/templates/mesoscluster.yaml @@ -44,7 +44,7 @@ parameters: description: flavor to use when booting the slave server dns_nameserver: - type: string + type: comma_delimited_list description: address of a dns nameserver reachable in your environment default: 8.8.8.8 diff --git a/magnum/drivers/swarm_fedora_atomic_v1/templates/cluster.yaml b/magnum/drivers/swarm_fedora_atomic_v1/templates/cluster.yaml index 1d0ad3c1f7..651361b33a 100644 --- a/magnum/drivers/swarm_fedora_atomic_v1/templates/cluster.yaml +++ b/magnum/drivers/swarm_fedora_atomic_v1/templates/cluster.yaml @@ -62,7 +62,7 @@ parameters: description: flavor to use when booting the swarm node dns_nameserver: - type: string + type: comma_delimited_list description: address of a dns nameserver reachable in your environment default: 8.8.8.8 diff --git a/magnum/drivers/swarm_fedora_atomic_v2/templates/swarmcluster.yaml b/magnum/drivers/swarm_fedora_atomic_v2/templates/swarmcluster.yaml index 4d4db3fe88..de4c6ab282 100644 --- a/magnum/drivers/swarm_fedora_atomic_v2/templates/swarmcluster.yaml +++ b/magnum/drivers/swarm_fedora_atomic_v2/templates/swarmcluster.yaml @@ -57,7 +57,7 @@ parameters: description: flavor to use when booting the swarm node dns_nameserver: - type: string + type: comma_delimited_list description: address of a dns nameserver reachable in your environment default: 8.8.8.8 diff --git a/magnum/tests/unit/api/controllers/v1/test_cluster_template.py b/magnum/tests/unit/api/controllers/v1/test_cluster_template.py index d1a882bcc9..b25665da2c 100644 --- a/magnum/tests/unit/api/controllers/v1/test_cluster_template.py +++ b/magnum/tests/unit/api/controllers/v1/test_cluster_template.py @@ -775,7 +775,7 @@ class TestPost(api_base.FunctionalTest): mock_image_data.return_value = {'name': 'mock_name', 'os_distro': 'fedora-atomic'} for k, v in cluster_template_config_dict.items(): - cfg.CONF.set_override(k, v, 'cluster_template') + cfg.CONF.set_override(k, v, 'cluster_template') with mock.patch.object( self.dbapi, 'create_cluster_template', wraps=self.dbapi.create_cluster_template) as cc_mock: @@ -1115,6 +1115,30 @@ class TestPost(api_base.FunctionalTest): self.assertRaises(AppError, self.post_json, '/clustertemplates', bdict) + @mock.patch('magnum.api.attr_validator.validate_image') + @mock.patch('oslo_utils.timeutils.utcnow') + def test_create_cluster_template_with_multi_dns(self, mock_utcnow, + mock_image_data): + bdict = apiutils.cluster_template_post_data( + dns_nameserver="8.8.8.8,114.114.114.114") + test_time = datetime.datetime(2000, 1, 1, 0, 0) + mock_utcnow.return_value = test_time + mock_image_data.return_value = {'name': 'mock_name', + 'os_distro': 'fedora-atomic'} + + response = self.post_json('/clustertemplates', bdict) + self.assertEqual(201, response.status_int) + # Check location header + self.assertIsNotNone(response.location) + expected_location = '/v1/clustertemplates/%s' % bdict['uuid'] + self.assertEqual(expected_location, + urlparse.urlparse(response.location).path) + self.assertEqual(bdict['uuid'], response.json['uuid']) + self.assertNotIn('updated_at', response.json.keys) + return_created_at = timeutils.parse_isotime( + response.json['created_at']).replace(tzinfo=None) + self.assertEqual(test_time, return_created_at) + class TestDelete(api_base.FunctionalTest): diff --git a/magnum/tests/unit/api/controllers/v1/test_types.py b/magnum/tests/unit/api/controllers/v1/test_types.py index 3cfadbd261..fada139dce 100644 --- a/magnum/tests/unit/api/controllers/v1/test_types.py +++ b/magnum/tests/unit/api/controllers/v1/test_types.py @@ -26,6 +26,24 @@ from magnum.common import utils from magnum.tests.unit.api import base +class TestDNSListType(base.FunctionalTest): + def test_valid_single_dns(self): + test_dns = "8.8.8.8" + with mock.patch.object(utils, 'validate_dns') as m_mock: + types.DNSListType.validate(test_dns) + m_mock.assert_called_once_with(test_dns) + + def test_valid_multi_dns(self): + test_dns = "8.8.8.8,114.114.114.114" + with mock.patch.object(utils, 'validate_dns') as m_mock: + types.DNSListType.validate(test_dns) + m_mock.assert_called_once_with(test_dns) + + def test_invalid_single_dns(self): + self.assertRaises(exception.InvalidDNS, + types.DNSListType.validate, 'invalid-dns') + + class TestMacAddressType(base.FunctionalTest): def test_valid_mac_addr(self): diff --git a/releasenotes/notes/support-multi-dns-server-0528be20f0e6aa62.yaml b/releasenotes/notes/support-multi-dns-server-0528be20f0e6aa62.yaml new file mode 100644 index 0000000000..1fafc59fca --- /dev/null +++ b/releasenotes/notes/support-multi-dns-server-0528be20f0e6aa62.yaml @@ -0,0 +1,6 @@ +--- +features: + - Support multi DNS server when creating template. + User can use a comma delimited ipv4 address list + to specify multi dns server, for example + "8.8.8.8,114.114.114.114" \ No newline at end of file