knox-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From su...@apache.org
Subject knox git commit: KNOX-719 YARN RM HA implementation for REST API and UI (Jeffrey E Rodriguez and Sumit Gupta)
Date Wed, 01 Mar 2017 03:12:12 GMT
Repository: knox
Updated Branches:
  refs/heads/master 9596f2dc2 -> 5ae580ed0


KNOX-719 YARN RM HA implementation for REST API and UI (Jeffrey E Rodriguez and Sumit Gupta)


Project: http://git-wip-us.apache.org/repos/asf/knox/repo
Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/5ae580ed
Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/5ae580ed
Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/5ae580ed

Branch: refs/heads/master
Commit: 5ae580ed00cb4cff5691bf5d7ee8ce208b1a6d05
Parents: 9596f2d
Author: Sumit Gupta <sumit@apache.org>
Authored: Tue Feb 28 22:10:42 2017 -0500
Committer: Sumit Gupta <sumit@apache.org>
Committed: Tue Feb 28 22:10:42 2017 -0500

----------------------------------------------------------------------
 .../hadoop/gateway/ha/provider/HaProvider.java  |   8 +
 .../hadoop/gateway/ha/provider/URLManager.java  |   2 +
 .../ha/provider/impl/DefaultHaProvider.java     |  10 +
 .../ha/provider/impl/DefaultURLManager.java     |  16 ++
 .../ha/provider/impl/DefaultHaProviderTest.java |   8 +
 gateway-release/pom.xml                         |   4 +
 .../services/yarn-rm/2.5.0/service.xml          |   1 +
 .../resources/services/yarnui/2.7.0/service.xml |   1 +
 gateway-service-rm/pom.xml                      |  81 +++++++
 .../gateway/rm/dispatch/RMHaBaseDispatcher.java | 220 +++++++++++++++++++
 .../gateway/rm/dispatch/RMHaDispatch.java       |  54 +++++
 .../gateway/rm/dispatch/RMUIHaDispatch.java     |  54 +++++
 .../gateway/rm/dispatch/SafeModeException.java  |  21 ++
 .../gateway/rm/dispatch/StandbyException.java   |  21 ++
 .../hadoop/gateway/rm/i18n/RMMessages.java      |  46 ++++
 .../gateway/rm/dispatch/RMHaDispatchTest.java   | 219 ++++++++++++++++++
 pom.xml                                         |   6 +
 17 files changed, 772 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/knox/blob/5ae580ed/gateway-provider-ha/src/main/java/org/apache/hadoop/gateway/ha/provider/HaProvider.java
----------------------------------------------------------------------
diff --git a/gateway-provider-ha/src/main/java/org/apache/hadoop/gateway/ha/provider/HaProvider.java
b/gateway-provider-ha/src/main/java/org/apache/hadoop/gateway/ha/provider/HaProvider.java
index 5e1b91d..71d929d 100644
--- a/gateway-provider-ha/src/main/java/org/apache/hadoop/gateway/ha/provider/HaProvider.java
+++ b/gateway-provider-ha/src/main/java/org/apache/hadoop/gateway/ha/provider/HaProvider.java
@@ -48,6 +48,14 @@ public interface HaProvider {
    public String getActiveURL(String serviceName);
 
    /**
+    * Sets a given URL that is known to be active for the service
+    *
+    * @param serviceName the name of the service
+    * @param url the active url
+    */
+   public void setActiveURL(String serviceName, String url);
+
+   /**
     * Mark the URL for the service as one that has failed. This method puts changes the active
URL to
     * the next available URL for the service.
     *

http://git-wip-us.apache.org/repos/asf/knox/blob/5ae580ed/gateway-provider-ha/src/main/java/org/apache/hadoop/gateway/ha/provider/URLManager.java
----------------------------------------------------------------------
diff --git a/gateway-provider-ha/src/main/java/org/apache/hadoop/gateway/ha/provider/URLManager.java
b/gateway-provider-ha/src/main/java/org/apache/hadoop/gateway/ha/provider/URLManager.java
index 27da958..e9de8f0 100644
--- a/gateway-provider-ha/src/main/java/org/apache/hadoop/gateway/ha/provider/URLManager.java
+++ b/gateway-provider-ha/src/main/java/org/apache/hadoop/gateway/ha/provider/URLManager.java
@@ -27,6 +27,8 @@ public interface URLManager {
 
   public String getActiveURL();
 
+  public void setActiveURL(String url);
+
   public List<String> getURLs();
 
   public void setURLs(List<String> urls);

http://git-wip-us.apache.org/repos/asf/knox/blob/5ae580ed/gateway-provider-ha/src/main/java/org/apache/hadoop/gateway/ha/provider/impl/DefaultHaProvider.java
----------------------------------------------------------------------
diff --git a/gateway-provider-ha/src/main/java/org/apache/hadoop/gateway/ha/provider/impl/DefaultHaProvider.java
b/gateway-provider-ha/src/main/java/org/apache/hadoop/gateway/ha/provider/impl/DefaultHaProvider.java
index 302275e..b1da180 100644
--- a/gateway-provider-ha/src/main/java/org/apache/hadoop/gateway/ha/provider/impl/DefaultHaProvider.java
+++ b/gateway-provider-ha/src/main/java/org/apache/hadoop/gateway/ha/provider/impl/DefaultHaProvider.java
@@ -76,6 +76,16 @@ public class DefaultHaProvider implements HaProvider {
   }
 
   @Override
+  public void setActiveURL(String serviceName, String url) {
+    if ( haServices.containsKey(serviceName) ) {
+      haServices.get(serviceName).setActiveURL(url);
+    } else {
+      LOG.noServiceFound(serviceName);
+    }
+
+  }
+
+  @Override
   public void markFailedURL(String serviceName, String url) {
     if ( haServices.containsKey(serviceName) ) {
       haServices.get(serviceName).markFailed(url);

http://git-wip-us.apache.org/repos/asf/knox/blob/5ae580ed/gateway-provider-ha/src/main/java/org/apache/hadoop/gateway/ha/provider/impl/DefaultURLManager.java
----------------------------------------------------------------------
diff --git a/gateway-provider-ha/src/main/java/org/apache/hadoop/gateway/ha/provider/impl/DefaultURLManager.java
b/gateway-provider-ha/src/main/java/org/apache/hadoop/gateway/ha/provider/impl/DefaultURLManager.java
index e5b11ef..484a580 100644
--- a/gateway-provider-ha/src/main/java/org/apache/hadoop/gateway/ha/provider/impl/DefaultURLManager.java
+++ b/gateway-provider-ha/src/main/java/org/apache/hadoop/gateway/ha/provider/impl/DefaultURLManager.java
@@ -24,6 +24,7 @@ import org.apache.hadoop.gateway.ha.provider.impl.i18n.HaMessages;
 import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
 
 import java.net.URI;
+import java.util.Iterator;
 import java.util.List;
 import java.util.concurrent.ConcurrentLinkedQueue;
 
@@ -52,6 +53,21 @@ public class DefaultURLManager implements URLManager {
   }
 
   @Override
+  public synchronized void setActiveURL(String url) {
+    String top = urls.peek();
+    if (top.equalsIgnoreCase(url)) {
+      return;
+    }
+    if (urls.contains(url)) {
+      urls.remove(url);
+      List<String> remainingList = getURLs();
+      urls.clear();
+      urls.add(url);
+      urls.addAll(remainingList);
+    }
+  }
+
+  @Override
   public List<String> getURLs() {
     return Lists.newArrayList(urls.iterator());
   }

http://git-wip-us.apache.org/repos/asf/knox/blob/5ae580ed/gateway-provider-ha/src/test/java/org/apache/hadoop/gateway/ha/provider/impl/DefaultHaProviderTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-ha/src/test/java/org/apache/hadoop/gateway/ha/provider/impl/DefaultHaProviderTest.java
b/gateway-provider-ha/src/test/java/org/apache/hadoop/gateway/ha/provider/impl/DefaultHaProviderTest.java
index 18a42e3..87a63f4 100644
--- a/gateway-provider-ha/src/test/java/org/apache/hadoop/gateway/ha/provider/impl/DefaultHaProviderTest.java
+++ b/gateway-provider-ha/src/test/java/org/apache/hadoop/gateway/ha/provider/impl/DefaultHaProviderTest.java
@@ -66,12 +66,20 @@ public class DefaultHaProviderTest {
       urls.add(url1);
       String url2 = "http://host2";
       urls.add(url2);
+      String url3 = "http://host3";
+      urls.add(url3);
       String serviceName = "foo";
       provider.addHaService(serviceName, urls);
       assertEquals(url1, provider.getActiveURL(serviceName));
       provider.markFailedURL(serviceName, url1);
       assertEquals(url2, provider.getActiveURL(serviceName));
       provider.markFailedURL(serviceName, url2);
+      assertEquals(url3, provider.getActiveURL(serviceName));
+      provider.markFailedURL(serviceName, url3);
       assertEquals(url1, provider.getActiveURL(serviceName));
+      provider.setActiveURL(serviceName, url3);
+      assertEquals(url3, provider.getActiveURL(serviceName));
+      provider.setActiveURL(serviceName, url2);
+      assertEquals(url2, provider.getActiveURL(serviceName));
    }
 }

http://git-wip-us.apache.org/repos/asf/knox/blob/5ae580ed/gateway-release/pom.xml
----------------------------------------------------------------------
diff --git a/gateway-release/pom.xml b/gateway-release/pom.xml
index 57003fc..eed7921 100644
--- a/gateway-release/pom.xml
+++ b/gateway-release/pom.xml
@@ -188,6 +188,10 @@
         </dependency>
         <dependency>
             <groupId>${gateway-group}</groupId>
+            <artifactId>gateway-service-rm</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${gateway-group}</groupId>
             <artifactId>gateway-service-storm</artifactId>
         </dependency>
         <dependency>

http://git-wip-us.apache.org/repos/asf/knox/blob/5ae580ed/gateway-service-definitions/src/main/resources/services/yarn-rm/2.5.0/service.xml
----------------------------------------------------------------------
diff --git a/gateway-service-definitions/src/main/resources/services/yarn-rm/2.5.0/service.xml
b/gateway-service-definitions/src/main/resources/services/yarn-rm/2.5.0/service.xml
index 6b4c6a5..beb7967 100644
--- a/gateway-service-definitions/src/main/resources/services/yarn-rm/2.5.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/yarn-rm/2.5.0/service.xml
@@ -56,4 +56,5 @@
         <testURL>/resourcemanager/v1/cluster/metrics</testURL>
         <testURL>/resourcemanager/v1/cluster/apps</testURL>
     </testURLs>
+    <dispatch classname="org.apache.hadoop.gateway.dispatch.DefaultDispatch" ha-classname="org.apache.hadoop.gateway.rm.dispatch.RMHaDispatch"/>
 </service>

http://git-wip-us.apache.org/repos/asf/knox/blob/5ae580ed/gateway-service-definitions/src/main/resources/services/yarnui/2.7.0/service.xml
----------------------------------------------------------------------
diff --git a/gateway-service-definitions/src/main/resources/services/yarnui/2.7.0/service.xml
b/gateway-service-definitions/src/main/resources/services/yarnui/2.7.0/service.xml
index 2e3b673..7411085 100644
--- a/gateway-service-definitions/src/main/resources/services/yarnui/2.7.0/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/yarnui/2.7.0/service.xml
@@ -39,4 +39,5 @@
             <rewrite apply="YARNUI/yarn/outbound/headers/sparkhistory/job" to="response.headers"/>
         </route>
     </routes>
+    <dispatch classname="org.apache.hadoop.gateway.dispatch.DefaultDispatch" ha-classname="org.apache.hadoop.gateway.rm.dispatch.RMUIHaDispatch"/>
 </service>

http://git-wip-us.apache.org/repos/asf/knox/blob/5ae580ed/gateway-service-rm/pom.xml
----------------------------------------------------------------------
diff --git a/gateway-service-rm/pom.xml b/gateway-service-rm/pom.xml
new file mode 100644
index 0000000..5f0734c
--- /dev/null
+++ b/gateway-service-rm/pom.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.knox</groupId>
+        <artifactId>gateway</artifactId>
+        <version>0.12.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>gateway-service-rm</artifactId>
+
+    <name>gateway-service-rm</name>
+    <description>The extension to the gateway for supporting RM.</description>
+
+    <licenses>
+        <license>
+            <name>The Apache Software License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+            <distribution>repo</distribution>
+        </license>
+    </licenses>
+
+    <dependencies>
+        <dependency>
+            <groupId>${gateway-group}</groupId>
+            <artifactId>gateway-spi</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${gateway-group}</groupId>
+            <artifactId>gateway-provider-rewrite</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${gateway-group}</groupId>
+            <artifactId>gateway-provider-ha</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${gateway-group}</groupId>
+            <artifactId>gateway-test-utils</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.easymock</groupId>
+            <artifactId>easymock</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest-library</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+    </dependencies>
+
+</project>

http://git-wip-us.apache.org/repos/asf/knox/blob/5ae580ed/gateway-service-rm/src/main/java/org/apache/hadoop/gateway/rm/dispatch/RMHaBaseDispatcher.java
----------------------------------------------------------------------
diff --git a/gateway-service-rm/src/main/java/org/apache/hadoop/gateway/rm/dispatch/RMHaBaseDispatcher.java
b/gateway-service-rm/src/main/java/org/apache/hadoop/gateway/rm/dispatch/RMHaBaseDispatcher.java
new file mode 100644
index 0000000..62912ec
--- /dev/null
+++ b/gateway-service-rm/src/main/java/org/apache/hadoop/gateway/rm/dispatch/RMHaBaseDispatcher.java
@@ -0,0 +1,220 @@
+package org.apache.hadoop.gateway.rm.dispatch;
+/**
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.
+ */
+import org.apache.hadoop.gateway.dispatch.DefaultDispatch;
+import org.apache.hadoop.gateway.filter.AbstractGatewayFilter;
+import org.apache.hadoop.gateway.ha.provider.HaProvider;
+import org.apache.hadoop.gateway.ha.provider.impl.HaServiceConfigConstants;
+import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
+import org.apache.hadoop.gateway.rm.i18n.RMMessages;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpRequestBase;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.entity.BufferedHttpEntity;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.URI;
+import java.util.concurrent.atomic.AtomicInteger;
+
+class  RMHaBaseDispatcher extends DefaultDispatch {
+    private static final String FAILOVER_COUNTER_ATTRIBUTE = "dispatch.ha.failover.counter";
+    private static final String RETRY_COUNTER_ATTRIBUTE = "dispatch.ha.retry.counter";
+    private static final String LOCATION = "Location";
+    private static final RMMessages LOG = MessagesFactory.get(RMMessages.class);
+    private int maxFailoverAttempts = HaServiceConfigConstants.DEFAULT_MAX_FAILOVER_ATTEMPTS;
+    private int failoverSleep = HaServiceConfigConstants.DEFAULT_FAILOVER_SLEEP;
+    private int maxRetryAttempts = HaServiceConfigConstants.DEFAULT_MAX_RETRY_ATTEMPTS;
+    private int retrySleep = HaServiceConfigConstants.DEFAULT_RETRY_SLEEP;
+    private String resourceRole = null;
+    private HttpResponse inboundResponse = null;
+
+    /**
+     *
+     * @return HttpReponse used for unit testing so we
+     * can inject inboundResponse before calling executeRequest method
+     */
+    private HttpResponse getInboundResponse() {
+        HttpResponse response = this.inboundResponse;
+        this.setInboundResponse(null);
+        return response;
+    }
+
+    void setInboundResponse(HttpResponse inboundResponse) {
+        this.inboundResponse = inboundResponse;
+    }
+
+
+
+    void setHaProvider(HaProvider haProvider) {
+        this.haProvider = haProvider;
+    }
+
+    private HaProvider haProvider;
+
+    void setMaxFailoverAttempts(int maxFailoverAttempts) {
+        this.maxFailoverAttempts = maxFailoverAttempts;
+    }
+
+    void setFailoverSleep(int failoverSleep) {
+        this.failoverSleep = failoverSleep;
+    }
+
+    void setMaxRetryAttempts(int maxRetryAttempts) {
+        this.maxRetryAttempts = maxRetryAttempts;
+    }
+
+    void setRetrySleep(int retrySleep) {
+        this.retrySleep = retrySleep;
+    }
+
+    void setResourceRole(String resourceRole) {
+        this.resourceRole = resourceRole;
+    }
+
+    @Override
+     protected void executeRequest(HttpUriRequest outboundRequest, HttpServletRequest inboundRequest,
HttpServletResponse outboundResponse) throws IOException {
+        HttpResponse inboundResponse = this.getInboundResponse();
+        try {
+           if( this.getInboundResponse() == null ) {
+             inboundResponse = executeOutboundRequest(outboundRequest);
+           }
+           writeOutboundResponse(outboundRequest, inboundRequest, outboundResponse, inboundResponse);
+        } catch (StandbyException e) {
+           LOG.errorReceivedFromStandbyNode(e);
+           failoverRequest(outboundRequest, inboundRequest, outboundResponse, inboundResponse,
e);
+        } catch (SafeModeException e) {
+           LOG.errorReceivedFromSafeModeNode(e);
+           retryRequest(outboundRequest, inboundRequest, outboundResponse, inboundResponse,
e);
+        } catch (IOException e) {
+           LOG.errorConnectingToServer(outboundRequest.getURI().toString(), e);
+           failoverRequest(outboundRequest, inboundRequest, outboundResponse, inboundResponse,
e);
+        }
+     }
+
+    /**
+     * Checks for specific outbound response codes/content to trigger a retry or failover
+     */
+    @Override
+    protected void writeOutboundResponse(HttpUriRequest outboundRequest, HttpServletRequest
inboundRequest, HttpServletResponse outboundResponse, HttpResponse inboundResponse) throws
IOException {
+       int status = inboundResponse.getStatusLine().getStatusCode();
+       if ( status  == 403 || status == 307) {
+          BufferedHttpEntity entity = new BufferedHttpEntity(inboundResponse.getEntity());
+          inboundResponse.setEntity(entity);
+          ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+          inboundResponse.getEntity().writeTo(outputStream);
+          String body = new String(outputStream.toByteArray());
+          if (body.contains("This is standby RM")) {
+             throw new StandbyException();
+          }
+          if (body.contains("SafeModeException") || body.contains("RetriableException"))
{
+             throw new SafeModeException();
+          }
+       }
+       super.writeOutboundResponse(outboundRequest, inboundRequest, outboundResponse, inboundResponse);
+    }
+
+    private void failoverRequest(HttpUriRequest outboundRequest, HttpServletRequest inboundRequest,
HttpServletResponse outboundResponse, HttpResponse inboundResponse, Exception exception) throws
IOException {
+       LOG.failingOverRequest(outboundRequest.getURI().toString());
+       URI uri;
+       String outboundURIs;
+       AtomicInteger counter = (AtomicInteger) inboundRequest.getAttribute(FAILOVER_COUNTER_ATTRIBUTE);
+       if (counter == null) {
+          counter = new AtomicInteger(0);
+       }
+       inboundRequest.setAttribute(FAILOVER_COUNTER_ATTRIBUTE, counter);
+        outboundURIs = outboundRequest.getURI().toString();
+
+       if (counter.incrementAndGet() <= maxFailoverAttempts) {
+          //null out target url so that rewriters run again
+          inboundRequest.setAttribute(AbstractGatewayFilter.TARGET_REQUEST_URL_ATTRIBUTE_NAME,
null);
+
+           uri = getUriFromInbound(inboundRequest, inboundResponse, outboundURIs);
+           ((HttpRequestBase) outboundRequest).setURI(uri);
+          if (failoverSleep > 0) {
+             try {
+                Thread.sleep(failoverSleep);
+             } catch (InterruptedException e) {
+                LOG.failoverSleepFailed(this.resourceRole, e);
+             }
+          }
+          executeRequest(outboundRequest, inboundRequest, outboundResponse);
+       } else {
+          LOG.maxFailoverAttemptsReached(maxFailoverAttempts, this.resourceRole);
+          if (inboundResponse != null) {
+             writeOutboundResponse(outboundRequest, inboundRequest, outboundResponse, inboundResponse);
+          } else {
+             throw new IOException(exception);
+          }
+       }
+    }
+
+    URI getUriFromInbound(HttpServletRequest inboundRequest, HttpResponse inboundResponse,
String outboundURIs) {
+         URI uri;
+         if( outboundURIs != null ) {
+           markFailedURL(outboundURIs);
+         }
+         try {
+            if( inboundResponse != null ) {
+               // We get redirection URI, failover condition we don't
+               // need to consult list of host.
+               String host = inboundResponse.getFirstHeader(LOCATION).getValue();
+               LOG.failoverRedirect(host);
+               uri = URI.create(host);
+            } else { // inboundRequest was null previous active node is down
+                     // get next URI in list to try.
+               uri = getDispatchUrl(inboundRequest);
+            }
+         } catch(Exception ex ) {
+            uri = getDispatchUrl(inboundRequest);
+         }
+         haProvider.setActiveURL(this.resourceRole, uri.toString());
+         return uri;
+     }
+
+    private void markFailedURL(String outboundURIs) {
+        haProvider.markFailedURL(this.resourceRole, outboundURIs);
+    }
+
+    private void retryRequest(HttpUriRequest outboundRequest, HttpServletRequest inboundRequest,
HttpServletResponse outboundResponse, HttpResponse inboundResponse, Exception exception) throws
IOException {
+       LOG.retryingRequest(outboundRequest.getURI().toString());
+       AtomicInteger counter = (AtomicInteger) inboundRequest.getAttribute(RETRY_COUNTER_ATTRIBUTE);
+       if (counter == null) {
+          counter = new AtomicInteger(0);
+       }
+       inboundRequest.setAttribute(RETRY_COUNTER_ATTRIBUTE, counter);
+       if (counter.incrementAndGet() <= maxRetryAttempts) {
+          if (retrySleep > 0) {
+             try {
+                Thread.sleep(retrySleep);
+             } catch (InterruptedException e) {
+                LOG.retrySleepFailed(this.resourceRole, e);
+             }
+          }
+          executeRequest(outboundRequest, inboundRequest, outboundResponse);
+       } else {
+          LOG.maxRetryAttemptsReached(maxRetryAttempts, this.resourceRole, outboundRequest.getURI().toString());
+          if (inboundResponse != null) {
+             writeOutboundResponse(outboundRequest, inboundRequest, outboundResponse, inboundResponse);
+          } else {
+             throw new IOException(exception);
+          }
+       }
+    }
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/5ae580ed/gateway-service-rm/src/main/java/org/apache/hadoop/gateway/rm/dispatch/RMHaDispatch.java
----------------------------------------------------------------------
diff --git a/gateway-service-rm/src/main/java/org/apache/hadoop/gateway/rm/dispatch/RMHaDispatch.java
b/gateway-service-rm/src/main/java/org/apache/hadoop/gateway/rm/dispatch/RMHaDispatch.java
new file mode 100644
index 0000000..8ddd21b
--- /dev/null
+++ b/gateway-service-rm/src/main/java/org/apache/hadoop/gateway/rm/dispatch/RMHaDispatch.java
@@ -0,0 +1,54 @@
+/**
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.gateway.rm.dispatch;
+
+import org.apache.hadoop.gateway.config.Configure;
+import org.apache.hadoop.gateway.ha.provider.HaProvider;
+import org.apache.hadoop.gateway.ha.provider.HaServiceConfig;
+
+import javax.servlet.ServletException;
+
+public class RMHaDispatch extends RMHaBaseDispatcher {
+    private static final String RESOURCE_ROLE = "RESOURCEMANAGER";
+    private HaProvider haProvider;
+
+    /**
+   * @throws javax.servlet.ServletException
+   */
+  public RMHaDispatch() {
+    super();
+  }
+   @Configure
+   public void setHaProvider(HaProvider haProvider) {
+        this.haProvider = haProvider;
+    }
+
+   @Override
+   public void init() {
+     super.init();
+     if (haProvider != null) {
+       super.setResourceRole(RESOURCE_ROLE);
+       HaServiceConfig serviceConfig = haProvider.getHaDescriptor().getServiceConfig(RESOURCE_ROLE);
+       super.setMaxFailoverAttempts( serviceConfig.getMaxFailoverAttempts());
+       super.setFailoverSleep( serviceConfig.getFailoverSleep());
+       super.setMaxRetryAttempts( serviceConfig.getMaxRetryAttempts());
+       super.setRetrySleep( serviceConfig.getRetrySleep());
+       super.setHaProvider(haProvider);
+     }
+   }
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/5ae580ed/gateway-service-rm/src/main/java/org/apache/hadoop/gateway/rm/dispatch/RMUIHaDispatch.java
----------------------------------------------------------------------
diff --git a/gateway-service-rm/src/main/java/org/apache/hadoop/gateway/rm/dispatch/RMUIHaDispatch.java
b/gateway-service-rm/src/main/java/org/apache/hadoop/gateway/rm/dispatch/RMUIHaDispatch.java
new file mode 100644
index 0000000..0e73abf
--- /dev/null
+++ b/gateway-service-rm/src/main/java/org/apache/hadoop/gateway/rm/dispatch/RMUIHaDispatch.java
@@ -0,0 +1,54 @@
+/**
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.gateway.rm.dispatch;
+
+import org.apache.hadoop.gateway.config.Configure;
+import org.apache.hadoop.gateway.ha.provider.HaProvider;
+import org.apache.hadoop.gateway.ha.provider.HaServiceConfig;
+
+import javax.servlet.ServletException;
+
+public class RMUIHaDispatch extends RMHaBaseDispatcher {
+    private static final String RESOURCE_ROLE = "YARNUI";
+    private HaProvider haProvider;
+
+    /**
+   * @throws javax.servlet.ServletException
+   */
+  public RMUIHaDispatch() throws ServletException {
+    super();
+  }
+   @Configure
+   public void setHaProvider(HaProvider haProvider) {
+        this.haProvider = haProvider;
+    }
+
+   @Override
+   public void init() {
+     super.init();
+     if (haProvider != null) {
+       super.setResourceRole(RESOURCE_ROLE);
+       HaServiceConfig serviceConfig = haProvider.getHaDescriptor().getServiceConfig(RESOURCE_ROLE);
+       super.setMaxFailoverAttempts( serviceConfig.getMaxFailoverAttempts());
+       super.setFailoverSleep( serviceConfig.getFailoverSleep());
+       super.setMaxRetryAttempts( serviceConfig.getMaxRetryAttempts());
+       super.setRetrySleep( serviceConfig.getRetrySleep());
+       super.setHaProvider(haProvider);
+     }
+   }
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/5ae580ed/gateway-service-rm/src/main/java/org/apache/hadoop/gateway/rm/dispatch/SafeModeException.java
----------------------------------------------------------------------
diff --git a/gateway-service-rm/src/main/java/org/apache/hadoop/gateway/rm/dispatch/SafeModeException.java
b/gateway-service-rm/src/main/java/org/apache/hadoop/gateway/rm/dispatch/SafeModeException.java
new file mode 100644
index 0000000..19d3430
--- /dev/null
+++ b/gateway-service-rm/src/main/java/org/apache/hadoop/gateway/rm/dispatch/SafeModeException.java
@@ -0,0 +1,21 @@
+/**
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.gateway.rm.dispatch;
+
+class SafeModeException extends RuntimeException {
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/5ae580ed/gateway-service-rm/src/main/java/org/apache/hadoop/gateway/rm/dispatch/StandbyException.java
----------------------------------------------------------------------
diff --git a/gateway-service-rm/src/main/java/org/apache/hadoop/gateway/rm/dispatch/StandbyException.java
b/gateway-service-rm/src/main/java/org/apache/hadoop/gateway/rm/dispatch/StandbyException.java
new file mode 100644
index 0000000..94fb792
--- /dev/null
+++ b/gateway-service-rm/src/main/java/org/apache/hadoop/gateway/rm/dispatch/StandbyException.java
@@ -0,0 +1,21 @@
+/**
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.gateway.rm.dispatch;
+
+class StandbyException extends RuntimeException {
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/5ae580ed/gateway-service-rm/src/main/java/org/apache/hadoop/gateway/rm/i18n/RMMessages.java
----------------------------------------------------------------------
diff --git a/gateway-service-rm/src/main/java/org/apache/hadoop/gateway/rm/i18n/RMMessages.java
b/gateway-service-rm/src/main/java/org/apache/hadoop/gateway/rm/i18n/RMMessages.java
new file mode 100644
index 0000000..2e5128d
--- /dev/null
+++ b/gateway-service-rm/src/main/java/org/apache/hadoop/gateway/rm/i18n/RMMessages.java
@@ -0,0 +1,46 @@
+/**
+ * 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.gateway.rm.i18n;
+
+import org.apache.hadoop.gateway.ha.dispatch.i18n.HaDispatchMessages;
+import org.apache.hadoop.gateway.i18n.messages.Message;
+import org.apache.hadoop.gateway.i18n.messages.MessageLevel;
+import org.apache.hadoop.gateway.i18n.messages.Messages;
+import org.apache.hadoop.gateway.i18n.messages.StackTrace;
+
+@Messages(logger = "org.apache.hadoop.gateway")
+public interface RMMessages extends HaDispatchMessages {
+
+  @Message(level = MessageLevel.INFO, text = "Received an error from a node in Standby: {0}")
+   void errorReceivedFromStandbyNode(@StackTrace(level = MessageLevel.DEBUG) Exception e);
+
+  @Message(level = MessageLevel.INFO, text = "Received an error from a node in SafeMode:
{0}")
+   void errorReceivedFromSafeModeNode(@StackTrace(level = MessageLevel.DEBUG) Exception e);
+
+  @Message(level = MessageLevel.INFO, text = "Retrying request to a server: {0}")
+   void retryingRequest(String uri);
+
+  @Message(level = MessageLevel.INFO, text = "Redirect to {0} because of accessing standby
server.")
+   void failoverRedirect(String redirect);
+
+  @Message(level = MessageLevel.INFO, text = "Maximum attempts {0} to retry reached for service:
{1} at url : {2}")
+   void maxRetryAttemptsReached(int attempts, String service, String url);
+
+  @Message(level = MessageLevel.INFO, text = "Error occurred while trying to sleep for retry
: {0} {1}")
+   void retrySleepFailed(String service, @StackTrace(level = MessageLevel.DEBUG) Exception
e);
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/5ae580ed/gateway-service-rm/src/test/java/org/apache/hadoop/gateway/rm/dispatch/RMHaDispatchTest.java
----------------------------------------------------------------------
diff --git a/gateway-service-rm/src/test/java/org/apache/hadoop/gateway/rm/dispatch/RMHaDispatchTest.java
b/gateway-service-rm/src/test/java/org/apache/hadoop/gateway/rm/dispatch/RMHaDispatchTest.java
new file mode 100644
index 0000000..88258c9
--- /dev/null
+++ b/gateway-service-rm/src/test/java/org/apache/hadoop/gateway/rm/dispatch/RMHaDispatchTest.java
@@ -0,0 +1,219 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.gateway.rm.dispatch;
+
+import org.apache.hadoop.gateway.ha.provider.HaDescriptor;
+import org.apache.hadoop.gateway.ha.provider.HaProvider;
+import org.apache.hadoop.gateway.ha.provider.HaServletContextListener;
+import org.apache.hadoop.gateway.ha.provider.impl.DefaultHaProvider;
+import org.apache.hadoop.gateway.ha.provider.impl.HaDescriptorFactory;
+import org.apache.http.client.methods.HttpRequestBase;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.params.BasicHttpParams;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.entity.ContentType;
+import org.apache.http.Header;
+import org.apache.http.message.BasicHttpResponse;
+import org.apache.http.ProtocolVersion;
+import org.apache.http.StatusLine;
+import org.apache.http.message.BasicStatusLine;
+import org.apache.http.message.BasicHeader;
+import org.easymock.EasyMock;
+import org.easymock.IAnswer;
+import org.junit.Assert;
+import org.junit.Test;
+
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.WriteListener;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class RMHaDispatchTest {
+    private static final String LOCATION = "Location";
+
+    @Test
+    public void testConnectivityFailure() throws Exception {
+        String serviceName = "RESOURCEMANAGER";
+        HaDescriptor descriptor = HaDescriptorFactory.createDescriptor();
+        descriptor.addServiceConfig(HaDescriptorFactory.createServiceConfig(serviceName,
"true", "1", "1000", "2", "1000", null, null));
+        HaProvider provider = new DefaultHaProvider(descriptor);
+        URI uri1 = new URI("http://unreachable-host");
+        URI uri2 = new URI("http://reachable-host");
+        ArrayList<String> urlList = new ArrayList<>();
+        urlList.add(uri1.toString());
+        urlList.add(uri2.toString());
+        provider.addHaService(serviceName, urlList);
+        FilterConfig filterConfig = EasyMock.createNiceMock(FilterConfig.class);
+        ServletContext servletContext = EasyMock.createNiceMock(ServletContext.class);
+
+        EasyMock.expect(filterConfig.getServletContext()).andReturn(servletContext).anyTimes();
+        EasyMock.expect(servletContext.getAttribute(HaServletContextListener.PROVIDER_ATTRIBUTE_NAME)).andReturn(provider).anyTimes();
+
+        BasicHttpParams params = new BasicHttpParams();
+
+        HttpUriRequest outboundRequest = EasyMock.createNiceMock(HttpRequestBase.class);
+        EasyMock.expect(outboundRequest.getMethod()).andReturn("GET").anyTimes();
+        EasyMock.expect(outboundRequest.getURI()).andReturn(uri1).anyTimes();
+        EasyMock.expect(outboundRequest.getParams()).andReturn(params).anyTimes();
+
+        HttpServletRequest inboundRequest = EasyMock.createNiceMock(HttpServletRequest.class);
+        EasyMock.expect(inboundRequest.getRequestURL()).andReturn(new StringBuffer(uri2.toString())).once();
+        EasyMock.expect(inboundRequest.getAttribute("dispatch.ha.failover.counter")).andReturn(new
AtomicInteger(0)).once();
+        EasyMock.expect(inboundRequest.getAttribute("dispatch.ha.failover.counter")).andReturn(new
AtomicInteger(1)).once();
+
+        HttpServletResponse outboundResponse = EasyMock.createNiceMock(HttpServletResponse.class);
+        EasyMock.expect(outboundResponse.getOutputStream()).andAnswer(new IAnswer<ServletOutputStream>()
{
+            @Override
+            public ServletOutputStream answer() throws Throwable {
+                return new ServletOutputStream() {
+                    @Override
+                    public void write(int b) throws IOException {
+                        throw new IOException("unreachable-host");
+                    }
+
+                    @Override
+                    public void setWriteListener(WriteListener arg0) {
+                    }
+
+                    @Override
+                    public boolean isReady() {
+                        return false;
+                    }
+                };
+            }
+        }).once();
+        EasyMock.replay(filterConfig, servletContext, outboundRequest, inboundRequest, outboundResponse);
+        Assert.assertEquals(uri1.toString(), provider.getActiveURL(serviceName));
+        RMHaDispatch dispatch = new RMHaDispatch();
+        dispatch.setHttpClient(new DefaultHttpClient());
+        dispatch.setHaProvider(provider);
+        dispatch.init();
+        long startTime = System.currentTimeMillis();
+        try {
+            dispatch.executeRequest(outboundRequest, inboundRequest, outboundResponse);
+        } catch (IOException e) {
+            //this is expected after the failover limit is reached
+        }
+        long elapsedTime = System.currentTimeMillis() - startTime;
+        Assert.assertEquals(uri2.toString(), provider.getActiveURL(serviceName));
+        //test to make sure the sleep took place
+        Assert.assertTrue(elapsedTime > 1000);
+    }
+
+    @Test
+    public void testConnectivityFailover() throws Exception {
+        String serviceName = "RESOURCEMANAGER";
+        HaDescriptor descriptor = HaDescriptorFactory.createDescriptor();
+        descriptor.addServiceConfig(HaDescriptorFactory.createServiceConfig(serviceName,
"true", "1", "1000", "2", "1000", null, null));
+        HaProvider provider = new DefaultHaProvider(descriptor);
+        URI uri1 = new URI("http://passive-host");
+        URI uri2 = new URI("http://other-host");
+        URI uri3 = new URI("http://active-host");
+        ArrayList<String> urlList = new ArrayList<>();
+        urlList.add(uri1.toString());
+        urlList.add(uri2.toString());
+        urlList.add(uri3.toString());
+        provider.addHaService(serviceName, urlList);
+        FilterConfig filterConfig = EasyMock.createNiceMock(FilterConfig.class);
+        ServletContext servletContext = EasyMock.createNiceMock(ServletContext.class);
+
+        EasyMock.expect(filterConfig.getServletContext()).andReturn(servletContext).anyTimes();
+        EasyMock.expect(servletContext.getAttribute(HaServletContextListener.PROVIDER_ATTRIBUTE_NAME)).andReturn(provider).anyTimes();
+
+
+        BasicHttpResponse inboundResponse = EasyMock.createNiceMock(BasicHttpResponse.class);
+        EasyMock.expect(inboundResponse.getStatusLine()).andReturn(getStatusLine()).anyTimes();
+        EasyMock.expect(inboundResponse.getEntity()).andReturn(getResponseEntity()).anyTimes();
+        EasyMock.expect(inboundResponse.getFirstHeader(LOCATION)).andReturn(getFirstHeader(uri3.toString())).anyTimes();
+
+        BasicHttpParams params = new BasicHttpParams();
+
+        HttpUriRequest outboundRequest = EasyMock.createNiceMock(HttpRequestBase.class);
+        EasyMock.expect(outboundRequest.getMethod()).andReturn("GET").anyTimes();
+        EasyMock.expect(outboundRequest.getURI()).andReturn(uri1).anyTimes();
+        EasyMock.expect(outboundRequest.getParams()).andReturn(params).anyTimes();
+
+        HttpServletRequest inboundRequest = EasyMock.createNiceMock(HttpServletRequest.class);
+        EasyMock.expect(inboundRequest.getRequestURL()).andReturn(new StringBuffer(uri2.toString())).once();
+        EasyMock.expect(inboundRequest.getAttribute("dispatch.ha.failover.counter")).andReturn(new
AtomicInteger(0)).once();
+        EasyMock.expect(inboundRequest.getAttribute("dispatch.ha.failover.counter")).andReturn(new
AtomicInteger(1)).once();
+
+        HttpServletResponse outboundResponse = EasyMock.createNiceMock(HttpServletResponse.class);
+        EasyMock.expect(outboundResponse.getOutputStream()).andAnswer(new IAnswer<ServletOutputStream>()
{
+            @Override
+            public ServletOutputStream answer() throws Throwable {
+                return new ServletOutputStream() {
+                    @Override
+                    public void write(int b) throws IOException {
+                        throw new IOException("unreachable-host");
+                    }
+
+                    @Override
+                    public void setWriteListener(WriteListener arg0) {
+                    }
+
+                    @Override
+                    public boolean isReady() {
+                        return false;
+                    }
+                };
+            }
+        }).once();
+        Assert.assertEquals(uri1.toString(), provider.getActiveURL(serviceName));
+        EasyMock.replay(filterConfig, servletContext, inboundResponse, outboundRequest, inboundRequest,
outboundResponse);
+
+        RMHaDispatch dispatch = new RMHaDispatch();
+        dispatch.setHttpClient(new DefaultHttpClient());
+        dispatch.setHaProvider(provider);
+        dispatch.init();
+        long startTime = System.currentTimeMillis();
+        try {
+            dispatch.setInboundResponse(inboundResponse);
+            dispatch.executeRequest(outboundRequest, inboundRequest, outboundResponse);
+        } catch (IOException e) {
+            //this is expected after the failover limit is reached
+        }
+        Assert.assertEquals(uri3.toString(), dispatch.getUriFromInbound(inboundRequest, inboundResponse,
null).toString());
+        long elapsedTime = System.currentTimeMillis() - startTime;
+        Assert.assertEquals(uri3.toString(), provider.getActiveURL(serviceName));
+        //test to make sure the sleep took place
+        Assert.assertTrue(elapsedTime > 1000);
+    }
+
+    private StringEntity getResponseEntity() {
+        String body = "This is standby RM";
+        return new StringEntity(body, ContentType.TEXT_HTML);
+    }
+
+    private StatusLine getStatusLine() {
+        ProtocolVersion p = new ProtocolVersion("HTTP", 1, 1);
+        return new BasicStatusLine(p, 307, "Code" + 307);
+    }
+
+    private Header getFirstHeader(String host) {
+        return new BasicHeader(LOCATION, host);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/5ae580ed/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 0c92572..781b86b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -79,6 +79,7 @@
         <module>gateway-service-knoxtoken</module>
         <module>gateway-service-webhdfs</module>
         <module>gateway-service-tgs</module>
+        <module>gateway-service-rm</module>
         <module>gateway-service-storm</module>
         <module>gateway-service-definitions</module>
         <module>gateway-shell</module>
@@ -621,6 +622,11 @@
             </dependency>
             <dependency>
                 <groupId>${gateway-group}</groupId>
+                <artifactId>gateway-service-rm</artifactId>
+                <version>${gateway-version}</version>
+            </dependency>
+            <dependency>
+                <groupId>${gateway-group}</groupId>
                 <artifactId>gateway-service-storm</artifactId>
                 <version>${gateway-version}</version>
             </dependency>


Mime
View raw message