Beispiel #1
0
    def apply(self, domain, post_records):
        """
        Apply record changes to domain
        """
        deleted_records, new_records = self.compare(domain, post_records)

        records = []
        for r in deleted_records:
            record = {"name": r["name"], "type": r["type"], "changetype": "DELETE", "records": []}
            records.append(record)
        postdata_for_delete = {"rrsets": records}

        records = []
        for r in new_records:
            record = {
                "name": r["name"],
                "type": r["type"],
                "changetype": "REPLACE",
                "records": [
                    {
                        "content": r["content"],
                        "disabled": r["disabled"],
                        "name": r["name"],
                        "ttl": r["ttl"],
                        "type": r["type"],
                    }
                ],
            }
            records.append(record)
        postdata_for_new = {"rrsets": records}

        try:
            headers = {}
            headers["X-API-Key"] = PDNS_API_KEY
            jdata1 = utils.fetch_json(
                urlparse.urljoin(PDNS_STATS_URL, "/servers/localhost/zones/%s" % domain),
                headers=headers,
                method="PATCH",
                data=postdata_for_delete,
            )
            # logging.debug(jdata1)

            jdata2 = utils.fetch_json(
                urlparse.urljoin(PDNS_STATS_URL, "/servers/localhost/zones/%s" % domain),
                headers=headers,
                method="PATCH",
                data=postdata_for_new,
            )
            # logging.debug(jdata2)

            if "error" in jdata2.keys():
                logging.error("Cannot apply record changes.")
                logging.debug(jdata2["error"])
                return {"status": "error", "msg": jdata2["error"]}
            else:
                logging.info("Record was applied successfully.")
                return {"status": "ok", "msg": "Record was applied successfully"}
        except Exception, e:
            logging.error("Cannot apply record changes to domain %s. DETAIL: %s" % (str(e), domain))
            return {"status": "error", "msg": "There was something wrong, please contact administrator"}
Beispiel #2
0
 def update_from_master(self, domain_name):
     """
     Update records from Master DNS server
     """
     domain = Domain.query.filter(Domain.name == domain_name).first()
     if domain:
         headers = {}
         headers['X-API-Key'] = PDNS_API_KEY
         try:
             jdata = utils.fetch_json(urlparse.urljoin(
                 PDNS_STATS_URL,
                 '/servers/localhost/zones/%s/axfr-retrieve' % domain),
                                      headers=headers,
                                      method='PUT')
             return {
                 'status': 'ok',
                 'msg': 'Update from Master successfully'
             }
         except:
             return {
                 'status':
                 'error',
                 'msg':
                 'There was something wrong, please contact administrator'
             }
     else:
         return {'status': 'error', 'msg': 'This domain doesnot exist'}
Beispiel #3
0
 def add(self,
         domain_name,
         domain_type,
         domain_ns=[],
         domain_master_ips=[]):
     """
     Add a domain to power dns
     """
     headers = {}
     headers['X-API-Key'] = PDNS_API_KEY
     post_data = {
         "name": domain_name,
         "kind": domain_type,
         "masters": domain_master_ips,
         "nameservers": domain_ns
     }
     try:
         jdata = utils.fetch_json(urlparse.urljoin(
             PDNS_STATS_URL, '/servers/localhost/zones'),
                                  headers=headers,
                                  method='POST',
                                  data=post_data)
         if 'error' in jdata.keys():
             logging.error(jdata['error'])
             return {'status': 'error', 'msg': jdata['error']}
         else:
             logging.info('Added domain %s successfully' % domain_name)
             return {'status': 'ok', 'msg': 'Added domain successfully'}
     except Exception, e:
         print traceback.format_exc()
         logging.error('Cannot add domain %s' % domain_name)
         logging.debug(str(e))
         return {'status': 'error', 'msg': 'Cannot add this domain.'}
Beispiel #4
0
 def delete(self, domain):
     """
     Delete a record from domain
     """
     headers = {}
     headers['X-API-Key'] = PDNS_API_KEY
     data = {"rrsets": [
                 {
                     "name": self.name,
                     "type": self.type,
                     "changetype": "DELETE",
                     "records": [ 
                         {
                             "name": self.name,
                             "type": self.type
                         } 
                     ]
                 }
             ]
         }
     try:
         jdata = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, '/servers/localhost/zones/%s' % domain), headers=headers, method='PATCH', data=data)
         logging.debug(jdata)
         return {'status': 'ok', 'msg': 'Record was removed successfully'}
     except:
         logging.error("Cannot remove record %s/%s/%s from domain %s" % (self.name, self.type, self.data, domain))
         return {'status': 'error', 'msg': 'There was something wrong, please contact administrator'}
Beispiel #5
0
 def get_domains(self):
     """
     Get all domains which has in PowerDNS
     jdata example:
         [
           {
             "id": "example.org.",
             "url": "/servers/localhost/zones/example.org.",
             "name": "example.org",
             "kind": "Native",
             "dnssec": false,
             "account": "",
             "masters": [],
             "serial": 2015101501,
             "notified_serial": 0,
             "last_check": 0
           }
         ]
     """
     headers = {}
     headers['X-API-Key'] = PDNS_API_KEY
     jdata = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL,
                                               '/servers/localhost/zones'),
                              headers=headers)
     return jdata
Beispiel #6
0
    def get_record_data(self, domain):
        """
        Query domain's DNS records via API
        """
        headers = {}
        headers['X-API-Key'] = PDNS_API_KEY
        try:
            jdata = utils.fetch_json(urlparse.urljoin(
                PDNS_STATS_URL,
                API_EXTENDED_URL + '/servers/localhost/zones/%s' % domain),
                                     headers=headers)
        except:
            logging.error(
                "Cannot fetch domain's record data from remote powerdns api")
            return False

        if NEW_SCHEMA:
            rrsets = jdata['rrsets']
            for rrset in rrsets:
                r_name = rrset['name'].rstrip('.')
                if PRETTY_IPV6_PTR:  # only if activated
                    if rrset['type'] == 'PTR':  # only ptr
                        if 'ip6.arpa' in r_name:  # only if v6-ptr
                            r_name = dns.reversename.to_address(
                                dns.name.from_text(r_name))

                rrset['name'] = r_name
                rrset['content'] = rrset['records'][0]['content']
                rrset['disabled'] = rrset['records'][0]['disabled']
            return {'records': rrsets}

        return jdata
Beispiel #7
0
 def add(self, domain_name, domain_type, domain_ns=[], domain_master_ips=[]):
     """
     Add a domain to power dns
     """
     headers = {}
     headers['X-API-Key'] = PDNS_API_KEY
     post_data = {
                     "name": domain_name,
                     "kind": domain_type,
                     "masters": domain_master_ips,
                     "nameservers": domain_ns
                 }
     try:
         jdata = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, '/servers/localhost/zones'), headers=headers, method='POST', data=post_data)
         if 'error' in jdata.keys():
             logging.error(jdata['error'])
             return {'status': 'error', 'msg': jdata['error']}
         else:
             logging.info('Added domain %s successfully' % domain_name)
             return {'status': 'ok', 'msg': 'Added domain successfully'}
     except Exception, e:
         print traceback.format_exc()
         logging.error('Cannot add domain %s' % domain_name)
         logging.debug(str(e))
         return {'status': 'error', 'msg': 'Cannot add this domain.'}
Beispiel #8
0
    def get_record_data(self, domain):
        """
        Query domain's DNS records via API
        """
        headers = {}
        headers['X-API-Key'] = PDNS_API_KEY
        try:
            jdata = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones/%s' % domain), headers=headers)
        except:
            logging.error("Cannot fetch domain's record data from remote powerdns api")
            return False

        if NEW_SCHEMA:
            rrsets = jdata['rrsets']
            for rrset in rrsets:
                r_name = rrset['name'].rstrip('.')
                if PRETTY_IPV6_PTR: # only if activated
                    if rrset['type'] == 'PTR': # only ptr
                        if 'ip6.arpa' in r_name: # only if v6-ptr
                            r_name = dns.reversename.to_address(dns.name.from_text(r_name))

                rrset['name'] = r_name
                rrset['content'] = rrset['records'][0]['content']
                rrset['disabled'] = rrset['records'][0]['disabled']
            return {'records': rrsets}

        return jdata
Beispiel #9
0
 def delete(self, domain):
     """
     Delete a record from domain
     """
     headers = {}
     headers['X-API-Key'] = PDNS_API_KEY
     data = {"rrsets": [
                 {
                     "name": self.name,
                     "type": self.type,
                     "changetype": "DELETE",
                     "records": [ 
                         {
                             "name": self.name,
                             "type": self.type
                         } 
                     ]
                 }
             ]
         }
     try:
         jdata = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones/%s' % domain), headers=headers, method='PATCH', data=data)
         logging.debug(jdata)
         return {'status': 'ok', 'msg': 'Record was removed successfully'}
     except:
         logging.error("Cannot remove record %s/%s/%s from domain %s" % (self.name, self.type, self.data, domain))
         return {'status': 'error', 'msg': 'There was something wrong, please contact administrator'}
Beispiel #10
0
 def add(self, domain_name, domain_type, domain_ns=[], domain_master_ips=[]):
     """
     Add a domain to power dns
     """
     headers = {}
     headers["X-API-Key"] = PDNS_API_KEY
     post_data = {"name": domain_name, "kind": domain_type, "masters": domain_master_ips, "nameservers": domain_ns}
     try:
         jdata = utils.fetch_json(
             urlparse.urljoin(PDNS_STATS_URL, "/servers/localhost/zones"),
             headers=headers,
             method="POST",
             data=post_data,
         )
         if "error" in jdata.keys():
             logging.error(jdata["error"])
             return {"status": "error", "msg": jdata["error"]}
         else:
             logging.info("Added domain %s successfully" % domain_name)
             return {"status": "ok", "msg": "Added domain successfully"}
     except Exception, e:
         print traceback.format_exc()
         logging.error("Cannot add domain %s" % domain_name)
         logging.debug(str(e))
         return {"status": "error", "msg": "Cannot add this domain."}
Beispiel #11
0
 def get_domain_dnssec(self, domain_name):
     """
     Get domain DNSSEC information
     """
     domain = Domain.query.filter(Domain.name == domain_name).first()
     if domain:
         headers = {}
         headers['X-API-Key'] = PDNS_API_KEY
         try:
             jdata = utils.fetch_json(urlparse.urljoin(
                 PDNS_STATS_URL, API_EXTENDED_URL +
                 '/servers/localhost/zones/%s/cryptokeys' % domain.name),
                                      headers=headers,
                                      method='GET')
             if 'error' in jdata:
                 return {
                     'status': 'error',
                     'msg': 'DNSSEC is not enabled for this domain'
                 }
             else:
                 return {'status': 'ok', 'dnssec': jdata}
         except:
             return {
                 'status':
                 'error',
                 'msg':
                 'There was something wrong, please contact administrator'
             }
     else:
         return {'status': 'error', 'msg': 'This domain doesnot exist'}
Beispiel #12
0
    def update(self):
        """
        Fetch zones (domains) from PowerDNS and update into DB
        """
        db_domain = Domain.query.all()
        list_db_domain = [d.name for d in db_domain]

        headers = {}
        headers['X-API-Key'] = PDNS_API_KEY
        try:
            jdata = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, '/servers/localhost/zones'), headers=headers)
            list_jdomain = [d['name'] for d in jdata]

            try:
                # domains should remove from db since it doesn't exist in powerdns anymore
                should_removed_db_domain = list(set(list_db_domain).difference(list_jdomain))
                for d in should_removed_db_domain:
                    # revoke permission before delete domain
                    domain = Domain.query.filter(Domain.name==d).first()
                    domain_user = DomainUser.query.filter(DomainUser.domain_id==domain.id)
                    if domain_user:
                        domain_user.delete()
                        db.session.commit()

                    # then remove domain
                    Domain.query.filter(Domain.name == d).delete()
                    db.session.commit()
            except:
                logging.error('Can not delete domain from DB')
                logging.debug(traceback.format_exc())
                db.session.rollback()

            # update/add new domain
            for data in jdata:
                d = Domain.query.filter(Domain.name == data['name']).first()
                if d:
                    #update exist domain
                    d.master = str(data['masters'])
                    d.type = data['kind']
                    d.serial = data['serial']
                    d.notified_serial = data['notified_serial']
                    d.last_check = data['last_check']
                else:
                    # add new domain
                    d = Domain()
                    d.name = data['name']
                    d.master = str(data['masters'])
                    d.type = data['kind']
                    d.serial = data['serial']
                    d.notified_serial = data['notified_serial']
                    d.last_check = data['last_check']
                    db.session.add(d)
                try:
                    db.session.commit()
                except:
                    db.session.rollback()
            return {'status': 'ok', 'msg': 'Domain table has been updated successfully'}
        except Exception, e:
            logging.error('Can not update domain table.' + str(e))
            return {'status': 'error', 'msg': 'Can not update domain table'}
Beispiel #13
0
    def add(self, domain):
        """
        Add a record to domain
        """
        # validate record first
        r = self.get_record_data(domain)
        records = r['records']
        check = filter(lambda check: check['name'] == self.name, records)
        if check:
            r = check[0]
            if r['type'] in ('A', 'AAAA' ,'CNAME'):
                return {'status': 'error', 'msg': 'Record already exists with type "A", "AAAA" or "CNAME"'}

        # continue if the record is ready to be added
        headers = {}
        headers['X-API-Key'] = PDNS_API_KEY

        if NEW_SCHEMA:
            data = {"rrsets": [
                        {
                            "name": self.name + '.',
                            "type": self.type,
                            "changetype": "REPLACE",
                            "ttl": self.ttl,
                            "records": [
                                {
                                    "content": self.data,
                                    "disabled": self.status,
                                }
                            ]
                        }
                    ]
                }
        else:
            data = {"rrsets": [
                        {
                            "name": self.name,
                            "type": self.type,
                            "changetype": "REPLACE",
                            "records": [
                                {
                                    "content": self.data,
                                    "disabled": self.status,
                                    "name": self.name,
                                    "ttl": self.ttl,
                                    "type": self.type,
                                    "set-ptr": self.auto_ptr
                                }
                            ]
                        }
                    ]
                }

        try:
            jdata = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones/%s' % domain), headers=headers, method='PATCH', data=data)
            logging.debug(jdata)
            return {'status': 'ok', 'msg': 'Record was added successfully'}
        except Exception, e:
            logging.error("Cannot add record %s/%s/%s to domain %s. DETAIL: %s" % (self.name, self.type, self.data, domain, str(e)))
            return {'status': 'error', 'msg': 'There was something wrong, please contact administrator'}
Beispiel #14
0
 def delete(self, domain):
     """
     Delete a record from domain
     """
     headers = {}
     headers["X-API-Key"] = PDNS_API_KEY
     data = {
         "rrsets": [
             {
                 "name": self.name,
                 "type": self.type,
                 "changetype": "DELETE",
                 "records": [{"name": self.name, "type": self.type}],
             }
         ]
     }
     try:
         jdata = utils.fetch_json(
             urlparse.urljoin(PDNS_STATS_URL, "/servers/localhost/zones/%s" % domain),
             headers=headers,
             method="PATCH",
             data=data,
         )
         logging.debug(jdata)
         return {"status": "ok", "msg": "Record was removed successfully"}
     except:
         logging.error("Cannot remove record %s/%s/%s from domain %s" % (self.name, self.type, self.data, domain))
         return {"status": "error", "msg": "There was something wrong, please contact administrator"}
Beispiel #15
0
    def add(self, domain):
        """
        Add a record to domain
        """
        # validate record first
        r = self.get_record_data(domain)
        records = r['records']
        check = filter(lambda check: check['name'] == self.name, records)
        if check:
            r = check[0]
            if r['type'] in ('A', 'AAAA' ,'CNAME'):
                return {'status': 'error', 'msg': 'Record already exists with type "A", "AAAA" or "CNAME"'}

        # continue if the record is ready to be added
        headers = {}
        headers['X-API-Key'] = PDNS_API_KEY

        if NEW_SCHEMA:
            data = {"rrsets": [
                        {
                            "name": self.name + '.',
                            "type": self.type,
                            "changetype": "REPLACE",
                            "ttl": self.ttl,
                            "records": [
                                {
                                    "content": self.data,
                                    "disabled": self.status,
                                }
                            ]
                        }
                    ]
                }
        else:
            data = {"rrsets": [
                        {
                            "name": self.name,
                            "type": self.type,
                            "changetype": "REPLACE",
                            "records": [
                                {
                                    "content": self.data,
                                    "disabled": self.status,
                                    "name": self.name,
                                    "ttl": self.ttl,
                                    "type": self.type
                                }
                            ]
                        }
                    ]
                }

        try:
            jdata = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones/%s' % domain), headers=headers, method='PATCH', data=data)
            logging.debug(jdata)
            return {'status': 'ok', 'msg': 'Record was added successfully'}
        except Exception, e:
            logging.error("Cannot add record %s/%s/%s to domain %s. DETAIL: %s" % (self.name, self.type, self.data, domain, str(e)))
            return {'status': 'error', 'msg': 'There was something wrong, please contact administrator'}
Beispiel #16
0
 def get_record_data(self, domain):
     """
     Query domain's DNS records via API
     """
     headers = {}
     headers['X-API-Key'] = PDNS_API_KEY
     try:
         jdata = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, '/servers/localhost/zones/%s' % domain), headers=headers)
     except:
         logging.error("Cannot fetch domain's record data from remote powerdns api")
         return False
     return jdata
Beispiel #17
0
    def get_statistic(self):
        """
        Get server statistics
        """
        headers = {}
        headers['X-API-Key'] = PDNS_API_KEY

        try:
            jdata = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/%s/statistics' % self.server_id), headers=headers, method='GET')
            return jdata
        except:
            logging.error("Can not get server statistics.")
            logging.debug(traceback.format_exc())
            return []
Beispiel #18
0
    def get_config(self):
        """
        Get server config
        """
        headers = {}
        headers['X-API-Key'] = PDNS_API_KEY

        try:
            jdata = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/%s/config' % self.server_id), headers=headers, method='GET')
            return jdata
        except:
            logging.error("Can not get server configuration.")
            logging.debug(traceback.format_exc())
            return []
Beispiel #19
0
 def get_statistic(self):
     """
     Get server statistics
     """
     headers = {}
     headers['X-API-Key'] = PDNS_API_KEY
     
     try:
         jdata = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, '/servers/%s/statistics' % self.server_id), headers=headers, method='GET')
         return jdata
     except:
         logging.error("Can not get server statistics.")
         logging.debug(traceback.format_exc())
         return []
Beispiel #20
0
    def update(self, domain, content):
        """
        Update single record
        """
        headers = {}
        headers['X-API-Key'] = PDNS_API_KEY

        if NEW_SCHEMA:
            data = {"rrsets": [
                        {
                            "name": self.name + '.',
                            "type": self.type,
                            "ttl": self.ttl,
                            "changetype": "REPLACE",
                            "records": [
                                {
                                    "content": content,
                                    "disabled": self.status,
                                }
                            ]
                        }
                    ]
                }
        else:
            data = {"rrsets": [
                        {
                            "name": self.name,
                            "type": self.type,
                            "changetype": "REPLACE",
                            "records": [
                                {
                                    "content": content,
                                    "disabled": self.status,
                                    "name": self.name,
                                    "ttl": self.ttl,
                                    "type": self.type,
                                    "priority": 10
                                }
                            ]
                        }
                    ]
                }
        try:
            jdata = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones/%s' % domain), headers=headers, method='PATCH', data=data)
            logging.debug("dyndns data: " % data)
            return {'status': 'ok', 'msg': 'Record was updated successfully'}
        except Exception, e:
            logging.error("Cannot add record %s/%s/%s to domain %s. DETAIL: %s" % (self.name, self.type, self.data, domain, str(e)))
            return {'status': 'error', 'msg': 'There was something wrong, please contact administrator'}
Beispiel #21
0
    def add(self, domain):
        """
        Add a record to domain
        """
        # validate record first
        r = self.get_record_data(domain)
        records = r["records"]
        check = filter(lambda check: check["name"] == self.name, records)
        if check:
            r = check[0]
            if r["type"] in ("A", "AAAA", "CNAME"):
                return {"status": "error", "msg": 'Record might was already exist with type "A", "AAAA", "CNAME"'}

        # continue if the record is ready to be added
        headers = {}
        headers["X-API-Key"] = PDNS_API_KEY
        data = {
            "rrsets": [
                {
                    "name": self.name,
                    "type": self.type,
                    "changetype": "REPLACE",
                    "records": [
                        {
                            "content": self.data,
                            "disabled": self.status,
                            "name": self.name,
                            "ttl": self.ttl,
                            "type": self.type,
                        }
                    ],
                }
            ]
        }
        try:
            jdata = utils.fetch_json(
                urlparse.urljoin(PDNS_STATS_URL, "/servers/localhost/zones/%s" % domain),
                headers=headers,
                method="PATCH",
                data=data,
            )
            logging.debug(jdata)
            return {"status": "ok", "msg": "Record was added successfully"}
        except Exception, e:
            logging.error(
                "Cannot add record %s/%s/%s to domain %s. DETAIL: %s"
                % (self.name, self.type, self.data, domain, str(e))
            )
            return {"status": "error", "msg": "There was something wrong, please contact administrator"}
Beispiel #22
0
    def update(self, domain, content):
        """
        Update single record
        """
        headers = {}
        headers['X-API-Key'] = PDNS_API_KEY

        if NEW_SCHEMA:
            data = {"rrsets": [
                        {
                            "name": self.name + '.',
                            "type": self.type,
                            "ttl": self.ttl,
                            "changetype": "REPLACE",
                            "records": [
                                {
                                    "content": content,
                                    "disabled": self.status,
                                }
                            ]
                        }
                    ]
                }
        else:
            data = {"rrsets": [
                        {
                            "name": self.name,
                            "type": self.type,
                            "changetype": "REPLACE",
                            "records": [
                                {
                                    "content": content,
                                    "disabled": self.status,
                                    "name": self.name,
                                    "ttl": self.ttl,
                                    "type": self.type,
                                    "priority": 10
                                }
                            ]
                        }
                    ]
                }
        try:
            jdata = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones/%s' % domain), headers=headers, method='PATCH', data=data)
            logging.debug("dyndns data: " % data)
            return {'status': 'ok', 'msg': 'Record was updated successfully'}
        except Exception, e:
            logging.error("Cannot add record %s/%s/%s to domain %s. DETAIL: %s" % (self.name, self.type, self.data, domain, str(e)))
            return {'status': 'error', 'msg': 'There was something wrong, please contact administrator'}
Beispiel #23
0
 def update_from_master(self, domain_name):
     """
     Update records from Master DNS server
     """
     domain = Domain.query.filter(Domain.name == domain_name).first()
     if domain:
         headers = {}
         headers['X-API-Key'] = PDNS_API_KEY
         try:
             jdata = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, '/servers/localhost/zones/%s/axfr-retrieve' % domain), headers=headers, method='PUT')
             return {'status': 'ok', 'msg': 'Update from Master successfully'}
         except:
             return {'status': 'error', 'msg': 'There was something wrong, please contact administrator'}
     else:
         return {'status': 'error', 'msg': 'This domain doesnot exist'}
Beispiel #24
0
 def get_record_data(self, domain):
     """
     Query domain's DNS records via API
     """
     headers = {}
     headers['X-API-Key'] = PDNS_API_KEY
     try:
         jdata = utils.fetch_json(urlparse.urljoin(
             PDNS_STATS_URL, '/servers/localhost/zones/%s' % domain),
                                  headers=headers)
     except:
         logging.error(
             "Cannot fetch domain's record data from remote powerdns api")
         return False
     return jdata
Beispiel #25
0
 def delete(self, domain_name):
     """
     Delete a single domain name from powerdns
     """
     headers = {}
     headers['X-API-Key'] = PDNS_API_KEY
     try:
         jdata = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones/%s' % domain_name), headers=headers, method='DELETE')
         logging.info('Delete domain %s successfully' % domain_name)
         return {'status': 'ok', 'msg': 'Delete domain successfully'}
     except Exception, e:
         print traceback.format_exc()
         logging.error('Cannot delete domain %s' % domain_name)
         logging.debug(str(e))
         return {'status': 'error', 'msg': 'Cannot delete domain'}
Beispiel #26
0
 def delete(self, domain_name):
     """
     Delete a single domain name from powerdns
     """
     headers = {}
     headers['X-API-Key'] = PDNS_API_KEY
     try:
         jdata = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, '/servers/localhost/zones/%s' % domain_name), headers=headers, method='DELETE')
         logging.info('Delete domain %s successfully' % domain_name)
         return {'status': 'ok', 'msg': 'Delete domain successfully'}
     except Exception, e:
         print traceback.format_exc()
         logging.error('Cannot delete domain %s' % domain_name)
         logging.debug(str(e))
         return {'status': 'error', 'msg': 'Cannot delete domain'}
Beispiel #27
0
    def get_config(self):
        """
        Get server config
        """
        headers = {}
        headers['X-API-Key'] = PDNS_API_KEY

        try:
            jdata = utils.fetch_json(urlparse.urljoin(
                PDNS_STATS_URL, '/servers/%s/config' % self.server_id),
                                     headers=headers,
                                     method='GET')
            return jdata
        except:
            logging.error("Can not get server configuration.")
            logging.debug(traceback.format_exc())
            return []
Beispiel #28
0
 def get_domain_dnssec(self, domain_name):
     """
     Get domain DNSSEC information
     """
     domain = Domain.query.filter(Domain.name == domain_name).first()
     if domain:
         headers = {}
         headers['X-API-Key'] = PDNS_API_KEY
         try:
             jdata = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones/%s/cryptokeys' % domain.name), headers=headers, method='GET')
             if 'error' in jdata:
                 return {'status': 'error', 'msg': 'DNSSEC is not enabled for this domain'}
             else:
                 return {'status': 'ok', 'dnssec': jdata}
         except:
             return {'status': 'error', 'msg': 'There was something wrong, please contact administrator'}
     else:
         return {'status': 'error', 'msg': 'This domain doesnot exist'}
Beispiel #29
0
 def delete(self, domain_name):
     """
     Delete a single domain name from powerdns
     """
     headers = {}
     headers["X-API-Key"] = PDNS_API_KEY
     try:
         jdata = utils.fetch_json(
             urlparse.urljoin(PDNS_STATS_URL, "/servers/localhost/zones/%s" % domain_name),
             headers=headers,
             method="DELETE",
         )
         logging.info("Delete domain %s successfully" % domain_name)
         return {"status": "ok", "msg": "Delete domain successfully"}
     except Exception, e:
         print traceback.format_exc()
         logging.error("Cannot delete domain %s" % domain_name)
         logging.debug(str(e))
         return {"status": "error", "msg": "Cannot delete domain"}
Beispiel #30
0
 def update_from_master(self, domain_name):
     """
     Update records from Master DNS server
     """
     domain = Domain.query.filter(Domain.name == domain_name).first()
     if domain:
         headers = {}
         headers["X-API-Key"] = PDNS_API_KEY
         try:
             jdata = utils.fetch_json(
                 urlparse.urljoin(PDNS_STATS_URL, "/servers/localhost/zones/%s/axfr-retrieve" % domain),
                 headers=headers,
                 method="PUT",
             )
             return {"status": "ok", "msg": "Update from Master successfully"}
         except:
             return {"status": "error", "msg": "There was something wrong, please contact administrator"}
     else:
         return {"status": "error", "msg": "This domain doesnot exist"}
Beispiel #31
0
    def get_record_data(self, domain):
        """
        Query domain's DNS records via API
        """
        headers = {}
        headers['X-API-Key'] = PDNS_API_KEY
        try:
            jdata = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones/%s' % domain), headers=headers)
        except:
            logging.error("Cannot fetch domain's record data from remote powerdns api")
            return False

        if NEW_SCHEMA:
            rrsets = jdata['rrsets']
            for rrset in rrsets:
                rrset['name'] = rrset['name'].rstrip('.')
                rrset['content'] = rrset['records'][0]['content']
                rrset['disabled'] = rrset['records'][0]['disabled']
            return {'records': rrsets}

        return jdata
Beispiel #32
0
    def get_record_data(self, domain):
        """
        Query domain's DNS records via API
        """
        headers = {}
        headers['X-API-Key'] = PDNS_API_KEY
        try:
            jdata = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones/%s' % domain), headers=headers)
        except:
            logging.error("Cannot fetch domain's record data from remote powerdns api")
            return False

        if NEW_SCHEMA:
            rrsets = jdata['rrsets']
            for rrset in rrsets:
                rrset['name'] = rrset['name'].rstrip('.')
                rrset['content'] = rrset['records'][0]['content']
                rrset['disabled'] = rrset['records'][0]['disabled']
            return {'records': rrsets}

        return jdata
Beispiel #33
0
 def get_domains(self):
     """
     Get all domains which has in PowerDNS
     jdata example:
         [
           {
             "id": "example.org.",
             "url": "/servers/localhost/zones/example.org.",
             "name": "example.org",
             "kind": "Native",
             "dnssec": false,
             "account": "",
             "masters": [],
             "serial": 2015101501,
             "notified_serial": 0,
             "last_check": 0
           }
         ]
     """
     headers = {}
     headers['X-API-Key'] = PDNS_API_KEY
     jdata = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, '/servers/localhost/zones'), headers=headers)
     return jdata
Beispiel #34
0
    def apply(self, domain, post_records):
        """
        Apply record changes to domain
        """
        deleted_records, new_records = self.compare(domain, post_records)

        records = []
        for r in deleted_records:
            record = {
                "name": r['name'],
                "type": r['type'],
                "changetype": "DELETE",
                "records": []
            }
            records.append(record)
        postdata_for_delete = {"rrsets": records}

        records = []
        for r in new_records:
            record = {
                "name":
                r['name'],
                "type":
                r['type'],
                "changetype":
                "REPLACE",
                "records": [{
                    "content": r['content'],
                    "disabled": r['disabled'],
                    "name": r['name'],
                    "ttl": r['ttl'],
                    "type": r['type'],
                }]
            }
            records.append(record)
        postdata_for_new = {"rrsets": records}

        try:
            headers = {}
            headers['X-API-Key'] = PDNS_API_KEY
            jdata1 = utils.fetch_json(urlparse.urljoin(
                PDNS_STATS_URL, '/servers/localhost/zones/%s' % domain),
                                      headers=headers,
                                      method='PATCH',
                                      data=postdata_for_delete)
            #logging.debug(jdata1)

            jdata2 = utils.fetch_json(urlparse.urljoin(
                PDNS_STATS_URL, '/servers/localhost/zones/%s' % domain),
                                      headers=headers,
                                      method='PATCH',
                                      data=postdata_for_new)
            #logging.debug(jdata2)

            if 'error' in jdata2.keys():
                logging.error('Cannot apply record changes.')
                logging.debug(jdata2['error'])
                return {'status': 'error', 'msg': jdata2['error']}
            else:
                logging.info('Record was applied successfully.')
                return {
                    'status': 'ok',
                    'msg': 'Record was applied successfully'
                }
        except Exception, e:
            logging.error(
                "Cannot apply record changes to domain %s. DETAIL: %s" %
                (str(e), domain))
            return {
                'status': 'error',
                'msg':
                'There was something wrong, please contact administrator'
            }
Beispiel #35
0
    def update(self):
        """
        Fetch zones (domains) from PowerDNS and update into DB
        """
        db_domain = Domain.query.all()
        list_db_domain = [d.name for d in db_domain]

        headers = {}
        headers['X-API-Key'] = PDNS_API_KEY
        try:
            jdata = utils.fetch_json(urlparse.urljoin(
                PDNS_STATS_URL, '/servers/localhost/zones'),
                                     headers=headers)
            list_jdomain = [d['name'] for d in jdata]

            try:
                # domains should remove from db since it doesn't exist in powerdns anymore
                should_removed_db_domain = list(
                    set(list_db_domain).difference(list_jdomain))
                for d in should_removed_db_domain:
                    # revoke permission before delete domain
                    domain = Domain.query.filter(Domain.name == d).first()
                    domain_user = DomainUser.query.filter(
                        DomainUser.domain_id == domain.id)
                    if domain_user:
                        domain_user.delete()
                        db.session.commit()

                    # then remove domain
                    Domain.query.filter(Domain.name == d).delete()
                    db.session.commit()
            except:
                logging.error('Can not delete domain from DB')
                logging.debug(traceback.format_exc())
                db.session.rollback()

            # update/add new domain
            for data in jdata:
                d = Domain.query.filter(Domain.name == data['name']).first()
                if d:
                    #update exist domain
                    d.master = str(data['masters'])
                    d.type = data['kind']
                    d.serial = data['serial']
                    d.notified_serial = data['notified_serial']
                    d.last_check = data['last_check']
                else:
                    # add new domain
                    d = Domain()
                    d.name = data['name']
                    d.master = str(data['masters'])
                    d.type = data['kind']
                    d.serial = data['serial']
                    d.notified_serial = data['notified_serial']
                    d.last_check = data['last_check']
                    db.session.add(d)
                try:
                    db.session.commit()
                except:
                    db.session.rollback()
            return {
                'status': 'ok',
                'msg': 'Domain table has been updated successfully'
            }
        except Exception, e:
            logging.error('Can not update domain table.' + str(e))
            return {'status': 'error', 'msg': 'Can not update domain table'}
Beispiel #36
0
    def apply(self, domain, post_records):
        """
        Apply record changes to domain
        """
        deleted_records, new_records = self.compare(domain, post_records)

        records = []
        for r in deleted_records:
            record = {
                        "name": r['name'],
                        "type": r['type'],
                        "changetype": "DELETE",
                        "records": [
                        ]
                    }
            records.append(record)
        postdata_for_delete = {"rrsets": records}

        records = []
        for r in new_records:
            record = {
                        "name": r['name'],
                        "type": r['type'],
                        "changetype": "REPLACE",
                        "records": [
                            {
                                "content": r['content'],
                                "disabled": r['disabled'],
                                "name": r['name'],
                                "ttl": r['ttl'],
                                "type": r['type'],
                                "priority": 10, # priority field for pdns 3.4.1. https://doc.powerdns.com/md/authoritative/upgrading/
                            }
                        ]
                    }
            records.append(record)

        # Adjustment to add multiple records which described in https://github.com/ngoduykhanh/PowerDNS-Admin/issues/5#issuecomment-181637576
        final_records = []
        records = sorted(records, key = lambda item: (item["name"], item["type"]))
        for key, group in itertools.groupby(records, lambda item: (item["name"], item["type"])):
            final_records.append({
                    "name": key[0],
                    "type": key[1],
                    "changetype": "REPLACE",
                    "records": [
                        {
                            "content": item['records'][0]['content'],
                            "disabled": item['records'][0]['disabled'],
                            "name": key[0],
                            "ttl": item['records'][0]['ttl'],
                            "type": key[1],
                            "priority": 10,
                        } for item in group
                    ]
                })

        postdata_for_new = {"rrsets": final_records}

        try:
            headers = {}
            headers['X-API-Key'] = PDNS_API_KEY
            jdata1 = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, '/servers/localhost/zones/%s' % domain), headers=headers, method='PATCH', data=postdata_for_delete)
            #logging.debug(jdata1)

            jdata2 = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, '/servers/localhost/zones/%s' % domain), headers=headers, method='PATCH', data=postdata_for_new)
            #logging.debug(jdata2)

            if 'error' in jdata2.keys():
                logging.error('Cannot apply record changes.')
                logging.debug(jdata2['error'])
                return {'status': 'error', 'msg': jdata2['error']}
            else:
                logging.info('Record was applied successfully.')
                return {'status': 'ok', 'msg': 'Record was applied successfully'}
        except Exception, e:
            logging.error("Cannot apply record changes to domain %s. DETAIL: %s" % (str(e), domain))
            return {'status': 'error', 'msg': 'There was something wrong, please contact administrator'}
Beispiel #37
0
    def update(self):
        """
        Fetch zones (domains) from PowerDNS and update into DB
        """
        db_domain = Domain.query.all()
        list_db_domain = [d.name for d in db_domain]
        dict_db_domain = dict((x.name,x) for x in db_domain)

        headers = {}
        headers['X-API-Key'] = PDNS_API_KEY
        try:
            jdata = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones'), headers=headers)
            list_jdomain = [d['name'].rstrip('.') for d in jdata]
            try:
                # domains should remove from db since it doesn't exist in powerdns anymore
                should_removed_db_domain = list(set(list_db_domain).difference(list_jdomain))
                for d in should_removed_db_domain:
                    # revoke permission before delete domain
                    domain = Domain.query.filter(Domain.name==d).first()
                    domain_user = DomainUser.query.filter(DomainUser.domain_id==domain.id)
                    if domain_user:
                        domain_user.delete()
                        db.session.commit()

                    # then remove domain
                    Domain.query.filter(Domain.name == d).delete()
                    db.session.commit()
            except:
                logging.error('Can not delete domain from DB')
                logging.debug(traceback.format_exc())
                db.session.rollback()

            # update/add new domain
            for data in jdata:
                d = dict_db_domain.get(data['name'].rstrip('.'), None)
                changed = False
                if d:
                    # existing domain, only update if something actually has changed
                    if ( d.master != str(data['masters'])
                        or d.type != data['kind']
                        or d.serial != data['serial']
                        or d.notified_serial != data['notified_serial']
                        or d.last_check != ( 1 if data['last_check'] else 0 )
                        or d.dnssec != data['dnssec'] ):

                            d.master = str(data['masters'])
                            d.type = data['kind']
                            d.serial = data['serial']
                            d.notified_serial = data['notified_serial']
                            d.last_check = 1 if data['last_check'] else 0
                            d.dnssec = 1 if data['dnssec'] else 0
                            changed = True

                else:
                    # add new domain
                    d = Domain()
                    d.name = data['name'].rstrip('.')
                    d.master = str(data['masters'])
                    d.type = data['kind']
                    d.serial = data['serial']
                    d.notified_serial = data['notified_serial']
                    d.last_check = data['last_check']
                    d.dnssec = 1 if data['dnssec'] else 0
                    db.session.add(d)
                    changed = True
                if changed:
                    try:
                        db.session.commit()
                    except:
                        db.session.rollback()
            return {'status': 'ok', 'msg': 'Domain table has been updated successfully'}
        except Exception, e:
            logging.error('Can not update domain table.' + str(e))
            return {'status': 'error', 'msg': 'Can not update domain table'}
Beispiel #38
0
    def apply(self, domain, post_records):
        """
        Apply record changes to domain
        """
        deleted_records, new_records = self.compare(domain, post_records)

        records = []
        for r in deleted_records:
            record = {
                        "name": r['name'] + '.' if NEW_SCHEMA else r['name'],
                        "type": r['type'],
                        "changetype": "DELETE",
                        "records": [
                        ]
                    }
            records.append(record)

        postdata_for_delete = {"rrsets": records}

        records = []
        for r in new_records:
            if NEW_SCHEMA:
                record = {
                            "name": r['name'] + '.',
                            "type": r['type'],
                            "changetype": "REPLACE",
                            "ttl": r['ttl'],
                            "records": [
                                {
                                    "content": r['content'],
                                    "disabled": r['disabled'],
                                }
                            ]
                        }
            else:
                record = {
                            "name": r['name'],
                            "type": r['type'],
                            "changetype": "REPLACE",
                            "records": [
                                {
                                    "content": r['content'],
                                    "disabled": r['disabled'],
                                    "name": r['name'],
                                    "ttl": r['ttl'],
                                    "type": r['type'],
                                    "priority": 10, # priority field for pdns 3.4.1. https://doc.powerdns.com/md/authoritative/upgrading/
                                }
                            ]
                        }

            records.append(record)

        # Adjustment to add multiple records which described in https://github.com/ngoduykhanh/PowerDNS-Admin/issues/5#issuecomment-181637576
        final_records = []
        records = sorted(records, key = lambda item: (item["name"], item["type"], item["changetype"]))
        for key, group in itertools.groupby(records, lambda item: (item["name"], item["type"], item["changetype"])):
            if NEW_SCHEMA:
                new_record = {
                        "name": key[0],
                        "type": key[1],
                        "changetype": key[2],
                        "ttl": None,
                        "records": []
                    }
                for item in group:
                    temp_content = item['records'][0]['content']
                    temp_disabled = item['records'][0]['disabled']
                    if key[1] in ['MX', 'CNAME', 'SRV', 'NS']:
                        if temp_content.strip()[-1:] != '.':
                            temp_content += '.'

                    if new_record['ttl'] is None:
                        new_record['ttl'] = item['ttl']
                    new_record['records'].append({
                        "content": temp_content,
                        "disabled": temp_disabled
                    })
                final_records.append(new_record)
                
            else:
                
                final_records.append({
                        "name": key[0],
                        "type": key[1],
                        "changetype": key[2],
                        "records": [
                            {
                                "content": item['records'][0]['content'],
                                "disabled": item['records'][0]['disabled'],
                                "name": key[0],
                                "ttl": item['records'][0]['ttl'],
                                "type": key[1],
                                "priority": 10,
                            } for item in group
                        ]
                    })

        postdata_for_new = {"rrsets": final_records}

        try:
            headers = {}
            headers['X-API-Key'] = PDNS_API_KEY
            jdata1 = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones/%s' % domain), headers=headers, method='PATCH', data=postdata_for_delete)
            jdata2 = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones/%s' % domain), headers=headers, method='PATCH', data=postdata_for_new)

            if 'error' in jdata2.keys():
                logging.error('Cannot apply record changes.')
                logging.debug(jdata2['error'])
                return {'status': 'error', 'msg': jdata2['error']}
            else:
                logging.info('Record was applied successfully.')
                return {'status': 'ok', 'msg': 'Record was applied successfully'}
        except Exception, e:
            logging.error("Cannot apply record changes to domain %s. DETAIL: %s" % (str(e), domain))
            return {'status': 'error', 'msg': 'There was something wrong, please contact administrator'}
Beispiel #39
0
    def update(self):
        """
        Fetch zones (domains) from PowerDNS and update into DB
        """
        db_domain = Domain.query.all()
        list_db_domain = [d.name for d in db_domain]
        dict_db_domain = dict((x.name,x) for x in db_domain)

        headers = {}
        headers['X-API-Key'] = PDNS_API_KEY
        try:
            jdata = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones'), headers=headers)
            list_jdomain = [d['name'].rstrip('.') for d in jdata]
            try:
                # domains should remove from db since it doesn't exist in powerdns anymore
                should_removed_db_domain = list(set(list_db_domain).difference(list_jdomain))
                for d in should_removed_db_domain:
                    # revoke permission before delete domain
                    domain = Domain.query.filter(Domain.name==d).first()
                    domain_user = DomainUser.query.filter(DomainUser.domain_id==domain.id)
                    if domain_user:
                        domain_user.delete()
                        db.session.commit()

                    # then remove domain
                    Domain.query.filter(Domain.name == d).delete()
                    db.session.commit()
            except:
                logging.error('Can not delete domain from DB')
                logging.debug(traceback.format_exc())
                db.session.rollback()

            # update/add new domain
            for data in jdata:
                d = dict_db_domain.get(data['name'].rstrip('.'), None)
                changed = False
                if d:
                    # existing domain, only update if something actually has changed
                    if ( d.master != str(data['masters'])
                        or d.type != data['kind']
                        or d.serial != data['serial']
                        or d.notified_serial != data['notified_serial']
                        or d.last_check != ( 1 if data['last_check'] else 0 )
                        or d.dnssec != data['dnssec'] ):

                            d.master = str(data['masters'])
                            d.type = data['kind']
                            d.serial = data['serial']
                            d.notified_serial = data['notified_serial']
                            d.last_check = 1 if data['last_check'] else 0
                            d.dnssec = 1 if data['dnssec'] else 0
                            changed = True

                else:
                    # add new domain
                    d = Domain()
                    d.name = data['name'].rstrip('.')
                    d.master = str(data['masters'])
                    d.type = data['kind']
                    d.serial = data['serial']
                    d.notified_serial = data['notified_serial']
                    d.last_check = data['last_check']
                    d.dnssec = 1 if data['dnssec'] else 0
                    db.session.add(d)
                    changed = True
                if changed:
                    try:
                        db.session.commit()
                    except:
                        db.session.rollback()
            return {'status': 'ok', 'msg': 'Domain table has been updated successfully'}
        except Exception, e:
            logging.error('Can not update domain table.' + str(e))
            return {'status': 'error', 'msg': 'Can not update domain table'}
Beispiel #40
0
    def apply(self, domain, post_records):
        """
        Apply record changes to domain
        """
        records = []
        for r in post_records:
            r_name = domain if r['record_name'] in ['@', ''] else r['record_name'] + '.' + domain
            r_type = r['record_type']
            if PRETTY_IPV6_PTR: # only if activated
                if NEW_SCHEMA: # only if new schema
                    if r_type == 'PTR': # only ptr
                        if ':' in r['record_name']: # dirty ipv6 check
                            r_name = r['record_name']
            
            record = {
                        "name": r_name,
                        "type": r_type,
                        "content": r['record_data'],
                        "disabled": True if r['record_status'] == 'Disabled' else False,
                        "ttl": int(r['record_ttl']) if r['record_ttl'] else 3600,
                    }
            records.append(record)
        
        deleted_records, new_records = self.compare(domain, records)

        records = []
        for r in deleted_records:
            r_name = r['name'] + '.' if NEW_SCHEMA else r['name']
            r_type = r['type']
            if PRETTY_IPV6_PTR: # only if activated
                if NEW_SCHEMA: # only if new schema
                    if r_type == 'PTR': # only ptr
                        if ':' in r['name']: # dirty ipv6 check
                            r_name = dns.reversename.from_address(r['name']).to_text()
                            
            record = {
                        "name": r_name,
                        "type": r_type,
                        "changetype": "DELETE",
                        "records": [
                        ]
                    }
            records.append(record)

        postdata_for_delete = {"rrsets": records}

        records = []
        for r in new_records:
            if NEW_SCHEMA:
                r_name = r['name'] + '.'
                r_type = r['type']
                if PRETTY_IPV6_PTR: # only if activated
                    if r_type == 'PTR': # only ptr
                        if ':' in r['name']: # dirty ipv6 check
                            r_name = r['name']

                record = {
                            "name": r_name,
                            "type": r_type,
                            "changetype": "REPLACE",
                            "ttl": r['ttl'],
                            "records": [
                                {
                                    "content": r['content'],
                                    "disabled": r['disabled'],
                                }
                            ]
                        }
            else:
                record = {
                            "name": r['name'],
                            "type": r['type'],
                            "changetype": "REPLACE",
                            "records": [
                                {
                                    "content": r['content'],
                                    "disabled": r['disabled'],
                                    "name": r['name'],
                                    "ttl": r['ttl'],
                                    "type": r['type'],
                                    "priority": 10, # priority field for pdns 3.4.1. https://doc.powerdns.com/md/authoritative/upgrading/
                                }
                            ]
                        }

            records.append(record)

        # Adjustment to add multiple records which described in https://github.com/ngoduykhanh/PowerDNS-Admin/issues/5#issuecomment-181637576
        final_records = []
        records = sorted(records, key = lambda item: (item["name"], item["type"], item["changetype"]))
        for key, group in itertools.groupby(records, lambda item: (item["name"], item["type"], item["changetype"])):
            if NEW_SCHEMA:
                r_name = key[0]
                r_type = key[1]
                r_changetype = key[2]
                
                if PRETTY_IPV6_PTR: # only if activated
                    if r_type == 'PTR': # only ptr
                        if ':' in r_name: # dirty ipv6 check
                            r_name = dns.reversename.from_address(r_name).to_text()
                
                new_record = {
                        "name": r_name,
                        "type": r_type,
                        "changetype": r_changetype,
                        "ttl": None,
                        "records": []
                    }
                for item in group:
                    temp_content = item['records'][0]['content']
                    temp_disabled = item['records'][0]['disabled']
                    if key[1] in ['MX', 'CNAME', 'SRV', 'NS']:
                        if temp_content.strip()[-1:] != '.':
                            temp_content += '.'

                    if new_record['ttl'] is None:
                        new_record['ttl'] = item['ttl']
                    new_record['records'].append({
                        "content": temp_content,
                        "disabled": temp_disabled
                    })
                final_records.append(new_record)

            else:

                final_records.append({
                        "name": key[0],
                        "type": key[1],
                        "changetype": key[2],
                        "records": [
                            {
                                "content": item['records'][0]['content'],
                                "disabled": item['records'][0]['disabled'],
                                "name": key[0],
                                "ttl": item['records'][0]['ttl'],
                                "type": key[1],
                                "priority": 10,
                            } for item in group
                        ]
                    })

        postdata_for_new = {"rrsets": final_records}

        try:
            headers = {}
            headers['X-API-Key'] = PDNS_API_KEY
            jdata1 = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones/%s' % domain), headers=headers, method='PATCH', data=postdata_for_delete)
            jdata2 = utils.fetch_json(urlparse.urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones/%s' % domain), headers=headers, method='PATCH', data=postdata_for_new)

            if 'error' in jdata2.keys():
                logging.error('Cannot apply record changes.')
                logging.debug(jdata2['error'])
                return {'status': 'error', 'msg': jdata2['error']}
            else:
                logging.info('Record was applied successfully.')
                return {'status': 'ok', 'msg': 'Record was applied successfully'}
        except Exception, e:
            logging.error("Cannot apply record changes to domain %s. DETAIL: %s" % (str(e), domain))
            return {'status': 'error', 'msg': 'There was something wrong, please contact administrator'}