ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jonathanhur...@apache.org
Subject [21/50] [abbrv] ambari git commit: AMBARI-21071. Ambari Infra Manager: add jobs/steps REST API endpoints (oleewere)
Date Wed, 24 May 2017 02:39:38 GMT
AMBARI-21071. Ambari Infra Manager: add jobs/steps REST API endpoints (oleewere)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/9ffef7fc
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/9ffef7fc
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/9ffef7fc

Branch: refs/heads/branch-feature-AMBARI-12556
Commit: 9ffef7fc58b4313dfdf8d96badce5198855934a7
Parents: c23602c
Author: oleewere <oleewere@gmail.com>
Authored: Fri May 19 14:41:42 2017 +0200
Committer: oleewere <oleewere@gmail.com>
Committed: Sat May 20 12:51:51 2017 +0200

----------------------------------------------------------------------
 .../org/apache/ambari/infra/InfraManager.java   |   1 +
 .../conf/batch/InfraManagerBatchConfig.java     |  55 ++++
 .../apache/ambari/infra/manager/JobManager.java | 274 +++++++++++++++++++
 .../infra/model/ExecutionContextResponse.java   |  40 +++
 .../ambari/infra/model/JobDetailsResponse.java  |  53 ++++
 .../model/JobExecutionDetailsResponse.java      |  49 ++++
 .../infra/model/JobExecutionInfoResponse.java   | 141 ++++++++++
 .../ambari/infra/model/JobExecutionRequest.java |  46 ++++
 .../infra/model/JobExecutionRestartRequest.java |  52 ++++
 .../infra/model/JobExecutionStopRequest.java    |  50 ++++
 .../infra/model/JobInstanceDetailsResponse.java |  54 ++++
 .../infra/model/JobInstanceStartRequest.java    |  49 ++++
 .../ambari/infra/model/JobOperationParams.java  |  31 +++
 .../apache/ambari/infra/model/JobRequest.java   |  37 +++
 .../apache/ambari/infra/model/PageRequest.java  |  49 ++++
 .../model/StepExecutionContextResponse.java     |  58 ++++
 .../infra/model/StepExecutionInfoResponse.java  | 115 ++++++++
 .../model/StepExecutionProgressResponse.java    |  53 ++++
 .../infra/model/StepExecutionRequest.java       |  49 ++++
 .../infra/model/wrapper/JobExecutionData.java   | 118 ++++++++
 .../infra/model/wrapper/StepExecutionData.java  | 133 +++++++++
 .../ambari/infra/rest/JobExceptionMapper.java   | 110 ++++++++
 .../apache/ambari/infra/rest/JobResource.java   | 151 ++++++++--
 23 files changed, 1748 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/9ffef7fc/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/InfraManager.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/InfraManager.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/InfraManager.java
index 656127e..227bab4 100644
--- a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/InfraManager.java
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/InfraManager.java
@@ -142,6 +142,7 @@ public class InfraManager {
     ServletHolder jerseyServlet = context.addServlet(org.glassfish.jersey.servlet.ServletContainer.class, "/api/v1/*");
     jerseyServlet.setInitOrder(1);
     jerseyServlet.setInitParameter("jersey.config.server.provider.packages","org.apache.ambari.infra.rest,io.swagger.jaxrs.listing");
+
     context.getSessionHandler().getSessionManager().setMaxInactiveInterval(SESSION_TIMEOUT);
     context.getSessionHandler().getSessionManager().getSessionCookieConfig().setName(INFRA_MANAGER_SESSION_ID);
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/9ffef7fc/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/batch/InfraManagerBatchConfig.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/batch/InfraManagerBatchConfig.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/batch/InfraManagerBatchConfig.java
index 7310626..c3d8db6 100644
--- a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/batch/InfraManagerBatchConfig.java
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/conf/batch/InfraManagerBatchConfig.java
@@ -21,6 +21,14 @@ package org.apache.ambari.infra.conf.batch;
 import org.apache.ambari.infra.job.dummy.DummyItemProcessor;
 import org.apache.ambari.infra.job.dummy.DummyItemWriter;
 import org.apache.ambari.infra.job.dummy.DummyObject;
+import org.springframework.batch.admin.service.JdbcSearchableJobExecutionDao;
+import org.springframework.batch.admin.service.JdbcSearchableJobInstanceDao;
+import org.springframework.batch.admin.service.JdbcSearchableStepExecutionDao;
+import org.springframework.batch.admin.service.JobService;
+import org.springframework.batch.admin.service.SearchableJobExecutionDao;
+import org.springframework.batch.admin.service.SearchableJobInstanceDao;
+import org.springframework.batch.admin.service.SearchableStepExecutionDao;
+import org.springframework.batch.admin.service.SimpleJobService;
 import org.springframework.batch.core.Job;
 import org.springframework.batch.core.Step;
 import org.springframework.batch.core.configuration.JobRegistry;
@@ -34,6 +42,9 @@ import org.springframework.batch.core.launch.JobOperator;
 import org.springframework.batch.core.launch.support.SimpleJobLauncher;
 import org.springframework.batch.core.launch.support.SimpleJobOperator;
 import org.springframework.batch.core.repository.JobRepository;
+import org.springframework.batch.core.repository.dao.DefaultExecutionContextSerializer;
+import org.springframework.batch.core.repository.dao.ExecutionContextDao;
+import org.springframework.batch.core.repository.dao.JdbcExecutionContextDao;
 import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
 import org.springframework.batch.item.ItemProcessor;
 import org.springframework.batch.item.ItemReader;
@@ -53,6 +64,7 @@ import org.springframework.context.annotation.Configuration;
 import org.springframework.core.io.ClassPathResource;
 import org.springframework.core.io.Resource;
 import org.springframework.core.task.SimpleAsyncTaskExecutor;
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.datasource.DriverManagerDataSource;
 import org.springframework.jdbc.datasource.init.DataSourceInitializer;
 import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
@@ -166,6 +178,49 @@ public class InfraManagerBatchConfig {
     return jobRegistryBeanPostProcessor;
   }
 
+  @Bean
+  public JdbcTemplate jdbcTemplate() {
+    return new JdbcTemplate(dataSource());
+  }
+
+  @Bean
+  public SearchableJobInstanceDao searchableJobInstanceDao() {
+    JdbcSearchableJobInstanceDao dao = new JdbcSearchableJobInstanceDao();
+    dao.setJdbcTemplate(jdbcTemplate());
+    return dao;
+  }
+
+  @Bean
+  public SearchableJobExecutionDao searchableJobExecutionDao() {
+    JdbcSearchableJobExecutionDao dao = new JdbcSearchableJobExecutionDao();
+    dao.setJdbcTemplate(jdbcTemplate());
+    dao.setDataSource(dataSource());
+    return dao;
+  }
+
+  @Bean
+  public SearchableStepExecutionDao searchableStepExecutionDao() {
+    JdbcSearchableStepExecutionDao dao = new JdbcSearchableStepExecutionDao();
+    dao.setDataSource(dataSource());
+    dao.setJdbcTemplate(jdbcTemplate());
+    return dao;
+  }
+
+  @Bean
+  public ExecutionContextDao executionContextDao() {
+    JdbcExecutionContextDao dao = new JdbcExecutionContextDao();
+    dao.setSerializer(new DefaultExecutionContextSerializer());
+    dao.setJdbcTemplate(jdbcTemplate());
+    return dao;
+  }
+
+  @Bean
+  public JobService jobService() throws Exception {
+    return new
+      SimpleJobService(searchableJobInstanceDao(), searchableJobExecutionDao(), searchableStepExecutionDao(),
+      jobRepository(), jobLauncher(), jobRegistry, executionContextDao());
+  }
+
   @Bean(name = "dummyStep")
   protected Step dummyStep(ItemReader<DummyObject> reader,
                        ItemProcessor<DummyObject, String> processor,

http://git-wip-us.apache.org/repos/asf/ambari/blob/9ffef7fc/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/manager/JobManager.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/manager/JobManager.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/manager/JobManager.java
new file mode 100644
index 0000000..fc0a4f7
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/manager/JobManager.java
@@ -0,0 +1,274 @@
+/*
+ * 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.ambari.infra.manager;
+
+import com.google.common.collect.Lists;
+import org.apache.ambari.infra.model.ExecutionContextResponse;
+import org.apache.ambari.infra.model.JobDetailsResponse;
+import org.apache.ambari.infra.model.JobExecutionDetailsResponse;
+import org.apache.ambari.infra.model.JobExecutionInfoResponse;
+import org.apache.ambari.infra.model.JobInstanceDetailsResponse;
+import org.apache.ambari.infra.model.JobOperationParams;
+import org.apache.ambari.infra.model.StepExecutionContextResponse;
+import org.apache.ambari.infra.model.StepExecutionInfoResponse;
+import org.apache.ambari.infra.model.StepExecutionProgressResponse;
+import org.springframework.batch.admin.history.StepExecutionHistory;
+import org.springframework.batch.admin.service.JobService;
+import org.springframework.batch.admin.service.NoSuchStepExecutionException;
+import org.springframework.batch.admin.web.JobInfo;
+import org.springframework.batch.admin.web.StepExecutionProgress;
+import org.springframework.batch.core.JobExecution;
+import org.springframework.batch.core.JobInstance;
+import org.springframework.batch.core.JobParametersBuilder;
+import org.springframework.batch.core.JobParametersInvalidException;
+import org.springframework.batch.core.StepExecution;
+import org.springframework.batch.core.launch.JobExecutionNotRunningException;
+import org.springframework.batch.core.launch.JobInstanceAlreadyExistsException;
+import org.springframework.batch.core.launch.JobOperator;
+import org.springframework.batch.core.launch.NoSuchJobException;
+import org.springframework.batch.core.launch.NoSuchJobExecutionException;
+import org.springframework.batch.core.launch.NoSuchJobInstanceException;
+import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
+import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
+import org.springframework.batch.core.repository.JobRestartException;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TimeZone;
+
+@Named
+public class JobManager {
+
+  @Inject
+  private JobService jobService;
+
+  @Inject
+  private JobOperator jobOperator;
+
+  private TimeZone timeZone = TimeZone.getDefault();
+
+  public Set<String> getAllJobNames() {
+    return jobOperator.getJobNames();
+  }
+
+  /**
+   * Launch a new job instance (based on job name) and applies customized parameters to it.
+   * Also add a new date parameter to make sure the job instance will be unique
+   */
+  public JobExecutionInfoResponse launchJob(String jobName, String params)
+    throws JobParametersInvalidException, JobInstanceAlreadyExistsException, NoSuchJobException,
+    JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {
+    // TODO: handle params
+    JobParametersBuilder jobParametersBuilder = new JobParametersBuilder();
+    jobParametersBuilder.addDate("date", new Date());
+    return new JobExecutionInfoResponse(jobService.launch(jobName, jobParametersBuilder.toJobParameters()), timeZone);
+  }
+
+  /**
+   * Get all executions ids that mapped to specific job name,
+   */
+  public Set<Long> getExecutionIdsByJobName(String jobName) throws NoSuchJobException {
+    return jobOperator.getRunningExecutions(jobName);
+  }
+
+  /**
+   * Stop all running job executions and returns with the number of stopped jobs.
+   */
+  public Integer stopAllJobs() {
+    return jobService.stopAll();
+  }
+
+  /**
+   * Gather job execution details by job execution id.
+   */
+  public JobExecutionDetailsResponse getExectionInfo(Long jobExecutionId) throws NoSuchJobExecutionException {
+    JobExecution jobExecution = jobService.getJobExecution(jobExecutionId);
+    List<StepExecutionInfoResponse> stepExecutionInfos = new ArrayList<StepExecutionInfoResponse>();
+    for (StepExecution stepExecution : jobExecution.getStepExecutions()) {
+      stepExecutionInfos.add(new StepExecutionInfoResponse(stepExecution, timeZone));
+    }
+    Collections.sort(stepExecutionInfos, new Comparator<StepExecutionInfoResponse>() {
+      @Override
+      public int compare(StepExecutionInfoResponse o1, StepExecutionInfoResponse o2) {
+        return o1.getId().compareTo(o2.getId());
+      }
+    });
+    return new JobExecutionDetailsResponse(new JobExecutionInfoResponse(jobExecution, timeZone), stepExecutionInfos);
+  }
+
+  /**
+   * Stop or abandon a running job execution by job execution id
+   */
+  public JobExecutionInfoResponse stopOrAbandonJobByExecutionId(Long jobExecutionId, JobOperationParams.JobStopOrAbandonOperationParam operation)
+    throws NoSuchJobExecutionException, JobExecutionNotRunningException, JobExecutionAlreadyRunningException {
+    JobExecution jobExecution;
+    if (JobOperationParams.JobStopOrAbandonOperationParam.STOP.equals(operation)) {
+      jobExecution = jobService.stop(jobExecutionId);
+    } else if (JobOperationParams.JobStopOrAbandonOperationParam.ABANDON.equals(operation)) {
+      jobExecution = jobService.abandon(jobExecutionId);
+    } else {
+      throw new UnsupportedOperationException("Unsupported operaration");
+    }
+    return new JobExecutionInfoResponse(jobExecution, timeZone);
+  }
+
+  /**
+   * Get execution context for a job execution instance. (context can be shipped between job executions)
+   */
+  public ExecutionContextResponse getExecutionContextByJobExecutionId(Long executionId) throws NoSuchJobExecutionException {
+    JobExecution jobExecution = jobService.getJobExecution(executionId);
+    Map<String, Object> executionMap = new HashMap<>();
+    for (Map.Entry<String, Object> entry : jobExecution.getExecutionContext().entrySet()) {
+      executionMap.put(entry.getKey(), entry.getValue());
+    }
+    return new ExecutionContextResponse(executionId, executionMap);
+  }
+
+  /**
+   * Restart a specific job instance with the same parameters. (only restart operation is supported here)
+   */
+  public JobExecutionInfoResponse restart(Long jobInstanceId, String jobName,
+                                          JobOperationParams.JobRestartOperationParam operation) throws NoSuchJobException, JobParametersInvalidException,
+    JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException, NoSuchJobExecutionException {
+    if (JobOperationParams.JobRestartOperationParam.RESTART.equals(operation)) {
+      Collection<JobExecution> jobExecutions = jobService.getJobExecutionsForJobInstance(jobName, jobInstanceId);
+      JobExecution jobExecution = jobExecutions.iterator().next();
+      Long jobExecutionId = jobExecution.getId();
+      return new JobExecutionInfoResponse(jobService.restart(jobExecutionId), timeZone);
+    } else {
+      throw new UnsupportedOperationException("Unsupported operation (try: RESTART)");
+    }
+  }
+
+  /**
+   * Get all job details. (paged)
+   */
+  public List<JobInfo> getAllJobs(int start, int pageSize) {
+    List<JobInfo> jobs = new ArrayList<>();
+    Collection<String> names = jobService.listJobs(start, pageSize);
+    for (String name : names) {
+      int count = 0;
+      try {
+        count = jobService.countJobExecutionsForJob(name);
+      }
+      catch (NoSuchJobException e) {
+        // shouldn't happen
+      }
+      boolean launchable = jobService.isLaunchable(name);
+      boolean incrementable = jobService.isIncrementable(name);
+      jobs.add(new JobInfo(name, count, null, launchable, incrementable));
+    }
+    return jobs;
+  }
+
+  /**
+   * Get all executions for unique job instance.
+   */
+  public List<JobExecutionInfoResponse> getExecutionsForJobInstance(String jobName, Long jobInstanceId) throws NoSuchJobInstanceException, NoSuchJobException {
+    List<JobExecutionInfoResponse> result = Lists.newArrayList();
+    JobInstance jobInstance = jobService.getJobInstance(jobInstanceId);
+    Collection<JobExecution> jobExecutions = jobService.getJobExecutionsForJobInstance(jobName, jobInstance.getInstanceId());
+    for (JobExecution jobExecution : jobExecutions) {
+      result.add(new JobExecutionInfoResponse(jobExecution, timeZone));
+    }
+    return result;
+  }
+
+  /**
+   * Get job details for a specific job. (paged)
+   */
+  public JobDetailsResponse getJobDetails(String jobName, int page, int size) throws NoSuchJobException {
+    List<JobInstanceDetailsResponse> jobInstanceResponses = Lists.newArrayList();
+    Collection<JobInstance> jobInstances = jobService.listJobInstances(jobName, page, size);
+
+    int count = jobService.countJobExecutionsForJob(jobName);
+    boolean launchable = jobService.isLaunchable(jobName);
+    boolean isIncrementable = jobService.isIncrementable(jobName);
+
+    for (JobInstance jobInstance: jobInstances) {
+      List<JobExecutionInfoResponse> executionInfos = Lists.newArrayList();
+      Collection<JobExecution> jobExecutions = jobService.getJobExecutionsForJobInstance(jobName, jobInstance.getId());
+      if (jobExecutions != null) {
+        for (JobExecution jobExecution : jobExecutions) {
+          executionInfos.add(new JobExecutionInfoResponse(jobExecution, timeZone));
+        }
+      }
+      jobInstanceResponses.add(new JobInstanceDetailsResponse(jobInstance, executionInfos));
+    }
+    return new JobDetailsResponse(new JobInfo(jobName, count, launchable, isIncrementable), jobInstanceResponses);
+  }
+
+  /**
+   * Get step execution details based for job execution id and step execution id.
+   */
+  public StepExecutionInfoResponse getStepExecution(Long jobExecutionId, Long stepExecutionId) throws NoSuchStepExecutionException, NoSuchJobExecutionException {
+    StepExecution stepExecution = jobService.getStepExecution(jobExecutionId, stepExecutionId);
+    return new StepExecutionInfoResponse(stepExecution, timeZone);
+  }
+
+  /**
+   * Get step execution context details. (execution context can be shipped between steps)
+   */
+  public StepExecutionContextResponse getStepExecutionContext(Long jobExecutionId, Long stepExecutionId) throws NoSuchStepExecutionException, NoSuchJobExecutionException {
+    StepExecution stepExecution = jobService.getStepExecution(jobExecutionId, stepExecutionId);
+    Map<String, Object> executionMap = new HashMap<>();
+    for (Map.Entry<String, Object> entry : stepExecution.getExecutionContext().entrySet()) {
+      executionMap.put(entry.getKey(), entry.getValue());
+    }
+    return new StepExecutionContextResponse(executionMap, jobExecutionId, stepExecutionId, stepExecution.getStepName());
+  }
+
+  /**
+   * Get step execution progress status detauls.
+   */
+  public StepExecutionProgressResponse getStepExecutionProgress(Long jobExecutionId, Long stepExecutionId) throws NoSuchStepExecutionException, NoSuchJobExecutionException {
+    StepExecution stepExecution = jobService.getStepExecution(jobExecutionId, stepExecutionId);
+    StepExecutionInfoResponse stepExecutionInfoResponse = new StepExecutionInfoResponse(stepExecution, timeZone);
+    String stepName = stepExecution.getStepName();
+    if (stepName.contains(":partition")) {
+      stepName = stepName.replaceAll("(:partition).*", "$1*");
+    }
+    String jobName = stepExecution.getJobExecution().getJobInstance().getJobName();
+    StepExecutionHistory stepExecutionHistory = computeHistory(jobName, stepName);
+    StepExecutionProgress stepExecutionProgress = new StepExecutionProgress(stepExecution, stepExecutionHistory);
+
+    return new StepExecutionProgressResponse(stepExecutionProgress, stepExecutionHistory, stepExecutionInfoResponse);
+
+  }
+
+  private StepExecutionHistory computeHistory(String jobName, String stepName) {
+    int total = jobService.countStepExecutionsForStep(jobName, stepName);
+    StepExecutionHistory stepExecutionHistory = new StepExecutionHistory(stepName);
+    for (int i = 0; i < total; i += 1000) {
+      for (StepExecution stepExecution : jobService.listStepExecutionsForStep(jobName, stepName, i, 1000)) {
+        stepExecutionHistory.append(stepExecution);
+      }
+    }
+    return stepExecutionHistory;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9ffef7fc/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/ExecutionContextResponse.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/ExecutionContextResponse.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/ExecutionContextResponse.java
new file mode 100644
index 0000000..2d46c54
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/ExecutionContextResponse.java
@@ -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.ambari.infra.model;
+
+import java.util.Map;
+
+public class ExecutionContextResponse {
+
+  private final Long jobExecutionId;
+  private final Map<String, Object> executionContextMap;
+
+  public ExecutionContextResponse(Long jobExecutionId, Map<String, Object> executionContextMap) {
+    this.jobExecutionId = jobExecutionId;
+    this.executionContextMap = executionContextMap;
+  }
+
+  public Long getJobExecutionId() {
+    return jobExecutionId;
+  }
+
+  public Map<String, Object> getExecutionContextMap() {
+    return executionContextMap;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9ffef7fc/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobDetailsResponse.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobDetailsResponse.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobDetailsResponse.java
new file mode 100644
index 0000000..cd34fef
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobDetailsResponse.java
@@ -0,0 +1,53 @@
+/*
+ * 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.ambari.infra.model;
+
+import org.springframework.batch.admin.web.JobInfo;
+
+import java.util.List;
+
+public class JobDetailsResponse {
+
+  private JobInfo jobInfo;
+  private List<JobInstanceDetailsResponse> jobInstanceDetailsResponseList;
+
+  public JobDetailsResponse() {
+  }
+
+  public JobDetailsResponse(JobInfo jobInfo, List<JobInstanceDetailsResponse> jobInstanceDetailsResponseList) {
+    this.jobInfo = jobInfo;
+    this.jobInstanceDetailsResponseList = jobInstanceDetailsResponseList;
+  }
+
+  public JobInfo getJobInfo() {
+    return jobInfo;
+  }
+
+  public void setJobInfo(JobInfo jobInfo) {
+    this.jobInfo = jobInfo;
+  }
+
+  public List<JobInstanceDetailsResponse> getJobInstanceDetailsResponseList() {
+    return jobInstanceDetailsResponseList;
+  }
+
+  public void setJobInstanceDetailsResponseList(List<JobInstanceDetailsResponse> jobInstanceDetailsResponseList) {
+    this.jobInstanceDetailsResponseList = jobInstanceDetailsResponseList;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9ffef7fc/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionDetailsResponse.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionDetailsResponse.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionDetailsResponse.java
new file mode 100644
index 0000000..695b57f
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionDetailsResponse.java
@@ -0,0 +1,49 @@
+/*
+ * 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.ambari.infra.model;
+
+import java.util.List;
+
+public class JobExecutionDetailsResponse {
+
+  private JobExecutionInfoResponse jobExecutionInfoResponse;
+
+  private List<StepExecutionInfoResponse> stepExecutionInfoList;
+
+  public JobExecutionDetailsResponse(JobExecutionInfoResponse jobExecutionInfoResponse, List<StepExecutionInfoResponse> stepExecutionInfoList) {
+    this.jobExecutionInfoResponse = jobExecutionInfoResponse;
+    this.stepExecutionInfoList = stepExecutionInfoList;
+  }
+
+  public JobExecutionInfoResponse getJobExecutionInfoResponse() {
+    return jobExecutionInfoResponse;
+  }
+
+  public void setJobExecutionInfoResponse(JobExecutionInfoResponse jobExecutionInfoResponse) {
+    this.jobExecutionInfoResponse = jobExecutionInfoResponse;
+  }
+
+  public List<StepExecutionInfoResponse> getStepExecutionInfoList() {
+    return stepExecutionInfoList;
+  }
+
+  public void setStepExecutionInfoList(List<StepExecutionInfoResponse> stepExecutionInfoList) {
+    this.stepExecutionInfoList = stepExecutionInfoList;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9ffef7fc/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionInfoResponse.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionInfoResponse.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionInfoResponse.java
new file mode 100644
index 0000000..a7e4a4f
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionInfoResponse.java
@@ -0,0 +1,141 @@
+/*
+ * 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.ambari.infra.model;
+
+import org.apache.ambari.infra.model.wrapper.JobExecutionData;
+import org.springframework.batch.admin.web.JobParametersExtractor;
+import org.springframework.batch.core.BatchStatus;
+import org.springframework.batch.core.JobExecution;
+import org.springframework.batch.core.JobInstance;
+import org.springframework.batch.core.converter.DefaultJobParametersConverter;
+import org.springframework.batch.core.converter.JobParametersConverter;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Properties;
+import java.util.TimeZone;
+
+public class JobExecutionInfoResponse {
+  private Long id;
+  private int stepExecutionCount;
+  private Long jobId;
+  private String jobName;
+  private String startDate = "";
+  private String startTime = "";
+  private String duration = "";
+  private JobExecutionData jobExecutionData;
+  private Properties jobParameters;
+  private String jobParametersString;
+  private boolean restartable = false;
+  private boolean abandonable = false;
+  private boolean stoppable = false;
+  private final TimeZone timeZone;
+
+
+  public JobExecutionInfoResponse(JobExecution jobExecution, TimeZone timeZone) {
+    JobParametersConverter converter = new DefaultJobParametersConverter();
+    this.jobExecutionData = new JobExecutionData(jobExecution);
+    this.timeZone = timeZone;
+    this.id = jobExecutionData.getId();
+    this.jobId = jobExecutionData.getJobId();
+    this.stepExecutionCount = jobExecutionData.getStepExecutions().size();
+    this.jobParameters = converter.getProperties(jobExecutionData.getJobParameters());
+    this.jobParametersString = (new JobParametersExtractor()).fromJobParameters(jobExecutionData.getJobParameters());
+    JobInstance jobInstance = jobExecutionData.getJobInstance();
+    if(jobInstance != null) {
+      this.jobName = jobInstance.getJobName();
+      BatchStatus endTime = jobExecutionData.getStatus();
+      this.restartable = endTime.isGreaterThan(BatchStatus.STOPPING) && endTime.isLessThan(BatchStatus.ABANDONED);
+      this.abandonable = endTime.isGreaterThan(BatchStatus.STARTED) && endTime != BatchStatus.ABANDONED;
+      this.stoppable = endTime.isLessThan(BatchStatus.STOPPING);
+    } else {
+      this.jobName = "?";
+    }
+
+    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+    SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
+    SimpleDateFormat durationFormat = new SimpleDateFormat("HH:mm:ss");
+
+    durationFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
+    timeFormat.setTimeZone(timeZone);
+    dateFormat.setTimeZone(timeZone);
+    if(jobExecutionData.getStartTime() != null) {
+      this.startDate = dateFormat.format(jobExecutionData.getStartTime());
+      this.startTime = timeFormat.format(jobExecutionData.getStartTime());
+      Date endTime1 = jobExecutionData.getEndTime() != null? jobExecutionData.getEndTime():new Date();
+      this.duration = durationFormat.format(new Date(endTime1.getTime() - jobExecutionData.getStartTime().getTime()));
+    }
+  }
+
+  public Long getId() {
+    return id;
+  }
+
+  public int getStepExecutionCount() {
+    return stepExecutionCount;
+  }
+
+  public Long getJobId() {
+    return jobId;
+  }
+
+  public String getJobName() {
+    return jobName;
+  }
+
+  public String getStartDate() {
+    return startDate;
+  }
+
+  public String getStartTime() {
+    return startTime;
+  }
+
+  public String getDuration() {
+    return duration;
+  }
+
+  public JobExecutionData getJobExecutionData() {
+    return jobExecutionData;
+  }
+
+  public Properties getJobParameters() {
+    return jobParameters;
+  }
+
+  public String getJobParametersString() {
+    return jobParametersString;
+  }
+
+  public boolean isRestartable() {
+    return restartable;
+  }
+
+  public boolean isAbandonable() {
+    return abandonable;
+  }
+
+  public boolean isStoppable() {
+    return stoppable;
+  }
+
+  public TimeZone getTimeZone() {
+    return timeZone;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9ffef7fc/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionRequest.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionRequest.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionRequest.java
new file mode 100644
index 0000000..b4c20e9
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionRequest.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.ambari.infra.model;
+
+import javax.ws.rs.PathParam;
+
+public class JobExecutionRequest {
+
+  @PathParam("jobName")
+  private String jobName;
+
+  @PathParam("jobInstanceId")
+  private Long jobInstanceId;
+
+  public String getJobName() {
+    return jobName;
+  }
+
+  public Long getJobInstanceId() {
+    return jobInstanceId;
+  }
+
+  public void setJobName(String jobName) {
+    this.jobName = jobName;
+  }
+
+  public void setJobInstanceId(Long jobInstanceId) {
+    this.jobInstanceId = jobInstanceId;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9ffef7fc/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionRestartRequest.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionRestartRequest.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionRestartRequest.java
new file mode 100644
index 0000000..88687e7
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionRestartRequest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.ambari.infra.model;
+
+public class JobExecutionRestartRequest {
+
+  private String jobName;
+
+  private Long jobInstanceId;
+
+  private JobOperationParams.JobRestartOperationParam operation;
+
+  public String getJobName() {
+    return jobName;
+  }
+
+  public void setJobName(String jobName) {
+    this.jobName = jobName;
+  }
+
+  public Long getJobInstanceId() {
+    return jobInstanceId;
+  }
+
+  public void setJobExecutionId(Long jobExecutionId) {
+    this.jobInstanceId = jobExecutionId;
+  }
+
+  public JobOperationParams.JobRestartOperationParam getOperation() {
+    return operation;
+  }
+
+  public void setOperation(JobOperationParams.JobRestartOperationParam operation) {
+    this.operation = operation;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9ffef7fc/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionStopRequest.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionStopRequest.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionStopRequest.java
new file mode 100644
index 0000000..b176f12
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobExecutionStopRequest.java
@@ -0,0 +1,50 @@
+/*
+ * 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.ambari.infra.model;
+
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+
+public class JobExecutionStopRequest {
+
+  @PathParam("jobExecutionId")
+  @NotNull
+  private Long jobExecutionId;
+
+  @QueryParam("operation")
+  @NotNull
+  private JobOperationParams.JobStopOrAbandonOperationParam operation;
+
+  public Long getJobExecutionId() {
+    return jobExecutionId;
+  }
+
+  public void setJobExecutionId(Long jobExecutionId) {
+    this.jobExecutionId = jobExecutionId;
+  }
+
+  public JobOperationParams.JobStopOrAbandonOperationParam getOperation() {
+    return operation;
+  }
+
+  public void setOperation(JobOperationParams.JobStopOrAbandonOperationParam operation) {
+    this.operation = operation;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9ffef7fc/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobInstanceDetailsResponse.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobInstanceDetailsResponse.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobInstanceDetailsResponse.java
new file mode 100644
index 0000000..af88654
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobInstanceDetailsResponse.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
+ * 
+ * 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.ambari.infra.model;
+
+import org.springframework.batch.core.JobInstance;
+
+import java.util.List;
+
+public class JobInstanceDetailsResponse {
+
+  private JobInstance jobInstance;
+
+  private List<JobExecutionInfoResponse> jobExecutionInfoResponseList;
+
+  public JobInstanceDetailsResponse() {
+  }
+
+  public JobInstanceDetailsResponse(JobInstance jobInstance, List<JobExecutionInfoResponse> jobExecutionInfoResponseList) {
+    this.jobInstance = jobInstance;
+    this.jobExecutionInfoResponseList = jobExecutionInfoResponseList;
+  }
+
+  public JobInstance getJobInstance() {
+    return jobInstance;
+  }
+
+  public void setJobInstance(JobInstance jobInstance) {
+    this.jobInstance = jobInstance;
+  }
+
+  public List<JobExecutionInfoResponse> getJobExecutionInfoResponseList() {
+    return jobExecutionInfoResponseList;
+  }
+
+  public void setJobExecutionInfoResponseList(List<JobExecutionInfoResponse> jobExecutionInfoResponseList) {
+    this.jobExecutionInfoResponseList = jobExecutionInfoResponseList;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9ffef7fc/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobInstanceStartRequest.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobInstanceStartRequest.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobInstanceStartRequest.java
new file mode 100644
index 0000000..905a4fa
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobInstanceStartRequest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.ambari.infra.model;
+
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+
+public class JobInstanceStartRequest {
+
+  @PathParam("jobName")
+  @NotNull
+  private String jobName;
+
+  @QueryParam("params")
+  String params;
+
+  public String getJobName() {
+    return jobName;
+  }
+
+  public void setJobName(String jobName) {
+    this.jobName = jobName;
+  }
+
+  public String getParams() {
+    return params;
+  }
+
+  public void setParams(String params) {
+    this.params = params;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9ffef7fc/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobOperationParams.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobOperationParams.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobOperationParams.java
new file mode 100644
index 0000000..e286deb
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobOperationParams.java
@@ -0,0 +1,31 @@
+/*
+ * 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.ambari.infra.model;
+
+public class JobOperationParams {
+
+  public enum JobStopOrAbandonOperationParam {
+    STOP, ABANDON;
+  }
+
+  public enum JobRestartOperationParam {
+    RESTART;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9ffef7fc/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobRequest.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobRequest.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobRequest.java
new file mode 100644
index 0000000..b4fd478
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/JobRequest.java
@@ -0,0 +1,37 @@
+/*
+ * 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.ambari.infra.model;
+
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.PathParam;
+
+public class JobRequest extends PageRequest {
+
+  @NotNull
+  @PathParam("jobName")
+  private String jobName;
+
+  public String getJobName() {
+    return jobName;
+  }
+
+  public void setJobName(String jobName) {
+    this.jobName = jobName;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9ffef7fc/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/PageRequest.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/PageRequest.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/PageRequest.java
new file mode 100644
index 0000000..679d4fd
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/PageRequest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.ambari.infra.model;
+
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.QueryParam;
+
+public class PageRequest {
+
+  @QueryParam("page")
+  @DefaultValue("0")
+  private int page;
+
+  @QueryParam("size")
+  @DefaultValue("20")
+  private int size;
+
+  public int getPage() {
+    return page;
+  }
+
+  public void setPage(int page) {
+    this.page = page;
+  }
+
+  public int getSize() {
+    return size;
+  }
+
+  public void setSize(int size) {
+    this.size = size;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9ffef7fc/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionContextResponse.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionContextResponse.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionContextResponse.java
new file mode 100644
index 0000000..0e67a87
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionContextResponse.java
@@ -0,0 +1,58 @@
+/*
+ * 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.ambari.infra.model;
+
+import java.util.Map;
+
+public class StepExecutionContextResponse {
+
+  private Map<String, Object> executionContextMap;
+
+  private Long jobExecutionId;
+
+  private Long stepExecutionId;
+
+  private String stepName;
+
+  public StepExecutionContextResponse() {
+  }
+
+  public StepExecutionContextResponse(Map<String, Object> executionContextMap, Long jobExecutionId, Long stepExecutionId, String stepName) {
+    this.executionContextMap = executionContextMap;
+    this.jobExecutionId = jobExecutionId;
+    this.stepExecutionId = stepExecutionId;
+    this.stepName = stepName;
+  }
+
+  public Map<String, Object> getExecutionContextMap() {
+    return executionContextMap;
+  }
+
+  public Long getJobExecutionId() {
+    return jobExecutionId;
+  }
+
+  public Long getStepExecutionId() {
+    return stepExecutionId;
+  }
+
+  public String getStepName() {
+    return stepName;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9ffef7fc/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionInfoResponse.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionInfoResponse.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionInfoResponse.java
new file mode 100644
index 0000000..ed04767
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionInfoResponse.java
@@ -0,0 +1,115 @@
+/*
+ * 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.ambari.infra.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import org.apache.ambari.infra.model.wrapper.StepExecutionData;
+import org.springframework.batch.core.JobExecution;
+import org.springframework.batch.core.StepExecution;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+public class StepExecutionInfoResponse {
+  private Long id;
+  private Long jobExecutionId;
+  private String jobName;
+  private String name;
+  private String startDate = "-";
+  private String startTime = "-";
+  private String duration = "-";
+  private StepExecutionData stepExecutionData;
+  private long durationMillis;
+
+  public StepExecutionInfoResponse(String jobName, Long jobExecutionId, String name, TimeZone timeZone) {
+    this.jobName = jobName;
+    this.jobExecutionId = jobExecutionId;
+    this.name = name;
+    this.stepExecutionData = new StepExecutionData(new StepExecution(name, new JobExecution(jobExecutionId)));
+  }
+
+  public StepExecutionInfoResponse(StepExecution stepExecution, TimeZone timeZone) {
+    this.stepExecutionData = new StepExecutionData(stepExecution);
+    this.id = stepExecutionData.getId();
+    this.name = stepExecutionData.getStepName();
+    this.jobName = stepExecutionData.getJobExecution() != null && stepExecutionData.getJobExecution().getJobInstance() != null? stepExecutionData.getJobExecution().getJobInstance().getJobName():"?";
+    this.jobExecutionId = stepExecutionData.getJobExecutionId();
+    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+    SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
+    SimpleDateFormat durationFormat = new SimpleDateFormat("HH:mm:ss");
+
+    durationFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
+    timeFormat.setTimeZone(timeZone);
+    dateFormat.setTimeZone(timeZone);
+    if(stepExecutionData.getStartTime() != null) {
+      this.startDate = dateFormat.format(stepExecutionData.getStartTime());
+      this.startTime = timeFormat.format(stepExecutionData.getStartTime());
+      Date endTime = stepExecutionData.getEndTime() != null? stepExecutionData.getEndTime():new Date();
+      this.durationMillis = endTime.getTime() - stepExecutionData.getStartTime().getTime();
+      this.duration = durationFormat.format(new Date(this.durationMillis));
+    }
+
+  }
+
+  public Long getId() {
+    return this.id;
+  }
+
+  public Long getJobExecutionId() {
+    return this.jobExecutionId;
+  }
+
+  public String getName() {
+    return this.name;
+  }
+
+  public String getJobName() {
+    return this.jobName;
+  }
+
+  public String getStartDate() {
+    return this.startDate;
+  }
+
+  public String getStartTime() {
+    return this.startTime;
+  }
+
+  public String getDuration() {
+    return this.duration;
+  }
+
+  public long getDurationMillis() {
+    return this.durationMillis;
+  }
+
+  public String getStatus() {
+    return this.id != null?this.stepExecutionData.getStatus().toString():"NONE";
+  }
+
+  public String getExitCode() {
+    return this.id != null?this.stepExecutionData.getExitStatus().getExitCode():"NONE";
+  }
+
+  @JsonIgnore
+  public StepExecutionData getStepExecution() {
+    return this.stepExecutionData;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9ffef7fc/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionProgressResponse.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionProgressResponse.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionProgressResponse.java
new file mode 100644
index 0000000..26f9ed4
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionProgressResponse.java
@@ -0,0 +1,53 @@
+/*
+ * 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.ambari.infra.model;
+
+import org.springframework.batch.admin.history.StepExecutionHistory;
+import org.springframework.batch.admin.web.StepExecutionProgress;
+
+public class StepExecutionProgressResponse {
+
+  private StepExecutionProgress stepExecutionProgress;
+
+  private StepExecutionHistory stepExecutionHistory;
+
+  private StepExecutionInfoResponse stepExecutionInfoResponse;
+
+  public StepExecutionProgressResponse() {
+  }
+
+  public StepExecutionProgressResponse(StepExecutionProgress stepExecutionProgress, StepExecutionHistory stepExecutionHistory,
+                                       StepExecutionInfoResponse stepExecutionInfoResponse) {
+    this.stepExecutionProgress = stepExecutionProgress;
+    this.stepExecutionHistory = stepExecutionHistory;
+    this.stepExecutionInfoResponse = stepExecutionInfoResponse;
+  }
+
+  public StepExecutionProgress getStepExecutionProgress() {
+    return stepExecutionProgress;
+  }
+
+  public StepExecutionHistory getStepExecutionHistory() {
+    return stepExecutionHistory;
+  }
+
+  public StepExecutionInfoResponse getStepExecutionInfoResponse() {
+    return stepExecutionInfoResponse;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9ffef7fc/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionRequest.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionRequest.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionRequest.java
new file mode 100644
index 0000000..2228171
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/StepExecutionRequest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.ambari.infra.model;
+
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.PathParam;
+
+public class StepExecutionRequest {
+
+  @PathParam("jobExecutionId")
+  @NotNull
+  private Long jobExecutionId;
+
+  @PathParam("stepExecutionId")
+  @NotNull
+  private Long stepExecutionId;
+
+  public Long getJobExecutionId() {
+    return jobExecutionId;
+  }
+
+  public void setJobExecutionId(Long jobExecutionId) {
+    this.jobExecutionId = jobExecutionId;
+  }
+
+  public Long getStepExecutionId() {
+    return stepExecutionId;
+  }
+
+  public void setStepExecutionId(Long stepExecutionId) {
+    this.stepExecutionId = stepExecutionId;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9ffef7fc/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/wrapper/JobExecutionData.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/wrapper/JobExecutionData.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/wrapper/JobExecutionData.java
new file mode 100644
index 0000000..28e262a
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/wrapper/JobExecutionData.java
@@ -0,0 +1,118 @@
+/*
+ * 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.ambari.infra.model.wrapper;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.google.common.collect.Lists;
+import org.springframework.batch.core.BatchStatus;
+import org.springframework.batch.core.ExitStatus;
+import org.springframework.batch.core.JobExecution;
+import org.springframework.batch.core.JobInstance;
+import org.springframework.batch.core.JobParameters;
+import org.springframework.batch.core.StepExecution;
+import org.springframework.batch.item.ExecutionContext;
+
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Wrapper for #{{@link JobExecution}}
+ */
+public class JobExecutionData {
+
+  private JobExecution jobExecution;
+
+  public JobExecutionData(JobExecution jobExecution) {
+    this.jobExecution = jobExecution;
+  }
+
+  @JsonIgnore
+  public JobExecution getJobExecution() {
+    return jobExecution;
+  }
+
+  @JsonIgnore
+  public Collection<StepExecution> getStepExecutions() {
+    return jobExecution.getStepExecutions();
+  }
+
+  public JobParameters getJobParameters() {
+    return jobExecution.getJobParameters();
+  }
+
+  public JobInstance getJobInstance() {
+    return jobExecution.getJobInstance();
+  }
+
+  public Collection<StepExecutionData> getStepExecutionDataList() {
+    List<StepExecutionData> stepExecutionDataList = Lists.newArrayList();
+    Collection<StepExecution> stepExecutions = getStepExecutions();
+    if (stepExecutions != null) {
+      for (StepExecution stepExecution : stepExecutions) {
+        stepExecutionDataList.add(new StepExecutionData(stepExecution));
+      }
+    }
+    return stepExecutionDataList;
+  }
+
+  public BatchStatus getStatus() {
+    return jobExecution.getStatus();
+  }
+
+  public Date getStartTime() {
+    return jobExecution.getStartTime();
+  }
+
+  public Date getCreateTime() {
+    return jobExecution.getCreateTime();
+  }
+
+  public Date getEndTime() {
+    return jobExecution.getEndTime();
+  }
+
+  public Date getLastUpdated() {
+    return jobExecution.getLastUpdated();
+  }
+
+  public ExitStatus getExitStatus() {
+    return jobExecution.getExitStatus();
+  }
+
+  public ExecutionContext getExecutionContext() {
+    return jobExecution.getExecutionContext();
+  }
+
+  public List<Throwable> getFailureExceptions() {
+    return jobExecution.getFailureExceptions();
+  }
+
+  public String getJobConfigurationName() {
+    return jobExecution.getJobConfigurationName();
+  }
+
+  public Long getId() {
+    return jobExecution.getId();
+  }
+
+  public Long getJobId() {
+    return jobExecution.getJobId();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9ffef7fc/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/wrapper/StepExecutionData.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/wrapper/StepExecutionData.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/wrapper/StepExecutionData.java
new file mode 100644
index 0000000..26552ae
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/model/wrapper/StepExecutionData.java
@@ -0,0 +1,133 @@
+/*
+ * 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.ambari.infra.model.wrapper;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import org.springframework.batch.core.BatchStatus;
+import org.springframework.batch.core.ExitStatus;
+import org.springframework.batch.core.JobExecution;
+import org.springframework.batch.core.StepExecution;
+import org.springframework.batch.item.ExecutionContext;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Wrapper for #{{@link StepExecution}}
+ */
+public class StepExecutionData {
+
+  @JsonIgnore
+  private final JobExecution jobExecution;
+
+  @JsonIgnore
+  private final StepExecution stepExecution;
+
+
+  public StepExecutionData(StepExecution stepExecution) {
+    this.stepExecution = stepExecution;
+    this.jobExecution = stepExecution.getJobExecution();
+  }
+
+  @JsonIgnore
+  public JobExecution getJobExecution() {
+    return jobExecution;
+  }
+
+  @JsonIgnore
+  public StepExecution getStepExecution() {
+    return stepExecution;
+  }
+
+  public String getStepName() {
+    return stepExecution.getStepName();
+  }
+
+  public int getReadCount() {
+    return stepExecution.getReadCount();
+  }
+
+  public BatchStatus getStatus() {
+    return stepExecution.getStatus();
+  }
+
+  public int getWriteCount() {
+    return stepExecution.getWriteCount();
+  }
+
+  public int getCommitCount() {
+    return stepExecution.getCommitCount();
+  }
+
+  public int getRollbackCount() {
+    return stepExecution.getRollbackCount();
+  }
+
+  public int getReadSkipCount() {
+    return stepExecution.getReadSkipCount();
+  }
+
+  public int getProcessSkipCount() {
+    return stepExecution.getProcessSkipCount();
+  }
+
+  public Date getStartTime() {
+    return stepExecution.getStartTime();
+  }
+
+  public int getWriteSkipCount() {
+    return stepExecution.getWriteSkipCount();
+  }
+
+  public Date getEndTime() {
+    return stepExecution.getEndTime();
+  }
+
+  public Date getLastUpdated() {
+    return stepExecution.getLastUpdated();
+  }
+
+  public ExecutionContext getExecutionContext() {
+    return stepExecution.getExecutionContext();
+  }
+
+  public ExitStatus getExitStatus() {
+    return stepExecution.getExitStatus();
+  }
+
+  public boolean isTerminateOnly() {
+    return stepExecution.isTerminateOnly();
+  }
+
+  public int getFilterCount() {
+    return stepExecution.getFilterCount();
+  }
+
+  public List<Throwable> getFailureExceptions() {
+    return stepExecution.getFailureExceptions();
+  }
+
+  public Long getId() {
+    return stepExecution.getId();
+  }
+
+  public Long getJobExecutionId() {
+    return stepExecution.getJobExecutionId();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9ffef7fc/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/rest/JobExceptionMapper.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/rest/JobExceptionMapper.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/rest/JobExceptionMapper.java
new file mode 100644
index 0000000..079cce3
--- /dev/null
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/rest/JobExceptionMapper.java
@@ -0,0 +1,110 @@
+/*
+ * 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.ambari.infra.rest;
+
+
+import com.google.common.collect.Maps;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.batch.admin.service.NoSuchStepExecutionException;
+import org.springframework.batch.core.JobParametersInvalidException;
+import org.springframework.batch.core.launch.JobExecutionNotFailedException;
+import org.springframework.batch.core.launch.JobExecutionNotRunningException;
+import org.springframework.batch.core.launch.JobExecutionNotStoppedException;
+import org.springframework.batch.core.launch.JobInstanceAlreadyExistsException;
+import org.springframework.batch.core.launch.JobParametersNotFoundException;
+import org.springframework.batch.core.launch.NoSuchJobException;
+import org.springframework.batch.core.launch.NoSuchJobExecutionException;
+import org.springframework.batch.core.launch.NoSuchJobInstanceException;
+import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
+import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
+import org.springframework.batch.core.repository.JobRestartException;
+import org.springframework.batch.core.step.NoSuchStepException;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+
+import javax.batch.operations.JobExecutionAlreadyCompleteException;
+import javax.inject.Named;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+import java.util.Map;
+
+@Named
+@Provider
+public class JobExceptionMapper implements ExceptionMapper<Throwable> {
+
+  private static final Logger LOG = LoggerFactory.getLogger(JobExceptionMapper.class);
+
+  private static final Map<Class, Response.Status> exceptionStatusCodeMap = Maps.newHashMap();
+
+  static {
+    exceptionStatusCodeMap.put(MethodArgumentNotValidException.class, Response.Status.BAD_REQUEST);
+    exceptionStatusCodeMap.put(NoSuchJobException.class, Response.Status.NOT_FOUND);
+    exceptionStatusCodeMap.put(NoSuchStepException.class, Response.Status.NOT_FOUND);
+    exceptionStatusCodeMap.put(NoSuchStepExecutionException.class, Response.Status.NOT_FOUND);
+    exceptionStatusCodeMap.put(NoSuchJobExecutionException.class, Response.Status.NOT_FOUND);
+    exceptionStatusCodeMap.put(NoSuchJobInstanceException.class, Response.Status.NOT_FOUND);
+    exceptionStatusCodeMap.put(JobExecutionNotRunningException.class, Response.Status.INTERNAL_SERVER_ERROR);
+    exceptionStatusCodeMap.put(JobExecutionNotStoppedException.class, Response.Status.INTERNAL_SERVER_ERROR);
+    exceptionStatusCodeMap.put(JobInstanceAlreadyExistsException.class, Response.Status.ACCEPTED);
+    exceptionStatusCodeMap.put(JobInstanceAlreadyCompleteException.class, Response.Status.ACCEPTED);
+    exceptionStatusCodeMap.put(JobExecutionAlreadyRunningException.class, Response.Status.ACCEPTED);
+    exceptionStatusCodeMap.put(JobExecutionAlreadyCompleteException.class, Response.Status.ACCEPTED);
+    exceptionStatusCodeMap.put(JobParametersNotFoundException.class, Response.Status.NOT_FOUND);
+    exceptionStatusCodeMap.put(JobExecutionNotFailedException.class, Response.Status.INTERNAL_SERVER_ERROR);
+    exceptionStatusCodeMap.put(JobRestartException.class, Response.Status.INTERNAL_SERVER_ERROR);
+    exceptionStatusCodeMap.put(JobParametersInvalidException.class, Response.Status.BAD_REQUEST);
+  }
+
+  @Override
+  public Response toResponse(Throwable throwable) {
+    LOG.error("REST Exception occurred:", throwable);
+    Response.Status status = Response.Status.INTERNAL_SERVER_ERROR;
+
+    for (Map.Entry<Class, Response.Status> entry : exceptionStatusCodeMap.entrySet()) {
+      if (throwable.getClass().isAssignableFrom(entry.getKey())) {
+        status = entry.getValue();
+        LOG.info("Exception mapped to: {} with status code: {}", entry.getKey().getCanonicalName(), entry.getValue().getStatusCode());
+        break;
+      }
+    }
+
+    return Response.status(status).entity(new StatusMessage(throwable.getMessage(), status.getStatusCode()))
+      .type(MediaType.APPLICATION_JSON_TYPE).build();
+  }
+
+  private class StatusMessage {
+    private String message;
+    private int statusCode;
+
+    StatusMessage(String message, int statusCode) {
+      this.message = message;
+      this.statusCode = statusCode;
+    }
+
+    public String getMessage() {
+      return message;
+    }
+
+    public int getStatusCode() {
+      return statusCode;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9ffef7fc/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/rest/JobResource.java
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/rest/JobResource.java b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/rest/JobResource.java
index 27fed40..7023957 100644
--- a/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/rest/JobResource.java
+++ b/ambari-infra/ambari-infra-manager/src/main/java/org/apache/ambari/infra/rest/JobResource.java
@@ -20,23 +20,46 @@ package org.apache.ambari.infra.rest;
 
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
-import org.springframework.batch.core.JobParametersBuilder;
+import org.apache.ambari.infra.manager.JobManager;
+import org.apache.ambari.infra.model.ExecutionContextResponse;
+import org.apache.ambari.infra.model.JobDetailsResponse;
+import org.apache.ambari.infra.model.JobExecutionDetailsResponse;
+import org.apache.ambari.infra.model.JobExecutionInfoResponse;
+import org.apache.ambari.infra.model.JobExecutionRequest;
+import org.apache.ambari.infra.model.JobExecutionRestartRequest;
+import org.apache.ambari.infra.model.JobExecutionStopRequest;
+import org.apache.ambari.infra.model.JobInstanceStartRequest;
+import org.apache.ambari.infra.model.JobRequest;
+import org.apache.ambari.infra.model.PageRequest;
+import org.apache.ambari.infra.model.StepExecutionContextResponse;
+import org.apache.ambari.infra.model.StepExecutionInfoResponse;
+import org.apache.ambari.infra.model.StepExecutionProgressResponse;
+import org.apache.ambari.infra.model.StepExecutionRequest;
+import org.springframework.batch.admin.service.NoSuchStepExecutionException;
+import org.springframework.batch.admin.web.JobInfo;
 import org.springframework.batch.core.JobParametersInvalidException;
-import org.springframework.batch.core.explore.JobExplorer;
+import org.springframework.batch.core.launch.JobExecutionNotRunningException;
 import org.springframework.batch.core.launch.JobInstanceAlreadyExistsException;
-import org.springframework.batch.core.launch.JobOperator;
 import org.springframework.batch.core.launch.NoSuchJobException;
+import org.springframework.batch.core.launch.NoSuchJobExecutionException;
+import org.springframework.batch.core.launch.NoSuchJobInstanceException;
+import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
+import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
+import org.springframework.batch.core.repository.JobRestartException;
 import org.springframework.context.annotation.Scope;
 
 import javax.inject.Inject;
 import javax.inject.Named;
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.BeanParam;
+import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import java.util.Date;
+import java.util.List;
 import java.util.Set;
 
 @Api(value = "jobs", description = "Job operations")
@@ -46,35 +69,123 @@ import java.util.Set;
 public class JobResource {
 
   @Inject
-  private JobOperator jobOperator;
+  private JobManager jobManager;
 
-  @Inject
-  private JobExplorer jobExplorer;
+  @GET
+  @Produces({"application/json"})
+  @ApiOperation("Get all jobs")
+  public List<JobInfo> getAllJobs(@BeanParam @Valid PageRequest request) {
+    return jobManager.getAllJobs(request.getPage(), request.getSize());
+  }
+
+  @POST
+  @Produces({"application/json"})
+  @Path("{jobName}")
+  @ApiOperation("Start a new job instance by job name.")
+  public JobExecutionInfoResponse startJob(@BeanParam @Valid JobInstanceStartRequest request)
+    throws JobParametersInvalidException, JobInstanceAlreadyExistsException, NoSuchJobException, JobExecutionAlreadyRunningException,
+    JobRestartException, JobInstanceAlreadyCompleteException {
+    return jobManager.launchJob(request.getJobName(), request.getParams());
+  }
 
   @GET
   @Produces({"application/json"})
+  @Path("/info/names")
   @ApiOperation("Get all job names")
   public Set<String> getAllJobNames() {
-    return jobOperator.getJobNames();
+    return jobManager.getAllJobNames();
+  }
+
+  @GET
+  @Produces({"application/json"})
+  @Path("/info/{jobName}")
+  @ApiOperation("Get job details by job name.")
+  public JobDetailsResponse getJobDetails(@BeanParam @Valid JobRequest jobRequest) throws NoSuchJobException {
+    return jobManager.getJobDetails(jobRequest.getJobName(), jobRequest.getPage(), jobRequest.getSize());
+  }
+
+  @GET
+  @Path("{jobName}/executions")
+  @Produces({"application/json"})
+  @ApiOperation("Get the id values of all the running job instances.")
+  public Set<Long> getExecutionIdsByJobName(@PathParam("jobName") @NotNull @Valid String jobName) throws NoSuchJobException {
+    return jobManager.getExecutionIdsByJobName(jobName);
   }
 
   @GET
-  @Path("executions/{jobName}")
   @Produces({"application/json"})
-  @ApiOperation("Get the id values of all the running job instances by job name")
-  public Set<Long> getExecutionIdsByJobName(
-    @PathParam("jobName") String jobName) throws NoSuchJobException {
-    return jobOperator.getRunningExecutions(jobName);
+  @Path("/executions/{jobExecutionId}")
+  @ApiOperation("Get job and step details for job execution instance.")
+  public JobExecutionDetailsResponse getExectionInfo(@PathParam("jobExecutionId") @Valid Long jobExecutionId) throws NoSuchJobExecutionException {
+    return jobManager.getExectionInfo(jobExecutionId);
+  }
+
+  @GET
+  @Produces({"application/json"})
+  @Path("/executions/{jobExecutionId}/context")
+  @ApiOperation("Get execution context for specific job.")
+  public ExecutionContextResponse getExecutionContextByJobExecId(@PathParam("jobExecutionId") Long executionId) throws NoSuchJobExecutionException {
+    return jobManager.getExecutionContextByJobExecutionId(executionId);
+  }
+
+
+  @DELETE
+  @Produces({"application/json"})
+  @Path("/executions/{jobExecutionId}")
+  @ApiOperation("Stop or abandon a running job execution.")
+  public JobExecutionInfoResponse stopOrAbandonJobExecution(@BeanParam @Valid JobExecutionStopRequest request)
+    throws NoSuchJobExecutionException, JobExecutionNotRunningException, JobExecutionAlreadyRunningException {
+    return jobManager.stopOrAbandonJobByExecutionId(request.getJobExecutionId(), request.getOperation());
+  }
+
+  @DELETE
+  @Produces({"application/json"})
+  @Path("/executions")
+  @ApiOperation("Stop all job executions.")
+  public Integer stopAll() {
+    return jobManager.stopAllJobs();
+  }
+
+  @GET
+  @Produces({"application/json"})
+  @Path("/{jobName}/{jobInstanceId}/executions")
+  @ApiOperation("Get execution for job instance.")
+  public List<JobExecutionInfoResponse> getExecutionsForInstance(@BeanParam @Valid JobExecutionRequest request) throws JobInstanceAlreadyCompleteException,
+    NoSuchJobExecutionException, JobExecutionAlreadyRunningException, JobParametersInvalidException, JobRestartException, NoSuchJobException, NoSuchJobInstanceException {
+    return jobManager.getExecutionsForJobInstance(request.getJobName(), request.getJobInstanceId());
   }
 
   @POST
   @Produces({"application/json"})
-  @Path("start/{jobName}")
-  public Long startJob(@PathParam("jobName") String jobName, @QueryParam("params") String params)
-    throws JobParametersInvalidException, JobInstanceAlreadyExistsException, NoSuchJobException {
-    JobParametersBuilder jobParametersBuilder = new JobParametersBuilder();
-    jobParametersBuilder.addDate("date", new Date());
-    return jobOperator.start(jobName, jobParametersBuilder.toJobParameters() + "," + params);
+  @Path("/{jobName}/{jobInstanceId}/executions")
+  @ApiOperation("Restart job instance.")
+  public JobExecutionInfoResponse restartJobInstance(@BeanParam @Valid JobExecutionRestartRequest request) throws JobInstanceAlreadyCompleteException,
+    NoSuchJobExecutionException, JobExecutionAlreadyRunningException, JobParametersInvalidException, JobRestartException, NoSuchJobException {
+    return jobManager.restart(request.getJobInstanceId(), request.getJobName(), request.getOperation());
+  }
+
+  @GET
+  @Produces({"application/json"})
+  @Path("/executions/{jobExecutionId}/steps/{stepExecutionId}")
+  @ApiOperation("Get step execution details.")
+  public StepExecutionInfoResponse getStepExecution(@BeanParam @Valid StepExecutionRequest request) throws NoSuchStepExecutionException, NoSuchJobExecutionException {
+    return jobManager.getStepExecution(request.getJobExecutionId(), request.getStepExecutionId());
+  }
+
+  @GET
+  @Produces({"application/json"})
+  @Path("/executions/{jobExecutionId}/steps/{stepExecutionId}/execution-context")
+  @ApiOperation("Get the execution context of step execution.")
+  public StepExecutionContextResponse getStepExecutionContext(@BeanParam @Valid StepExecutionRequest request) throws NoSuchStepExecutionException, NoSuchJobExecutionException {
+    return jobManager.getStepExecutionContext(request.getJobExecutionId(), request.getStepExecutionId());
+  }
+
+  @GET
+  @Produces({"application/json"})
+  @Path("/executions/{jobExecutionId}/steps/{stepExecutionId}/progress")
+  @ApiOperation("Get progress of step execution.")
+  public StepExecutionProgressResponse getStepExecutionProgress(@BeanParam @Valid StepExecutionRequest request) throws NoSuchStepExecutionException, NoSuchJobExecutionException {
+    return jobManager.getStepExecutionProgress(request.getJobExecutionId(), request.getStepExecutionId());
   }
 
 }


Mime
View raw message