You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@slider.apache.org by st...@apache.org on 2014/10/20 10:30:37 UTC

git commit: SLIDER-539 Web view to list outstanding container requests

Repository: incubator-slider
Updated Branches:
  refs/heads/develop a2c266126 -> ff7b8c37f


SLIDER-539 Web view to list outstanding container requests


Project: http://git-wip-us.apache.org/repos/asf/incubator-slider/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-slider/commit/ff7b8c37
Tree: http://git-wip-us.apache.org/repos/asf/incubator-slider/tree/ff7b8c37
Diff: http://git-wip-us.apache.org/repos/asf/incubator-slider/diff/ff7b8c37

Branch: refs/heads/develop
Commit: ff7b8c37f22e82ea36b18c22703a007bb67c5511
Parents: a2c2661
Author: Steve Loughran <st...@apache.org>
Authored: Sun Oct 19 14:20:23 2014 +0100
Committer: Steve Loughran <st...@apache.org>
Committed: Sun Oct 19 14:20:23 2014 +0100

----------------------------------------------------------------------
 .../slider/server/appmaster/state/AppState.java | 17 +++++
 .../appmaster/state/ProviderAppState.java       |  4 +
 .../server/appmaster/state/RoleHistory.java     |  6 +-
 .../server/appmaster/state/RoleStatus.java      | 25 +++++++
 .../state/StateAccessForProviders.java          |  3 +-
 .../server/appmaster/web/view/IndexBlock.java   | 78 ++++++++++++++------
 .../appmaster/web/view/TestIndexBlock.groovy    | 32 +++++++-
 7 files changed, 136 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/ff7b8c37/slider-core/src/main/java/org/apache/slider/server/appmaster/state/AppState.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/AppState.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/state/AppState.java
index 834eaf2..21cb6d2 100644
--- a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/AppState.java
+++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/state/AppState.java
@@ -787,6 +787,23 @@ public class AppState {
     return lookupRoleStatus(ContainerPriority.extractRole(c));
   }
 
+  /**
+   * Get a clone of the role status list. Concurrent events may mean this
+   * list (or indeed, some of the role status entries) may be inconsistent
+   * @return a snapshot of the role status entries
+   */
+  public List<RoleStatus> cloneRoleStatusList() {
+    Collection<RoleStatus> statuses = roleStatusMap.values();
+    List<RoleStatus> statusList = new ArrayList<RoleStatus>(statuses.size());
+    try {
+      for (RoleStatus status : statuses) {
+        statusList.add((RoleStatus)(status.clone()));
+      }
+    } catch (CloneNotSupportedException e) {
+      log.warn("Unexpected cloning failure: {}", e, e);
+    }
+    return statusList;
+  }
 
 
   public RoleStatus lookupRoleStatus(String name) throws YarnRuntimeException {

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/ff7b8c37/slider-core/src/main/java/org/apache/slider/server/appmaster/state/ProviderAppState.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/ProviderAppState.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/state/ProviderAppState.java
index 9c5da12..d5a041b 100644
--- a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/ProviderAppState.java
+++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/state/ProviderAppState.java
@@ -211,4 +211,8 @@ public class ProviderAppState implements StateAccessForProviders {
     appState.refreshClusterStatus();
   }
 
+  @Override
+  public List<RoleStatus> cloneRoleStatusList() {
+    return appState.cloneRoleStatusList();
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/ff7b8c37/slider-core/src/main/java/org/apache/slider/server/appmaster/state/RoleHistory.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/RoleHistory.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/state/RoleHistory.java
index dca7384..01fedc6 100644
--- a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/RoleHistory.java
+++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/state/RoleHistory.java
@@ -350,7 +350,7 @@ public class RoleHistory {
    * Handler for bootstrap event
    */
   public void onBootstrap() {
-    log.info("Role history bootstrapped");
+    log.debug("Role history bootstrapped");
   }
 
   /**
@@ -371,7 +371,7 @@ public class RoleHistory {
     }
     if (loaded != null) {
       thawSuccessful = true;
-      log.info("loaded history from {}", loaded);
+      log.debug("loaded history from {}", loaded);
       // delete any old entries
       try {
         int count = historyWriter.purgeOlderHistoryEntries(filesystem, loaded);
@@ -469,7 +469,7 @@ public class RoleHistory {
     
     List<NodeInstance> targets = getNodesForRoleId(roleKey);
     int cnt = targets == null ? 0 : targets.size();
-    log.info("There're {} nodes to consider for {}", cnt, role.getName());
+    log.debug("There're {} nodes to consider for {}", cnt, role.getName());
     while (targets != null && !targets.isEmpty() && nodeInstance == null) {
       NodeInstance head = targets.remove(0);
       if (head.getActiveRoleInstances(roleKey) == 0) {

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/ff7b8c37/slider-core/src/main/java/org/apache/slider/server/appmaster/state/RoleStatus.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/RoleStatus.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/state/RoleStatus.java
index 63b5931..f9feca3 100644
--- a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/RoleStatus.java
+++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/state/RoleStatus.java
@@ -22,6 +22,8 @@ import org.apache.slider.api.StatusKeys;
 import org.apache.slider.providers.PlacementPolicy;
 import org.apache.slider.providers.ProviderRole;
 
+import java.io.Serializable;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -298,4 +300,27 @@ public final class RoleStatus implements Cloneable {
     stats.put(StatusKeys.STATISTICS_CONTAINERS_START_FAILED, getStartFailed());
     return stats;
   }
+
+  /**
+   * Compare two role status entries by name
+   */
+  public static class CompareByName implements Comparator<RoleStatus>,
+      Serializable {
+    @Override
+    public int compare(RoleStatus o1, RoleStatus o2) {
+      return o1.getName().compareTo(o2.getName());
+    }
+  }
+  
+  /**
+   * Compare two role status entries by key
+   */
+  public static class CompareByKey implements Comparator<RoleStatus>,
+      Serializable {
+    @Override
+    public int compare(RoleStatus o1, RoleStatus o2) {
+      return Integer.compare(o1.getKey(), o2.getKey());
+    }
+  }
+  
 }

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/ff7b8c37/slider-core/src/main/java/org/apache/slider/server/appmaster/state/StateAccessForProviders.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/StateAccessForProviders.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/state/StateAccessForProviders.java
index b907b06..75076ed 100644
--- a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/StateAccessForProviders.java
+++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/state/StateAccessForProviders.java
@@ -201,9 +201,8 @@ public interface StateAccessForProviders {
 
   /**
    * Update the cluster description with anything interesting
-   * @param providerStatus status from the provider for the cluster info section
    */
   void refreshClusterStatus();
-  
 
+  List<RoleStatus> cloneRoleStatusList();
 }

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/ff7b8c37/slider-core/src/main/java/org/apache/slider/server/appmaster/web/view/IndexBlock.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/web/view/IndexBlock.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/view/IndexBlock.java
index 54bdb09..91c70ee 100644
--- a/slider-core/src/main/java/org/apache/slider/server/appmaster/web/view/IndexBlock.java
+++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/view/IndexBlock.java
@@ -16,20 +16,25 @@
  */
 package org.apache.slider.server.appmaster.web.view;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.inject.Inject;
-import org.apache.commons.lang.StringUtils;
 import org.apache.hadoop.yarn.webapp.hamlet.Hamlet;
 import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.DIV;
 import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.UL;
 import org.apache.hadoop.yarn.webapp.view.HtmlBlock;
+import org.apache.slider.api.ClusterDescription;
 import org.apache.slider.api.StatusKeys;
 import org.apache.slider.common.tools.SliderUtils;
 import org.apache.slider.providers.ProviderService;
+import org.apache.slider.server.appmaster.state.RoleStatus;
 import org.apache.slider.server.appmaster.state.StateAccessForProviders;
 import org.apache.slider.server.appmaster.web.WebAppApi;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Map.Entry;
 
@@ -37,15 +42,14 @@ import java.util.Map.Entry;
  * 
  */
 public class IndexBlock extends HtmlBlock {
-  private static final String HBASE = "HBase";
   private static final Logger log = LoggerFactory.getLogger(IndexBlock.class);
 
-  private StateAccessForProviders appState;
+  private StateAccessForProviders appView;
   private ProviderService providerService;
 
   @Inject
   public IndexBlock(WebAppApi slider) {
-    this.appState = slider.getAppState();
+    this.appView = slider.getAppState();
     this.providerService = slider.getProviderService();
   }
 
@@ -57,45 +61,73 @@ public class IndexBlock extends HtmlBlock {
   }
 
   // An extra method to make testing easier since you can't make an instance of Block
+  @VisibleForTesting
   protected void doIndex(Hamlet html, String providerName) {
-    DIV<Hamlet> div = html.div("general_info").h1("index_header", providerName + " cluster: '" + appState.getClusterStatus().name + "'");
+    ClusterDescription clusterStatus = appView.getClusterStatus();
+    DIV<Hamlet> div = html.div("general_info")
+                          .h1("index_header",
+                              "Application: '" + clusterStatus.name + "'");
 
     UL<DIV<Hamlet>> ul = div.ul();
 
-    ul.li("Total number of containers for cluster: " + appState.getNumOwnedContainers());
-    ul.li("Cluster created: " + getInfoAvoidingNulls(StatusKeys.INFO_CREATE_TIME_HUMAN));
-    ul.li("Cluster last flexed: " + getInfoAvoidingNulls(StatusKeys.INFO_FLEX_TIME_HUMAN));
-    ul.li("Cluster running since: " + getInfoAvoidingNulls(StatusKeys.INFO_LIVE_TIME_HUMAN));
-    ul.li("Cluster HDFS storage path: " + appState.getClusterStatus().dataPath);
-    ul.li("Cluster configuration path: " + appState.getClusterStatus().originConfigurationPath);
+    ul.li("Total number of containers for application: " + appView.getNumOwnedContainers());
+    ul.li("Application created: " +
+          getInfoAvoidingNulls(StatusKeys.INFO_CREATE_TIME_HUMAN));
+    ul.li("Application last flexed: " + getInfoAvoidingNulls(StatusKeys.INFO_FLEX_TIME_HUMAN));
+    ul.li("Application running since: " + getInfoAvoidingNulls(StatusKeys.INFO_LIVE_TIME_HUMAN));
+    ul.li("Application HDFS storage path: " + clusterStatus.dataPath);
+    ul.li("Application configuration path: " + clusterStatus.originConfigurationPath);
 
     ul._()._();
 
     html.div("provider_info").h3(providerName + " specific information");
     ul = div.ul();
-    addProviderServiceOptions(providerService, ul);
+    addProviderServiceOptions(providerService, ul, clusterStatus);
     ul._()._();
-  }
-
-  private String getProviderName() {
-    String providerServiceName = providerService.getName().toLowerCase();
 
-    // Get HBase properly capitalized
-    if (providerServiceName.contains("hbase")) {
-      return HBASE;
+    html.div("container_instances").h3("Component Instances");
+
+    Hamlet.TABLE<DIV<Hamlet>> table = div.table();
+    table.tr()
+         .th("Component")
+         .th("Desired")
+         .th("Actual")
+         .th("Requested")
+         .th("Failed")
+         .th("Failed to start")
+         ._();
+
+    List<RoleStatus> roleStatuses = appView.cloneRoleStatusList();
+    Collections.sort(roleStatuses, new RoleStatus.CompareByName());
+    for (RoleStatus status : roleStatuses) {
+      table.tr()
+           .td(status.getName())
+           .th(String.format("%d", status.getDesired()))
+           .th(String.format("%d", status.getActual()))
+           .th(String.format("%d", status.getRequested()))
+           .th(String.format("%d", status.getFailed()))
+           .th(String.format("%d", status.getStartFailed()))
+            ._();
     }
 
-    return StringUtils.capitalize(providerServiceName);
+    table._()._();
+  }
+
+  private String getProviderName() {
+    String providerServiceName = providerService.getName().toLowerCase(Locale.ENGLISH);
+    return providerServiceName;
   }
 
   private String getInfoAvoidingNulls(String key) {
-    String createTime = appState.getClusterStatus().getInfo(key);
+    String createTime = appView.getClusterStatus().getInfo(key);
 
     return null == createTime ? "N/A" : createTime;
   }
 
-  protected void addProviderServiceOptions(ProviderService providerService, UL<DIV<Hamlet>> ul) {
-    Map<String, String> details = providerService.buildMonitorDetails(appState.getClusterStatus());
+  protected void addProviderServiceOptions(ProviderService providerService,
+      UL<DIV<Hamlet>> ul, ClusterDescription clusterStatus) {
+    Map<String, String> details = providerService.buildMonitorDetails(
+        clusterStatus);
     if (null == details) {
       return;
     }

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/ff7b8c37/slider-core/src/test/groovy/org/apache/slider/server/appmaster/web/view/TestIndexBlock.groovy
----------------------------------------------------------------------
diff --git a/slider-core/src/test/groovy/org/apache/slider/server/appmaster/web/view/TestIndexBlock.groovy b/slider-core/src/test/groovy/org/apache/slider/server/appmaster/web/view/TestIndexBlock.groovy
index a3a4118..d232ecb 100644
--- a/slider-core/src/test/groovy/org/apache/slider/server/appmaster/web/view/TestIndexBlock.groovy
+++ b/slider-core/src/test/groovy/org/apache/slider/server/appmaster/web/view/TestIndexBlock.groovy
@@ -82,6 +82,20 @@ public class TestIndexBlock extends BaseMockAppStateTest {
 
   @Test
   public void testIndex() {
+    def role0 = role0Status
+    def role1 = role1Status
+    role0.desired = 8
+    role0.incActual()
+    role0.incActual()
+    role0.incActual()
+    role0.incActual()
+    role0.incActual()
+    role1.incRequested()
+    role1.incRequested()
+    role1.incRequested()
+    role0.noteFailed(false, "")
+    role0.noteFailed(true, "")
+
     StringWriter sw = new StringWriter(64);
     PrintWriter pw = new PrintWriter(sw);
 
@@ -89,7 +103,23 @@ public class TestIndexBlock extends BaseMockAppStateTest {
     
     int level = hamlet.nestLevel();
     indexBlock.doIndex(hamlet, "accumulo");
+
+    def body = sw.toString()
+    log.info(body)
+    assertEquals(body, level, hamlet.nestLevel())
+    // verify role data came out
+    assert body.contains("role0")
+    // 
+    assert body.contains("8")
+    assert body.contains("5")
+    assert body.contains("3")
+    assert body.contains("2")
+    assert body.contains("1")
     
-    assert level == hamlet.nestLevel();
+    assert body.contains("role1")
+    assert body.contains("role2")
+    // verify that the sorting took place
+    assert body.indexOf("role0") < body.indexOf("role1")
+    assert body.indexOf("role1") < body.indexOf("role2")
   }
 }
\ No newline at end of file