commit 5c85f41856f91e13ac5850588effab69f6dfe9d3 Author: eyang Date: Wed Oct 18 21:14:51 2017 -0400 YARN-7326. Added upstream DNS lookup, and recursion. diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/main/java/org/apache/hadoop/registry/server/dns/RegistryDNS.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/main/java/org/apache/hadoop/registry/server/dns/RegistryDNS.java index d7a415d..6f24ea7 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/main/java/org/apache/hadoop/registry/server/dns/RegistryDNS.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/main/java/org/apache/hadoop/registry/server/dns/RegistryDNS.java @@ -37,8 +37,10 @@ import org.xbill.DNS.DNSSEC; import org.xbill.DNS.DSRecord; import org.xbill.DNS.ExtendedFlags; +import org.xbill.DNS.ExtendedResolver; import org.xbill.DNS.Flags; import org.xbill.DNS.Header; +import org.xbill.DNS.Lookup; import org.xbill.DNS.Message; import org.xbill.DNS.NSRecord; import org.xbill.DNS.Name; @@ -49,9 +51,12 @@ import org.xbill.DNS.RRset; import org.xbill.DNS.Rcode; import org.xbill.DNS.Record; +import org.xbill.DNS.Resolver; +import org.xbill.DNS.ResolverConfig; import org.xbill.DNS.SOARecord; import org.xbill.DNS.Section; import org.xbill.DNS.SetResponse; +import org.xbill.DNS.SimpleResolver; import org.xbill.DNS.TSIG; import org.xbill.DNS.TSIGRecord; import org.xbill.DNS.TextParseException; @@ -68,6 +73,7 @@ import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; +import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.nio.channels.DatagramChannel; import java.nio.channels.ServerSocketChannel; @@ -134,6 +140,16 @@ private boolean channelsInitialized = false; /** + * Lock to update resolver only once per request. + */ + private final Object resolverUpdateLock = new Object(); + + /** + * Whether resolver update has been requested. + */ + private boolean resolverUpdateRequested = true; + + /** * Construct the service. * * @param name service name @@ -171,6 +187,44 @@ public void initializeChannels(Configuration conf) throws Exception { addNIOTCP(addr, port); } + private void updateDNSServer() { + synchronized (resolverUpdateLock) { + if (!resolverUpdateRequested) { + return; + } + resolverUpdateRequested = false; + ResolverConfig.refresh(); + ExtendedResolver resolver; + try { + resolver = new ExtendedResolver(); + } catch (UnknownHostException e) { + LOG.error("Can not resolve DNS servers: ", e); + return; + } + for (Resolver check : resolver.getResolvers()) { + if (check instanceof SimpleResolver) { + check.setTimeout(30); + } else { + LOG.error("Not simple resolver!!!?" + check); + } + } + synchronized (Lookup.class) { + Lookup.setDefaultResolver(resolver); + Lookup.setDefaultSearchPath(ResolverConfig.getCurrentConfig() + .searchPath()); + } + String message = "DNS servers: "; + if (ResolverConfig.getCurrentConfig().servers() == null) { + message += ResolverConfig.getCurrentConfig().servers(); + } else { + for (String server : ResolverConfig.getCurrentConfig() + .servers()) { + message += server + " "; + } + } + LOG.info(message); + } + } /** * Initializes the registry. * @@ -183,6 +237,7 @@ protected void serviceInit(Configuration conf) throws Exception { // create the zone. for now create a "dummy" SOA record try { + updateDNSServer(); setDomainName(conf); initializeZones(conf); @@ -975,6 +1030,7 @@ private DatagramChannel openUDPChannel(InetAddress addr, int port) response.getHeader().setFlag(Flags.QR); if (query.getHeader().getFlag(Flags.RD)) { response.getHeader().setFlag(Flags.RD); + response.getHeader().setFlag(Flags.RA); } response.addRecord(queryRecord, Section.QUESTION); @@ -994,6 +1050,11 @@ private DatagramChannel openUDPChannel(InetAddress addr, int port) byte rcode = addAnswer(response, name, type, dclass, 0, flags); if (rcode != Rcode.NOERROR && rcode != Rcode.NXDOMAIN) { return errorMessage(query, rcode); + } else if (rcode == Rcode.NXDOMAIN) { + rcode = remoteLookup(response, name); + if (rcode != Rcode.NOERROR && rcode != Rcode.NXDOMAIN) { + return errorMessage(query, rcode); + } } addAdditional(response, flags); @@ -1009,6 +1070,44 @@ private DatagramChannel openUDPChannel(InetAddress addr, int port) } /** + * Lookup record from upstream DNS servers. + */ + private byte remoteLookup(Message response, Name name) { + // Forward lookup to primary DNS servers + Record[] answers = getRecords(name, Type.ANY); + try { + for (Record r : answers) { + if (r.getType() == Type.SOA) { + response.addRecord(r, Section.AUTHORITY); + } else { + response.addRecord(r, Section.ANSWER); + } + } + } catch (NullPointerException e) { + return Rcode.NXDOMAIN; + } catch (Throwable e) { + return Rcode.SERVFAIL; + } + return Rcode.NOERROR; + } + + /** + * Requests records for the given resource name. + * + * @param name + * @return + */ + protected Record[] getRecords(Name name, int type) { + try { + return new Lookup(name, type).run(); + } catch (NullPointerException | + ExceptionInInitializerError e) { + LOG.error("Fail to lookup: " + name, e); + } + return null; + } + + /** * Create a query to forward to the primary DNS server (if configured). * NOTE: Experimental * @@ -1180,7 +1279,7 @@ byte addAnswer(Message response, Name name, int type, int dclass, rcode = Rcode.NOTAUTH; } } - LOG.info("found record? {}", sr != null && sr.isSuccessful()); + LOG.info("found local record? {}", sr != null && sr.isSuccessful()); if (sr != null) { if (sr.isCNAME()) { @@ -1241,6 +1340,7 @@ byte addAnswer(Message response, Name name, int type, int dclass, } } } + return rcode; } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/test/java/org/apache/hadoop/registry/server/dns/TestRegistryDNS.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/test/java/org/apache/hadoop/registry/server/dns/TestRegistryDNS.java index ac8d939..412f593 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/test/java/org/apache/hadoop/registry/server/dns/TestRegistryDNS.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/test/java/org/apache/hadoop/registry/server/dns/TestRegistryDNS.java @@ -601,6 +601,12 @@ public void testSplitReverseZoneNames() throws Exception { assertEquals(4, registryDNS.getZoneCount()); } + @Test + public void testExampleDotCom() throws Exception { + Name name = Name.fromString("example.com."); + Record[] records = getRegistryDNS().getRecords(name, Type.SOA); + assertNotNull("example.com exists:", records); + } public RegistryDNS getRegistryDNS() { return registryDNS; }