From c85b47645f6d1a655387ac6da37afddbc5febb44 Mon Sep 17 00:00:00 2001 From: Frank Brehm Date: Tue, 16 Jan 2018 18:29:14 +0100 Subject: [PATCH] Improving pp_lib/pdns_app.py: * Deactivating comments on updating SOA * New methods increase_serial(), set_nameservers() and notify_zone() to class PpPDNSApplication --- pp_lib/pdns_app.py | 143 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 135 insertions(+), 8 deletions(-) diff --git a/pp_lib/pdns_app.py b/pp_lib/pdns_app.py index 9197aea..38e5fce 100644 --- a/pp_lib/pdns_app.py +++ b/pp_lib/pdns_app.py @@ -32,7 +32,7 @@ from .cfg_app import PpCfgAppError, PpConfigApplication from .pdns_zone import PdnsApiZone from .pdns_record import PdnsApiRecord, PdnsSoaData, PdnsApiRrset -__version__ = '0.6.1' +__version__ = '0.6.2' LOG = logging.getLogger(__name__) _LIBRARY_NAME = "pp-pdns-api-client" @@ -650,15 +650,16 @@ class PpPDNSApplication(PpConfigApplication): 'ttl': ttl, 'changetype': 'REPLACE', 'records': [], + 'comments': [], } - if comment: - comment_rec = { - 'content': comment, - 'account': getpass.getuser(), - 'modified_at': time.time(), - } - rrset['comments'] = [comment_rec] +# if comment: +# comment_rec = { +# 'content': comment, +# 'account': getpass.getuser(), +# 'modified_at': int(time.time() + 0.5), +# } +# rrset['comments'] = [comment_rec] record = { 'content': new_soa.data, @@ -676,6 +677,132 @@ class PpPDNSApplication(PpConfigApplication): self.patch_zone(zone, payload) + # ------------------------------------------------------------------------- + def increase_serial(self, zone_name, comment=None): + + zone = self.get_api_zone(zone_name) + if not zone: + raise PpPDNSAppError("Did not found zone for {!r}.".format(zone_name)) + + LOG.info("Increasing serial in SOA of zone {!r} ....".format(zone_name)) + + api_host_address = None + for addr_info in socket.getaddrinfo(self.api_host, 53, family=socket.AF_INET): + api_host_address = addr_info[4][0] + break + + api_soa = zone.get_soa() + if not api_soa: + raise PpPDNSAppError("Could not find SOA for zone {!r}.".format(zone_name)) + if self.verbose > 2: + LOG.debug("Got SOA for zone {z!r} by API:\n{s}".format( + z=zone_name, s=api_soa)) + + dns_soa = zone.get_soa_by_dns(api_host_address) + if self.verbose > 2: + LOG.debug("Got SOA for zone {z!r} from DNS by {h!r}:\n{s}".format( + h=self.api_host, z=zone_name, s=dns_soa)) + + new_serial = zone.get_new_serial(dns_soa.serial) + LOG.debug("Got new serial number for zone {z!r}: {s}.".format( + z=zone_name, s=new_serial)) + + api_soa.serial = new_serial + return self.update_soa(zone, api_soa, comment) + + # ------------------------------------------------------------------------- + def set_nameservers( + self, zone, new_nameservers, for_zone=None, comment=None, new_ttl=None, + do_serial=True, do_notify=True): + + current_nameservers = zone.get_zone_nameservers(for_zone=for_zone) + if for_zone: + LOG.debug("Current nameservers of {f!r} in zone {z!r}:\n{ns}".format( + f=for_zone, z=zone.name, ns=pp(current_nameservers))) + else: + LOG.debug("Current nameservers of zone {z!r}:\n{ns}".format( + z=zone.name, ns=pp(current_nameservers))) + + ns2remove = [] + ns2add = [] + + for ns in current_nameservers: + if ns not in new_nameservers: + ns2remove.append(ns) + for ns in new_nameservers: + if ns not in current_nameservers: + ns2add.append(ns) + + if not ns2remove and not ns2add: + if for_zone: + msg = "Subzone {f!r} has already the expected nameservers in zone {z!r}." + else: + msg = "Zone {z!r} has already the expected nameservers." + LOG.info(msg.format(f=for_zone, z=zone.name)) + return False + + LOG.debug("Nameservers to remove from zone {z!r}:\n{ns}".format( + z=zone.name, ns=pp(ns2remove))) + LOG.debug("Nameservers to add to zone {z!r}:\n{ns}".format( + z=zone.name, ns=pp(ns2add))) + + ns_ttl = None + if not new_ttl: + cur_rrset = zone.get_ns_rrset(for_zone=for_zone) + ns_ttl = cur_rrset.ttl + else: + ns_ttl = int(new_ttl) + LOG.debug("TTL for NS records: {}.".format(ns_ttl)) + + rrset_name = zone.name.lower() + if for_zone: + rrset_name = for_zone.lower() + + records = [] + for ns in new_nameservers: + record = { + "name": rrset_name, + "type": "NS", + "content": ns, + "disabled": False, + "set-ptr": False, + } + records.append(record) + rrset = { + "name": rrset_name, + "type": "NS", + "ttl": ns_ttl, + "changetype": "REPLACE", + "records": records, + } + + if comment: + comment_rec = { + 'content': comment, + 'account': getpass.getuser(), + 'modified_at': int(time.time() + 0.5), + } + rrset['comments'] = [comment_rec] + + payload = {"rrsets": [rrset]} + + self.patch_zone(zone, payload) + + if do_serial: + self.increase_serial(zone.name) + + if do_notify: + self.notify_zone(zone) + + return True + + # ------------------------------------------------------------------------- + def notify_zone(self, zone): + + LOG.info("Notifying slaves of zone {!r} ...".format(zone.name)) + + path = "/servers/{}/zones/{}/notify".format(self.api_servername, zone.name) + return self.perform_request(path, 'PUT', '', may_simulate=True) # ============================================================================= -- 2.39.5