001 /** 002 * Copyright (c) 2010 Yahoo! Inc. All rights reserved. 003 * Licensed under the Apache License, Version 2.0 (the "License"); 004 * you may not use this file except in compliance with the License. 005 * You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software 010 * distributed under the License is distributed on an "AS IS" BASIS, 011 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012 * See the License for the specific language governing permissions and 013 * limitations under the License. See accompanying LICENSE file. 014 */ 015 package org.apache.oozie.command.wf; 016 017 import org.apache.oozie.client.WorkflowJob; 018 import org.apache.oozie.client.SLAEvent.SlaAppType; 019 import org.apache.oozie.client.SLAEvent.Status; 020 import org.apache.oozie.ErrorCode; 021 import org.apache.oozie.WorkflowActionBean; 022 import org.apache.oozie.WorkflowJobBean; 023 import org.apache.oozie.XException; 024 import org.apache.oozie.command.CommandException; 025 import org.apache.oozie.command.PreconditionException; 026 import org.apache.oozie.command.coord.CoordActionUpdateXCommand; 027 import org.apache.oozie.executor.jpa.JPAExecutorException; 028 import org.apache.oozie.executor.jpa.WorkflowActionUpdateJPAExecutor; 029 import org.apache.oozie.executor.jpa.WorkflowActionsGetForJobJPAExecutor; 030 import org.apache.oozie.executor.jpa.WorkflowJobGetJPAExecutor; 031 import org.apache.oozie.executor.jpa.WorkflowJobUpdateJPAExecutor; 032 import org.apache.oozie.service.JPAService; 033 import org.apache.oozie.service.Services; 034 import org.apache.oozie.workflow.WorkflowException; 035 import org.apache.oozie.workflow.WorkflowInstance; 036 import org.apache.oozie.workflow.lite.LiteWorkflowInstance; 037 import org.apache.oozie.util.InstrumentUtils; 038 import org.apache.oozie.util.LogUtils; 039 import org.apache.oozie.util.ParamChecker; 040 import org.apache.oozie.util.db.SLADbXOperations; 041 042 import java.util.Date; 043 import java.util.List; 044 045 /** 046 * Kill workflow job and its workflow instance and queue a {@link WorkflowActionKillXCommand} to kill the workflow 047 * actions. 048 */ 049 public class KillXCommand extends WorkflowXCommand<Void> { 050 051 private String wfId; 052 private WorkflowJobBean wfJob; 053 private List<WorkflowActionBean> actionList; 054 private JPAService jpaService = null; 055 056 public KillXCommand(String wfId) { 057 super("kill", "kill", 1); 058 this.wfId = ParamChecker.notEmpty(wfId, "wfId"); 059 } 060 061 @Override 062 protected boolean isLockRequired() { 063 return true; 064 } 065 066 @Override 067 protected String getEntityKey() { 068 return this.wfId; 069 } 070 071 @Override 072 protected void loadState() throws CommandException { 073 try { 074 jpaService = Services.get().get(JPAService.class); 075 if (jpaService != null) { 076 this.wfJob = jpaService.execute(new WorkflowJobGetJPAExecutor(wfId)); 077 this.actionList = jpaService.execute(new WorkflowActionsGetForJobJPAExecutor(wfId)); 078 LogUtils.setLogInfo(wfJob, logInfo); 079 } 080 else { 081 throw new CommandException(ErrorCode.E0610); 082 } 083 } 084 catch (XException ex) { 085 throw new CommandException(ex); 086 } 087 } 088 089 @Override 090 protected void verifyPrecondition() throws CommandException, PreconditionException { 091 if (wfJob.getStatus() != WorkflowJob.Status.PREP && wfJob.getStatus() != WorkflowJob.Status.RUNNING 092 && wfJob.getStatus() != WorkflowJob.Status.SUSPENDED && wfJob.getStatus() != WorkflowJob.Status.FAILED) { 093 throw new PreconditionException(ErrorCode.E0725, wfJob.getId()); 094 } 095 } 096 097 @Override 098 protected Void execute() throws CommandException { 099 LOG.info("STARTED WorkflowKillXCommand for jobId=" + wfId); 100 101 wfJob.setEndTime(new Date()); 102 103 if (wfJob.getStatus() != WorkflowJob.Status.FAILED) { 104 InstrumentUtils.incrJobCounter(getName(), 1, getInstrumentation()); 105 wfJob.setStatus(WorkflowJob.Status.KILLED); 106 SLADbXOperations.writeStausEvent(wfJob.getSlaXml(), wfJob.getId(), Status.KILLED, SlaAppType.WORKFLOW_JOB); 107 try { 108 wfJob.getWorkflowInstance().kill(); 109 } 110 catch (WorkflowException e) { 111 throw new CommandException(ErrorCode.E0725, e.getMessage(), e); 112 } 113 WorkflowInstance wfInstance = wfJob.getWorkflowInstance(); 114 ((LiteWorkflowInstance) wfInstance).setStatus(WorkflowInstance.Status.KILLED); 115 wfJob.setWorkflowInstance(wfInstance); 116 } 117 try { 118 for (WorkflowActionBean action : actionList) { 119 if (action.getStatus() == WorkflowActionBean.Status.RUNNING 120 || action.getStatus() == WorkflowActionBean.Status.DONE) { 121 action.setPending(); 122 action.setStatus(WorkflowActionBean.Status.KILLED); 123 124 jpaService.execute(new WorkflowActionUpdateJPAExecutor(action)); 125 126 queue(new ActionKillXCommand(action.getId(), action.getType())); 127 } 128 if (action.getStatus() == WorkflowActionBean.Status.PREP 129 || action.getStatus() == WorkflowActionBean.Status.START_RETRY 130 || action.getStatus() == WorkflowActionBean.Status.START_MANUAL 131 || action.getStatus() == WorkflowActionBean.Status.END_RETRY 132 || action.getStatus() == WorkflowActionBean.Status.END_MANUAL) { 133 134 action.setStatus(WorkflowActionBean.Status.KILLED); 135 action.resetPending(); 136 SLADbXOperations.writeStausEvent(action.getSlaXml(), action.getId(), Status.KILLED, 137 SlaAppType.WORKFLOW_ACTION); 138 jpaService.execute(new WorkflowActionUpdateJPAExecutor(action)); 139 } 140 } 141 jpaService.execute(new WorkflowJobUpdateJPAExecutor(wfJob)); 142 queue(new NotificationXCommand(wfJob)); 143 } 144 catch (JPAExecutorException je) { 145 throw new CommandException(je); 146 } 147 finally { 148 if(wfJob.getStatus() == WorkflowJob.Status.KILLED) { 149 new WfEndXCommand(wfJob).call(); //To delete the WF temp dir 150 } 151 // update coordinator action 152 new CoordActionUpdateXCommand(wfJob).call(); 153 } 154 155 LOG.info("ENDED WorkflowKillXCommand for jobId=" + wfId); 156 return null; 157 } 158 159 }