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
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
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
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
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
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
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()
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
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()
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
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
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
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
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()
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')