]> Frank Brehm's Git Trees - pixelpark/admin-tools.git/commitdiff
Improving pp_lib/pdns_app.py:
authorFrank Brehm <frank.brehm@pixelpark.com>
Tue, 16 Jan 2018 17:29:14 +0000 (18:29 +0100)
committerFrank Brehm <frank.brehm@pixelpark.com>
Tue, 16 Jan 2018 17:29:14 +0000 (18:29 +0100)
* Deactivating comments on updating SOA
* New methods increase_serial(), set_nameservers() and notify_zone() to class PpPDNSApplication

pp_lib/pdns_app.py

index 9197aea1d53ba38306a2b901c37c91792b6eb8b1..38e5fce97489a05cf1b7c8b28483ac715c80b784 100644 (file)
@@ -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)
 
 # =============================================================================