Repository: incubator-slider Updated Branches: refs/heads/develop ad33f069e -> fad546eab
SLIDER-771 root web UI to link to REST API Project: http://git-wip-us.apache.org/repos/asf/incubator-slider/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-slider/commit/d3c08bdb Tree: http://git-wip-us.apache.org/repos/asf/incubator-slider/tree/d3c08bdb Diff: http://git-wip-us.apache.org/repos/asf/incubator-slider/diff/d3c08bdb Branch: refs/heads/develop Commit: d3c08bdbccc2037bbb4bdb78879a7a37f61cb0ec Parents: 00542b8 Author: Steve Loughran <[email protected]> Authored: Tue Feb 3 20:58:27 2015 +0000 Committer: Steve Loughran <[email protected]> Committed: Tue Feb 3 20:58:27 2015 +0000 ---------------------------------------------------------------------- .../providers/AbstractProviderService.java | 5 ++ .../slider/providers/ProviderService.java | 6 ++ .../providers/agent/AgentProviderService.java | 5 ++ .../slideram/SliderAMProviderService.java | 5 ++ .../server/appmaster/web/view/IndexBlock.java | 82 ++++++++++++++------ .../server/appmaster/web/view/NavBlock.java | 35 +++++++-- .../slider/agent/rest/TestStandaloneREST.groovy | 1 - .../agent/standalone/DemoStandaloneAM.groovy | 71 +++++++++++++++++ .../model/mock/MockProviderService.groovy | 5 ++ 9 files changed, 182 insertions(+), 33 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/d3c08bdb/slider-core/src/main/java/org/apache/slider/providers/AbstractProviderService.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/providers/AbstractProviderService.java b/slider-core/src/main/java/org/apache/slider/providers/AbstractProviderService.java index c628d8a..6856400 100644 --- a/slider-core/src/main/java/org/apache/slider/providers/AbstractProviderService.java +++ b/slider-core/src/main/java/org/apache/slider/providers/AbstractProviderService.java @@ -58,6 +58,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; +import java.util.Locale; import java.util.Map; /** @@ -101,6 +102,10 @@ public abstract class AbstractProviderService this.amState = amState; } + @Override + public String getHumanName() { + return getName().toLowerCase(Locale.ENGLISH); + } @Override public void bind(StateAccessForProviders stateAccessor, http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/d3c08bdb/slider-core/src/main/java/org/apache/slider/providers/ProviderService.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/providers/ProviderService.java b/slider-core/src/main/java/org/apache/slider/providers/ProviderService.java index dd891db..28cef01 100644 --- a/slider-core/src/main/java/org/apache/slider/providers/ProviderService.java +++ b/slider-core/src/main/java/org/apache/slider/providers/ProviderService.java @@ -156,6 +156,12 @@ public interface ProviderService extends ProviderCore, */ Map<String, String> buildMonitorDetails(ClusterDescription clusterSpec); + /** + * Get a human friendly name for web UIs and messages + * @return a name string. Default is simply the service instance name. + */ + String getHumanName(); + public void bind(StateAccessForProviders stateAccessor, QueueAccess queueAccess, List<Container> liveContainers); http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/d3c08bdb/slider-core/src/main/java/org/apache/slider/providers/agent/AgentProviderService.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/providers/agent/AgentProviderService.java b/slider-core/src/main/java/org/apache/slider/providers/agent/AgentProviderService.java index ad8ef43..69857d2 100644 --- a/slider-core/src/main/java/org/apache/slider/providers/agent/AgentProviderService.java +++ b/slider-core/src/main/java/org/apache/slider/providers/agent/AgentProviderService.java @@ -196,6 +196,11 @@ public class AgentProviderService extends AbstractProviderService implements } @Override + public String getHumanName() { + return "Slider Agent"; + } + + @Override public List<ProviderRole> getRoles() { return AgentRoles.getRoles(); } http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/d3c08bdb/slider-core/src/main/java/org/apache/slider/providers/slideram/SliderAMProviderService.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/providers/slideram/SliderAMProviderService.java b/slider-core/src/main/java/org/apache/slider/providers/slideram/SliderAMProviderService.java index 408e311..cee7a97 100644 --- a/slider-core/src/main/java/org/apache/slider/providers/slideram/SliderAMProviderService.java +++ b/slider-core/src/main/java/org/apache/slider/providers/slideram/SliderAMProviderService.java @@ -67,6 +67,11 @@ public class SliderAMProviderService extends AbstractProviderService implements } @Override + public String getHumanName() { + return "Slider Application"; + } + + @Override public Configuration loadProviderConfigurationInformation(File confDir) throws BadCommandArgumentsException, IOException { http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/d3c08bdb/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 59a03f9..ef020fd 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 @@ -24,6 +24,7 @@ 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.api.types.ApplicationLivenessInformation; import org.apache.slider.common.tools.SliderUtils; import org.apache.slider.providers.ProviderService; import org.apache.slider.server.appmaster.state.RoleStatus; @@ -64,26 +65,51 @@ public class IndexBlock extends HtmlBlock { @VisibleForTesting protected void doIndex(Hamlet html, String providerName) { ClusterDescription clusterStatus = appView.getClusterStatus(); + String name = clusterStatus.name; + if (name.startsWith(" ") || name.endsWith(" ")) { + name = "'" + name + "'"; + } DIV<Hamlet> div = html.div("general_info") .h1("index_header", - "Application: '" + clusterStatus.name + "'"); + "Application: " + name); + + ApplicationLivenessInformation liveness = + appView.getApplicationLivenessInformation(); + String livestatus = + liveness.allRequestsSatisfied + ? "all containers allocated" + : String.format("Awaiting %d containers", liveness.requestsOutstanding); + Hamlet.TABLE<DIV<Hamlet>> table1 = div.table(); + table1.tr() + .td("Status") + .td(livestatus) + ._(); + table1.tr() + .td("Total number of containers") + .td(Integer.toString(appView.getNumOwnedContainers())) + ._(); + table1.tr() + .td("Create time: ") + .td(getInfoAvoidingNulls(StatusKeys.INFO_CREATE_TIME_HUMAN)) + ._(); + table1.tr() + .td("Running since: ") + .td(getInfoAvoidingNulls(StatusKeys.INFO_LIVE_TIME_HUMAN)) + ._(); + table1.tr() + .td("Time last flexed: ") + .td(getInfoAvoidingNulls(StatusKeys.INFO_FLEX_TIME_HUMAN)) + ._(); + table1.tr() + .td("Application storage path: ") + .td(clusterStatus.dataPath) + ._(); + table1.tr() + .td("Application configuration path: ") + .td(clusterStatus.originConfigurationPath) + ._(); + table1._()._(); - UL<DIV<Hamlet>> ul = div.ul(); - - 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, clusterStatus); - ul._()._(); html.div("container_instances").h3("Component Instances"); @@ -102,20 +128,28 @@ public class IndexBlock extends HtmlBlock { 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())) + .td(String.format("%d", status.getDesired())) + .td(String.format("%d", status.getActual())) + .td(String.format("%d", status.getRequested())) + .td(String.format("%d", status.getFailed())) + .td(String.format("%d", status.getStartFailed())) ._(); } table._()._(); + + // some spacing + html.p()._(); + html.p()._(); + + html.div("provider_info").h3(providerName + " information"); + UL<DIV<Hamlet>> ul = div.ul(); + addProviderServiceOptions(providerService, ul, clusterStatus); + ul._()._(); } private String getProviderName() { - String providerServiceName = providerService.getName().toLowerCase(Locale.ENGLISH); - return providerServiceName; + return providerService.getHumanName(); } private String getInfoAvoidingNulls(String key) { http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/d3c08bdb/slider-core/src/main/java/org/apache/slider/server/appmaster/web/view/NavBlock.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/web/view/NavBlock.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/view/NavBlock.java index 1bdf1bd..b2327ba 100644 --- a/slider-core/src/main/java/org/apache/slider/server/appmaster/web/view/NavBlock.java +++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/view/NavBlock.java @@ -17,8 +17,10 @@ package org.apache.slider.server.appmaster.web.view; import org.apache.hadoop.yarn.webapp.view.HtmlBlock; -import org.apache.slider.server.appmaster.web.SliderAMWebApp; -import org.apache.slider.server.appmaster.web.rest.RestPaths; +import static org.apache.slider.server.appmaster.web.SliderAMWebApp.*; +import static org.apache.slider.server.appmaster.web.rest.RestPaths.*; + +import static org.apache.hadoop.yarn.util.StringHelper.ujoin; /** * @@ -32,12 +34,21 @@ public class NavBlock extends HtmlBlock { h3("Slider"). ul(). li().a(this.prefix(), "Overview")._(). - li().a(this.prefix() + SliderAMWebApp.CONTAINER_STATS, "Statistics")._(). - li().a(this.prefix() + SliderAMWebApp.CLUSTER_SPEC, "Specification")._(). - li().a(rootPath(RestPaths.SYSTEM_METRICS), "Metrics")._(). - li().a(rootPath(RestPaths.SYSTEM_METRICS_JSON), "Metrics as JSON")._(). - li().a(rootPath(RestPaths.SYSTEM_HEALTHCHECK), "Health")._(). - li().a(rootPath(RestPaths.SYSTEM_THREADS), "Threads")._() + li().a(relPath(CONTAINER_STATS), "Statistics")._(). + li().a(relPath(CLUSTER_SPEC), "Specification")._(). + li().a(relPath(CLUSTER_SPEC), "Specification")._(). + li().a(rootPath(SYSTEM_METRICS_JSON), "Metrics")._(). + li().a(rootPath(SYSTEM_HEALTHCHECK), "Health")._(). + li().a(rootPath(SYSTEM_THREADS), "Threads")._(). + _() + .h3("REST API"). + ul(). + li().a(apiPath(MODEL_DESIRED), "Specified")._(). + li().a(apiPath(MODEL_RESOLVED), "Resolved")._(). + li().a(apiPath(LIVE_RESOURCES), "Resources")._(). + li().a(apiPath(LIVE_COMPONENTS), "Components")._(). + li().a(apiPath(LIVE_CONTAINERS), "Containers")._(). + li().a(apiPath(LIVE_LIVENESS), "Liveness")._() ._() ._(); } @@ -45,4 +56,12 @@ public class NavBlock extends HtmlBlock { private String rootPath(String absolutePath) { return root_url(absolutePath); } + + private String relPath(String... args) { + return ujoin(this.prefix(), args); + } + private String apiPath(String api) { + return root_url(SLIDER_PATH_APPLICATION, api); + } + } http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/d3c08bdb/slider-core/src/test/groovy/org/apache/slider/agent/rest/TestStandaloneREST.groovy ---------------------------------------------------------------------- diff --git a/slider-core/src/test/groovy/org/apache/slider/agent/rest/TestStandaloneREST.groovy b/slider-core/src/test/groovy/org/apache/slider/agent/rest/TestStandaloneREST.groovy index e4ce295..7306c48 100644 --- a/slider-core/src/test/groovy/org/apache/slider/agent/rest/TestStandaloneREST.groovy +++ b/slider-core/src/test/groovy/org/apache/slider/agent/rest/TestStandaloneREST.groovy @@ -85,7 +85,6 @@ class TestStandaloneREST extends AgentMiniClusterTestBase { def metrics = GET(directAM, SYSTEM_METRICS) log.info metrics } - GET(proxyAM) http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/d3c08bdb/slider-core/src/test/groovy/org/apache/slider/agent/standalone/DemoStandaloneAM.groovy ---------------------------------------------------------------------- diff --git a/slider-core/src/test/groovy/org/apache/slider/agent/standalone/DemoStandaloneAM.groovy b/slider-core/src/test/groovy/org/apache/slider/agent/standalone/DemoStandaloneAM.groovy new file mode 100644 index 0000000..0b90ffe --- /dev/null +++ b/slider-core/src/test/groovy/org/apache/slider/agent/standalone/DemoStandaloneAM.groovy @@ -0,0 +1,71 @@ +/* + * 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.slider.agent.standalone + +import groovy.transform.CompileStatic +import groovy.util.logging.Slf4j +import org.apache.hadoop.yarn.api.records.ApplicationReport +import org.apache.slider.agent.AgentMiniClusterTestBase +import org.apache.slider.client.SliderClient +import org.apache.slider.core.main.ServiceLauncher +import org.junit.After +import org.junit.Test + +/** + * This is a test with the name "Demo" so it doesn't run. + * All it does is start the AM, print the URLs and then + * sleep for a while. + */ +@CompileStatic +@Slf4j +class DemoStandaloneAM extends AgentMiniClusterTestBase { + + + + @After + void fixclientname() { + sliderClientClassName = DEFAULT_SLIDER_CLIENT + } + + @Test(timeout = 600000L) + public void testDemoStandaloneAM() throws Throwable { + + describe "create a standalone AM then pause to allow the user " + + "to explore the web and YARN UI integration" + //launch fake master + String clustername = createMiniCluster("", configuration, 1, true) + + + ServiceLauncher<SliderClient> launcher = + createStandaloneAM(clustername, true, false) + SliderClient client = launcher.service + addToTeardown(client); + + ApplicationReport report = waitForClusterLive(client) + URI uri = new URI(report.originalTrackingUrl) + + logReport(report) + + describe "YARN RM proxy: ${report.trackingUrl}" + describe "Direct Application ${report.originalTrackingUrl}" + + sleep(5 * 60 * 1000) + + } +} http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/d3c08bdb/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/mock/MockProviderService.groovy ---------------------------------------------------------------------- diff --git a/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/mock/MockProviderService.groovy b/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/mock/MockProviderService.groovy index 7efcd96..e62c24e 100644 --- a/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/mock/MockProviderService.groovy +++ b/slider-core/src/test/groovy/org/apache/slider/server/appmaster/model/mock/MockProviderService.groovy @@ -53,6 +53,11 @@ import org.apache.slider.server.services.yarnregistry.YarnRegistryViewForProvide class MockProviderService implements ProviderService { @Override + String getHumanName() { + return null + } + + @Override public String getName() { return null; }
