sync-from-pdns.py 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  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('domain-name', nargs='*',
  9. help='Domain name to import. If omitted, will import all domains that are known locally.')
  10. def handle(self, *args, **options):
  11. domains = Domain.objects.all()
  12. if options['domain-name']:
  13. domains = domains.filter(name__in=options['domain-name'])
  14. domain_names = domains.values_list('name', flat=True)
  15. for domain_name in options['domain-name']:
  16. if domain_name not in domain_names:
  17. raise CommandError('{} is not a known domain'.format(domain_name))
  18. for domain in domains:
  19. self.stdout.write('%s ...' % domain.name, ending='')
  20. try:
  21. self._sync_domain(domain)
  22. self.stdout.write(' synced')
  23. except Exception as e:
  24. self.stdout.write(' failed')
  25. msg = 'Error while processing {}: {}'.format(domain.name, e)
  26. raise CommandError(msg)
  27. @staticmethod
  28. @transaction.atomic
  29. def _sync_domain(domain):
  30. domain.rrset_set.all().delete()
  31. rrsets = []
  32. rrs = []
  33. for rrset_data in pdns.get_rrset_datas(domain):
  34. if rrset_data['type'] in RR_SET_TYPES_AUTOMATIC:
  35. continue
  36. records = rrset_data.pop('records')
  37. rrset = RRset(**rrset_data)
  38. rrsets.append(rrset)
  39. rrs.extend([RR(rrset=rrset, content=record) for record in records])
  40. RRset.objects.bulk_create(rrsets)
  41. RR.objects.bulk_create(rrs)