コード例 #1
0
ファイル: zone_migrate.py プロジェクト: Ziaunys/chili
def migrate_A(zone, root_domain, soa, views):
    names = []
    for (name, ttl, rdata) in zone.iterate_rdatas('A'):
        names.append((name.to_text().strip('.'), rdata))
    sorted_names = list(sorted(names, cmp=lambda n1, n2: -1 if
                               len(n1[0].split('.')) > len(n2[0].split('.')) else 1))

    for name, rdata in sorted_names:
        print str(name) + " A " + str(rdata)
        if name.startswith("unusedspace"):
            print "Skipping {0} A {1}".format(name, rdata)
            continue
        exists_domain = Domain.objects.filter(name=name)
        if exists_domain:
            label = ''
            domain = exists_domain[0]
        else:
            label = name.split('.')[0]
            domain_name = '.'.join(name.split('.')[1:])
            domain = ensure_domain(domain_name, force=True)
        a, _ = AddressRecord.objects.get_or_create(label=label,
                                                   domain=domain, ip_str=rdata.to_text(), ip_type='4')
        for view in views:
            a.views.add(view)
            a.save()
コード例 #2
0
ファイル: zone_migrate.py プロジェクト: Ziaunys/chili
def migrate_SRV(zone, root_domain, soa, views):
    for (name, ttl, rdata) in zone.iterate_rdatas('SRV'):
        target = rdata.target.to_text().strip('.')
        if target == "":
            target = "."
        port = rdata.port
        weight = rdata.weight
        prio = rdata.priority
        name = name.to_text().strip('.')
        print str(name) + " SRV " + str(rdata)
        exists_domain = Domain.objects.filter(name=name)
        if exists_domain:
            label = ''
            domain = exists_domain[0]
        else:
            label = name.split('.')[0]
            domain_name = name.split('.')[1:]
            domain = ensure_domain('.'.join(domain_name), force=True)

        if not SRV.objects.filter(label=label, domain=domain,
                                  target=target, port=port, weight=weight,
                                  priority=prio).exists():
            srv = SRV(label=label, domain=domain,
                      target=target, port=port, weight=weight,
                      priority=prio)
            srv.full_clean()
            srv.save()
            for view in views:
                srv.views.add(view)
                srv.save()
コード例 #3
0
def _create_ipv4_intr_from_range(label, domain_name, system, mac, range_start,
                                 range_end):
    if range_start >= range_end - 1:
        errors['ip'] = ErrorList(["The start ip must be less than end ip."])
        return None, errors

    ip = find_free_ip(range_start, range_end, ip_type='4')
    errors = ErrorDict()
    if not ip:
        errors['ip'] = ErrorList([
            "Could not find free ip in range {0} - "
            "{1}".format(range_start, range_end)
        ])
        return None, errors

    domain = ensure_domain(domain_name, inherit_soa=True)
    try:
        intr = StaticInterface(label=label,
                               domain=domain,
                               ip_str=str(ip),
                               ip_type='4',
                               system=system,
                               mac=mac)
        intr.clean()
    except ValidationError, e:
        errors['interface'] = ErrorList(e.messages)
コード例 #4
0
ファイル: zone_migrate.py プロジェクト: Ziaunys/chili
def migrate_AAAA(zone, root_domain, soa, views):
    for (name, ttl, rdata) in zone.iterate_rdatas('AAAA'):
        name = name.to_text().strip('.')
        print str(name) + " AAAA " + str(rdata)
        exists_domain = Domain.objects.filter(name=name)
        if exists_domain:
            label = ''
            domain = exists_domain[0]
        else:
            label = name.split('.')[0]
            if label.startswith('unused'):
                continue
            domain_name = '.'.join(name.split('.')[1:])
            domain = ensure_domain(domain_name, force=True)

        ip_upper, ip_lower = ipv6_to_longs(rdata.to_text())
        if AddressRecord.objects.filter(label=label,
                                        domain=domain, ip_upper=ip_upper, ip_lower=ip_lower,
                                        ip_type='6').exists():
            a = AddressRecord.objects.get(label=label,
                                          domain=domain, ip_type='6', ip_upper=ip_upper,
                                          ip_lower=ip_lower)
        else:
            a = AddressRecord(label=label, domain=domain,
                              ip_str=rdata.to_text(), ip_type='6')
            a.clean()
            a.save()
        for view in views:
            a.views.add(view)
            a.save()
コード例 #5
0
ファイル: dns_migrate.py プロジェクト: ngokevin/chili
    def gen_domain(self):
        """Generates a Domain object for this Zone from a hostname.

        :uniqueness: domain
        """
        if not (self.dname in BAD_DNAMES or "in-addr.arpa" in self.dname):
            return ensure_domain(name=self.dname, force=True)
コード例 #6
0
ファイル: zone_migrate.py プロジェクト: jirwin/cyder
def migrate_A(zone, root_domain, soa, views):
    names = []
    for (name, ttl, rdata) in zone.iterate_rdatas('A'):
        names.append((name.to_text().strip('.'), rdata))
    sorted_names = list(
        sorted(names,
               cmp=lambda n1, n2: -1
               if len(n1[0].split('.')) > len(n2[0].split('.')) else 1))

    for name, rdata in sorted_names:
        print str(name) + " A " + str(rdata)
        if name.startswith("unusedspace"):
            print "Skipping {0} A {1}".format(name, rdata)
            continue
        exists_domain = Domain.objects.filter(name=name)
        if exists_domain:
            label = ''
            domain = exists_domain[0]
        else:
            label = name.split('.')[0]
            domain_name = '.'.join(name.split('.')[1:])
            domain = ensure_domain(domain_name, force=True)
        a, _ = AddressRecord.objects.get_or_create(label=label,
                                                   domain=domain,
                                                   ip_str=rdata.to_text(),
                                                   ip_type='4')
        for view in views:
            a.views.add(view)
            a.save()
コード例 #7
0
ファイル: dns_migrate.py プロジェクト: jirwin/cyder
    def gen_domain(self):
        """Generates a Domain object for this Zone from a hostname.

        :uniqueness: domain
        """
        if not (self.dname in BAD_DNAMES or 'in-addr.arpa' in self.dname):
            return ensure_domain(name=self.dname, force=True)
コード例 #8
0
ファイル: zone_migrate.py プロジェクト: jirwin/cyder
def migrate_NS(zone, root_domain, soa, views):
    for (name, ttl, rdata) in zone.iterate_rdatas('NS'):
        name = name.to_text().strip('.')
        print str(name) + " NS " + str(rdata)
        domain_name = '.'.join(name.split('.')[1:])
        domain = ensure_domain(name, force=True)
        ns, _ = Nameserver.objects.get_or_create(
            domain=domain, server=rdata.target.to_text().strip('.'))
        for view in views:
            ns.views.add(view)
            ns.save()
コード例 #9
0
ファイル: zone_migrate.py プロジェクト: Ziaunys/chili
def migrate_NS(zone, root_domain, soa, views):
    for (name, ttl, rdata) in zone.iterate_rdatas('NS'):
        name = name.to_text().strip('.')
        print str(name) + " NS " + str(rdata)
        domain_name = '.'.join(name.split('.')[1:])
        domain = ensure_domain(name, force=True)
        ns, _ = Nameserver.objects.get_or_create(domain=domain,
                                                 server=rdata.target.to_text().strip('.'))
        for view in views:
            ns.views.add(view)
            ns.save()
コード例 #10
0
ファイル: dns_migrate.py プロジェクト: church29/cyder
    def gen_domain(self):
        """Generates a Domain object for this Zone from a hostname.

        :uniqueness: domain
        """
        if not (self.dname in BAD_DNAMES):
            try:
                domain = ensure_domain(name=self.dname, force=True,
                                       update_range_usage=False)
                domain.clean()
                domain.save()
                return domain
            except ValidationError, e:
                print "Could not migrate domain %s: %s" % (self.dname, e)
                return None
コード例 #11
0
ファイル: test_full_name.py プロジェクト: murrown/cyder
    def test_basic_add_remove9(self):
        # Make sure all record types block.
        Domain.objects.create(name='foo22')
        f_c = create_zone('foo.foo22')
        self.assertFalse(f_c.purgeable)

        fqdn = "y.z.foo.foo22"
        label, the_domain = ensure_label_domain(fqdn)
        self.ctnr.domains.add(the_domain)
        addr = AddressRecord.objects.create(
            label=label, ctnr=self.ctnr, domain=the_domain, ip_type='4',
            ip_str="10.2.3.4")
        self.assertFalse(prune_tree(the_domain))

        new_domain = ensure_domain('y.z.foo.foo22')
        self.assertFalse(new_domain.purgeable)
コード例 #12
0
ファイル: test_full_name.py プロジェクト: OSU-Net/cyder
    def test_basic_add_remove9(self):
        # Make sure all record types block.
        Domain.objects.create(name='foo22')
        f_c = create_zone('foo.foo22')
        self.assertFalse(f_c.purgeable)

        fqdn = "y.z.foo.foo22"
        label, the_domain = ensure_label_domain(fqdn)
        self.ctnr.domains.add(the_domain)
        addr = AddressRecord.objects.create(
            label=label, ctnr=self.ctnr, domain=the_domain, ip_type='4',
            ip_str="10.2.3.4")
        self.assertFalse(prune_tree(the_domain))

        new_domain = ensure_domain('y.z.foo.foo22')
        self.assertFalse(new_domain.purgeable)
コード例 #13
0
ファイル: zone_migrate.py プロジェクト: Ziaunys/chili
def populate_forward_dns(zone, root_domain_name, views):
    soa = migrate_soa(zone, root_domain_name)
    root_domain = ensure_domain(root_domain_name, force=True)
    migrate_A(zone, root_domain, soa, views)
    migrate_AAAA(zone, root_domain, soa, views)
    migrate_CNAME(zone, root_domain, soa, views)
    migrate_NS(zone, root_domain, soa, views)
    migrate_MX(zone, root_domain, soa, views)
    migrate_TXT(zone, root_domain, soa, views)
    migrate_SRV(zone, root_domain, soa, views)
    if root_domain.soa == soa:
        clobber_soa = None
    else:
        clobber_soa = root_domain.soa
    null_zone_tree(root_domain, clobber_soa)
    color_zone_tree(root_domain, clobber_soa, soa)
コード例 #14
0
ファイル: zone_migrate.py プロジェクト: jirwin/cyder
def populate_forward_dns(zone, root_domain_name, views):
    soa = migrate_soa(zone, root_domain_name)
    root_domain = ensure_domain(root_domain_name, force=True)
    migrate_A(zone, root_domain, soa, views)
    migrate_AAAA(zone, root_domain, soa, views)
    migrate_CNAME(zone, root_domain, soa, views)
    migrate_NS(zone, root_domain, soa, views)
    migrate_MX(zone, root_domain, soa, views)
    migrate_TXT(zone, root_domain, soa, views)
    migrate_SRV(zone, root_domain, soa, views)
    if root_domain.soa == soa:
        clobber_soa = None
    else:
        clobber_soa = root_domain.soa
    null_zone_tree(root_domain, clobber_soa)
    color_zone_tree(root_domain, clobber_soa, soa)
コード例 #15
0
    def gen_domain(self):
        """Generates a Domain object for this Zone from a hostname.

        :uniqueness: domain
        """
        if not (self.dname in BAD_DNAMES):
            try:
                domain = ensure_domain(name=self.dname,
                                       force=True,
                                       update_range_usage=False)
                domain.clean()
                domain.save()
                return domain
            except ValidationError, e:
                print "Could not migrate domain %s: %s" % (self.dname, e)
                return None
コード例 #16
0
ファイル: zone_migrate.py プロジェクト: Ziaunys/chili
def populate_reverse_dns(zone, name_reversed, root_domain_name, views):
    ensure_domain("arpa", force=True)
    ensure_domain("in-addr.arpa", force=True)
    ensure_domain("ipv6.arpa", force=True)
    soa = migrate_soa(zone, root_domain_name)
    root_domain = ensure_domain(root_domain_name, force=True)
    migrate_NS(zone, root_domain, soa, views)
    migrate_MX(zone, root_domain, soa, views)
    migrate_PTR(zone, root_domain, soa, views)
    if root_domain.soa == soa:
        clobber_soa = None
    else:
        clobber_soa = root_domain.soa
    null_zone_tree(root_domain, clobber_soa)
    color_zone_tree(root_domain, root_domain.soa, soa)
コード例 #17
0
ファイル: zone_migrate.py プロジェクト: jirwin/cyder
def populate_reverse_dns(zone, name_reversed, root_domain_name, views):
    ensure_domain("arpa", force=True)
    ensure_domain("in-addr.arpa", force=True)
    ensure_domain("ipv6.arpa", force=True)
    soa = migrate_soa(zone, root_domain_name)
    root_domain = ensure_domain(root_domain_name, force=True)
    migrate_NS(zone, root_domain, soa, views)
    migrate_MX(zone, root_domain, soa, views)
    migrate_PTR(zone, root_domain, soa, views)
    if root_domain.soa == soa:
        clobber_soa = None
    else:
        clobber_soa = root_domain.soa
    null_zone_tree(root_domain, clobber_soa)
    color_zone_tree(root_domain, root_domain.soa, soa)
コード例 #18
0
ファイル: zone_migrate.py プロジェクト: Ziaunys/chili
def migrate_MX(zone, root_domain, soa, views):
    for (name, ttl, rdata) in zone.iterate_rdatas('MX'):
        name = name.to_text().strip('.')
        print str(name) + " MX " + str(rdata)
        exists_domain = Domain.objects.filter(name=name)
        if exists_domain:
            label = ''
            domain = exists_domain[0]
        else:
            label = name.split('.')[0]
            domain_name = '.'.join(name.split('.')[1:])
            domain = ensure_domain(domain_name, force=True)
        priority = rdata.preference
        server = rdata.exchange.to_text().strip('.')
        mx, _ = MX.objects.get_or_create(label=label, domain=domain,
                                         server=server, priority=priority, ttl="3600")
        for view in views:
            mx.views.add(view)
            mx.save()
コード例 #19
0
ファイル: utils.py プロジェクト: Ziaunys/chili
def _create_ipv4_intr_from_range(label, domain_name, system, mac, range_start,
                                 range_end):
    if range_start >= range_end - 1:
        errors['ip'] = ErrorList(["The start ip must be less than end ip."])
        return None, errors

    ip = find_free_ip(range_start, range_end, ip_type='4')
    errors = ErrorDict()
    if not ip:
        errors['ip'] = ErrorList(["Could not find free ip in range {0} - "
                                  "{1}".format(range_start, range_end)])
        return None, errors

    domain = ensure_domain(domain_name, inherit_soa=True)
    try:
        intr = StaticInterface(label=label, domain=domain, ip_str=str(ip),
                               ip_type='4', system=system, mac=mac)
        intr.clean()
    except ValidationError, e:
        errors['interface'] = ErrorList(e.messages)
コード例 #20
0
ファイル: zone_migrate.py プロジェクト: Ziaunys/chili
def migrate_CNAME(zone, root_domain, soa, views):
    for (name, ttl, rdata) in zone.iterate_rdatas('CNAME'):
        name = name.to_text().strip('.')
        print str(name) + " CNAME " + str(rdata)
        exists_domain = Domain.objects.filter(name=name)
        if exists_domain:
            label = ''
            domain = exists_domain[0]
        else:
            label = name.split('.')[0]
            domain_name = name.split('.')[1:]
            domain = ensure_domain('.'.join(domain_name), force=True)
        data = rdata.target.to_text().strip('.')

        if not CNAME.objects.filter(label=label, domain=domain,
                                    target=data).exists():
            cn = CNAME(label=label, domain=domain, target=data)
            cn.full_clean()
            cn.save()
            for view in views:
                cn.views.add(view)
                cn.save()
コード例 #21
0
ファイル: zone_migrate.py プロジェクト: jirwin/cyder
def migrate_CNAME(zone, root_domain, soa, views):
    for (name, ttl, rdata) in zone.iterate_rdatas('CNAME'):
        name = name.to_text().strip('.')
        print str(name) + " CNAME " + str(rdata)
        exists_domain = Domain.objects.filter(name=name)
        if exists_domain:
            label = ''
            domain = exists_domain[0]
        else:
            label = name.split('.')[0]
            domain_name = name.split('.')[1:]
            domain = ensure_domain('.'.join(domain_name), force=True)
        data = rdata.target.to_text().strip('.')

        if not CNAME.objects.filter(label=label, domain=domain,
                                    target=data).exists():
            cn = CNAME(label=label, domain=domain, target=data)
            cn.full_clean()
            cn.save()
            for view in views:
                cn.views.add(view)
                cn.save()
コード例 #22
0
ファイル: zone_migrate.py プロジェクト: jirwin/cyder
def migrate_MX(zone, root_domain, soa, views):
    for (name, ttl, rdata) in zone.iterate_rdatas('MX'):
        name = name.to_text().strip('.')
        print str(name) + " MX " + str(rdata)
        exists_domain = Domain.objects.filter(name=name)
        if exists_domain:
            label = ''
            domain = exists_domain[0]
        else:
            label = name.split('.')[0]
            domain_name = '.'.join(name.split('.')[1:])
            domain = ensure_domain(domain_name, force=True)
        priority = rdata.preference
        server = rdata.exchange.to_text().strip('.')
        mx, _ = MX.objects.get_or_create(label=label,
                                         domain=domain,
                                         server=server,
                                         priority=priority,
                                         ttl="3600")
        for view in views:
            mx.views.add(view)
            mx.save()
コード例 #23
0
ファイル: zone_migrate.py プロジェクト: Ziaunys/chili
def migrate_TXT(zone, root_domain, soa, views):
    for (name, ttl, rdata) in zone.iterate_rdatas('TXT'):
        name = name.to_text().strip('.')
        print str(name) + " TXT " + str(rdata)
        exists_domain = Domain.objects.filter(name=name)
        if exists_domain:
            label = ''
            domain = exists_domain[0]
        else:
            label = name.split('.')[0]
            domain_name = name.split('.')[1:]
            domain = ensure_domain('.'.join(domain_name), force=True)
        data = rdata.to_text().strip('"')

        if not TXT.objects.filter(label=label, domain=domain,
                                  txt_data=data).exists():
            txt = TXT(label=label, domain=domain, txt_data=data)
            txt.full_clean()
            txt.save()
            for view in views:
                txt.views.add(view)
                txt.save()
コード例 #24
0
ファイル: zone_migrate.py プロジェクト: jirwin/cyder
def migrate_TXT(zone, root_domain, soa, views):
    for (name, ttl, rdata) in zone.iterate_rdatas('TXT'):
        name = name.to_text().strip('.')
        print str(name) + " TXT " + str(rdata)
        exists_domain = Domain.objects.filter(name=name)
        if exists_domain:
            label = ''
            domain = exists_domain[0]
        else:
            label = name.split('.')[0]
            domain_name = name.split('.')[1:]
            domain = ensure_domain('.'.join(domain_name), force=True)
        data = rdata.to_text().strip('"')

        if not TXT.objects.filter(label=label, domain=domain,
                                  txt_data=data).exists():
            txt = TXT(label=label, domain=domain, txt_data=data)
            txt.full_clean()
            txt.save()
            for view in views:
                txt.views.add(view)
                txt.save()
コード例 #25
0
ファイル: zone_migrate.py プロジェクト: jirwin/cyder
def migrate_AAAA(zone, root_domain, soa, views):
    for (name, ttl, rdata) in zone.iterate_rdatas('AAAA'):
        name = name.to_text().strip('.')
        print str(name) + " AAAA " + str(rdata)
        exists_domain = Domain.objects.filter(name=name)
        if exists_domain:
            label = ''
            domain = exists_domain[0]
        else:
            label = name.split('.')[0]
            if label.startswith('unused'):
                continue
            domain_name = '.'.join(name.split('.')[1:])
            domain = ensure_domain(domain_name, force=True)

        ip_upper, ip_lower = ipv6_to_longs(rdata.to_text())
        if AddressRecord.objects.filter(label=label,
                                        domain=domain,
                                        ip_upper=ip_upper,
                                        ip_lower=ip_lower,
                                        ip_type='6').exists():
            a = AddressRecord.objects.get(label=label,
                                          domain=domain,
                                          ip_type='6',
                                          ip_upper=ip_upper,
                                          ip_lower=ip_lower)
        else:
            a = AddressRecord(label=label,
                              domain=domain,
                              ip_str=rdata.to_text(),
                              ip_type='6')
            a.clean()
            a.save()
        for view in views:
            a.views.add(view)
            a.save()
コード例 #26
0
ファイル: zone_migrate.py プロジェクト: jirwin/cyder
def migrate_SRV(zone, root_domain, soa, views):
    for (name, ttl, rdata) in zone.iterate_rdatas('SRV'):
        target = rdata.target.to_text().strip('.')
        if target == "":
            target = "."
        port = rdata.port
        weight = rdata.weight
        prio = rdata.priority
        name = name.to_text().strip('.')
        print str(name) + " SRV " + str(rdata)
        exists_domain = Domain.objects.filter(name=name)
        if exists_domain:
            label = ''
            domain = exists_domain[0]
        else:
            label = name.split('.')[0]
            domain_name = name.split('.')[1:]
            domain = ensure_domain('.'.join(domain_name), force=True)

        if not SRV.objects.filter(label=label,
                                  domain=domain,
                                  target=target,
                                  port=port,
                                  weight=weight,
                                  priority=prio).exists():
            srv = SRV(label=label,
                      domain=domain,
                      target=target,
                      port=port,
                      weight=weight,
                      priority=prio)
            srv.full_clean()
            srv.save()
            for view in views:
                srv.views.add(view)
                srv.save()
コード例 #27
0
def create_zone_ajax(request):
    """
    This view tries to create a new zone and returns an JSON with either
    'success' = True or 'success' = False and some errors. By default all
    records are created and added to the public view.

    Throughout this function note that objects that are created are recorded,
    and if an error is caught, the previously created objects are deleted. This
    backing-out *may* be better handling by a transaction. Django has this sort
    of thing (middleware and decorators), but I'm in a time crunch so this
    manual deletetion will have to do.
    """

    qd = request.POST.copy()
    # See if the domain exists.
    # Fail if it already exists or if it's under a delegated domain.
    root_domain = qd.get('root_domain', None)

    if not root_domain:
        error = "Please specify a root_domain"
        return HttpResponse(json.dumps({'success': False, 'error': error}))

    if Domain.objects.filter(name=root_domain).exists():
        error = gt("<b>{0}</b> is already a domain. To make it a new zone, "
                   "assign it a newly created SOA.".format(root_domain))
        return HttpResponse(json.dumps({'success': False, 'error': error}))

    primary = qd.get('soa_primary', None)
    if not primary:
        error = "Please specify a primary nameserver for the SOA record."
        return HttpResponse(json.dumps({'success': False, 'error': error}))
    contact = qd.get('soa_contact', None)
    if not contact:
        error = "Please specify a contact address for the SOA record."
        return HttpResponse(json.dumps({'success': False, 'error': error}))
    contact.replace('@', '.')

    # Find all the NS entries
    nss = []
    for k, v in request.POST.iteritems():
        if k.startswith('nameserver_'):
            ttl = qd.get('ttl_{0}'.format(k[-1:]), 3600)
            server = v
            nss.append(Nameserver(server=server, ttl=ttl))

    if not nss:
        # They must create at least one nameserver
        error = gt("You must choose an authoritative nameserver to serve this "
                   "zone")
        return HttpResponse(json.dumps({'success': False, 'error': error}))

    # We want all domains created up to this point to inherit their
    # master_domain's soa. We will override the return domain's SOA.
    # Everything under this domain can be purgeable becase we will set this
    # domain to non-purgeable. This will also allow us to call prune tree.
    domain = ensure_domain(root_domain,
                           purgeable=True,
                           inherit_soa=False,
                           force=True)

    soa = SOA(primary=primary,
              contact=contact,
              serial=int(time.time()),
              description="SOA for {0}".format(root_domain))
    try:
        soa.save()
    except ValidationError, e:
        _clean_domain_tree(domain)
        return HttpResponse(
            json.dumps({
                'success': False,
                'error': e.messages[0]
            }))
コード例 #28
0
ファイル: helpers.py プロジェクト: alecdhuse/cyder
def create_zone_ajax(request):
    """This view tries to create a new zone and returns an JSON with either
    'success' = True or 'success' = False and some errors. By default all
    records are created and added to the public view.

    Throughout this function note that objects that are created are recorded,
    and if an error is caught, the previously created objects are deleted. This
    backing-out *may* be better handling by a transaction. Django has this sort
    of thing (middleware and decorators), but I'm in a time crunch so this
    manual deletetion will have to do.
    """

    qd = request.POST.copy()
    # See if the domain exists.
    # Fail if it already exists or if it's under a delegated domain.
    root_domain = qd.get('root_domain', None)

    if not root_domain:
        error = "Please specify a root_domain"
        return HttpResponse(json.dumps({'success': False, 'error': error}))

    if Domain.objects.filter(name=root_domain).exists():
        error = gt("<b>{0}</b> is already a domain. To make it a new zone, "
                   "assign it a newly created SOA.".format(root_domain))
        return HttpResponse(json.dumps({'success': False, 'error': error}))

    primary = qd.get('soa_primary', None)
    if not primary:
        error = "Please specify a primary nameserver for the SOA record."
        return HttpResponse(json.dumps({'success': False, 'error': error}))
    contact = qd.get('soa_contact', None)
    if not contact:
        error = "Please specify a contact address for the SOA record."
        return HttpResponse(json.dumps({'success': False, 'error': error}))
    contact.replace('@', '.')

    # Find all the NS entries
    nss = []
    for k, v in request.POST.iteritems():
        if k.startswith('nameserver_'):
            ttl = qd.get('ttl_{0}'.format(k[-1:]), 3600)
            server = v
            nss.append(Nameserver(server=server, ttl=ttl))

    if not nss:
        # They must create at least one nameserver
        error = gt("You must choose an authoritative nameserver to serve this "
                   "zone")
        return HttpResponse(json.dumps({'success': False, 'error': error}))

    # We want all domains created up to this point to inherit their
    # master_domain's soa. We will override the return domain's SOA.
    # Everything under this domain can be purgeable becase we will set this
    # domain to non-purgeable. This will also allow us to call prune tree.
    domain = ensure_domain(root_domain, purgeable=True,
                           inherit_soa=False, force=True)

    soa = SOA(primary=primary, contact=contact, serial=int(time.time()),
              description="SOA for {0}".format(root_domain))
    try:
        soa.save()
    except ValidationError, e:
        _clean_domain_tree(domain)
        return HttpResponse(json.dumps({'success': False,
                                        'error': e.messages[0]}))