Index: hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/AHSJAXBContextResolver.java =================================================================== --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/AHSJAXBContextResolver.java (revision 0) +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/AHSJAXBContextResolver.java (working copy) @@ -0,0 +1,61 @@ +/** + * 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.server.applicationhistoryservice.webapp; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import javax.ws.rs.ext.ContextResolver; +import javax.ws.rs.ext.Provider; +import javax.xml.bind.JAXBContext; + +import org.apache.hadoop.yarn.server.applicationhistoryservice.webapp.dao.AHSAppAttemptInfo; +import org.apache.hadoop.yarn.server.applicationhistoryservice.webapp.dao.AHSAppAttemptsInfo; +import org.apache.hadoop.yarn.server.applicationhistoryservice.webapp.dao.AHSAppInfo; +import org.apache.hadoop.yarn.server.applicationhistoryservice.webapp.dao.AHSAppsInfo; +import org.apache.hadoop.yarn.server.applicationhistoryservice.webapp.dao.AHSContainerInfo; +import org.apache.hadoop.yarn.server.applicationhistoryservice.webapp.dao.AHSContainersInfo; + +import com.google.inject.Singleton; +import com.sun.jersey.api.json.JSONConfiguration; +import com.sun.jersey.api.json.JSONJAXBContext; + +@Singleton +@Provider +@SuppressWarnings("unchecked") +public class AHSJAXBContextResolver implements ContextResolver { + + private JAXBContext context; + private final Set types; + + private final Class[] cTypes = { AHSAppsInfo.class, AHSAppInfo.class, + AHSAppAttemptsInfo.class, AHSAppAttemptInfo.class, + AHSContainersInfo.class, AHSContainerInfo.class }; + + public AHSJAXBContextResolver() throws Exception { + this.types = new HashSet(Arrays.asList(cTypes)); + this.context = new JSONJAXBContext(JSONConfiguration.natural() + .rootUnwrapping(false).build(), cTypes); + } + + @Override + public JAXBContext getContext(Class objectType) { + return (types.contains(objectType)) ? context : null; + } +} \ No newline at end of file Index: hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/AHSWebServices.java =================================================================== --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/AHSWebServices.java (revision 0) +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/AHSWebServices.java (working copy) @@ -0,0 +1,282 @@ +/** + * 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.server.applicationhistoryservice.webapp; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; + +import org.apache.hadoop.yarn.api.records.ApplicationAttemptId; +import org.apache.hadoop.yarn.api.records.ApplicationId; +import org.apache.hadoop.yarn.api.records.ContainerId; +import org.apache.hadoop.yarn.factories.RecordFactory; +import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider; +import org.apache.hadoop.yarn.server.applicationhistoryservice.ApplicationHistoryReader; +import org.apache.hadoop.yarn.server.applicationhistoryservice.records.ApplicationAttemptHistoryData; +import org.apache.hadoop.yarn.server.applicationhistoryservice.records.ApplicationHistoryData; +import org.apache.hadoop.yarn.server.applicationhistoryservice.records.ContainerHistoryData; +import org.apache.hadoop.yarn.server.applicationhistoryservice.webapp.dao.AHSAppAttemptInfo; +import org.apache.hadoop.yarn.server.applicationhistoryservice.webapp.dao.AHSAppAttemptsInfo; +import org.apache.hadoop.yarn.server.applicationhistoryservice.webapp.dao.AHSAppInfo; +import org.apache.hadoop.yarn.server.applicationhistoryservice.webapp.dao.AHSAppsInfo; +import org.apache.hadoop.yarn.server.applicationhistoryservice.webapp.dao.AHSContainerInfo; +import org.apache.hadoop.yarn.server.applicationhistoryservice.webapp.dao.AHSContainersInfo; +import org.apache.hadoop.yarn.server.applicationhistoryservice.webapp.dao.AHSInfo; +import org.apache.hadoop.yarn.util.ConverterUtils; +import org.apache.hadoop.yarn.webapp.NotFoundException; + +import com.google.inject.Inject; + +@Path("/ws/v1/applicationhistory") +public class AHSWebServices { + + @Context + private HttpServletResponse response; + + private ApplicationHistoryReader appHistoryReader; + + private static RecordFactory recordFactory = + RecordFactoryProvider.getRecordFactory(null); + + @Inject + public AHSWebServices(ApplicationHistoryReader appHistoryReader) { + this.appHistoryReader = appHistoryReader; + } + + private void init() { + // clear content type + response.setContentType(null); + } + + @GET + @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + public AHSInfo get() { + return getAHSInfo(); + } + + @GET + @Path("/info") + @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + public AHSInfo getAHSInfo() { + init(); + return new AHSInfo(); + } + + @GET + @Path("/apps/{appid}") + @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + public AHSAppInfo getApp(@Context HttpServletRequest hsr, + @PathParam("appid") String appId) { + init(); + if (appId == null || appId.isEmpty()) { + throw new NotFoundException("appId, " + appId + ", is empty or null"); + } + ApplicationId id = ConverterUtils.toApplicationId(recordFactory, appId); + if (id == null) { + throw new NotFoundException("malformed appId"); + } + ApplicationHistoryData application; + try { + application = appHistoryReader.getApplication(id); + } catch (IOException e) { + throw new RuntimeException("Failed to get the application for appId:" + + appId, e); + } + if (application == null) { + throw new NotFoundException("app with id: " + appId + " not found"); + } + return new AHSAppInfo(application); + } + + @GET + @Path("/apps") + @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + public AHSAppsInfo getApps() { + init(); + + Map appsData; + try { + appsData = appHistoryReader.getAllApplications(); + } catch (IOException e) { + throw new RuntimeException("Failed to get all applications", e); + } + if (appsData == null || appsData.isEmpty()) { + throw new NotFoundException("All Applications data is empty."); + } + AHSAppsInfo appsInfo = new AHSAppsInfo(); + for (ApplicationHistoryData appData : appsData.values()) { + appsInfo.add(new AHSAppInfo(appData)); + } + return appsInfo; + } + + @GET + @Path("/{appid}/appattempts") + @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + public AHSAppAttemptsInfo getAppAttempts(@Context HttpServletRequest hsr, + @PathParam("appid") String appId) { + init(); + if (appId == null || appId.isEmpty()) { + throw new NotFoundException("appId, " + appId + ", is empty or null"); + } + ApplicationId id = ConverterUtils.toApplicationId(recordFactory, appId); + if (id == null) { + throw new NotFoundException("malformed appId"); + } + + Map attempts; + try { + attempts = appHistoryReader.getApplicationAttempts(id); + } catch (IOException e) { + throw new RuntimeException( + "Failed to get appattempts for appId:" + appId, e); + } + if (attempts == null || attempts.isEmpty()) { + throw new NotFoundException("appattempts for appId: " + appId + + " not found"); + } + AHSAppAttemptsInfo appAttemptsInfo = new AHSAppAttemptsInfo(); + for (ApplicationAttemptHistoryData appAttemptHistoryData : attempts + .values()) { + appAttemptsInfo.add(new AHSAppAttemptInfo(appAttemptHistoryData)); + } + return appAttemptsInfo; + } + + @GET + @Path("/appattempts/{appattemptid}") + @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + public AHSAppAttemptInfo getAppAttempt(@Context HttpServletRequest hsr, + @PathParam("appattemptid") String appAttemptId) { + init(); + if (appAttemptId == null || appAttemptId.isEmpty()) { + throw new NotFoundException("appAttemptId, " + appAttemptId + + ", is empty or null"); + } + ApplicationAttemptId id = + ConverterUtils.toApplicationAttemptId(appAttemptId); + if (id == null) { + throw new NotFoundException("malformed appAttempt"); + } + ApplicationAttemptHistoryData appAttemptHistoryData; + try { + appAttemptHistoryData = appHistoryReader.getApplicationAttempt(id); + } catch (Exception e) { + throw new RuntimeException("Failed to get the application for appId:" + + appAttemptId, e); + } + if (appAttemptHistoryData == null) { + throw new NotFoundException("app with id: " + appAttemptId + " not found"); + } + return new AHSAppAttemptInfo(appAttemptHistoryData); + } + + @GET + @Path("/{appIdOrAppAttemptId}/containers") + @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + public AHSContainersInfo getContainers( + @PathParam("appIdOrAppAttemptId") String appIdOrAppAttemptId) { + init(); + if (appIdOrAppAttemptId == null || appIdOrAppAttemptId.isEmpty()) { + throw new NotFoundException("appAttemptId, " + appIdOrAppAttemptId + + ", is empty or null"); + } + Collection appAttemptIds = + new ArrayList(); + if (appIdOrAppAttemptId.startsWith(ConverterUtils.APPLICATION_PREFIX)) { + ApplicationId appId = + ConverterUtils.toApplicationId(recordFactory, appIdOrAppAttemptId); + if (appId == null) { + throw new NotFoundException("malformed appId"); + } + Map applicationAttempts; + try { + applicationAttempts = appHistoryReader.getApplicationAttempts(appId); + } catch (IOException e) { + throw new RuntimeException("Failed to get appaattemps :" + appId, e); + } + appAttemptIds.addAll(applicationAttempts.keySet()); + } else { + ApplicationAttemptId attemptId = + ConverterUtils.toApplicationAttemptId(appIdOrAppAttemptId); + if (attemptId == null) { + throw new NotFoundException("malformed appAttemptId"); + } + appAttemptIds.add(attemptId); + } + + AHSContainersInfo containersInfo = new AHSContainersInfo(); + for (ApplicationAttemptId appAttemptId : appAttemptIds) { + Map containers; + try { + containers = appHistoryReader.getContainers(appAttemptId); + } catch (IOException e) { + throw new RuntimeException("Failed to get containers for appAttemptId:" + + appAttemptId, e); + } + if (containers != null) { + for (ContainerHistoryData containerInfo : containers.values()) { + containersInfo.add(new AHSContainerInfo(containerInfo)); + } + } + } + if (containersInfo.getContainers().isEmpty()) { + throw new NotFoundException("Containers for : " + appIdOrAppAttemptId + + " not found"); + } + return containersInfo; + } + + @GET + @Path("/containers/{containerid}") + @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + public AHSContainerInfo getContainer(@Context HttpServletRequest hsr, + @PathParam("containerid") String containerId) { + init(); + if (containerId == null || containerId.isEmpty()) { + throw new NotFoundException("containerId, " + containerId + + ", is empty or null"); + } + ContainerId id = ConverterUtils.toContainerId(containerId); + if (id == null) { + throw new NotFoundException("malformed containerId"); + } + ContainerHistoryData containerHistoryData; + try { + containerHistoryData = appHistoryReader.getContainer(id); + } catch (Exception e) { + throw new RuntimeException("Failed to get the application for appId:" + + containerId, e); + } + if (containerHistoryData == null) { + throw new NotFoundException("app with id: " + containerId + " not found"); + } + return new AHSContainerInfo(containerHistoryData); + } + +} Index: hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/dao/AHSAppAttemptInfo.java =================================================================== --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/dao/AHSAppAttemptInfo.java (revision 0) +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/dao/AHSAppAttemptInfo.java (working copy) @@ -0,0 +1,94 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.yarn.server.applicationhistoryservice.webapp.dao; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.hadoop.yarn.api.records.ContainerId; +import org.apache.hadoop.yarn.api.records.FinalApplicationStatus; +import org.apache.hadoop.yarn.server.applicationhistoryservice.records.ApplicationAttemptHistoryData; + +@XmlRootElement(name = "applicationAttempt") +@XmlAccessorType(XmlAccessType.FIELD) +public class AHSAppAttemptInfo { + + private String applicationAttemptId; + private String host; + private int rpcPort; + private FinalApplicationStatus finalApplicationStatus; + private String trackingURL; + private String masterContainerId; + private String diagnosticsInfo; + + public AHSAppAttemptInfo() { + } + + public AHSAppAttemptInfo(ApplicationAttemptHistoryData appAttemptHistoryData) { + applicationAttemptId = appAttemptHistoryData.getApplicationAttemptId() + .toString(); + host = appAttemptHistoryData.getHost(); + if (host == null) { + host = ""; + } + rpcPort = appAttemptHistoryData.getRPCPort(); + finalApplicationStatus = appAttemptHistoryData.getFinalApplicationStatus(); + trackingURL = appAttemptHistoryData.getTrackingURL(); + if (trackingURL == null) { + trackingURL = ""; + } + ContainerId masterContainerId = appAttemptHistoryData + .getMasterContainerId(); + this.masterContainerId = (masterContainerId == null) ? "" + : masterContainerId.toString(); + diagnosticsInfo = appAttemptHistoryData.getDiagnosticsInfo(); + if (diagnosticsInfo == null) { + diagnosticsInfo = ""; + } + } + + public String getApplicationAttemptId() { + return applicationAttemptId; + } + + public String getHost() { + return host; + } + + public int getRpcPort() { + return rpcPort; + } + + public FinalApplicationStatus getFinalApplicationStatus() { + return finalApplicationStatus; + } + + public String getTrackingURL() { + return trackingURL; + } + + public String getMasterContainerId() { + return masterContainerId; + } + + public String getDiagnosticsInfo() { + return diagnosticsInfo; + } + +} Index: hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/dao/AHSAppAttemptsInfo.java =================================================================== --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/dao/AHSAppAttemptsInfo.java (revision 0) +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/dao/AHSAppAttemptsInfo.java (working copy) @@ -0,0 +1,40 @@ +/** + * 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.server.applicationhistoryservice.webapp.dao; + +import java.util.ArrayList; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "appAttempts") +@XmlAccessorType(XmlAccessType.FIELD) +public class AHSAppAttemptsInfo { + @XmlElement(name = "appAttempt") + private ArrayList attempts = new ArrayList(); + + public void add(AHSAppAttemptInfo info) { + this.attempts.add(info); + } + + public ArrayList getAttempts() { + return this.attempts; + } +} Index: hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/dao/AHSAppInfo.java =================================================================== --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/dao/AHSAppInfo.java (revision 0) +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/dao/AHSAppInfo.java (working copy) @@ -0,0 +1,117 @@ +/** + * 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.server.applicationhistoryservice.webapp.dao; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.hadoop.yarn.api.records.ApplicationId; +import org.apache.hadoop.yarn.api.records.FinalApplicationStatus; +import org.apache.hadoop.yarn.server.applicationhistoryservice.records.ApplicationHistoryData; +import org.apache.hadoop.yarn.util.Times; + +@XmlRootElement(name = "application") +@XmlAccessorType(XmlAccessType.FIELD) +public class AHSAppInfo { + + private String appIdNum; + private ApplicationId applicationId; + private String id; + private String user; + private String name; + private String queue; + private FinalApplicationStatus finalStatus; + private String diagnostics; + private String applicationType; + private long startedTime; + private long finishedTime; + private long elapsedTime; + + public AHSAppInfo() { + } // JAXB needs this + + public AHSAppInfo(ApplicationHistoryData app) { + if (app != null) { + this.applicationId = app.getApplicationId(); + this.applicationType = app.getApplicationType(); + this.appIdNum = String.valueOf(app.getApplicationId().getId()); + this.id = app.getApplicationId().toString(); + this.user = app.getUser().toString(); + this.name = app.getApplicationName(); + this.queue = app.getQueue().toString(); + this.diagnostics = app.getDiagnosticsInfo(); + if (diagnostics == null || diagnostics.isEmpty()) { + this.diagnostics = ""; + } + this.finalStatus = app.getFinalApplicationStatus(); + this.startedTime = app.getStartTime(); + this.finishedTime = app.getFinishTime(); + this.elapsedTime = Times.elapsed(app.getStartTime(), app.getFinishTime()); + } + } + + public ApplicationId getApplicationId() { + return this.applicationId; + } + + public String getAppId() { + return this.id; + } + + public String getAppIdNum() { + return this.appIdNum; + } + + public String getUser() { + return this.user; + } + + public String getQueue() { + return this.queue; + } + + public String getName() { + return this.name; + } + + public String getNote() { + return this.diagnostics; + } + + public String getFinalStatus() { + return this.finalStatus.toString(); + } + + public long getStartTime() { + return this.startedTime; + } + + public long getFinishTime() { + return this.finishedTime; + } + + public long getElapsedTime() { + return this.elapsedTime; + } + + public String getApplicationType() { + return this.applicationType; + } + +} Index: hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/dao/AHSAppsInfo.java =================================================================== --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/dao/AHSAppsInfo.java (revision 0) +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/dao/AHSAppsInfo.java (working copy) @@ -0,0 +1,40 @@ +/** + * 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.server.applicationhistoryservice.webapp.dao; + +import java.util.ArrayList; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "apps") +@XmlAccessorType(XmlAccessType.FIELD) +public class AHSAppsInfo { + @XmlElement(name = "app") + private ArrayList apps = new ArrayList(); + + public void add(AHSAppInfo info) { + this.apps.add(info); + } + + public ArrayList getApps() { + return this.apps; + } +} Index: hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/dao/AHSContainerInfo.java =================================================================== --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/dao/AHSContainerInfo.java (revision 0) +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/dao/AHSContainerInfo.java (working copy) @@ -0,0 +1,103 @@ +/** + * 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.server.applicationhistoryservice.webapp.dao; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.hadoop.yarn.api.records.ContainerState; +import org.apache.hadoop.yarn.api.records.Resource; +import org.apache.hadoop.yarn.server.applicationhistoryservice.records.ContainerHistoryData; + +@XmlRootElement(name = "container") +@XmlAccessorType(XmlAccessType.FIELD) +public class AHSContainerInfo { + + private String containerId; + + private Resource resource; + + private String nodeId; + + private int priority; + + private String diagnosticsInfo; + + private ContainerState finalContainerStatus; + + private long startTime; + + private long finishTime; + + private String logURL; + + public AHSContainerInfo() { + } + + public AHSContainerInfo(ContainerHistoryData containerHistoryData) { + containerId = containerHistoryData.getContainerId().toString(); + resource = containerHistoryData.getAllocatedResource(); + nodeId = containerHistoryData.getAssignedNode().toString(); + priority = containerHistoryData.getPriority().getPriority(); + diagnosticsInfo = containerHistoryData.getDiagnosticsInfo(); + finalContainerStatus = containerHistoryData.getFinalContainerStatus(); + startTime = containerHistoryData.getStartTime(); + finishTime = containerHistoryData.getFinishTime(); + logURL = containerHistoryData.getLogURL(); + if (logURL == null) { + logURL = ""; + } + } + + public String getContainerId() { + return containerId; + } + + public Resource getResource() { + return resource; + } + + public String getNodeId() { + return nodeId; + } + + public int getPriority() { + return priority; + } + + public String getDiagnosticsInfo() { + return diagnosticsInfo; + } + + public ContainerState getFinalContainerStatus() { + return finalContainerStatus; + } + + public long getStartTime() { + return startTime; + } + + public long getFinishTime() { + return finishTime; + } + + public String getLogURL() { + return logURL; + } +} Index: hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/dao/AHSContainersInfo.java =================================================================== --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/dao/AHSContainersInfo.java (revision 0) +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/dao/AHSContainersInfo.java (working copy) @@ -0,0 +1,40 @@ +/** + * 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.server.applicationhistoryservice.webapp.dao; + +import java.util.ArrayList; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "containers") +@XmlAccessorType(XmlAccessType.FIELD) +public class AHSContainersInfo { + @XmlElement(name = "container") + private ArrayList containers = new ArrayList(); + + public void add(AHSContainerInfo info) { + this.containers.add(info); + } + + public ArrayList getContainers() { + return this.containers; + } +} Index: hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/TestAHSWebServices.java =================================================================== --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/TestAHSWebServices.java (revision 0) +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/applicationhistoryservice/webapp/TestAHSWebServices.java (working copy) @@ -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 + * + * 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.server.applicationhistoryservice.webapp; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.IOException; + +import javax.ws.rs.core.MediaType; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.yarn.api.records.ApplicationAttemptId; +import org.apache.hadoop.yarn.api.records.ApplicationId; +import org.apache.hadoop.yarn.server.applicationhistoryservice.ApplicationHistoryReader; +import org.apache.hadoop.yarn.webapp.GenericExceptionHandler; +import org.apache.hadoop.yarn.webapp.WebApp; +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; +import org.junit.Before; +import org.junit.Test; + +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.servlet.GuiceServletContextListener; +import com.google.inject.servlet.ServletModule; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.WebResource; +import com.sun.jersey.guice.spi.container.servlet.GuiceContainer; +import com.sun.jersey.test.framework.JerseyTest; +import com.sun.jersey.test.framework.WebAppDescriptor; + +public class TestAHSWebServices extends JerseyTest { + + private static Configuration conf = new Configuration(); + private static AHSWebApp webApp; + private static MockApplicationHistoryReader appHSReader; + + private Injector injector = Guice.createInjector(new ServletModule() { + @Override + protected void configureServlets() { + try { + appHSReader = new MockApplicationHistoryReader(4, 2, 3); + } catch (IOException e) { + throw new RuntimeException(e); + } + webApp = mock(AHSWebApp.class); + when(webApp.name()).thenReturn("hsmockwebapp"); + + bind(AHSJAXBContextResolver.class); + bind(AHSWebServices.class); + bind(GenericExceptionHandler.class); + bind(WebApp.class).toInstance(webApp); + bind(ApplicationHistoryReader.class).toInstance(appHSReader); + bind(Configuration.class).toInstance(conf); + + serve("/*").with(GuiceContainer.class); + } + }); + + public class GuiceServletConfig extends GuiceServletContextListener { + + @Override + protected Injector getInjector() { + return injector; + } + } + + @Before + @Override + public void setUp() throws Exception { + super.setUp(); + + } + + public TestAHSWebServices() { + super(new WebAppDescriptor.Builder( + "org.apache.hadoop.yarn.server.applicationhistoryservice.webapp") + .contextListenerClass(GuiceServletConfig.class).filterClass( + com.google.inject.servlet.GuiceFilter.class).contextPath( + "jersey-guice-filter").servletPath("/").build()); + } + + @Test + public void testApps() throws JSONException, Exception { + WebResource r = resource(); + ClientResponse response = + r.path("ws").path("v1").path("applicationhistory").path("apps").accept( + MediaType.APPLICATION_JSON).get(ClientResponse.class); + assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); + JSONObject json = response.getEntity(JSONObject.class); + assertEquals("incorrect number of elements", 1, json.length()); + JSONObject apps = json.getJSONObject("apps"); + JSONArray arr = apps.getJSONArray("app"); + assertEquals("incorrect number of apps", 4, arr.length()); + } + + @Test + public void testApplication() throws JSONException, Exception { + WebResource r = resource(); + String appId = + appHSReader.getAllApplications().keySet().iterator().next().toString(); + ClientResponse response = + r.path("ws").path("v1").path("applicationhistory").path("apps").path( + appId).accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); + JSONObject json = response.getEntity(JSONObject.class); + assertEquals("incorrect number of elements", 1, json.length()); + JSONObject app = json.getJSONObject("application"); + assertEquals(appId, app.getString("id")); + } + + @Test + public void testAppAttempts() throws JSONException, Exception { + WebResource r = resource(); + String appId = + appHSReader.getAllApplications().keySet().iterator().next().toString(); + ClientResponse response = + r.path("ws").path("v1").path("applicationhistory").path(appId).path( + "appattempts").accept(MediaType.APPLICATION_JSON).get( + ClientResponse.class); + assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); + JSONObject json = response.getEntity(JSONObject.class); + assertEquals("incorrect number of elements", 1, json.length()); + JSONObject apps = json.getJSONObject("appAttempts"); + JSONArray arr = apps.getJSONArray("appAttempt"); + assertEquals("incorrect number of appattempts", 2, arr.length()); + } + + @Test + public void testAppAttempt() throws JSONException, Exception { + WebResource r = resource(); + ApplicationId appId = + appHSReader.getAllApplications().keySet().iterator().next(); + String appAttemptId = + appHSReader.getApplicationAttempts(appId).keySet().iterator().next() + .toString(); + ClientResponse response = + r.path("ws").path("v1").path("applicationhistory").path("appattempts") + .path(appAttemptId).accept(MediaType.APPLICATION_JSON).get( + ClientResponse.class); + assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); + JSONObject json = response.getEntity(JSONObject.class); + assertEquals("incorrect number of elements", 1, json.length()); + JSONObject container = json.getJSONObject("applicationAttempt"); + assertEquals(appAttemptId, container.getString("applicationAttemptId")); + } + + @Test + public void testAppContainers() throws JSONException, Exception { + String appId = + appHSReader.getAllApplications().keySet().iterator().next().toString(); + verifyContainers(appId, 6); + } + + @Test + public void testAppAttemptContainers() throws JSONException, Exception { + ApplicationId appId = + appHSReader.getAllApplications().keySet().iterator().next(); + String appAttemptId = + appHSReader.getApplicationAttempts(appId).keySet().iterator().next() + .toString(); + verifyContainers(appAttemptId, 3); + } + + @Test + public void testContainer() throws JSONException, Exception { + WebResource r = resource(); + ApplicationId appId = + appHSReader.getAllApplications().keySet().iterator().next(); + ApplicationAttemptId appAttemptId = + appHSReader.getApplicationAttempts(appId).keySet().iterator().next(); + String containerId = + appHSReader.getContainers(appAttemptId).keySet().iterator().next() + .toString(); + ClientResponse response = + r.path("ws").path("v1").path("applicationhistory").path("containers") + .path(containerId).accept(MediaType.APPLICATION_JSON).get( + ClientResponse.class); + assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); + JSONObject json = response.getEntity(JSONObject.class); + assertEquals("incorrect number of elements", 1, json.length()); + JSONObject container = json.getJSONObject("container"); + assertEquals(containerId, container.getString("containerId")); + } + + private void verifyContainers(String appAttemptId, int expected) + throws JSONException { + WebResource r = resource(); + ClientResponse response = + r.path("ws").path("v1").path("applicationhistory").path(appAttemptId) + .path("containers").accept(MediaType.APPLICATION_JSON).get( + ClientResponse.class); + assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getType()); + JSONObject json = response.getEntity(JSONObject.class); + assertEquals("incorrect number of elements", 1, json.length()); + JSONObject apps = json.getJSONObject("containers"); + JSONArray arr = apps.getJSONArray("container"); + assertEquals("incorrect number of containers", expected, arr.length()); + } + +}