/**
* Copyright 2016 vip.com.
* <p>
* Licensed 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.
* </p>
*/
package com.vip.saturn.job.console.controller;
import java.util.Collection;
import java.util.List;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import com.vip.saturn.job.console.domain.*;
import com.vip.saturn.job.console.exception.SaturnJobConsoleException;
import com.vip.saturn.job.console.utils.SaturnConstants;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.google.common.base.Strings;
import com.vip.saturn.job.console.service.ExecutorService;
import com.vip.saturn.job.console.service.JobDimensionService;
import com.vip.saturn.job.console.service.JobOperationService;
import com.vip.saturn.job.console.service.RegistryCenterService;
import com.vip.saturn.job.console.service.ServerDimensionService;
@RestController
@RequestMapping("job")
public class JobOperationController extends AbstractController {
protected static Logger AUDITLOGGER = LoggerFactory.getLogger("AUDITLOG");
protected static Logger LOGGER = LoggerFactory.getLogger(JobOperationController.class);
protected static final int DEFAULT_RECORD_COUNT = 100;
@Resource
private JobDimensionService jobDimensionService;
@Resource
private JobOperationService jobOperationService;
@Resource
private ServerDimensionService serverDimensionService;
@Resource
private ExecutorService executorService;
@Resource
private RegistryCenterService registryCenterService;
@RequestMapping(value = "toggleJobEnabledState", method = RequestMethod.POST)
public RequestResult toggleJobEnabledState(HttpServletRequest request, String jobName, Boolean state, Boolean confirmed) {
RequestResult requestResult = new RequestResult();
if(state == null) {
requestResult.setSuccess(false);
requestResult.setMessage("更改的状态有误。");
return requestResult;
}
Boolean isJobEnabled = jobDimensionService.isJobEnabled(jobName);
if (isJobEnabled == state) {
if (state) {
requestResult.setSuccess(false);
requestResult.setMessage("作业已经是启动状态。");
return requestResult;
} else {
requestResult.setSuccess(false);
requestResult.setMessage("作业已经是禁用状态。");
return requestResult;
}
}
if(confirmed != null && !confirmed) {
try {
if (state) { // 启用时,检查其依赖的作业是否已经启动
List<JobConfig> dependentJobsStatus = jobDimensionService.getDependentJobsStatus(jobName);
if (dependentJobsStatus != null) {
String unableJobs = "";
for (JobConfig jobConfig : dependentJobsStatus) {
if (!jobConfig.getEnabled()) {
unableJobs += jobConfig.getJobName() + ",";
}
}
if (!unableJobs.equals("")) {
requestResult.setSuccess(false);
requestResult.setMessage("该作业依赖的作业(" + unableJobs.substring(0, unableJobs.length() - 1) + ")不处于启用状态,是否继续启用该作业?");
requestResult.setObj("confirmDependencies");
return requestResult;
}
}
} else { // 禁用时,检查依赖它的作业是否已经禁用
List<JobConfig> dependedJobsStatus = jobDimensionService.getDependedJobsStatus(jobName);
if (dependedJobsStatus != null) {
String enableJobs = "";
for (JobConfig jobConfig : dependedJobsStatus) {
if (jobConfig.getEnabled()) {
enableJobs += jobConfig.getJobName() + ",";
}
}
if (!enableJobs.equals("")) {
requestResult.setSuccess(false);
requestResult.setMessage("依赖该作业的作业(" + enableJobs.substring(0, enableJobs.length() - 1) + ")不处于禁用状态,是否继续禁用作业?");
requestResult.setObj("confirmDependencies");
return requestResult;
}
}
}
} catch (SaturnJobConsoleException e) {
requestResult.setSuccess(false);
requestResult.setMessage(e.getMessage());
return requestResult;
} catch (Exception e) {
requestResult.setSuccess(false);
requestResult.setMessage(e.toString());
return requestResult;
}
}
JobStatus js = jobDimensionService.getJobStatus(jobName);
// enabled job
if (state) {
if (JobStatus.STOPPED.equals(js)) {
jobOperationService.setJobEnabledState(jobName, state);
requestResult.setSuccess(true);
return requestResult;
} else {
requestResult.setSuccess(false);
requestResult.setMessage("作业不处于stopped状态,不能启用。");
return requestResult;
}
} else {
if (JobStatus.RUNNING.equals(js) || JobStatus.READY.equals(js)) {
jobOperationService.setJobEnabledState(jobName, state);
requestResult.setSuccess(true);
return requestResult;
} else {
requestResult.setSuccess(false);
requestResult.setMessage("作业不处于running或ready状态,不能禁用。");
return requestResult;
}
}
}
@RequestMapping(value = "batchToggleJobEnabledState", method = RequestMethod.POST)
public RequestResult batchToggleJobEnabledState(HttpServletRequest request, String jobNames,Boolean state, Boolean confirmed) {
RequestResult requestResult = new RequestResult();
if(state == null) {
requestResult.setSuccess(false);
requestResult.setMessage("更改的状态有误。");
return requestResult;
}
String[] jobNameArr = jobNames.split(",");
if(jobNameArr == null || jobNameArr.length == 0){
requestResult.setSuccess(false);
requestResult.setMessage("没有选中任何要操作的作业。");
return requestResult;
}
if(confirmed != null && !confirmed) {
for(String jobName : jobNameArr) {
if(jobName != null && jobName.trim().length() > 0) {
jobName = jobName.trim();
try {
if (state) { // 启用时,检查其依赖的作业是否已经启动
List<JobConfig> dependentJobsStatus = jobDimensionService.getDependentJobsStatus(jobName);
if (dependentJobsStatus != null) {
String unableJobs = "";
for (JobConfig jobConfig : dependentJobsStatus) {
if (!jobConfig.getEnabled()) {
unableJobs += jobConfig.getJobName() + ",";
}
}
if (!unableJobs.equals("")) {
requestResult.setSuccess(false);
requestResult.setMessage("有作业依赖的作业还没启用,是否继续批量启用作业?");
requestResult.setObj("confirmDependencies");
return requestResult;
}
}
} else { // 禁用时,检查依赖它的作业是否已经禁用
List<JobConfig> dependedJobsStatus = jobDimensionService.getDependedJobsStatus(jobName);
if (dependedJobsStatus != null) {
String enableJobs = "";
for (JobConfig jobConfig : dependedJobsStatus) {
if (jobConfig.getEnabled()) {
enableJobs += jobConfig.getJobName();
}
}
if (!enableJobs.equals("")) {
requestResult.setSuccess(false);
requestResult.setMessage("有作业被依赖的作业还没禁用,是否继续批量禁用作业?");
requestResult.setObj("confirmDependencies");
return requestResult;
}
}
}
} catch (SaturnJobConsoleException e) {
requestResult.setSuccess(false);
requestResult.setMessage(e.getMessage());
return requestResult;
} catch (Exception e) {
requestResult.setSuccess(false);
requestResult.setMessage(e.toString());
return requestResult;
}
}
}
}
StringBuilder messageSbf = new StringBuilder();
for(String jobName : jobNameArr){
try{
Boolean isJobEnabled = jobDimensionService.isJobEnabled(jobName);
if (isJobEnabled == state) {
if (state) {
messageSbf.append("作业【" + jobName +"】已经是启动状态,");
} else {
messageSbf.append("作业【" + jobName +"】已经是禁用状态,");
}
}
JobStatus js = jobDimensionService.getJobStatus(jobName);
// enabled job
if (state) {
if (JobStatus.STOPPED.equals(js)) {
jobOperationService.setJobEnabledState(jobName, state);
} else {
messageSbf.append("作业【"+jobName+"】不处于stopped状态,不能启用,");
}
} else {
if (JobStatus.RUNNING.equals(js) || JobStatus.READY.equals(js)) {
jobOperationService.setJobEnabledState(jobName, state);
} else {
messageSbf.append("作业【"+jobName+"】不处于running或ready状态,不能禁用,");
}
}
}catch(Exception e){
AUDITLOGGER.error(e.getMessage(), e);
messageSbf.append("操作作业【"+jobName+"】出现内部错误,");
continue;
}
}
if(messageSbf.length() == 0){
requestResult.setSuccess(true);
return requestResult;
} else {
requestResult.setSuccess(false);
requestResult.setMessage(messageSbf.substring(0, messageSbf.length() - 1)); //去掉最后一个逗号
return requestResult;
}
}
@RequestMapping(value = "remove/executor", method = RequestMethod.POST)
@ResponseBody
public String removeExecutor(final String executor, final HttpServletRequest request) {
if (executor.contains(",")) {
StringBuilder removeAllExecutorMsg = new StringBuilder();
// 多个executor
String[] executors = executor.split(",");
for (int i = 0; i < executors.length; i++) {
String delExecutor = executors[i];
String removeOneExecutorMsg = removeOneExecutor(delExecutor);
if(!SaturnConstants.DEAL_SUCCESS.equals(removeOneExecutorMsg)){
removeAllExecutorMsg.append(removeOneExecutorMsg).append(",");
}
}
if(StringUtils.isBlank(removeAllExecutorMsg.toString())){
return SaturnConstants.DEAL_SUCCESS;
}
return removeAllExecutorMsg.substring(0,removeAllExecutorMsg.toString().length()-1);
}
return removeOneExecutor(executor);
}
private String removeOneExecutor(String delExecutor) {
if ( ServerStatus.ONLINE.equals(serverDimensionService.getExecutorStatus(delExecutor))) {
return "无法删除ONLINE的Executor:("+delExecutor+")";
}
serverDimensionService.removeOffLineExecutor(delExecutor);
return SaturnConstants.DEAL_SUCCESS;
}
@RequestMapping(value = "remove/job", method = RequestMethod.POST)
public RequestResult removeStoppedJob(String jobName, HttpServletRequest request) throws InterruptedException {
RequestResult requestResult = new RequestResult();
JobStatus jobStatus = jobDimensionService.getJobStatus(jobName);
if (JobStatus.STOPPED.equals(jobStatus)) {
String result = executorService.removeJob(jobName);
if(SaturnConstants.DEAL_SUCCESS.equals(result)) {
requestResult.setSuccess(true);
return requestResult;
} else {
requestResult.setSuccess(false);
requestResult.setMessage(result);
return requestResult;
}
// let zk and the watchers update theirselves.
} else {
requestResult.setSuccess(false);
requestResult.setMessage("作业【"+jobName+ "】不处于STOPPED状态,不能删除.");
return requestResult;
}
}
@RequestMapping(value = "batchRemove/jobs", method = RequestMethod.POST)
public String batchRemoveStoppedJob(final String jobNames, HttpServletRequest request) throws InterruptedException {
String[] jobNamesArr = jobNames.split(",");
if(jobNamesArr == null || jobNamesArr.length == 0){
AUDITLOGGER.warn("batchRemoveJobs is null");
return "批量删除作业为空";
}
StringBuilder errorLog = new StringBuilder();
for(String jobName : jobNamesArr){
JobStatus jobStatus = jobDimensionService.getJobStatus(jobName);
if (JobStatus.STOPPED.equals(jobStatus)) {
String removeResult = executorService.removeJob(jobName);
if(!SaturnConstants.DEAL_SUCCESS.equals(removeResult)){
errorLog.append(removeResult).append(",");
}
// let zk and the watchers update theirselves.
} else {
errorLog.append("作业【"+jobName+ "】不处于STOPPED状态,不能删除.").append(",");
continue;
}
}
if(Strings.isNullOrEmpty(errorLog.toString())){
return SaturnConstants.DEAL_SUCCESS;
}
if(errorLog.toString().split(",").length != jobNamesArr.length){
return errorLog.toString()+"其他作业已成功删除";// 说明有作业已被成功删除,加个后缀提示
}
return errorLog.substring(0,errorLog.length()-1).toString();// 去掉最后一个逗号
}
@RequestMapping(value = "runAllOneTime", method = RequestMethod.POST)
@ResponseBody
public String runAllOneTime(final JobServer jobServer, HttpServletRequest request) {
JobStatus js = jobDimensionService.getJobStatus(jobServer.getJobName());
if (JobStatus.READY.equals(js)) {
Collection<JobServer> servers = jobDimensionService.getServers(jobServer.getJobName());
if (servers != null) {
for (JobServer server: servers) {
if (ServerStatus.ONLINE.equals(server.getStatus())) {
jobOperationService.runAtOnceByJobnameAndExecutorName( jobServer.getJobName(), server.getExecutorName());
}
}
return SaturnConstants.DEAL_SUCCESS;
}
return "无online executor.";
} else {
return "作业不在ready状态,不能执行立即运行。";
}
}
@RequestMapping(value = "stopAllOneTime", method = RequestMethod.POST)
@ResponseBody
public String stopAllOneTime(final JobServer jobServer, HttpServletRequest request) {
String jobName = jobServer.getJobName();
String jobType = jobDimensionService.getJobType(jobName);
if(jobType != null && (jobType.equals(JobBriefInfo.JobType.MSG_JOB.name()))) {
boolean jobEnabled = jobDimensionService.isJobEnabled(jobName);
if(jobEnabled) {
return "作业不处于禁用状态,不能强行终止作业。";
} else {
return stopOnceTime(jobName);
}
} else {
JobStatus js = jobDimensionService.getJobStatus(jobServer.getJobName());
if (JobStatus.STOPPING.equals(js)) {
return stopOnceTime(jobName);
}
return "作业不处于stopping状态,不能强行终止作业。";
}
}
private String stopOnceTime(String jobName) {
Collection<JobServer> servers = jobDimensionService.getServers(jobName);
if (servers == null || servers.size() == 0) {
return "该作业没有executor接管,不能强行终止作业。";
}
for (JobServer server : servers) {
jobOperationService.stopAtOnceByJobnameAndExecutorName(jobName, server.getExecutorName());
}
return SaturnConstants.DEAL_SUCCESS;
}
}