Index: hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-timelineservice/src/main/java/org/apache/hadoop/yarn/server/timelineservice/reader/TimelineReaderWebServices.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-timelineservice/src/main/java/org/apache/hadoop/yarn/server/timelineservice/reader/TimelineReaderWebServices.java (revision 64f30da42813182e9cf69ec306c1f1c0c633ece0) +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-timelineservice/src/main/java/org/apache/hadoop/yarn/server/timelineservice/reader/TimelineReaderWebServices.java (date 1558100555000) @@ -48,6 +48,7 @@ import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.util.Time; import org.apache.hadoop.yarn.api.records.timeline.TimelineAbout; +import org.apache.hadoop.yarn.api.records.timeline.TimelineHealth; import org.apache.hadoop.yarn.api.records.timelineservice.FlowActivityEntity; import org.apache.hadoop.yarn.api.records.timelineservice.TimelineEntity; import org.apache.hadoop.yarn.api.records.timelineservice.TimelineEntityType; @@ -218,6 +219,42 @@ return TimelineUtils.createTimelineAbout("Timeline Reader API"); } + /** + * Health check rest end point. + * + * @param req Servlet request. + * @param res Servlet response. + * + * @return TimelineHealth.OK with 200 OK if service is running + * TimlineHeaalth.BAD with 500 if reader connection fails + */ + @GET + @Path("/health") + @Produces(MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8) + public Response health( + @Context HttpServletRequest req, + @Context HttpServletResponse res + ) { + Response response; + + TimelineReaderContext timelineReaderContext = TimelineReaderWebServicesUtils + .createTimelineReaderContext("", "", "", "0", + "", TimelineEntityType.YARN_FLOW_RUN.toString(), "0", + "0"); + try { + this.getTimelineReaderManager().getEntityTypes(timelineReaderContext); + response = + Response.ok(new TimelineHealth(TimelineHealth.TimelineHealthStatus.OK)).build(); + } catch (Exception e) { + LOG.info("Exception during health check: " + e.getMessage(), e); + response = Response.serverError().entity( + new TimelineHealth(TimelineHealth.TimelineHealthStatus.BAD) + ).build(); + } + + return response; + } + /** * Return a single entity for a given entity type and UID which is a delimited * string containing clusterid, userid, flow name, flowrun id and app id. Index: hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/application.hbs IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/application.hbs (revision 64f30da42813182e9cf69ec306c1f1c0c633ece0) +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/application.hbs (date 1558083381000) @@ -56,11 +56,12 @@ (current) {{/link-to}} {{/link-to}} - {{#link-to 'yarn-flow-activity' tagName="li"}} - {{#link-to 'yarn-flow-activity' class="navigation-link"}}Flow Activity - (current) - {{/link-to}} - {{/link-to}} + {{#link-to 'yarn-flow-activity' tagName="li" disabled=flowPageDisabled }} + {{#link-to 'yarn-flow-activity' class="navigation-link"}}Flow Activity + (current) + {{/link-to}} + {{/link-to}} + {{#link-to 'yarn-nodes.table' tagName="li" current-when="yarn-nodes.table yarn-nodes.heatmap"}} {{#link-to 'yarn-nodes.table' class="navigation-link"}}Nodes (current) Index: hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/tree-selector.js IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/tree-selector.js (revision 64f30da42813182e9cf69ec306c1f1c0c633ece0) +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/tree-selector.js (date 1558093776000) @@ -1,3 +1,4 @@ +/** /** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -192,7 +193,8 @@ .style( "fill", function(d) { - const usedCapacity = getUsedCapacity(d.queueData.get("partitionMap"), this.filteredPartition); + const usedCapacity = getUsedCapacity(d.queueData, this.filteredPartition); + if (usedCapacity <= 60.0) { return "#60cea5"; } else if (usedCapacity <= 100.0) { @@ -216,7 +218,8 @@ }) .text( function(d) { - const usedCapacity = getUsedCapacity(d.queueData.get("partitionMap"), this.filteredPartition); + const usedCapacity = getUsedCapacity(d.queueData, this.filteredPartition); + if (usedCapacity >= 100.0) { return usedCapacity.toFixed(0) + "%"; } else { @@ -372,6 +375,39 @@ }); -const getUsedCapacity = (partitionMap, filter=PARTITION_LABEL) => { - return partitionMap[filter].absoluteUsedCapacity; +const getUsedCapacity = (queueData, filter=PARTITION_LABEL) => { + + const type = queueData.get("type"); + var result; + + switch (type) { + case "capacity": + const partitionMap = queueData.get("partitionMap"); + if (null == partitionMap || null == partitionMap[filter] || null == partitionMap[filter].absoluteUsedCapacity) { + result = 0.0; + } else { + result = partitionMap[filter].absoluteUsedCapacity; + } + break; + + case "fair": + if (null == queueData.get("fairResources") || null == queueData.get("fairResources").memory || null == queueData.get("usedResources") || null == queueData.get("usedResources").memory || 0 == queueData.get("fairResources").memory) { + result = 0.0; + } else { + result = queueData.get("usedResources").memory / queueData.get("fairResources").memory * 100; + } + break; + + case "fifo": + if (null == queueData.get("usedCapacity") || (null == queueData.get("capacity")) || (queueData.get("capacity") == 0)) { + result = 0.0; + } else { + result = queueData.get("usedCapacity") / queueData.get("capacity") * 100; + } + break; + + default: + result = 0.0; + } + return result; }; \ No newline at end of file Index: hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow/info.js IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow/info.js (revision 64f30da42813182e9cf69ec306c1f1c0c633ece0) +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow/info.js (date 1556628307000) @@ -20,6 +20,7 @@ import Converter from 'yarn-ui/utils/converter'; export default Ember.Controller.extend({ + flowUid: function() { return this.get('model.flowUid'); }.property('model.flowUid'), Index: hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/application.js IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/application.js (revision 64f30da42813182e9cf69ec306c1f1c0c633ece0) +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/application.js (date 1558019753000) @@ -17,6 +17,7 @@ */ import Ember from 'ember'; +import ENV from '../config/environment'; /** * Base controller for application. @@ -73,4 +74,8 @@ } return null; }.property('model.userInfo'), -}); + + flowPageDisabled: Ember.computed(function() { + return this.get("env.app.atsV2HealthStatus") !== "OK"; + }) +}); \ No newline at end of file Index: hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/records/timeline/TimelineHealth.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/records/timeline/TimelineHealth.java (date 1557740139000) +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/records/timeline/TimelineHealth.java (date 1557740139000) @@ -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 + * + * 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.yarn.api.records.timeline; + + +import org.apache.hadoop.classification.InterfaceAudience; +import org.apache.hadoop.classification.InterfaceStability; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * This class holds health information for ATS. + */ +@XmlRootElement(name = "health") +@XmlAccessorType(XmlAccessType.NONE) +@InterfaceAudience.Public +@InterfaceStability.Unstable +public class TimelineHealth { + + public enum TimelineHealthStatus { + OK, + BAD + } + + private TimelineHealthStatus healthStatus; + + public TimelineHealth(TimelineHealthStatus healthy) { + this.healthStatus = healthy; + } + + @XmlElement(name = "healthStatus") + public TimelineHealthStatus getHealthStatus() { + return healthStatus; + } +} +