hadoop-common-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ey...@apache.org
Subject [14/18] hadoop git commit: HADOOP-15821. Move YARN Registry to Hadoop Registry. Contributed by Íñigo Goiri
Date Sat, 20 Oct 2018 00:00:37 GMT
http://git-wip-us.apache.org/repos/asf/hadoop/blob/e2a9fa84/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/impl/zk/ZookeeperConfigOptions.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/impl/zk/ZookeeperConfigOptions.java b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/impl/zk/ZookeeperConfigOptions.java
new file mode 100644
index 0000000..edcf085
--- /dev/null
+++ b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/impl/zk/ZookeeperConfigOptions.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.registry.client.impl.zk;
+
+import org.apache.zookeeper.client.ZooKeeperSaslClient;
+import org.apache.zookeeper.server.ZooKeeperSaslServer;
+
+/**
+ * Configuration options which are internal to Zookeeper,
+ * as well as some other ZK constants
+ * <p>
+ * Zookeeper options are passed via system properties prior to the ZK
+ * Methods/classes being invoked. This implies that:
+ * <ol>
+ *   <li>There can only be one instance of a ZK client or service class
+ *   in a single JVM —else their configuration options will conflict.</li>
+ *   <li>It is safest to set these properties immediately before
+ *   invoking ZK operations.</li>
+ * </ol>
+ *
+ */
+public interface ZookeeperConfigOptions {
+  /**
+   * Enable SASL secure clients: {@value}.
+   * This is usually set to true, with ZK set to fall back to
+   * non-SASL authentication if the SASL auth fails
+   * by the property
+   * {@link #PROP_ZK_SERVER_MAINTAIN_CONNECTION_DESPITE_SASL_FAILURE}.
+   * <p>
+   * As a result, clients will default to attempting SASL-authentication,
+   * but revert to classic authentication/anonymous access on failure.
+   */
+  String PROP_ZK_ENABLE_SASL_CLIENT =
+      "zookeeper.sasl.client";
+
+  /**
+   * Default flag for the ZK client: {@value}.
+   */
+  String DEFAULT_ZK_ENABLE_SASL_CLIENT = "true";
+
+  /**
+   * System property for the JAAS client context : {@value}.
+   *
+   * For SASL authentication to work, this must point to a
+   * context within the
+   *
+   * <p>
+   *   Default value is derived from
+   *   {@link ZooKeeperSaslClient#LOGIN_CONTEXT_NAME_KEY}
+   */
+  String PROP_ZK_SASL_CLIENT_CONTEXT =
+      ZooKeeperSaslClient.LOGIN_CONTEXT_NAME_KEY;
+
+  /**
+   * The SASL client username: {@value}.
+   * <p>
+   * Set this to the <i>short</i> name of the client, e.g, "user",
+   * not {@code user/host}, or {@code user/host@REALM}
+   */
+  String PROP_ZK_SASL_CLIENT_USERNAME = "zookeeper.sasl.client.username";
+
+  /**
+   * The SASL Server context, referring to a context in the JVM's
+   * JAAS context file: {@value}
+   */
+  String PROP_ZK_SERVER_SASL_CONTEXT =
+      ZooKeeperSaslServer.LOGIN_CONTEXT_NAME_KEY;
+
+  /**
+   * Should ZK Server allow failed SASL clients to downgrade to classic
+   * authentication on a SASL auth failure: {@value}.
+   */
+  String PROP_ZK_SERVER_MAINTAIN_CONNECTION_DESPITE_SASL_FAILURE =
+      "zookeeper.maintain_connection_despite_sasl_failure";
+
+  /**
+   * should the ZK Server Allow failed SASL clients: {@value}.
+   */
+  String PROP_ZK_ALLOW_FAILED_SASL_CLIENTS =
+      "zookeeper.allowSaslFailedClients";
+
+  /**
+   * Kerberos realm of the server: {@value}.
+   */
+  String PROP_ZK_SERVER_REALM = "zookeeper.server.realm";
+
+  /**
+   * Path to a kinit binary: {@value}.
+   * Defaults to <code>"/usr/bin/kinit"</code>
+   */
+  String PROP_ZK_KINIT_PATH = "zookeeper.kinit";
+
+  /**
+   * ID scheme for SASL: {@value}.
+   */
+  String SCHEME_SASL = "sasl";
+
+  /**
+   * ID scheme for digest auth: {@value}.
+   */
+  String SCHEME_DIGEST = "digest";
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/e2a9fa84/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/impl/zk/package-info.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/impl/zk/package-info.java b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/impl/zk/package-info.java
new file mode 100644
index 0000000..f7ae983
--- /dev/null
+++ b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/impl/zk/package-info.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Core Zookeeper support.
+ * <p>
+ * This package contains the low-level bindings to Curator and Zookeeper,
+ * including everything related to registry security.
+ * <p>
+ * The class {@link org.apache.hadoop.registry.client.impl.zk.CuratorService}
+ * is a YARN service which offers access to a Zookeeper instance via
+ * Apache Curator.
+ * <p>
+ * The {@link org.apache.hadoop.registry.client.impl.zk.RegistrySecurity}
+ * implements the security support in the registry, though a set of
+ * static methods and as a YARN service.
+ * <p>
+ * To work with ZK, system properties need to be set before invoking
+ * some operations/instantiating some objects. The definitions of these
+ * are kept in {@link org.apache.hadoop.registry.client.impl.zk.ZookeeperConfigOptions}.
+ *
+ *
+ */
+package org.apache.hadoop.registry.client.impl.zk;

http://git-wip-us.apache.org/repos/asf/hadoop/blob/e2a9fa84/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/AddressTypes.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/AddressTypes.java b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/AddressTypes.java
new file mode 100644
index 0000000..61298e6
--- /dev/null
+++ b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/AddressTypes.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.registry.client.types;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+
+/**
+ * Enum of address types -as integers.
+ * Why integers and not enums? Cross platform serialization as JSON
+ */
+@InterfaceAudience.Public
+@InterfaceStability.Evolving
+public interface AddressTypes {
+
+  /**
+   * hostname/FQDN and port pair: {@value}.
+   * The host/domain name and port are set as separate strings in the address
+   * list, e.g.
+   * <pre>
+   *   ["namenode.example.org", "9870"]
+   * </pre>
+   */
+  public static final String ADDRESS_HOSTNAME_AND_PORT = "host/port";
+  public static final String ADDRESS_HOSTNAME_FIELD = "host";
+  public static final String ADDRESS_PORT_FIELD = "port";
+
+
+  /**
+   * Path <code>/a/b/c</code> style: {@value}.
+   * The entire path is encoded in a single entry
+   *
+   * <pre>
+   *   ["/users/example/dataset"]
+   * </pre>
+   */
+  public static final String ADDRESS_PATH = "path";
+
+
+
+  /**
+   * URI entries: {@value}.
+   * <pre>
+   *   ["http://example.org"]
+   * </pre>
+   */
+  public static final String ADDRESS_URI = "uri";
+
+  /**
+   * Zookeeper addresses as a triple : {@value}.
+   * <p>
+   * These are provide as a 3 element tuple of: hostname, port
+   * and optionally path (depending on the application)
+   * <p>
+   *   A single element would be
+   * <pre>
+   *   ["zk1","2181","/registry"]
+   * </pre>
+   *  An endpoint with multiple elements would list them as
+   * <pre>
+   *   [
+   *    ["zk1","2181","/registry"]
+   *    ["zk2","1600","/registry"]
+   *   ]
+   * </pre>
+   *
+   * the third element in each entry , the path, MUST be the same in each entry.
+   * A client reading the addresses of an endpoint is free to pick any
+   * of the set, so they must be the same.
+   *
+   */
+  public static final String ADDRESS_ZOOKEEPER = "zktriple";
+
+  /**
+   * Any other address: {@value}.
+   */
+  public static final String ADDRESS_OTHER = "";
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/e2a9fa84/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/Endpoint.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/Endpoint.java b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/Endpoint.java
new file mode 100644
index 0000000..392884f
--- /dev/null
+++ b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/Endpoint.java
@@ -0,0 +1,247 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.registry.client.types;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.google.common.base.Preconditions;
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.hadoop.registry.client.binding.JsonSerDeser;
+import org.apache.hadoop.registry.client.binding.RegistryTypeUtils;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Description of a single service/component endpoint.
+ * It is designed to be marshalled as JSON.
+ * <p>
+ * Every endpoint can have more than one address entry, such as
+ * a list of URLs to a replicated service, or a (hostname, port)
+ * pair. Each of these address entries is represented as a string list,
+ * as that is the only reliably marshallable form of a tuple JSON can represent.
+ *
+ *
+ */
+@InterfaceAudience.Public
+@InterfaceStability.Evolving
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public final class Endpoint implements Cloneable {
+
+  /**
+   * API implemented at the end of the binding
+   */
+  public String api;
+
+  /**
+   * Type of address. The standard types are defined in
+   * {@link AddressTypes}
+   */
+  public String addressType;
+
+  /**
+   * Protocol type. Some standard types are defined in
+   * {@link ProtocolTypes}
+   */
+  public String protocolType;
+
+  /**
+   * a list of address tuples —tuples whose format depends on the address type
+   */
+  public List<Map<String, String>> addresses;
+
+  /**
+   * Create an empty instance.
+   */
+  public Endpoint() {
+  }
+
+  /**
+   * Create an endpoint from another endpoint.
+   * This is a deep clone with a new list of addresses.
+   * @param that the endpoint to copy from
+   */
+  public Endpoint(Endpoint that) {
+    this.api = that.api;
+    this.addressType = that.addressType;
+    this.protocolType = that.protocolType;
+    this.addresses = newAddresses(that.addresses.size());
+    for (Map<String, String> address : that.addresses) {
+      Map<String, String> addr2 = new HashMap<String, String>(address.size());
+      addr2.putAll(address);
+      addresses.add(addr2);
+    }
+  }
+
+  /**
+   * Build an endpoint with a list of addresses
+   * @param api API name
+   * @param addressType address type
+   * @param protocolType protocol type
+   * @param addrs addresses
+   */
+  public Endpoint(String api,
+      String addressType,
+      String protocolType,
+      List<Map<String, String>> addrs) {
+    this.api = api;
+    this.addressType = addressType;
+    this.protocolType = protocolType;
+    this.addresses = newAddresses(0);
+    if (addrs != null) {
+      addresses.addAll(addrs);
+    }
+  }
+
+  /**
+   * Build an endpoint with an empty address list
+   * @param api API name
+   * @param addressType address type
+   * @param protocolType protocol type
+   */
+  public Endpoint(String api,
+      String addressType,
+      String protocolType) {
+    this.api = api;
+    this.addressType = addressType;
+    this.protocolType = protocolType;
+    this.addresses = newAddresses(0);
+  }
+
+  /**
+   * Build an endpoint with a single address entry.
+   * <p>
+   * This constructor is superfluous given the varags constructor is equivalent
+   * for a single element argument. However, type-erasure in java generics
+   * causes javac to warn about unchecked generic array creation. This
+   * constructor, which represents the common "one address" case, does
+   * not generate compile-time warnings.
+   * @param api API name
+   * @param addressType address type
+   * @param protocolType protocol type
+   * @param addr address. May be null —in which case it is not added
+   */
+  public Endpoint(String api,
+      String addressType,
+      String protocolType,
+      Map<String, String> addr) {
+    this(api, addressType, protocolType);
+    if (addr != null) {
+      addresses.add(addr);
+    }
+  }
+
+  /**
+   * Build an endpoint with a list of addresses
+   * @param api API name
+   * @param addressType address type
+   * @param protocolType protocol type
+   * @param addrs addresses. Null elements will be skipped
+   */
+  public Endpoint(String api,
+      String addressType,
+      String protocolType,
+      Map<String, String>...addrs) {
+    this(api, addressType, protocolType);
+    for (Map<String, String> addr : addrs) {
+      if (addr!=null) {
+        addresses.add(addr);
+      }
+    }
+  }
+
+  /**
+   * Create a new address structure of the requested size
+   * @param size size to create
+   * @return the new list
+   */
+  private List<Map<String, String>> newAddresses(int size) {
+    return new ArrayList<Map<String, String>>(size);
+  }
+
+  /**
+   * Build an endpoint from a list of URIs; each URI
+   * is ASCII-encoded and added to the list of addresses.
+   * @param api API name
+   * @param protocolType protocol type
+   * @param uris URIs to convert to a list of tup;les
+   */
+  public Endpoint(String api,
+      String protocolType,
+      URI... uris) {
+    this.api = api;
+    this.addressType = AddressTypes.ADDRESS_URI;
+
+    this.protocolType = protocolType;
+    List<Map<String, String>> addrs = newAddresses(uris.length);
+    for (URI uri : uris) {
+      addrs.add(RegistryTypeUtils.uri(uri.toString()));
+    }
+    this.addresses = addrs;
+  }
+
+  @Override
+  public String toString() {
+      return marshalToString.toString(this);
+  }
+
+  /**
+   * Validate the record by checking for null fields and other invalid
+   * conditions
+   * @throws NullPointerException if a field is null when it
+   * MUST be set.
+   * @throws RuntimeException on invalid entries
+   */
+  public void validate() {
+    Preconditions.checkNotNull(api, "null API field");
+    Preconditions.checkNotNull(addressType, "null addressType field");
+    Preconditions.checkNotNull(protocolType, "null protocolType field");
+    Preconditions.checkNotNull(addresses, "null addresses field");
+    for (Map<String, String> address : addresses) {
+      Preconditions.checkNotNull(address, "null element in address");
+    }
+  }
+
+  /**
+   * Shallow clone: the lists of addresses are shared
+   * @return a cloned instance
+   * @throws CloneNotSupportedException
+   */
+  @Override
+  public Object clone() throws CloneNotSupportedException {
+    return super.clone();
+  }
+
+
+  /**
+   * Static instance of service record marshalling
+   */
+  private static class Marshal extends JsonSerDeser<Endpoint> {
+    private Marshal() {
+      super(Endpoint.class);
+    }
+  }
+
+  private static final Marshal marshalToString = new Marshal();
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/e2a9fa84/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/ProtocolTypes.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/ProtocolTypes.java b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/ProtocolTypes.java
new file mode 100644
index 0000000..b836b00
--- /dev/null
+++ b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/ProtocolTypes.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.registry.client.types;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+
+/**
+ * some common protocol types
+ */
+@InterfaceAudience.Public
+@InterfaceStability.Evolving
+public interface ProtocolTypes {
+
+  /**
+   * Addresses are URIs of Hadoop Filesystem paths: {@value}.
+   */
+  String PROTOCOL_FILESYSTEM = "hadoop/filesystem";
+
+  /**
+   * Hadoop IPC,  "classic" or protobuf : {@value}.
+   */
+  String PROTOCOL_HADOOP_IPC = "hadoop/IPC";
+
+  /**
+   * Corba IIOP: {@value}.
+   */
+  String PROTOCOL_IIOP = "IIOP";
+
+  /**
+   * REST: {@value}.
+   */
+  String PROTOCOL_REST = "REST";
+
+  /**
+   * Java RMI: {@value}.
+   */
+  String PROTOCOL_RMI = "RMI";
+
+  /**
+   * SunOS RPC, as used by NFS and similar: {@value}.
+   */
+  String PROTOCOL_SUN_RPC = "sunrpc";
+
+  /**
+   * Thrift-based protocols: {@value}.
+   */
+  String PROTOCOL_THRIFT = "thrift";
+
+  /**
+   * Custom TCP protocol: {@value}.
+   */
+  String PROTOCOL_TCP = "tcp";
+
+  /**
+   * Custom UPC-based protocol : {@value}.
+   */
+  String PROTOCOL_UDP = "udp";
+
+  /**
+   * Default value —the protocol is unknown : "{@value}"
+   */
+  String PROTOCOL_UNKNOWN = "";
+
+  /**
+   * Web page: {@value}.
+   *
+   * This protocol implies that the URLs are designed for
+   * people to view via web browsers.
+   */
+  String PROTOCOL_WEBUI = "webui";
+
+  /**
+   * Web Services: {@value}.
+   */
+  String PROTOCOL_WSAPI = "WS-*";
+
+  /**
+   * A zookeeper binding: {@value}.
+   */
+  String PROTOCOL_ZOOKEEPER_BINDING = "zookeeper";
+
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/e2a9fa84/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/RegistryPathStatus.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/RegistryPathStatus.java b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/RegistryPathStatus.java
new file mode 100644
index 0000000..acd2b21
--- /dev/null
+++ b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/RegistryPathStatus.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.registry.client.types;
+
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+
+/**
+ * Output of a <code>RegistryOperations.stat()</code> call
+ */
+@InterfaceAudience.Public
+@InterfaceStability.Evolving
+@JsonIgnoreProperties(ignoreUnknown = true)
+public final class RegistryPathStatus {
+
+  /**
+   * Short path in the registry to this entry
+   */
+  public final String path;
+
+  /**
+   * Timestamp
+   */
+  public final long time;
+
+  /**
+   * Entry size in bytes, as returned by the storage infrastructure.
+   * In zookeeper, even "empty" nodes have a non-zero size.
+   */
+  public final long size;
+
+  /**
+   * Number of child nodes
+   */
+  public final int children;
+
+  /**
+   * Construct an instance
+   * @param path full path
+   * @param time time
+   * @param size entry size
+   * @param children number of children
+   */
+  public RegistryPathStatus(
+      @JsonProperty("path") String path,
+      @JsonProperty("time") long time,
+      @JsonProperty("size") long size,
+      @JsonProperty("children") int children) {
+    this.path = path;
+    this.time = time;
+    this.size = size;
+    this.children = children;
+  }
+
+  /**
+   * Equality operator checks size, time and path of the entries.
+   * It does <i>not</i> check {@link #children}.
+   * @param other the other entry
+   * @return true if the entries are considered equal.
+   */
+  @Override
+  public boolean equals(Object other) {
+    if (this == other) {
+      return true;
+    }
+    if (other == null || getClass() != other.getClass()) {
+      return false;
+    }
+
+    RegistryPathStatus status = (RegistryPathStatus) other;
+
+    if (size != status.size) {
+      return false;
+    }
+    if (time != status.time) {
+      return false;
+    }
+    if (path != null ? !path.equals(status.path) : status.path != null) {
+      return false;
+    }
+    return true;
+  }
+
+  /**
+   * The hash code is derived from the path.
+   * @return hash code for storing the path in maps.
+   */
+  @Override
+  public int hashCode() {
+    return path != null ? path.hashCode() : 0;
+  }
+
+  @Override
+  public String toString() {
+    final StringBuilder sb =
+        new StringBuilder("RegistryPathStatus{");
+    sb.append("path='").append(path).append('\'');
+    sb.append(", time=").append(time);
+    sb.append(", size=").append(size);
+    sb.append(", children=").append(children);
+    sb.append('}');
+    return sb.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/e2a9fa84/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/ServiceRecord.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/ServiceRecord.java b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/ServiceRecord.java
new file mode 100644
index 0000000..9bb02c3
--- /dev/null
+++ b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/ServiceRecord.java
@@ -0,0 +1,312 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.registry.client.types;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.google.common.base.Preconditions;
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * JSON-marshallable description of a single component.
+ * It supports the deserialization of unknown attributes, but does
+ * not support their creation.
+ */
+@InterfaceAudience.Public
+@InterfaceStability.Evolving
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class ServiceRecord implements Cloneable {
+
+  /**
+   * A type string which MUST be in the serialized json. This permits
+   * fast discarding of invalid entries
+   */
+  public static final String RECORD_TYPE = "JSONServiceRecord";
+
+  /**
+   * The type field. This must be the string {@link #RECORD_TYPE}
+   */
+  public String type = RECORD_TYPE;
+
+  /**
+   * Description string
+   */
+  public String description;
+
+  /**
+   * map to handle unknown attributes.
+   */
+  private Map<String, String> attributes = new HashMap<String, String>(4);
+
+  /**
+   * List of endpoints intended for use to external callers
+   */
+  public List<Endpoint> external = new ArrayList<Endpoint>();
+
+  /**
+   * List of endpoints for use <i>within</i> an application.
+   */
+  public List<Endpoint> internal = new ArrayList<Endpoint>();
+
+  /**
+   * Create a service record with no ID, description or registration time.
+   * Endpoint lists are set to empty lists.
+   */
+  public ServiceRecord() {
+  }
+
+  /**
+   * Deep cloning constructor
+   * @param that service record source
+   */
+  public ServiceRecord(ServiceRecord that) {
+    this.description = that.description;
+    // others
+    Map<String, String> thatAttrs = that.attributes;
+    for (Map.Entry<String, String> entry : thatAttrs.entrySet()) {
+      attributes.put(entry.getKey(), entry.getValue());
+    }
+    // endpoints
+    List<Endpoint> src = that.internal;
+    if (src != null) {
+      internal = new ArrayList<Endpoint>(src.size());
+      for (Endpoint endpoint : src) {
+        internal.add(new Endpoint(endpoint));
+      }
+    }
+    src = that.external;
+    if (src != null) {
+      external = new ArrayList<Endpoint>(src.size());
+      for (Endpoint endpoint : src) {
+        external.add(new Endpoint(endpoint));
+      }
+    }
+  }
+
+  /**
+   * Add an external endpoint
+   * @param endpoint endpoint to set
+   */
+  public void addExternalEndpoint(Endpoint endpoint) {
+    Preconditions.checkArgument(endpoint != null);
+    endpoint.validate();
+    external.add(endpoint);
+  }
+
+  /**
+   * Add an internal endpoint
+   * @param endpoint endpoint to set
+   */
+  public void addInternalEndpoint(Endpoint endpoint) {
+    Preconditions.checkArgument(endpoint != null);
+    endpoint.validate();
+    internal.add(endpoint);
+  }
+
+  /**
+   * Look up an internal endpoint
+   * @param api API
+   * @return the endpoint or null if there was no match
+   */
+  public Endpoint getInternalEndpoint(String api) {
+    return findByAPI(internal, api);
+  }
+
+  /**
+   * Look up an external endpoint
+   * @param api API
+   * @return the endpoint or null if there was no match
+   */
+  public Endpoint getExternalEndpoint(String api) {
+    return findByAPI(external, api);
+  }
+
+  /**
+   * Handle unknown attributes by storing them in the
+   * {@link #attributes} map
+   * @param key attribute name
+   * @param value attribute value.
+   */
+  @JsonAnySetter
+  public void set(String key, Object value) {
+    attributes.put(key, value.toString());
+  }
+
+  /**
+   * The map of "other" attributes set when parsing. These
+   * are not included in the JSON value of this record when it
+   * is generated.
+   * @return a map of any unknown attributes in the deserialized JSON.
+   */
+  @JsonAnyGetter
+  public Map<String, String> attributes() {
+    return attributes;
+  }
+
+  /**
+   * Get the "other" attribute with a specific key
+   * @param key key to look up
+   * @return the value or null
+   */
+  public String get(String key) {
+    return attributes.get(key);
+  }
+
+  /**
+   * Get the "other" attribute with a specific key.
+   * @param key key to look up
+   * @param defVal default value
+   * @return the value as a string,
+   * or <code>defval</code> if the value was not present
+   */
+  public String get(String key, String defVal) {
+    String val = attributes.get(key);
+    return val != null ? val: defVal;
+  }
+
+  /**
+   * Find an endpoint by its API
+   * @param list list
+   * @param api api name
+   * @return the endpoint or null if there was no match
+   */
+  private Endpoint findByAPI(List<Endpoint> list,  String api) {
+    for (Endpoint endpoint : list) {
+      if (endpoint.api.equals(api)) {
+        return endpoint;
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public String toString() {
+    final StringBuilder sb =
+        new StringBuilder("ServiceRecord{");
+    sb.append("description='").append(description).append('\'');
+    sb.append("; external endpoints: {");
+    for (Endpoint endpoint : external) {
+      sb.append(endpoint).append("; ");
+    }
+    sb.append("}; internal endpoints: {");
+    for (Endpoint endpoint : internal) {
+      sb.append(endpoint != null ? endpoint.toString() : "NULL ENDPOINT");
+      sb.append("; ");
+    }
+    sb.append('}');
+
+    if (!attributes.isEmpty()) {
+      sb.append(", attributes: {");
+      for (Map.Entry<String, String> attr : attributes.entrySet()) {
+        sb.append("\"").append(attr.getKey()).append("\"=\"")
+          .append(attr.getValue()).append("\" ");
+      }
+    } else {
+
+      sb.append(", attributes: {");
+    }
+    sb.append('}');
+
+    sb.append('}');
+    return sb.toString();
+  }
+
+  /**
+   * Shallow clone: all endpoints will be shared across instances
+   * @return a clone of the instance
+   * @throws CloneNotSupportedException
+   */
+  @Override
+  protected Object clone() throws CloneNotSupportedException {
+    return super.clone();
+  }
+
+  @Override
+  public int hashCode() {
+    // Generated by eclipse
+    final int prime = 31;
+    int result = 1;
+    result =
+        prime * result + ((attributes == null) ? 0 : attributes.hashCode());
+    result =
+        prime * result + ((description == null) ? 0 : description.hashCode());
+    result = prime * result + ((external == null) ? 0 : external.hashCode());
+    result = prime * result + ((internal == null) ? 0 : internal.hashCode());
+    result = prime * result + ((type == null) ? 0 : type.hashCode());
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+    if (obj == null) {
+      return false;
+    }
+    if (getClass() != obj.getClass()) {
+      return false;
+    }
+    ServiceRecord other = (ServiceRecord) obj;
+    if (attributes == null) {
+      if (other.attributes != null) {
+        return false;
+      }
+    } else if (!attributes.equals(other.attributes)) {
+      return false;
+    }
+    if (description == null) {
+      if (other.description != null) {
+        return false;
+      }
+    } else if (!description.equals(other.description)) {
+      return false;
+    }
+    if (external == null) {
+      if (other.external != null) {
+        return false;
+      }
+    } else if (!external.equals(other.external)) {
+      return false;
+    }
+    if (internal == null) {
+      if (other.internal != null) {
+        return false;
+      }
+    } else if (!internal.equals(other.internal)) {
+      return false;
+    }
+    if (type == null) {
+      if (other.type != null) {
+        return false;
+      }
+    } else if (!type.equals(other.type)) {
+      return false;
+    }
+    return true;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/e2a9fa84/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/package-info.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/package-info.java b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/package-info.java
new file mode 100644
index 0000000..1c926be
--- /dev/null
+++ b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/package-info.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * This package contains all the data types which can be saved to the registry
+ * and/or marshalled to and from JSON.
+ * <p>
+ * The core datatypes, {@link org.apache.hadoop.registry.client.types.ServiceRecord},
+ * and {@link org.apache.hadoop.registry.client.types.Endpoint} are
+ * what is used to describe services and their protocol endpoints in the registry.
+ * <p>
+ * Some adjacent interfaces exist to list attributes of the fields:
+ * <ul>
+ *   <li>{@link org.apache.hadoop.registry.client.types.AddressTypes}</li>
+ *   <li>{@link org.apache.hadoop.registry.client.types.yarn.PersistencePolicies}</li>
+ *   <li>{@link org.apache.hadoop.registry.client.types.ProtocolTypes}</li>
+ * </ul>
+ *
+ * The {@link org.apache.hadoop.registry.client.types.RegistryPathStatus}
+ * class is not saved to the registry —it is the status of a registry
+ * entry that can be retrieved from the API call. It is still
+ * designed to be marshalled to and from JSON, as it can be served up
+ * from REST front ends to the registry.
+ *
+ */
+package org.apache.hadoop.registry.client.types;

http://git-wip-us.apache.org/repos/asf/hadoop/blob/e2a9fa84/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/yarn/PersistencePolicies.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/yarn/PersistencePolicies.java b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/yarn/PersistencePolicies.java
new file mode 100644
index 0000000..e4c7272
--- /dev/null
+++ b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/yarn/PersistencePolicies.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.registry.client.types.yarn;
+
+import org.apache.hadoop.registry.client.types.ServiceRecord;
+
+/**
+ * Persistence policies for {@link ServiceRecord}
+ */
+
+public interface PersistencePolicies {
+
+  /**
+   * The record persists until removed manually: {@value}.
+   */
+  String PERMANENT = "permanent";
+
+  /**
+   * Remove when the YARN application defined in the id field
+   * terminates: {@value}.
+   */
+  String APPLICATION = "application";
+
+  /**
+   * Remove when the current YARN application attempt ID finishes: {@value}.
+   */
+  String APPLICATION_ATTEMPT = "application-attempt";
+
+  /**
+   * Remove when the YARN container in the ID field finishes: {@value}
+   */
+  String CONTAINER = "container";
+
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/e2a9fa84/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/yarn/YarnRegistryAttributes.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/yarn/YarnRegistryAttributes.java b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/yarn/YarnRegistryAttributes.java
new file mode 100644
index 0000000..b6e7a20
--- /dev/null
+++ b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/types/yarn/YarnRegistryAttributes.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.registry.client.types.yarn;
+
+/**
+ * YARN specific attributes in the registry.
+ */
+public final class YarnRegistryAttributes {
+
+  /**
+   * Hidden constructor.
+   */
+  private YarnRegistryAttributes() {
+  }
+
+  /**
+   * ID. For containers: container ID. For application instances,
+   * application ID.
+   */
+  public static final String YARN_ID = "yarn:id";
+  public static final String YARN_PERSISTENCE = "yarn:persistence";
+  public static final String YARN_PATH = "yarn:path";
+  public static final String YARN_HOSTNAME = "yarn:hostname";
+  public static final String YARN_IP = "yarn:ip";
+  public static final String YARN_COMPONENT = "yarn:component";
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/e2a9fa84/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/conf/RegistryConfiguration.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/conf/RegistryConfiguration.java b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/conf/RegistryConfiguration.java
new file mode 100644
index 0000000..ab06399
--- /dev/null
+++ b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/conf/RegistryConfiguration.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.registry.conf;
+
+import org.apache.hadoop.conf.Configuration;
+
+/**
+ * Intermediate configuration class to import the keys from YarnConfiguration
+ * in yarn-default.xml and yarn-site.xml. Once hadoop-yarn-registry is totally
+ * deprecated, this should be deprecated.
+ */
+public class RegistryConfiguration extends Configuration {
+
+  static {
+    Configuration.addDefaultResource("yarn-default.xml");
+    Configuration.addDefaultResource("yarn-site.xml");
+  }
+
+  /**
+   * Default constructor which relies on the static method to import the YARN
+   * settings.
+   */
+  public RegistryConfiguration() {
+    super();
+  }
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/e2a9fa84/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/conf/package-info.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/conf/package-info.java b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/conf/package-info.java
new file mode 100644
index 0000000..50d03eb
--- /dev/null
+++ b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/conf/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Configuration for the Hadoop Service Registry.
+ */
+package org.apache.hadoop.registry.conf;

http://git-wip-us.apache.org/repos/asf/hadoop/blob/e2a9fa84/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/server/dns/ApplicationServiceRecordProcessor.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/server/dns/ApplicationServiceRecordProcessor.java b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/server/dns/ApplicationServiceRecordProcessor.java
new file mode 100644
index 0000000..0b5f724
--- /dev/null
+++ b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/server/dns/ApplicationServiceRecordProcessor.java
@@ -0,0 +1,366 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.registry.server.dns;
+
+import org.apache.hadoop.registry.client.types.Endpoint;
+import org.apache.hadoop.registry.client.types.ServiceRecord;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xbill.DNS.Name;
+import org.xbill.DNS.Type;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A processor for generating application DNS records from registry service
+ * records.
+ */
+public class ApplicationServiceRecordProcessor extends
+    BaseServiceRecordProcessor {
+  private static final Logger LOG =
+      LoggerFactory.getLogger(ApplicationServiceRecordProcessor.class);
+  /**
+   * Create an application service record processor.
+   *
+   * @param record       the service record
+   * @param path         the service record registry node path
+   * @param domain       the DNS zone/domain name
+   * @param zoneSelector returns the zone associated with the provided name.
+   * @throws Exception  if an issue is generated during instantiation.
+   */
+  public ApplicationServiceRecordProcessor(
+      ServiceRecord record, String path, String domain,
+      ZoneSelector zoneSelector) throws Exception {
+    super(record, path, domain, zoneSelector);
+  }
+
+  /**
+   * Initializes the DNS record type to descriptor mapping based on the
+   * provided service record.
+   *
+   * @param serviceRecord the registry service record.
+   * @throws Exception if an issue is encountered.
+   */
+  @Override public void initTypeToInfoMapping(ServiceRecord serviceRecord)
+      throws Exception {
+    if (serviceRecord.external.isEmpty()) {
+      LOG.info(serviceRecord.description + ": No external endpoints defined.");
+      return;
+    }
+    for (int type : getRecordTypes()) {
+      switch (type) {
+      case Type.A:
+        createAInfo(serviceRecord);
+        break;
+      case Type.AAAA:
+        createAAAAInfo(serviceRecord);
+        break;
+      case Type.TXT:
+        createTXTInfo(serviceRecord);
+        break;
+      case Type.CNAME:
+        createCNAMEInfo(serviceRecord);
+        break;
+      case Type.SRV:
+        createSRVInfo(serviceRecord);
+        break;
+      default:
+        throw new IllegalArgumentException("Unknown type " + type);
+
+      }
+    }
+  }
+
+  /**
+   * Create an application TXT record descriptor.
+   *
+   * @param serviceRecord the service record.
+   * @throws Exception if there is an issue during descriptor creation.
+   */
+  protected void createTXTInfo(ServiceRecord serviceRecord) throws Exception {
+    List<Endpoint> endpoints = serviceRecord.external;
+    List<RecordDescriptor> recordDescriptors = new ArrayList<>();
+    TXTApplicationRecordDescriptor txtInfo;
+    for (Endpoint endpoint : endpoints) {
+      txtInfo = new TXTApplicationRecordDescriptor(
+          serviceRecord, endpoint);
+      recordDescriptors.add(txtInfo);
+    }
+    registerRecordDescriptor(Type.TXT, recordDescriptors);
+  }
+
+  /**
+   * Create an application SRV record descriptor.
+   *
+   * @param serviceRecord the service record.
+   * @throws Exception if there is an issue during descriptor creation.
+   */
+  protected void createSRVInfo(ServiceRecord serviceRecord) throws Exception {
+    List<Endpoint> endpoints = serviceRecord.external;
+    List<RecordDescriptor> recordDescriptors = new ArrayList<>();
+    SRVApplicationRecordDescriptor srvInfo;
+    for (Endpoint endpoint : endpoints) {
+      srvInfo = new SRVApplicationRecordDescriptor(
+          serviceRecord, endpoint);
+      recordDescriptors.add(srvInfo);
+    }
+    registerRecordDescriptor(Type.SRV, recordDescriptors);
+  }
+
+  /**
+   * Create an application CNAME record descriptor.
+   *
+   * @param serviceRecord the service record.
+   * @throws Exception if there is an issue during descriptor creation.
+   */
+  protected void createCNAMEInfo(ServiceRecord serviceRecord) throws Exception {
+    List<Endpoint> endpoints = serviceRecord.external;
+    List<RecordDescriptor> recordDescriptors = new ArrayList<>();
+    CNAMEApplicationRecordDescriptor cnameInfo;
+    for (Endpoint endpoint : endpoints) {
+      cnameInfo = new CNAMEApplicationRecordDescriptor(
+          serviceRecord, endpoint);
+      recordDescriptors.add(cnameInfo);
+    }
+    registerRecordDescriptor(Type.CNAME, recordDescriptors);
+  }
+
+  /**
+   * Create an application AAAA record descriptor.
+   *
+   * @param record the service record.
+   * @throws Exception if there is an issue during descriptor creation.
+   */
+  protected void createAAAAInfo(ServiceRecord record)
+      throws Exception {
+    AAAAApplicationRecordDescriptor
+        recordInfo = new AAAAApplicationRecordDescriptor(
+        getPath(), record);
+    registerRecordDescriptor(Type.AAAA, recordInfo);
+  }
+
+  /**
+   * Create an application A record descriptor.
+   *
+   * @param record the service record.
+   * @throws Exception if there is an issue during descriptor creation.
+   */
+  protected void createAInfo(ServiceRecord record) throws Exception {
+    AApplicationRecordDescriptor recordInfo = new AApplicationRecordDescriptor(
+        getPath(), record);
+    registerRecordDescriptor(Type.A, recordInfo);
+  }
+
+  /**
+   * Returns the record types associated with a container service record.
+   *
+   * @return the record type array
+   */
+  @Override public int[] getRecordTypes() {
+    return new int[] {Type.A, Type.AAAA, Type.CNAME, Type.SRV, Type.TXT};
+  }
+
+  /**
+   * An application TXT record descriptor.
+   */
+  class TXTApplicationRecordDescriptor
+      extends ApplicationRecordDescriptor<List<String>> {
+
+    /**
+     * Creates an application TXT record descriptor.
+     *
+     * @param record service record
+     * @throws Exception
+     */
+    public TXTApplicationRecordDescriptor(ServiceRecord record,
+        Endpoint endpoint) throws Exception {
+      super(record, endpoint);
+    }
+
+    /**
+     * Initializes the descriptor parameters.
+     *
+     * @param serviceRecord the service record.
+     */
+    @Override protected void init(ServiceRecord serviceRecord)
+        throws Exception {
+      if (getEndpoint() != null) {
+        this.setNames(new Name[] {getServiceName(), getEndpointName()});
+        this.setTarget(getTextRecords(getEndpoint()));
+      }
+    }
+
+  }
+
+  /**
+   * An application SRV record descriptor.
+   */
+  class SRVApplicationRecordDescriptor extends
+      ApplicationRecordDescriptor<RecordCreatorFactory.HostPortInfo> {
+
+    /**
+     * Creates an application SRV record descriptor.
+     *
+     * @param record service record
+     * @throws Exception
+     */
+    public SRVApplicationRecordDescriptor(ServiceRecord record,
+        Endpoint endpoint) throws Exception {
+      super(record, endpoint);
+    }
+
+    /**
+     * Initializes the descriptor parameters.
+     *
+     * @param serviceRecord the service record.
+     */
+    @Override protected void init(ServiceRecord serviceRecord)
+        throws Exception {
+      if (getEndpoint() != null) {
+        this.setNames(new Name[] {getServiceName(), getEndpointName()});
+        this.setTarget(new RecordCreatorFactory.HostPortInfo(
+            Name.fromString(getHost(getEndpoint()) + "."), getPort(
+            getEndpoint())));
+      }
+    }
+
+  }
+
+  /**
+   * An application CNAME record descriptor.
+   */
+  class CNAMEApplicationRecordDescriptor extends
+      ApplicationRecordDescriptor<Name> {
+
+    /**
+     * Creates an application CNAME record descriptor.
+     *
+     * @param path   registry path for service record
+     * @param record service record
+     * @throws Exception
+     */
+    public CNAMEApplicationRecordDescriptor(String path,
+        ServiceRecord record) throws Exception {
+      super(record);
+    }
+
+    /**
+     * Creates an application CNAME record descriptor.  This descriptor is the
+     * source for API related CNAME records.
+     *
+     * @param record   service record
+     * @param endpoint the API endpoint
+     * @throws Exception
+     */
+    public CNAMEApplicationRecordDescriptor(ServiceRecord record,
+        Endpoint endpoint) throws Exception {
+      super(record, endpoint);
+    }
+
+    /**
+     * Initializes the descriptor parameters.
+     *
+     * @param serviceRecord the service record.
+     */
+    @Override protected void init(ServiceRecord serviceRecord)
+        throws Exception {
+      if (getEndpoint() != null) {
+        this.setNames(new Name[] {getEndpointName()});
+        this.setTarget(getServiceName());
+      }
+    }
+
+  }
+
+  /**
+   * An application A record descriptor.
+   */
+  class AApplicationRecordDescriptor
+      extends ApplicationRecordDescriptor<InetAddress> {
+
+    /**
+     * Creates an application A record descriptor.
+     *
+     * @param path   registry path for service record
+     * @param record service record
+     * @throws Exception
+     */
+    public AApplicationRecordDescriptor(String path,
+        ServiceRecord record) throws Exception {
+      super(record);
+    }
+
+    /**
+     * Initializes the descriptor parameters.
+     *
+     * @param serviceRecord the service record.
+     */
+    @Override protected void init(ServiceRecord serviceRecord)
+        throws Exception {
+      this.setNames(new Name[] {getServiceName()});
+      List<Endpoint> endpoints = serviceRecord.external;
+      if (endpoints.isEmpty()) {
+        return;
+      }
+      // TODO:  do we need a "hostname" attribute for an application record or
+      // can we rely on the first endpoint record.
+      this.setTarget(InetAddress.getByName(
+          getHost(endpoints.get(0))));
+    }
+
+  }
+
+  /**
+   * An application AAAA record descriptor.
+   */
+  class AAAAApplicationRecordDescriptor extends AApplicationRecordDescriptor {
+
+    /**
+     * Creates an application AAAA record descriptor.
+     *
+     * @param path   registry path for service record
+     * @param record service record
+     * @throws Exception
+     */
+    public AAAAApplicationRecordDescriptor(String path,
+        ServiceRecord record) throws Exception {
+      super(path, record);
+    }
+
+    /**
+     * Initializes the descriptor parameters.
+     *
+     * @param serviceRecord the service record.
+     */
+    @Override protected void init(ServiceRecord serviceRecord)
+        throws Exception {
+      super.init(serviceRecord);
+      if (getTarget() == null) {
+        return;
+      }
+      try {
+        this.setTarget(getIpv6Address(getTarget()));
+      } catch (UnknownHostException e) {
+        throw new IllegalStateException(e);
+      }
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/e2a9fa84/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/server/dns/BaseServiceRecordProcessor.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/server/dns/BaseServiceRecordProcessor.java b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/server/dns/BaseServiceRecordProcessor.java
new file mode 100644
index 0000000..f30c0c2
--- /dev/null
+++ b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/server/dns/BaseServiceRecordProcessor.java
@@ -0,0 +1,470 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.registry.server.dns;
+
+import org.apache.hadoop.fs.PathNotFoundException;
+import org.apache.hadoop.registry.client.binding.RegistryPathUtils;
+import org.apache.hadoop.registry.client.types.AddressTypes;
+import org.apache.hadoop.registry.client.types.Endpoint;
+import org.apache.hadoop.registry.client.types.ServiceRecord;
+import org.xbill.DNS.Name;
+import org.xbill.DNS.ReverseMap;
+import org.xbill.DNS.TextParseException;
+
+import java.io.IOException;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.URI;
+import java.net.UnknownHostException;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Provides common service record processing logic.
+ */
+public abstract class BaseServiceRecordProcessor
+    implements ServiceRecordProcessor {
+
+  private final ZoneSelector zoneSelctor;
+  private Map<Integer, List<RecordDescriptor>> typeToDescriptorMap =
+      new HashMap<>();
+  private String path;
+  private String domain;
+
+  private static final String YARN_SERVICE_API_PREFIX =
+      "classpath:org.apache.hadoop.yarn.service.";
+  private static final String HTTP_API_TYPE = "http://";
+
+  /**
+   * Creates a service record processor.
+   *
+   * @param record       the service record.
+   * @param path         the node path for the record in the registry.
+   * @param domain       the target DNS domain for the service record
+   *                     associated DNS records.
+   * @param zoneSelector A selector of the best zone for a given DNS name.
+   * @throws Exception if an issue is generated during instantiation.
+   */
+  public BaseServiceRecordProcessor(ServiceRecord record, String path,
+      String domain, ZoneSelector zoneSelector)
+      throws Exception {
+    this.setPath(path);
+    this.domain = domain;
+    this.zoneSelctor = zoneSelector;
+    initTypeToInfoMapping(record);
+  }
+
+  /**
+   * Return the IPv6 mapped address for the provided IPv4 address. Utilized
+   * to create corresponding AAAA records.
+   *
+   * @param address the IPv4 address.
+   * @return the mapped IPv6 address.
+   * @throws UnknownHostException
+   */
+  static InetAddress getIpv6Address(InetAddress address)
+      throws UnknownHostException {
+    String[] octets = address.getHostAddress().split("\\.");
+    byte[] octetBytes = new byte[4];
+    for (int i = 0; i < 4; ++i) {
+      octetBytes[i] = (byte) Integer.parseInt(octets[i]);
+    }
+
+    byte[] ipv4asIpV6addr = new byte[16];
+    ipv4asIpV6addr[10] = (byte) 0xff;
+    ipv4asIpV6addr[11] = (byte) 0xff;
+    ipv4asIpV6addr[12] = octetBytes[0];
+    ipv4asIpV6addr[13] = octetBytes[1];
+    ipv4asIpV6addr[14] = octetBytes[2];
+    ipv4asIpV6addr[15] = octetBytes[3];
+
+    return Inet6Address.getByAddress(null, ipv4asIpV6addr, 0);
+  }
+
+  /**
+   * Reverse the string representation of the input IP address.
+   *
+   * @param ip the string representation of the IP address.
+   * @return the reversed IP address.
+   * @throws UnknownHostException if the ip is unknown.
+   */
+  protected Name reverseIP(String ip) throws UnknownHostException {
+    return ReverseMap.fromAddress(ip);
+  }
+
+  /**
+   * Manages the creation and registration of service record generated DNS
+   * records.
+   *
+   * @param command the DNS registration command object (e.g. add_record,
+   *                remove record)
+   * @throws IOException if the creation or registration generates an issue.
+   */
+  @SuppressWarnings({"unchecked"})
+  public void manageDNSRecords(RegistryDNS.RegistryCommand command)
+      throws IOException {
+    for (Map.Entry<Integer, List<RecordDescriptor>> entry :
+        typeToDescriptorMap.entrySet()) {
+      for (RecordDescriptor recordDescriptor : entry.getValue()) {
+        for (Name name : recordDescriptor.getNames()) {
+          RecordCreatorFactory.RecordCreator recordCreator =
+              RecordCreatorFactory.getRecordCreator(entry.getKey());
+          command.exec(zoneSelctor.findBestZone(name),
+              recordCreator.create(name, recordDescriptor.getTarget()));
+        }
+      }
+    }
+  }
+
+  /**
+   * Add the DNS record descriptor object to the record type to descriptor
+   * mapping.
+   *
+   * @param type             the DNS record type.
+   * @param recordDescriptor the DNS record descriptor
+   */
+  protected void registerRecordDescriptor(int type,
+      RecordDescriptor recordDescriptor) {
+    List<RecordDescriptor> infos = new ArrayList<>();
+    infos.add(recordDescriptor);
+    typeToDescriptorMap.put(type, infos);
+  }
+
+  /**
+   * Add the DNS record descriptor objects to the record type to descriptor
+   * mapping.
+   *
+   * @param type              the DNS record type.
+   * @param recordDescriptors the DNS record descriptors
+   */
+  protected void registerRecordDescriptor(int type,
+      List<RecordDescriptor> recordDescriptors) {
+    typeToDescriptorMap.put(type, recordDescriptors);
+  }
+
+  /**
+   * Return the path associated with the record.
+   * @return the path.
+   */
+  protected String getPath() {
+    return path;
+  }
+
+  /**
+   * Set the path associated with the record.
+   * @param path the path.
+   */
+  protected void setPath(String path) {
+    this.path = path;
+  }
+
+  /**
+   * A descriptor container the information to be populated into a DNS record.
+   *
+   * @param <T> the DNS record type/class.
+   */
+  abstract class RecordDescriptor<T> {
+    private final ServiceRecord record;
+    private Name[] names;
+    private T target;
+
+    /**
+     * Creates a DNS record descriptor.
+     *
+     * @param record the associated service record.
+     */
+    public RecordDescriptor(ServiceRecord record) {
+      this.record = record;
+    }
+
+    /**
+     * Returns the DNS names associated with the record type and information.
+     *
+     * @return the array of names.
+     */
+    public Name[] getNames() {
+      return names;
+    }
+
+    /**
+     * Return the target object for the DNS record.
+     *
+     * @return the DNS record target.
+     */
+    public T getTarget() {
+      return target;
+    }
+
+    /**
+     * Initializes the names and information for this DNS record descriptor.
+     *
+     * @param serviceRecord the service record.
+     * @throws Exception
+     */
+    protected abstract void init(ServiceRecord serviceRecord) throws Exception;
+
+    /**
+     * Returns the service record.
+     * @return the service record.
+     */
+    public ServiceRecord getRecord() {
+      return record;
+    }
+
+    /**
+     * Sets the names associated with the record type and information.
+     * @param names the names.
+     */
+    public void setNames(Name[] names) {
+      this.names = names;
+    }
+
+    /**
+     * Sets the target object associated with the record.
+     * @param target the target.
+     */
+    public void setTarget(T target) {
+      this.target = target;
+    }
+  }
+
+  /**
+   * A container-based DNS record descriptor.
+   *
+   * @param <T> the DNS record type/class.
+   */
+  abstract class ContainerRecordDescriptor<T> extends RecordDescriptor<T> {
+
+    public ContainerRecordDescriptor(String path, ServiceRecord record)
+        throws Exception {
+      super(record);
+      init(record);
+    }
+
+    /**
+     * Returns the DNS name constructed from the YARN container ID.
+     *
+     * @return the container ID name.
+     * @throws TextParseException
+     */
+    protected Name getContainerIDName() throws TextParseException {
+      String containerID = RegistryPathUtils.lastPathEntry(getPath());
+      return Name.fromString(String.format("%s.%s", containerID, domain));
+    }
+
+    /**
+     * Returns the DNS name constructed from the container role/component name.
+     *
+     * @return the DNS naem.
+     * @throws PathNotFoundException
+     * @throws TextParseException
+     */
+    protected Name getContainerName()
+        throws PathNotFoundException, TextParseException {
+      String service = RegistryPathUtils.lastPathEntry(
+          RegistryPathUtils.parentOf(RegistryPathUtils.parentOf(getPath())));
+      String description = getRecord().description.toLowerCase();
+      String user = RegistryPathUtils.getUsername(getPath());
+      return Name.fromString(MessageFormat.format("{0}.{1}.{2}.{3}",
+          description,
+          service,
+          user,
+          domain));
+    }
+
+    /**
+     * Return the DNS name constructed from the component name.
+     *
+     * @return the DNS naem.
+     * @throws PathNotFoundException
+     * @throws TextParseException
+     */
+    protected Name getComponentName()
+        throws PathNotFoundException, TextParseException {
+      String service = RegistryPathUtils.lastPathEntry(
+          RegistryPathUtils.parentOf(RegistryPathUtils.parentOf(getPath())));
+      String component = getRecord().get("yarn:component").toLowerCase();
+      String user = RegistryPathUtils.getUsername(getPath());
+      return Name.fromString(MessageFormat.format("{0}.{1}.{2}.{3}",
+          component,
+          service,
+          user,
+          domain));
+    }
+
+  }
+
+  /**
+   * An application-based DNS record descriptor.
+   *
+   * @param <T> the DNS record type/class.
+   */
+  abstract class ApplicationRecordDescriptor<T> extends RecordDescriptor<T> {
+
+    private Endpoint srEndpoint;
+
+    /**
+     * Creates an application associated DNS record descriptor.
+     *
+     * @param record the service record.
+     * @throws Exception
+     */
+    public ApplicationRecordDescriptor(ServiceRecord record)
+        throws Exception {
+      this(record, null);
+    }
+
+    /**
+     * Creates an application associated DNS record descriptor.  The endpoint
+     * is leverated to create an associated application API record.
+     *
+     * @param record   the service record.
+     * @param endpoint an API endpoint.
+     * @throws Exception
+     */
+    public ApplicationRecordDescriptor(ServiceRecord record,
+        Endpoint endpoint) throws Exception {
+      super(record);
+      this.setEndpoint(endpoint);
+      init(record);
+    }
+
+    /**
+     * Get the service's DNS name for registration.
+     *
+     * @return the service DNS name.
+     * @throws TextParseException
+     */
+    protected Name getServiceName() throws TextParseException {
+      String user = RegistryPathUtils.getUsername(getPath());
+      String service =
+          String.format("%s.%s.%s",
+              RegistryPathUtils.lastPathEntry(getPath()),
+              user,
+              domain);
+      return Name.fromString(service);
+    }
+
+    /**
+     * Get the host from the provided endpoint record.
+     *
+     * @param endpoint the endpoint info.
+     * @return the host name.
+     */
+    protected String getHost(Endpoint endpoint) {
+      String host = null;
+      // assume one address for now
+      Map<String, String> address = endpoint.addresses.get(0);
+      if (endpoint.addressType.equals(AddressTypes.ADDRESS_HOSTNAME_AND_PORT)) {
+        host = address.get(AddressTypes.ADDRESS_HOSTNAME_FIELD);
+      } else if (endpoint.addressType.equals(AddressTypes.ADDRESS_URI)) {
+        URI uri = URI.create(address.get("uri"));
+        host = uri.getHost();
+      }
+      return host;
+    }
+
+    /**
+     * Get the post from the provided endpoint record.
+     *
+     * @param endpoint the endpoint info.
+     * @return the port.
+     */
+    protected int getPort(Endpoint endpoint) {
+      int port = -1;
+      // assume one address for now
+      Map<String, String> address = endpoint.addresses.get(0);
+      if (endpoint.addressType.equals(AddressTypes.ADDRESS_HOSTNAME_AND_PORT)) {
+        port = Integer.parseInt(address.get(AddressTypes.ADDRESS_PORT_FIELD));
+      } else if (endpoint.addressType.equals(AddressTypes.ADDRESS_URI)) {
+        URI uri = URI.create(address.get("uri"));
+        port = uri.getPort();
+      }
+      return port;
+    }
+
+    /**
+     * Get the list of strings that can be related in a TXT record for the given
+     * endpoint.
+     *
+     * @param endpoint the endpoint information.
+     * @return the list of strings relating endpoint info.
+     */
+    protected List<String> getTextRecords(Endpoint endpoint) {
+      Map<String, String> address = endpoint.addresses.get(0);
+      List<String> txtRecs = new ArrayList<String>();
+      txtRecs.add("api=" + getDNSApiFragment(endpoint.api));
+      if (endpoint.addressType.equals(AddressTypes.ADDRESS_URI)) {
+        URI uri = URI.create(address.get("uri"));
+        txtRecs.add("path=" + uri.getPath());
+      }
+      return txtRecs;
+    }
+
+    /**
+     * Get an API name that is compatible with DNS standards (and shortened).
+     *
+     * @param api the api indicator.
+     * @return the shortened and compatible api name.
+     */
+    protected String getDNSApiFragment(String api) {
+      String dnsApi = null;
+      if (api.startsWith(YARN_SERVICE_API_PREFIX)) {
+        dnsApi = api.substring(YARN_SERVICE_API_PREFIX.length());
+      } else if (api.startsWith(HTTP_API_TYPE)) {
+        dnsApi = "http";
+      }
+      assert dnsApi != null;
+      dnsApi = dnsApi.replace('.', '-');
+      return dnsApi;
+    }
+
+    /**
+     * Return the DNS name associated with the API endpoint.
+     *
+     * @return the name.
+     * @throws TextParseException
+     */
+    protected Name getEndpointName() throws TextParseException {
+      return Name.fromString(String.format("%s-api.%s",
+          getDNSApiFragment(
+              getEndpoint().api),
+          getServiceName()));
+    }
+
+    /**
+     * Returns the endpoint.
+     * @return the endpoint.
+     */
+    public Endpoint getEndpoint() {
+      return srEndpoint;
+    }
+
+    /**
+     * Sets the endpoint.
+     * @param endpoint the endpoint.
+     */
+    public void setEndpoint(
+        Endpoint endpoint) {
+      this.srEndpoint = endpoint;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/e2a9fa84/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/server/dns/ContainerServiceRecordProcessor.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/server/dns/ContainerServiceRecordProcessor.java b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/server/dns/ContainerServiceRecordProcessor.java
new file mode 100644
index 0000000..e40a177
--- /dev/null
+++ b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/server/dns/ContainerServiceRecordProcessor.java
@@ -0,0 +1,284 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.registry.server.dns;
+
+import org.apache.hadoop.fs.PathNotFoundException;
+import org.apache.hadoop.registry.client.types.ServiceRecord;
+import org.apache.hadoop.registry.client.types.yarn.YarnRegistryAttributes;
+import org.xbill.DNS.Name;
+import org.xbill.DNS.TextParseException;
+import org.xbill.DNS.Type;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A processor for generating container DNS records from registry service
+ * records.
+ */
+public class ContainerServiceRecordProcessor extends
+    BaseServiceRecordProcessor {
+
+  /**
+   * Create a container service record processor.
+   * @param record the service record
+   * @param path the service record registry node path
+   * @param domain the DNS zone/domain name
+   * @param zoneSelector returns the zone associated with the provided name.
+   * @throws Exception if an issue is generated during instantiation.
+   */
+  public ContainerServiceRecordProcessor(
+      ServiceRecord record, String path, String domain,
+      ZoneSelector zoneSelector) throws Exception {
+    super(record, path, domain, zoneSelector);
+  }
+
+  /**
+   * Initializes the DNS record type to descriptor mapping based on the
+   * provided service record.
+   * @param serviceRecord  the registry service record.
+   * @throws Exception if an issue arises.
+   */
+  @Override public void initTypeToInfoMapping(ServiceRecord serviceRecord)
+      throws Exception {
+    if (serviceRecord.get(YarnRegistryAttributes.YARN_IP) != null) {
+      for (int type : getRecordTypes()) {
+        switch (type) {
+        case Type.A:
+          createAInfo(serviceRecord);
+          break;
+        case Type.AAAA:
+          createAAAAInfo(serviceRecord);
+          break;
+        case Type.PTR:
+          createPTRInfo(serviceRecord);
+          break;
+        case Type.TXT:
+          createTXTInfo(serviceRecord);
+          break;
+        default:
+          throw new IllegalArgumentException("Unknown type " + type);
+
+        }
+      }
+    }
+  }
+
+  /**
+   * Create a container TXT record descriptor.
+   * @param serviceRecord the service record.
+   * @throws Exception if the descriptor creation yields an issue.
+   */
+  protected void createTXTInfo(ServiceRecord serviceRecord) throws Exception {
+    TXTContainerRecordDescriptor txtInfo =
+        new TXTContainerRecordDescriptor(getPath(), serviceRecord);
+    registerRecordDescriptor(Type.TXT, txtInfo);
+  }
+
+  /**
+   * Creates a container PTR record descriptor.
+   * @param record the service record.
+   * @throws Exception if the descriptor creation yields an issue.
+   */
+  protected void createPTRInfo(ServiceRecord record) throws Exception {
+    PTRContainerRecordDescriptor
+        ptrInfo = new PTRContainerRecordDescriptor(getPath(), record);
+    registerRecordDescriptor(Type.PTR, ptrInfo);
+  }
+
+  /**
+   * Creates a container AAAA (IPv6) record descriptor.
+   * @param record the service record
+   * @throws Exception if the descriptor creation yields an issue.
+   */
+  protected void createAAAAInfo(ServiceRecord record)
+      throws Exception {
+    AAAAContainerRecordDescriptor
+        recordInfo = new AAAAContainerRecordDescriptor(
+        getPath(), record);
+    registerRecordDescriptor(Type.AAAA, recordInfo);
+  }
+
+  /**
+   * Creates a container A (IPv4) record descriptor.
+   * @param record service record.
+   * @throws Exception if the descriptor creation yields an issue.
+   */
+  protected void createAInfo(ServiceRecord record) throws Exception {
+    AContainerRecordDescriptor recordInfo = new AContainerRecordDescriptor(
+        getPath(), record);
+    registerRecordDescriptor(Type.A, recordInfo);
+  }
+
+  /**
+   * Returns the record types associated with a container service record.
+   * @return the record type array
+   */
+  @Override public int[] getRecordTypes() {
+    return new int[] {Type.A, Type.AAAA, Type.PTR, Type.TXT};
+  }
+
+  /**
+   * A container TXT record descriptor.
+   */
+  class TXTContainerRecordDescriptor
+      extends ContainerRecordDescriptor<List<String>> {
+
+    /**
+     * Creates a container TXT record descriptor.
+     * @param path registry path for service record
+     * @param record service record
+     * @throws Exception
+     */
+    public TXTContainerRecordDescriptor(String path,
+        ServiceRecord record) throws Exception {
+      super(path, record);
+    }
+
+    /**
+     * Initializes the descriptor parameters.
+     * @param serviceRecord  the service record.
+     */
+    @Override protected void init(ServiceRecord serviceRecord) {
+      try {
+        this.setNames(new Name[] {getContainerName()});
+      } catch (TextParseException e) {
+        // log
+      } catch (PathNotFoundException e) {
+        // log
+      }
+      List<String> txts = new ArrayList<>();
+      txts.add("id=" + serviceRecord.get(YarnRegistryAttributes.YARN_ID));
+      this.setTarget(txts);
+    }
+
+  }
+
+  /**
+   * A container PTR record descriptor.
+   */
+  class PTRContainerRecordDescriptor extends ContainerRecordDescriptor<Name> {
+
+    /**
+     * Creates a container PTR record descriptor.
+     * @param path registry path for service record
+     * @param record service record
+     * @throws Exception
+     */
+    public PTRContainerRecordDescriptor(String path,
+        ServiceRecord record) throws Exception {
+      super(path, record);
+    }
+
+    /**
+     * Initializes the descriptor parameters.
+     * @param serviceRecord  the service record.
+     */
+    @Override protected void init(ServiceRecord serviceRecord) {
+      String host = serviceRecord.get(YarnRegistryAttributes.YARN_HOSTNAME);
+      String ip = serviceRecord.get(YarnRegistryAttributes.YARN_IP);
+      Name reverseLookupName = null;
+      if (host != null && ip != null) {
+        try {
+          reverseLookupName = reverseIP(ip);
+        } catch (UnknownHostException e) {
+          //LOG
+        }
+      }
+      this.setNames(new Name[] {reverseLookupName});
+      try {
+        this.setTarget(getContainerName());
+      } catch (TextParseException e) {
+        //LOG
+      } catch (PathNotFoundException e) {
+        //LOG
+      }
+    }
+
+  }
+
+
+  /**
+   * A container A record descriptor.
+   */
+  class AContainerRecordDescriptor
+      extends ContainerRecordDescriptor<InetAddress> {
+
+    /**
+     * Creates a container A record descriptor.
+     * @param path registry path for service record
+     * @param record service record
+     * @throws Exception
+     */
+    public AContainerRecordDescriptor(String path,
+        ServiceRecord record) throws Exception {
+      super(path, record);
+    }
+
+    /**
+     * Initializes the descriptor parameters.
+     * @param serviceRecord  the service record.
+     */
+    @Override protected void init(ServiceRecord serviceRecord) {
+      String ip = serviceRecord.get(YarnRegistryAttributes.YARN_IP);
+      if (ip == null) {
+        throw new IllegalArgumentException("No IP specified");
+      }
+      try {
+        this.setTarget(InetAddress.getByName(ip));
+        this.setNames(new Name[] {getContainerName(), getContainerIDName(),
+            getComponentName()});
+      } catch (Exception e) {
+        throw new IllegalStateException(e);
+      }
+
+    }
+
+  }
+
+  /**
+   * A container AAAA record descriptor.
+   */
+  class AAAAContainerRecordDescriptor extends AContainerRecordDescriptor {
+
+    /**
+     * Creates a container AAAA record descriptor.
+     * @param path registry path for service record
+     * @param record service record
+     * @throws Exception
+     */
+    public AAAAContainerRecordDescriptor(String path,
+        ServiceRecord record) throws Exception {
+      super(path, record);
+    }
+
+    /**
+     * Initializes the descriptor parameters.
+     * @param serviceRecord  the service record.
+     */
+    @Override protected void init(ServiceRecord serviceRecord) {
+      super.init(serviceRecord);
+      try {
+        this.setTarget(getIpv6Address(getTarget()));
+      } catch (UnknownHostException e) {
+        throw new IllegalStateException(e);
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/e2a9fa84/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/server/dns/LookupTask.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/server/dns/LookupTask.java b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/server/dns/LookupTask.java
new file mode 100644
index 0000000..c2fc4a9
--- /dev/null
+++ b/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/server/dns/LookupTask.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.registry.server.dns;
+
+import java.util.concurrent.Callable;
+
+import org.xbill.DNS.Lookup;
+import org.xbill.DNS.Name;
+import org.xbill.DNS.Record;
+
+public class LookupTask implements Callable<Record[]> {
+
+  private Name name;
+  private int type;
+
+  public LookupTask(Name name, int type) {
+    this.name = name;
+    this.type = type;
+  }
+
+  @Override
+  public Record[] call() throws Exception {
+    return new Lookup(name, type).run();
+  }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: common-commits-unsubscribe@hadoop.apache.org
For additional commands, e-mail: common-commits-help@hadoop.apache.org


Mime
View raw message