sync-from-pdns.py 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. from django.core.management import BaseCommand, CommandError
  2. from django.db import transaction
  3. from desecapi import pdns
  4. from desecapi.models import Domain, RRset, RR, RR_SET_TYPES_AUTOMATIC
  5. class Command(BaseCommand):
  6. help = "Import authoritative data from pdns, making the local database consistent with pdns."
  7. def add_arguments(self, parser):
  8. parser.add_argument(
  9. "domain-name",
  10. nargs="*",
  11. help="Domain name to import. If omitted, will import all domains that are known locally.",
  12. )
  13. def handle(self, *args, **options):
  14. domains = Domain.objects.all()
  15. if options["domain-name"]:
  16. domains = domains.filter(name__in=options["domain-name"])
  17. domain_names = domains.values_list("name", flat=True)
  18. for domain_name in options["domain-name"]:
  19. if domain_name not in domain_names:
  20. raise CommandError("{} is not a known domain".format(domain_name))
  21. for domain in domains:
  22. self.stdout.write("%s ..." % domain.name, ending="")
  23. try:
  24. self._sync_domain(domain)
  25. self.stdout.write(" synced")
  26. except Exception as e:
  27. self.stdout.write(" failed")
  28. msg = "Error while processing {}: {}".format(domain.name, e)
  29. raise CommandError(msg)
  30. @staticmethod
  31. @transaction.atomic
  32. def _sync_domain(domain):
  33. domain.rrset_set.all().delete()
  34. rrsets = []
  35. rrs = []
  36. for rrset_data in pdns.get_rrset_datas(domain):
  37. if rrset_data["type"] in RR_SET_TYPES_AUTOMATIC:
  38. continue
  39. records = rrset_data.pop("records")
  40. rrset = RRset(**rrset_data)
  41. rrsets.append(rrset)
  42. rrs.extend([RR(rrset=rrset, content=record) for record in records])
  43. RRset.objects.bulk_create(rrsets)
  44. RR.objects.bulk_create(rrs)