Пример #1
0
    def render(self, session, service, protocol, dns_domain, target,
               dns_environment, **kwargs):
        name = "_%s._%s" % (service.strip().lower(), protocol.strip().lower())
        dbfqdn = Fqdn.get_unique(session, name=name, dns_domain=dns_domain,
                                 dns_environment=dns_environment)
        if target:
            dbtarget = Fqdn.get_unique(session, target, compel=True)
        else:
            dbtarget = None

        rrs = []
        if dbfqdn:
            for rr in dbfqdn.dns_records:
                if not isinstance(rr, SrvRecord):  # pragma: no cover
                    # This case can't happen right now. Maybe one day if we
                    # add support for DNSSEC...
                    continue
                if dbtarget and rr.target != dbtarget:
                    continue
                rrs.append(rr)

        if not rrs:
            if dbtarget:
                msg = ", with target %s" % dbtarget.fqdn
            else:
                msg = ""
            raise NotFoundException("%s for service %s, protocol %s in DNS "
                                    "domain %s%s not found." %
                                    (SrvRecord._get_class_label(), service,
                                     protocol, dns_domain, msg))

        map(delete_dns_record, rrs)
        session.flush()

        return
Пример #2
0
def rename_hardware(session, dbhw_ent, rename_to):
    if "." in rename_to:
        if not dbhw_ent.primary_name:
            raise ArgumentError(
                "{0} does not have a primary name, renaming "
                "using an FQDN is not possible.".format(dbhw_ent))
        old_domain = dbhw_ent.primary_name.fqdn.dns_domain
        dns_env = dbhw_ent.primary_name.fqdn.dns_environment
        new_label, new_domain = parse_fqdn(session, rename_to)
    else:
        new_label = rename_to
        if dbhw_ent.primary_name:
            old_domain = new_domain = dbhw_ent.primary_name.fqdn.dns_domain
            dns_env = dbhw_ent.primary_name.fqdn.dns_environment
        else:
            new_domain = None
            dns_env = None

    old_domain.lock_row()
    if new_domain != old_domain:
        new_domain.lock_row()

    dbhw_ent.check_label(new_label)
    HardwareEntity.get_unique(session, new_label, preclude=True)

    old_label = dbhw_ent.label

    fqdns = []
    for addr in dbhw_ent.all_addresses():
        fqdns.extend([dns_rec.fqdn for dns_rec in addr.dns_records])
    # This case handles reserved names
    if dbhw_ent.primary_name and dbhw_ent.primary_name.fqdn not in fqdns:
        fqdns.append(dbhw_ent.primary_name.fqdn)

    # Filter out unrelated FQDNs
    fqdns = [
        fqdn for fqdn in fqdns if fqdn.dns_domain == old_domain and (
            fqdn.name == old_label or fqdn.name.startswith(old_label + "-"))
    ]

    # Update all state in one go, so disable autoflush for now.
    with session.no_autoflush:
        dbhw_ent.label = new_label

        for dbfqdn in fqdns:
            new_name = new_label + dbfqdn.name[len(old_label):]
            Fqdn.get_unique(session,
                            name=new_name,
                            dns_domain=new_domain,
                            dns_environment=dns_env,
                            preclude=True)
            dbfqdn.dns_domain = new_domain
            dbfqdn.name = new_name
Пример #3
0
def rename_hardware(session, dbhw_ent, rename_to):
    if "." in rename_to:
        if not dbhw_ent.primary_name:
            raise ArgumentError("{0} does not have a primary name, renaming "
                                "using an FQDN is not possible."
                                .format(dbhw_ent))
        old_domain = dbhw_ent.primary_name.fqdn.dns_domain
        dns_env = dbhw_ent.primary_name.fqdn.dns_environment
        new_label, new_domain = parse_fqdn(session, rename_to)
    else:
        new_label = rename_to
        if dbhw_ent.primary_name:
            old_domain = new_domain = dbhw_ent.primary_name.fqdn.dns_domain
            dns_env = dbhw_ent.primary_name.fqdn.dns_environment
        else:
            new_domain = None
            dns_env = None

    old_domain.lock_row()
    if new_domain != old_domain:
        new_domain.lock_row()

    dbhw_ent.check_label(new_label)
    HardwareEntity.get_unique(session, new_label, preclude=True)

    old_label = dbhw_ent.label

    fqdns = []
    for addr in dbhw_ent.all_addresses():
        fqdns.extend([dns_rec.fqdn for dns_rec in addr.dns_records])
    # This case handles reserved names
    if dbhw_ent.primary_name and dbhw_ent.primary_name.fqdn not in fqdns:
        fqdns.append(dbhw_ent.primary_name.fqdn)

    # Filter out unrelated FQDNs
    fqdns = [fqdn for fqdn in fqdns if fqdn.dns_domain == old_domain and
             (fqdn.name == old_label or fqdn.name.startswith(old_label + "-"))]

    # Update all state in one go, so disable autoflush for now.
    with session.no_autoflush:
        dbhw_ent.label = new_label

        for dbfqdn in fqdns:
            new_name = new_label + dbfqdn.name[len(old_label):]
            Fqdn.get_unique(session, name=new_name, dns_domain=new_domain,
                            dns_environment=dns_env, preclude=True)
            dbfqdn.dns_domain = new_domain
            dbfqdn.name = new_name
Пример #4
0
    def render(self, session, service, protocol, dns_domain, priority, weight,
               target, port, dns_environment, comments, **kwargs):
        dbdns_env = DnsEnvironment.get_unique_or_default(session,
                                                         dns_environment)
        dbdns_domain = DnsDomain.get_unique(session, dns_domain, compel=True)
        if dbdns_domain.restricted:
            raise ArgumentError("{0} is restricted, SRV records are not allowed."
                                .format(dbdns_domain))

        # TODO: we could try looking up the port based on the service, but there
        # are some caveats:
        # - the protocol name used in SRV record may not match the name used in
        #   /etc/services
        # - socket.getservent() may return bogus information (like it does for
        #   e.g. 'kerberos')

        service = service.strip().lower()
        target = target.strip().lower()

        dbtarget = Fqdn.get_unique(session, target, compel=True)
        dbsrv_rec = SrvRecord(service=service, protocol=protocol,
                              priority=priority, weight=weight, target=dbtarget,
                              port=port, dns_domain=dbdns_domain,
                              dns_environment=dbdns_env, comments=comments)
        session.add(dbsrv_rec)

        session.flush()

        return
Пример #5
0
    def render(self, session, service, protocol, dns_domain, priority, weight,
               target, port, dns_environment, comments, **kwargs):
        dbdns_env = DnsEnvironment.get_unique_or_default(
            session, dns_environment)
        dbdns_domain = DnsDomain.get_unique(session, dns_domain, compel=True)
        if dbdns_domain.restricted:
            raise ArgumentError(
                "{0} is restricted, SRV records are not allowed.".format(
                    dbdns_domain))

        # TODO: we could try looking up the port based on the service, but there
        # are some caveats:
        # - the protocol name used in SRV record may not match the name used in
        #   /etc/services
        # - socket.getservent() may return bogus information (like it does for
        #   e.g. 'kerberos')

        service = service.strip().lower()
        target = target.strip().lower()

        dbtarget = Fqdn.get_unique(session, target, compel=True)
        dbsrv_rec = SrvRecord(service=service,
                              protocol=protocol,
                              priority=priority,
                              weight=weight,
                              target=dbtarget,
                              port=port,
                              dns_domain=dbdns_domain,
                              dns_environment=dbdns_env,
                              comments=comments)
        session.add(dbsrv_rec)

        session.flush()

        return
Пример #6
0
def rename_interface(session, dbinterface, rename_to):
    rename_to = rename_to.strip().lower()

    dbhw_ent = dbinterface.hardware_entity
    for iface in dbhw_ent.interfaces:
        if iface.name == rename_to:
            raise ArgumentError(
                "{0} already has an interface named {1}.".format(
                    dbhw_ent, rename_to))

    fqdn_changes = []

    if dbhw_ent.primary_name:
        primary_fqdn = dbhw_ent.primary_name.fqdn
        short = primary_fqdn.name
        dbdns_domain = primary_fqdn.dns_domain
        dbdns_env = primary_fqdn.dns_environment

        dbdns_domain.lock_row()

        # Rename DNS entries that follow the standard naming convention, except
        # the primary name. The primary name should not have an interface
        # suffix, but who knows...
        for addr in dbinterface.assignments:
            if addr.label:
                old_name = "%s-%s-%s" % (short, dbinterface.name, addr.label)
                new_name = "%s-%s-%s" % (short, rename_to, addr.label)
            else:
                old_name = "%s-%s" % (short, dbinterface.name)
                new_name = "%s-%s" % (short, rename_to)
            fqdn_changes.extend([
                (dns_rec.fqdn, new_name) for dns_rec in addr.dns_records
                if dns_rec.fqdn.name == old_name and dns_rec.fqdn.dns_domain ==
                dbdns_domain and dns_rec.fqdn != primary_fqdn
            ])
    else:
        dbdns_domain = dbdns_env = None

    with session.no_autoflush:
        dbinterface.name = rename_to
        for dbfqdn, new_name in fqdn_changes:
            Fqdn.get_unique(session,
                            name=new_name,
                            dns_domain=dbdns_domain,
                            dns_environment=dbdns_env,
                            preclude=True)
            dbfqdn.name = new_name
Пример #7
0
 def render(self, session, fqdn, dns_environment, **kwargs):
     self.deprecated_command("The show_fqdn command is deprecated.  Please "
                             "use search_dns instead.", **kwargs)
     dbdns_env = DnsEnvironment.get_unique_or_default(session, dns_environment)
     dbfqdn = Fqdn.get_unique(session, fqdn=fqdn, dns_environment=dbdns_env,
                              compel=True)
     q = session.query(DnsRecord)
     q = q.filter_by(fqdn=dbfqdn)
     return q.all()
Пример #8
0
def rename_interface(session, dbinterface, rename_to):
    rename_to = rename_to.strip().lower()

    dbhw_ent = dbinterface.hardware_entity
    for iface in dbhw_ent.interfaces:
        if iface.name == rename_to:
            raise ArgumentError("{0} already has an interface named {1}."
                                .format(dbhw_ent, rename_to))

    fqdn_changes = []

    if dbhw_ent.primary_name:
        primary_fqdn = dbhw_ent.primary_name.fqdn
        short = primary_fqdn.name
        dbdns_domain = primary_fqdn.dns_domain
        dbdns_env = primary_fqdn.dns_environment

        dbdns_domain.lock_row()

        # Rename DNS entries that follow the standard naming convention, except
        # the primary name. The primary name should not have an interface
        # suffix, but who knows...
        for addr in dbinterface.assignments:
            if addr.label:
                old_name = "%s-%s-%s" % (short, dbinterface.name, addr.label)
                new_name = "%s-%s-%s" % (short, rename_to, addr.label)
            else:
                old_name = "%s-%s" % (short, dbinterface.name)
                new_name = "%s-%s" % (short, rename_to)
            fqdn_changes.extend([(dns_rec.fqdn, new_name) for dns_rec
                                 in addr.dns_records
                                 if dns_rec.fqdn.name == old_name and
                                    dns_rec.fqdn.dns_domain == dbdns_domain and
                                    dns_rec.fqdn != primary_fqdn])
    else:
        dbdns_domain = dbdns_env = None

    with session.no_autoflush:
        dbinterface.name = rename_to
        for dbfqdn, new_name in fqdn_changes:
            Fqdn.get_unique(session, name=new_name, dns_domain=dbdns_domain,
                            dns_environment=dbdns_env, preclude=True)
            dbfqdn.name = new_name
Пример #9
0
 def render(self, session, fqdn, dns_environment, **kwargs):
     self.deprecated_command(
         "The show_fqdn command is deprecated.  Please "
         "use search_dns instead.", **kwargs)
     dbdns_env = DnsEnvironment.get_unique_or_default(
         session, dns_environment)
     dbfqdn = Fqdn.get_unique(session,
                              fqdn=fqdn,
                              dns_environment=dbdns_env,
                              compel=True)
     q = session.query(DnsRecord)
     q = q.filter_by(fqdn=dbfqdn)
     return q.all()
Пример #10
0
    def render(self, session, service, protocol, dns_domain, target,
               dns_environment, **kwargs):
        name = "_%s._%s" % (service.strip().lower(), protocol.strip().lower())
        dbfqdn = Fqdn.get_unique(session,
                                 name=name,
                                 dns_domain=dns_domain,
                                 dns_environment=dns_environment)
        if target:
            dbtarget = Fqdn.get_unique(session, target, compel=True)
        else:
            dbtarget = None

        rrs = []
        if dbfqdn:
            for rr in dbfqdn.dns_records:
                if not isinstance(rr, SrvRecord):  # pragma: no cover
                    # This case can't happen right now. Maybe one day if we
                    # add support for DNSSEC...
                    continue
                if dbtarget and rr.target != dbtarget:
                    continue
                rrs.append(rr)

        if not rrs:
            if dbtarget:
                msg = ", with target %s" % dbtarget.fqdn
            else:
                msg = ""
            raise NotFoundException("%s for service %s, protocol %s in DNS "
                                    "domain %s%s not found." %
                                    (SrvRecord._get_class_label(), service,
                                     protocol, dns_domain, msg))

        map(delete_dns_record, rrs)
        session.flush()

        return
Пример #11
0
    def get_unique(cls,
                   session,
                   fqdn=None,
                   name=None,
                   dns_domain=None,
                   dns_environment=None,
                   compel=False,
                   preclude=False,
                   **kwargs):
        # Proxy FQDN lookup to the Fqdn class
        if not fqdn or not isinstance(fqdn, Fqdn):
            if not isinstance(dns_environment, DnsEnvironment):
                dns_environment = DnsEnvironment.get_unique_or_default(
                    session, dns_environment)
            if fqdn:
                if name or dns_domain:  # pragma: no cover
                    raise TypeError("fqdn and name/dns_domain cannot be mixed")
                (name, dns_domain) = parse_fqdn(session, fqdn)
            try:
                # Do not pass preclude=True to Fqdn
                fqdn = Fqdn.get_unique(session,
                                       name=name,
                                       dns_domain=dns_domain,
                                       dns_environment=dns_environment,
                                       compel=compel)
            except NotFoundException:
                # Replace the "Fqdn ... not found" message with a more user
                # friendly one
                msg = "%s %s.%s, %s not found." % (
                    cls._get_class_label(), name, dns_domain,
                    format(dns_environment, "l"))
                raise NotFoundException(msg)
            if not fqdn:
                return None

        # We already have the FQDN, no need to load it again
        if "query_options" not in kwargs:
            kwargs["query_options"] = [lazyload("fqdn")]

        result = super(DnsRecord, cls).get_unique(session,
                                                  fqdn=fqdn,
                                                  compel=compel,
                                                  preclude=preclude,
                                                  **kwargs)
        if result:
            # Make sure not to load the relation again if we already know its
            # value
            set_committed_value(result, 'fqdn', fqdn)
        return result
Пример #12
0
    def render(self,
               session,
               fqdn,
               record_type,
               dns_environment,
               network_environment=None,
               **arguments):

        if network_environment:
            if not isinstance(network_environment, NetworkEnvironment):
                network_environment = NetworkEnvironment.get_unique_or_default(
                    session, network_environment)
            if not dns_environment:
                dns_environment = network_environment.dns_environment

        dbdns_env = DnsEnvironment.get_unique_or_default(
            session, dns_environment)
        # No compel here. query(DnsRecord).filter_by(fqdn=None) will fail if the
        # FQDN is invalid, and that will give a better error message.
        dbfqdn = Fqdn.get_unique(session, fqdn=fqdn, dns_environment=dbdns_env)

        if record_type:
            if record_type in DNS_RRTYPE_MAP:
                cls = DNS_RRTYPE_MAP[record_type]
            else:
                cls = DnsRecord.polymorphic_subclass(
                    record_type, "Unknown DNS record type")
        else:
            cls = DnsRecord

        # We want to query(ARecord) instead of
        # query(DnsRecord).filter_by(record_type='a_record'), because the former
        # works for DynamicStub as well
        q = session.query(cls)
        if cls == DnsRecord:
            q = q.with_polymorphic('*')
        q = q.filter_by(fqdn=dbfqdn)
        result = q.all()
        if not result:
            raise NotFoundException("%s %s not found." %
                                    (cls._get_class_label(), fqdn))
        return result
Пример #13
0
    def get_unique(cls, session, fqdn=None, name=None, dns_domain=None,
                   dns_environment=None, compel=False, preclude=False, **kwargs):
        # Proxy FQDN lookup to the Fqdn class
        if not fqdn or not isinstance(fqdn, Fqdn):
            if not isinstance(dns_environment, DnsEnvironment):
                dns_environment = DnsEnvironment.get_unique_or_default(session,
                                                                       dns_environment)
            if fqdn:
                if name or dns_domain:  # pragma: no cover
                    raise TypeError("fqdn and name/dns_domain cannot be mixed")
                (name, dns_domain) = parse_fqdn(session, fqdn)
            try:
                # Do not pass preclude=True to Fqdn
                fqdn = Fqdn.get_unique(session, name=name,
                                       dns_domain=dns_domain,
                                       dns_environment=dns_environment,
                                       compel=compel)
            except NotFoundException:
                # Replace the "Fqdn ... not found" message with a more user
                # friendly one
                msg = "%s %s.%s, %s not found." % (cls._get_class_label(),
                                                   name, dns_domain,
                                                   format(dns_environment, "l"))
                raise NotFoundException(msg)
            if not fqdn:
                return None

        # We already have the FQDN, no need to load it again
        if "query_options" not in kwargs:
            kwargs["query_options"] = [lazyload("fqdn")]

        result = super(DnsRecord, cls).get_unique(session, fqdn=fqdn,
                                                  compel=compel,
                                                  preclude=preclude, **kwargs)
        if result:
            # Make sure not to load the relation again if we already know its
            # value
            set_committed_value(result, 'fqdn', fqdn)
        return result
Пример #14
0
    def render(self, session, fqdn, record_type, dns_environment,
               network_environment=None, **arguments):

        if network_environment:
            if not isinstance(network_environment, NetworkEnvironment):
                network_environment = NetworkEnvironment.get_unique_or_default(session,
                                                                               network_environment)
            if not dns_environment:
                dns_environment = network_environment.dns_environment

        dbdns_env = DnsEnvironment.get_unique_or_default(session,
                                                         dns_environment)
        # No compel here. query(DnsRecord).filter_by(fqdn=None) will fail if the
        # FQDN is invalid, and that will give a better error message.
        dbfqdn = Fqdn.get_unique(session, fqdn=fqdn,
                                 dns_environment=dbdns_env)

        if record_type:
            if record_type in DNS_RRTYPE_MAP:
                cls = DNS_RRTYPE_MAP[record_type]
            else:
                cls = DnsRecord.polymorphic_subclass(record_type,
                                                     "Unknown DNS record type")
        else:
            cls = DnsRecord

        # We want to query(ARecord) instead of
        # query(DnsRecord).filter_by(record_type='a_record'), because the former
        # works for DynamicStub as well
        q = session.query(cls)
        if cls == DnsRecord:
            q = q.with_polymorphic('*')
        q = q.filter_by(fqdn=dbfqdn)
        result = q.all()
        if not result:
            raise NotFoundException("%s %s not found." %
                                    (cls._get_class_label(), fqdn))
        return result
Пример #15
0
    def render(self, session, fqdn, dns_environment, dns_domain, shortname,
               record_type, ip, network, network_environment, target,
               target_domain, primary_name, used, reverse_override,
               reverse_ptr, fullinfo, style, **kwargs):
        if record_type:
            record_type = record_type.strip().lower()
            if record_type in DNS_RRTYPE_MAP:
                cls = DNS_RRTYPE_MAP[record_type]
            else:
                cls = DnsRecord.polymorphic_subclass(
                    record_type, "Unknown DNS record type")
            q = session.query(cls)
        else:
            q = session.query(DnsRecord)
            q = q.with_polymorphic('*')

        dbnet_env = NetworkEnvironment.get_unique_or_default(
            session, network_environment)
        if network_environment:
            # The network environment determines the DNS environment
            dbdns_env = dbnet_env.dns_environment
        else:
            dbdns_env = DnsEnvironment.get_unique_or_default(
                session, dns_environment)

        if fqdn:
            dbfqdn = Fqdn.get_unique(session,
                                     fqdn=fqdn,
                                     dns_environment=dbdns_env,
                                     compel=True)
            q = q.filter_by(fqdn=dbfqdn)

        q = q.join((Fqdn, DnsRecord.fqdn_id == Fqdn.id))
        q = q.filter_by(dns_environment=dbdns_env)
        q = q.options(contains_eager('fqdn'))

        if dns_domain:
            dbdns_domain = DnsDomain.get_unique(session,
                                                dns_domain,
                                                compel=True)
            q = q.filter_by(dns_domain=dbdns_domain)
        if shortname:
            q = q.filter_by(name=shortname)

        q = q.join(DnsDomain)
        q = q.options(contains_eager('fqdn.dns_domain'))
        q = q.order_by(Fqdn.name, DnsDomain.name)

        q = q.reset_joinpoint()

        if ip:
            q = q.join(Network)
            q = q.filter_by(network_environment=dbnet_env)
            q = q.reset_joinpoint()
            q = q.filter(ARecord.ip == ip)
        if network:
            dbnetwork = Network.get_unique(session,
                                           network,
                                           network_environment=dbnet_env,
                                           compel=True)
            q = q.filter(ARecord.network == dbnetwork)
        if target:
            dbtarget = Fqdn.get_unique(session,
                                       fqdn=target,
                                       dns_environment=dbdns_env,
                                       compel=True)
            q = q.filter(
                or_(Alias.target == dbtarget, SrvRecord.target == dbtarget))
        if target_domain:
            dbdns_domain = DnsDomain.get_unique(session,
                                                target_domain,
                                                compel=True)
            TargetFqdn = aliased(Fqdn)
            q = q.join((TargetFqdn,
                        or_(Alias.target_id == TargetFqdn.id,
                            SrvRecord.target_id == TargetFqdn.id)))
            q = q.filter(TargetFqdn.dns_domain == dbdns_domain)
        if primary_name is not None:
            if primary_name:
                q = q.filter(DnsRecord.hardware_entity.has())
            else:
                q = q.filter(~DnsRecord.hardware_entity.has())
        if used is not None:
            if used:
                q = q.join(
                    AddressAssignment,
                    and_(ARecord.network_id == AddressAssignment.network_id,
                         ARecord.ip == AddressAssignment.ip))
            else:
                q = q.outerjoin(
                    AddressAssignment,
                    and_(ARecord.network_id == AddressAssignment.network_id,
                         ARecord.ip == AddressAssignment.ip))
                q = q.filter(AddressAssignment.id == None)
            q = q.reset_joinpoint()
        if reverse_override is not None:
            if reverse_override:
                q = q.filter(ARecord.reverse_ptr.has())
            else:
                q = q.filter(~ARecord.reverse_ptr.has())
        if reverse_ptr:
            dbtarget = Fqdn.get_unique(session,
                                       fqdn=reverse_ptr,
                                       dns_environment=dbdns_env,
                                       compel=True)
            q = q.filter(ARecord.reverse_ptr == dbtarget)

        if fullinfo:
            q = q.options(undefer('comments'))
            q = q.options(subqueryload('hardware_entity'))
            q = q.options(undefer('alias_cnt'))
            return q.all()
        elif style == "raw":
            return StringAttributeList(q.all(), 'fqdn')
        else:
            # This is for the CSV formatter
            return q.all()
Пример #16
0
    def render(self, session, fqdn, dns_environment, dns_domain, shortname,
               record_type, ip, network, network_environment, target,
               target_domain, primary_name, used, reverse_override, reverse_ptr,
               fullinfo, style, **kwargs):
        if record_type:
            record_type = record_type.strip().lower()
            if record_type in DNS_RRTYPE_MAP:
                cls = DNS_RRTYPE_MAP[record_type]
            else:
                cls = DnsRecord.polymorphic_subclass(record_type,
                                                     "Unknown DNS record type")
            q = session.query(cls)
        else:
            q = session.query(DnsRecord)
            q = q.with_polymorphic('*')

        dbnet_env = NetworkEnvironment.get_unique_or_default(session,
                                                             network_environment)
        if network_environment:
            # The network environment determines the DNS environment
            dbdns_env = dbnet_env.dns_environment
        else:
            dbdns_env = DnsEnvironment.get_unique_or_default(session,
                                                             dns_environment)

        if fqdn:
            dbfqdn = Fqdn.get_unique(session, fqdn=fqdn,
                                     dns_environment=dbdns_env, compel=True)
            q = q.filter_by(fqdn=dbfqdn)

        q = q.join((Fqdn, DnsRecord.fqdn_id == Fqdn.id))
        q = q.filter_by(dns_environment=dbdns_env)
        q = q.options(contains_eager('fqdn'))

        if dns_domain:
            dbdns_domain = DnsDomain.get_unique(session, dns_domain,
                                                compel=True)
            q = q.filter_by(dns_domain=dbdns_domain)
        if shortname:
            q = q.filter_by(name=shortname)

        q = q.join(DnsDomain)
        q = q.options(contains_eager('fqdn.dns_domain'))
        q = q.order_by(Fqdn.name, DnsDomain.name)

        q = q.reset_joinpoint()

        if ip:
            q = q.join(Network)
            q = q.filter_by(network_environment=dbnet_env)
            q = q.reset_joinpoint()
            q = q.filter(ARecord.ip == ip)
        if network:
            dbnetwork = Network.get_unique(session, network,
                                           network_environment=dbnet_env, compel=True)
            q = q.filter(ARecord.network == dbnetwork)
        if target:
            dbtarget = Fqdn.get_unique(session, fqdn=target,
                                       dns_environment=dbdns_env, compel=True)
            q = q.filter(or_(Alias.target == dbtarget,
                             SrvRecord.target == dbtarget))
        if target_domain:
            dbdns_domain = DnsDomain.get_unique(session, target_domain,
                                                compel=True)
            TargetFqdn = aliased(Fqdn)
            q = q.join((TargetFqdn, or_(Alias.target_id == TargetFqdn.id,
                                        SrvRecord.target_id == TargetFqdn.id)))
            q = q.filter(TargetFqdn.dns_domain == dbdns_domain)
        if primary_name is not None:
            if primary_name:
                q = q.filter(DnsRecord.hardware_entity.has())
            else:
                q = q.filter(~DnsRecord.hardware_entity.has())
        if used is not None:
            if used:
                q = q.join(AddressAssignment,
                           and_(ARecord.network_id == AddressAssignment.network_id,
                                ARecord.ip == AddressAssignment.ip))
            else:
                q = q.outerjoin(AddressAssignment,
                                and_(ARecord.network_id == AddressAssignment.network_id,
                                     ARecord.ip == AddressAssignment.ip))
                q = q.filter(AddressAssignment.id == None)
            q = q.reset_joinpoint()
        if reverse_override is not None:
            if reverse_override:
                q = q.filter(ARecord.reverse_ptr.has())
            else:
                q = q.filter(~ARecord.reverse_ptr.has())
        if reverse_ptr:
            dbtarget = Fqdn.get_unique(session, fqdn=reverse_ptr,
                                       dns_environment=dbdns_env, compel=True)
            q = q.filter(ARecord.reverse_ptr == dbtarget)

        if fullinfo or style != "raw":
            q = q.options(undefer('comments'),
                          subqueryload('hardware_entity'),
                          lazyload('hardware_entity.primary_name'),
                          undefer('alias_cnt'))
            return q.all()
        else:
            return StringAttributeList(q.all(), 'fqdn')