From 1fb560e996abc3490a0c18ec8d192f7d37a0af76 Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Sun, 8 Dec 2019 23:32:03 -0500 Subject: [PATCH] Add DNS nameservers to networks --- client-api/api_lib/api.py | 8 ++++---- client-api/pvc-api.py | 16 ++++++++++++++-- client-cli/pvc.py | 18 ++++++++++++++---- client-common/network.py | 8 +++++++- node-daemon/pvcd/DNSAggregatorInstance.py | 6 +++++- node-daemon/pvcd/VXNetworkInstance.py | 12 ++++++++++++ 6 files changed, 56 insertions(+), 12 deletions(-) diff --git a/client-api/api_lib/api.py b/client-api/api_lib/api.py index ad083ca4..fa7942e2 100755 --- a/client-api/api_lib/api.py +++ b/client-api/api_lib/api.py @@ -516,14 +516,14 @@ def net_list(limit=None): pvc_common.stopZKConnection(zk_conn) return flask.jsonify(retdata), retcode -def net_add(vni, description, nettype, domain, +def net_add(vni, description, nettype, domain, name_servers, ip4_network, ip4_gateway, ip6_network, ip6_gateway, dhcp4_flag, dhcp4_start, dhcp4_end): """ Add a virtual client network to the PVC cluster. """ zk_conn = pvc_common.startZKConnection(config['coordinators']) - retflag, retdata = pvc_network.add_network(zk_conn, vni, description, nettype, domain, + retflag, retdata = pvc_network.add_network(zk_conn, vni, description, nettype, domain, name_servers, ip4_network, ip4_gateway, ip6_network, ip6_gateway, dhcp4_flag, dhcp4_start, dhcp4_end) if retflag: @@ -537,7 +537,7 @@ def net_add(vni, description, nettype, domain, } return flask.jsonify(output), retcode -def net_modify(vni, description, domain, +def net_modify(vni, description, domain, name_servers, ip4_network, ip4_gateway, ip6_network, ip6_gateway, dhcp4_flag, dhcp4_start, dhcp4_end): @@ -545,7 +545,7 @@ def net_modify(vni, description, domain, Modify a virtual client network in the PVC cluster. """ zk_conn = pvc_common.startZKConnection(config['coordinators']) - retflag, retdata = pvc_network.modify_network(zk_conn, vni, description, domain, + retflag, retdata = pvc_network.modify_network(zk_conn, vni, description, domain, name_servers, ip4_network, ip4_gateway, ip6_network, ip6_gateway, dhcp4_flag, dhcp4_start, dhcp4_end) if retflag: diff --git a/client-api/pvc-api.py b/client-api/pvc-api.py index b3382fbd..e618825f 100755 --- a/client-api/pvc-api.py +++ b/client-api/pvc-api.py @@ -413,6 +413,12 @@ def api_net_root(): else: domain = None + # Get network name servers + if 'name_server' in flask.request.values: + name_servers = flask.request.values.getlist('name_server') + else: + name_servers = None + # Get ipv4 network if 'ip4_network' in flask.request.values: ip4_network = flask.request.values['ip4_network'] @@ -455,7 +461,7 @@ def api_net_root(): else: dhcp4_end = None - return pvcapi.net_add(vni, description, nettype, domain, + return pvcapi.net_add(vni, description, nettype, domain, name_servers, ip4_network, ip4_gateway, ip6_network, ip6_gateway, dhcp4_flag, dhcp4_start, dhcp4_end) @@ -479,6 +485,12 @@ def api_net_element(network): else: domain = None + # Get network name servers + if 'name_server' in flask.request.values: + name_servers = flask.request.values.getlist('name_server') + else: + name_servers = None + # Get ipv4 network if 'ip4_network' in flask.request.values: ip4_network = flask.request.values['ip4_network'] @@ -521,7 +533,7 @@ def api_net_element(network): else: dhcp4_end = None - return pvcapi.net_modify(network, description, domain, + return pvcapi.net_modify(network, description, domain, name_servers, ip4_network, ip4_gateway, ip6_network, ip6_gateway, dhcp4_flag, dhcp4_start, dhcp4_end) diff --git a/client-cli/pvc.py b/client-cli/pvc.py index a1f0fa20..1a51ebda 100755 --- a/client-cli/pvc.py +++ b/client-cli/pvc.py @@ -727,6 +727,11 @@ def cli_network(): default=None, help='Domain name of the network.' ) +@click.option( + '--dns-server', 'name_servers', + multiple=True, + help='DNS nameserver for network' +) @click.option( '-i', '--ipnet', 'ip_network', default=None, @@ -766,7 +771,7 @@ def cli_network(): @click.argument( 'vni' ) -def net_add(vni, description, nettype, domain, ip_network, ip_gateway, ip6_network, ip6_gateway, dhcp_flag, dhcp_start, dhcp_end): +def net_add(vni, description, nettype, domain, ip_network, ip_gateway, ip6_network, ip6_gateway, dhcp_flag, dhcp_start, dhcp_end, name_servers): """ Add a new virtual network with VXLAN identifier VNI to the cluster. @@ -788,7 +793,7 @@ def net_add(vni, description, nettype, domain, ip_network, ip_gateway, ip6_netwo exit(1) zk_conn = pvc_common.startZKConnection(zk_host) - retcode, retmsg = pvc_network.add_network(zk_conn, vni, description, nettype, domain, ip_network, ip_gateway, ip6_network, ip6_gateway, dhcp_flag, dhcp_start, dhcp_end) + retcode, retmsg = pvc_network.add_network(zk_conn, vni, description, nettype, domain, name_servers, ip_network, ip_gateway, ip6_network, ip6_gateway, dhcp_flag, dhcp_start, dhcp_end) cleanup(retcode, retmsg, zk_conn) ############################################################################### @@ -805,6 +810,11 @@ def net_add(vni, description, nettype, domain, ip_network, ip_gateway, ip6_netwo default=None, help='Domain name of the network.' ) +@click.option( + '--dns-server', 'name_servers', + multiple=True, + help='DNS nameserver for network' +) @click.option( '-i', '--ipnet', 'ip4_network', default=None, @@ -844,7 +854,7 @@ def net_add(vni, description, nettype, domain, ip_network, ip_gateway, ip6_netwo @click.argument( 'vni' ) -def net_modify(vni, description, domain, ip6_network, ip6_gateway, ip4_network, ip4_gateway, dhcp_flag, dhcp_start, dhcp_end): +def net_modify(vni, description, domain, name_servers, ip6_network, ip6_gateway, ip4_network, ip4_gateway, dhcp_flag, dhcp_start, dhcp_end): """ Modify details of virtual network VNI. All fields optional; only specified fields will be updated. @@ -853,7 +863,7 @@ def net_modify(vni, description, domain, ip6_network, ip6_gateway, ip4_network, """ zk_conn = pvc_common.startZKConnection(zk_host) - retcode, retmsg = pvc_network.modify_network(zk_conn, vni, description=description, domain=domain, ip6_network=ip6_network, ip6_gateway=ip6_gateway, ip4_network=ip4_network, ip4_gateway=ip4_gateway, dhcp_flag=dhcp_flag, dhcp_start=dhcp_start, dhcp_end=dhcp_end) + retcode, retmsg = pvc_network.modify_network(zk_conn, vni, description=description, domain=domain, name_servers=name_servers, ip6_network=ip6_network, ip6_gateway=ip6_gateway, ip4_network=ip4_network, ip4_gateway=ip4_gateway, dhcp_flag=dhcp_flag, dhcp_start=dhcp_start, dhcp_end=dhcp_end) cleanup(retcode, retmsg, zk_conn) ############################################################################### diff --git a/client-common/network.py b/client-common/network.py index b6fef518..25e76cd1 100644 --- a/client-common/network.py +++ b/client-common/network.py @@ -134,6 +134,7 @@ def getNetworkInformation(zk_conn, vni): description = zkhandler.readdata(zk_conn, '/networks/{}'.format(vni)) nettype = zkhandler.readdata(zk_conn, '/networks/{}/nettype'.format(vni)) domain = zkhandler.readdata(zk_conn, '/networks/{}/domain'.format(vni)) + name_servers = zkhandler.readdata(zk_conn, '/networks/{}/name_servers'.format(vni)) ip6_network = zkhandler.readdata(zk_conn, '/networks/{}/ip6_network'.format(vni)) ip6_gateway = zkhandler.readdata(zk_conn, '/networks/{}/ip6_gateway'.format(vni)) dhcp6_flag = zkhandler.readdata(zk_conn, '/networks/{}/dhcp6_flag'.format(vni)) @@ -149,6 +150,7 @@ def getNetworkInformation(zk_conn, vni): 'description': description, 'type': nettype, 'domain': domain, + 'name_servers': name_servers.split(','), 'ip6': { 'network': ip6_network, 'gateway': ip6_gateway, @@ -223,7 +225,7 @@ def isValidIP(ipaddr): # Direct functions # def add_network(zk_conn, vni, description, nettype, - domain, ip4_network, ip4_gateway, ip6_network, ip6_gateway, + domain, name_servers, ip4_network, ip4_gateway, ip6_network, ip6_gateway, dhcp4_flag, dhcp4_start, dhcp4_end): # Ensure start and end DHCP ranges are set if the flag is set if dhcp4_flag and ( not dhcp4_start or not dhcp4_end ): @@ -254,6 +256,7 @@ def add_network(zk_conn, vni, description, nettype, '/networks/{}'.format(vni): description, '/networks/{}/nettype'.format(vni): nettype, '/networks/{}/domain'.format(vni): domain, + '/networks/{}/name_servers'.format(vni): ','.join(name_servers), '/networks/{}/ip6_network'.format(vni): ip6_network, '/networks/{}/ip6_gateway'.format(vni): ip6_gateway, '/networks/{}/dhcp6_flag'.format(vni): dhcp6_flag, @@ -278,6 +281,8 @@ def modify_network(zk_conn, vni, **parameters): zk_data.update({'/networks/{}'.format(vni): parameters['description']}) if parameters['domain']: zk_data.update({'/networks/{}/domain'.format(vni): parameters['domain']}) + if parameters['name_servers']: + zk_data.update({'/networks/{}/name_servers'.format(vni): ','.join(parameters['name_servers'])}) if parameters['ip4_network']: zk_data.update({'/networks/{}/ip4_network'.format(vni): parameters['ip4_network']}) if parameters['ip4_gateway']: @@ -644,6 +649,7 @@ def format_info(network_information, long_output): ainformation.append('{}Description:{} {}'.format(ansiprint.purple(), ansiprint.end(), network_information['description'])) if network_information['type'] == 'managed': ainformation.append('{}Domain:{} {}'.format(ansiprint.purple(), ansiprint.end(), network_information['domain'])) + ainformation.append('{}DNS Servers:{} {}'.format(ansiprint.purple(), ansiprint.end(), ', '.join(network_information['name_servers']))) if network_information['ip6']['network'] != "None": ainformation.append('') ainformation.append('{}IPv6 network:{} {}'.format(ansiprint.purple(), ansiprint.end(), network_information['ip6']['network'])) diff --git a/node-daemon/pvcd/DNSAggregatorInstance.py b/node-daemon/pvcd/DNSAggregatorInstance.py index 868c7dc9..13bb90ad 100644 --- a/node-daemon/pvcd/DNSAggregatorInstance.py +++ b/node-daemon/pvcd/DNSAggregatorInstance.py @@ -222,7 +222,11 @@ class DNSNetworkInstance(object): (domain_id, network_domain, 'nsX.{d} root.{d} 1 10800 1800 86400 86400'.format(d=self.config['upstream_domain']), 'SOA', 86400, 0) ) - ns_servers = ['pvc-ns.{}'.format(self.config['upstream_domain'])] + if self.network.name_servers: + ns_servers = self.network.name_servers + else: + ns_servers = ['pvc-dns.{}'.format(self.config['upstream_domain'])] + for ns_server in ns_servers: sql_curs.execute( """ diff --git a/node-daemon/pvcd/VXNetworkInstance.py b/node-daemon/pvcd/VXNetworkInstance.py index 3a23f22d..8902c238 100644 --- a/node-daemon/pvcd/VXNetworkInstance.py +++ b/node-daemon/pvcd/VXNetworkInstance.py @@ -90,6 +90,7 @@ class VXNetworkInstance(object): self.old_description = None self.description = None self.domain = None + self.name_servers = None self.ip6_gateway = zkhandler.readdata(self.zk_conn, '/networks/{}/ip6_gateway'.format(self.vni)) self.ip6_network = zkhandler.readdata(self.zk_conn, '/networks/{}/ip6_network'.format(self.vni)) self.ip6_cidrnetmask = zkhandler.readdata(self.zk_conn, '/networks/{}/ip6_network'.format(self.vni)).split('/')[-1] @@ -180,6 +181,17 @@ add rule inet filter forward ip6 saddr {netaddr6} counter jump {vxlannic}-out domain = data.decode('ascii') self.domain = domain + @self.zk_conn.DataWatch('/networks/{}/name_servers'.format(self.vni)) + def watch_network_name_servers(data, stat, event=''): + if event and event.type == 'DELETED': + # The key has been deleted after existing before; terminate this watcher + # because this class instance is about to be reaped in Daemon.py + return False + + if data and self.name_servers != data.decode('ascii'): + name_servers = data.decode('ascii').split(',') + self.name_servers = name_servers + @self.zk_conn.DataWatch('/networks/{}/ip6_network'.format(self.vni)) def watch_network_ip6_network(data, stat, event=''): if event and event.type == 'DELETED':