From ee18fcaef76b9638c53a371f476e009e2cf587c0 Mon Sep 17 00:00:00 2001 From: Kiran Pawar Date: Tue, 19 Jan 2021 13:00:40 +0100 Subject: [PATCH] Delete reverse floating IP records on FIP deletion When floating ip is created without dns_name and dns_domain, ptr record is created in desigate. After setting ptrdname on ptr record, new reverse floating ip record is created within zone. After deletion of floating ip the record still exist. Fix this issue by trying to delete recordset within zone by admin_client and allowed to see all projects. Keep the existing logic of floating ip deletion with dns_domain and dns_name as it was. Closes-Bug: #1746627 --- neutron/db/dns_db.py | 7 +++ .../externaldns/drivers/designate/driver.py | 61 ++++++++++++++++--- 2 files changed, 60 insertions(+), 8 deletions(-) diff --git a/neutron/db/dns_db.py b/neutron/db/dns_db.py index 5d49ec42c5d..148f31fb041 100644 --- a/neutron/db/dns_db.py +++ b/neutron/db/dns_db.py @@ -187,6 +187,10 @@ def _process_dns_floatingip_delete(self, context, floatingip_data): context, dns_data_db['published_dns_domain'], dns_data_db['published_dns_name'], [floatingip_data['floating_ip_address']]) + else: + self._delete_floatingip_from_external_dns_service( + context, None, None, + [floatingip_data['floating_ip_address']]) def _validate_floatingip_dns(self, dns_name, dns_domain): if dns_domain and not dns_name: @@ -209,6 +213,9 @@ def _get_internal_port_dns_data(self, context, floatingip_data): def _delete_floatingip_from_external_dns_service(self, context, dns_domain, dns_name, records): + if not self.dns_driver: + return + ips = [str(r) for r in records] try: self.dns_driver.delete_record_set(context, dns_domain, dns_name, diff --git a/neutron/services/externaldns/drivers/designate/driver.py b/neutron/services/externaldns/drivers/designate/driver.py index 48a6ea0c105..18fd14a7b79 100644 --- a/neutron/services/externaldns/drivers/designate/driver.py +++ b/neutron/services/externaldns/drivers/designate/driver.py @@ -23,6 +23,7 @@ from neutron_lib import constants from neutron_lib.exceptions import dns as dns_exc from oslo_config import cfg +from oslo_log import log as logging from neutron.conf.services import extdns_designate_driver from neutron.services.externaldns import driver @@ -37,6 +38,8 @@ CONF = cfg.CONF extdns_designate_driver.register_designate_opts() +LOG = logging.getLogger(__name__) + def get_clients(context): global _SESSION @@ -61,6 +64,34 @@ def get_clients(context): return client, admin_client +def get_all_projects_client(context, edit_managed=False): + global _SESSION + + if not _SESSION: + _SESSION = loading.load_session_from_conf_options( + CONF, 'designate') + + auth = token_endpoint.Token(CONF.designate.url, context.auth_token) + client = d_client.Client(session=_SESSION, auth=auth, + all_projects=True, + edit_managed=edit_managed) + if CONF.designate.auth_type: + admin_auth = loading.load_auth_from_conf_options( + CONF, 'designate') + else: + admin_auth = password.Password( + auth_url=CONF.designate.admin_auth_url, + username=CONF.designate.admin_username, + password=CONF.designate.admin_password, + tenant_name=CONF.designate.admin_tenant_name, + tenant_id=CONF.designate.admin_tenant_id) + admin_client = d_client.Client(session=_SESSION, auth=admin_auth, + endpoint_override=CONF.designate.url, + all_projects=True, + edit_managed=edit_managed) + return client, admin_client + + class Designate(driver.ExternalDNSService): """Driver for Designate.""" @@ -147,17 +178,31 @@ def _get_bytes_or_nybles_to_skip(self, in_addr_name): def delete_record_set(self, context, dns_domain, dns_name, records): designate, designate_admin = get_clients(context) - ids_to_delete = self._get_ids_ips_to_delete( - dns_domain, '%s.%s' % (dns_name, dns_domain), records, designate) - for _id in ids_to_delete: - designate.recordsets.delete(dns_domain, _id) + if dns_domain and dns_name: + ids_to_delete = self._get_ids_ips_to_delete( + dns_domain, '%s.%s' % (dns_name, dns_domain), + records, designate) + for _id in ids_to_delete: + designate.recordsets.delete(dns_domain, _id) + if not CONF.designate.allow_reverse_dns_lookup: return - for record in records: - in_addr_name = netaddr.IPAddress(record).reverse_dns - in_addr_zone_name = self._get_in_addr_zone_name(in_addr_name) - designate_admin.recordsets.delete(in_addr_zone_name, in_addr_name) + if not dns_domain and not dns_name: + designate, designate_admin = get_all_projects_client(context, True) + + try: + for record in records: + in_addr_name = netaddr.IPAddress(record).reverse_dns + in_addr_zone_name = self._get_in_addr_zone_name(in_addr_name) + designate_admin.recordsets.delete(in_addr_zone_name, + in_addr_name) + except Exception as e: + if dns_domain and dns_name: + raise e + else: + LOG.debug("PTR record not found for floating IP " + "created without dns_domain and dns_name") def _get_ids_ips_to_delete(self, dns_domain, name, records, designate_client):