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.ErrorCode; 018 import org.apache.oozie.WorkflowActionBean; 019 import org.apache.oozie.WorkflowJobBean; 020 import org.apache.oozie.XException; 021 import org.apache.oozie.client.SLAEvent.SlaAppType; 022 import org.apache.oozie.client.SLAEvent.Status; 023 import org.apache.oozie.command.CommandException; 024 import org.apache.oozie.command.PreconditionException; 025 import org.apache.oozie.executor.jpa.JPAExecutorException; 026 import org.apache.oozie.executor.jpa.WorkflowActionGetJPAExecutor; 027 import org.apache.oozie.executor.jpa.WorkflowActionUpdateJPAExecutor; 028 import org.apache.oozie.executor.jpa.WorkflowJobGetJPAExecutor; 029 import org.apache.oozie.executor.jpa.WorkflowJobUpdateJPAExecutor; 030 import org.apache.oozie.action.ActionExecutor; 031 import org.apache.oozie.action.ActionExecutorException; 032 import org.apache.oozie.service.ActionService; 033 import org.apache.oozie.service.JPAService; 034 import org.apache.oozie.service.UUIDService; 035 import org.apache.oozie.service.Services; 036 import org.apache.oozie.util.LogUtils; 037 import org.apache.oozie.util.Instrumentation; 038 import org.apache.oozie.util.db.SLADbXOperations; 039 040 /** 041 * Kill workflow action and invoke action executor to kill the underlying context. 042 * 043 */ 044 public class ActionKillXCommand extends ActionXCommand<Void> { 045 private String actionId; 046 private String jobId; 047 private WorkflowJobBean wfJob; 048 private WorkflowActionBean wfAction; 049 private JPAService jpaService = null; 050 051 public ActionKillXCommand(String actionId, String type) { 052 super("action.kill", type, 0); 053 this.actionId = actionId; 054 this.jobId = Services.get().get(UUIDService.class).getId(actionId); 055 } 056 057 public ActionKillXCommand(String actionId) { 058 this(actionId, "action.kill"); 059 } 060 061 @Override 062 protected boolean isLockRequired() { 063 return true; 064 } 065 066 @Override 067 protected String getEntityKey() { 068 return this.jobId; 069 } 070 071 @Override 072 protected void loadState() throws CommandException { 073 try { 074 jpaService = Services.get().get(JPAService.class); 075 076 if (jpaService != null) { 077 this.wfJob = jpaService.execute(new WorkflowJobGetJPAExecutor(jobId)); 078 this.wfAction = jpaService.execute(new WorkflowActionGetJPAExecutor(actionId)); 079 LogUtils.setLogInfo(wfJob, logInfo); 080 LogUtils.setLogInfo(wfAction, logInfo); 081 } 082 else { 083 throw new CommandException(ErrorCode.E0610); 084 } 085 } 086 catch (XException ex) { 087 throw new CommandException(ex); 088 } 089 } 090 091 @Override 092 protected void verifyPrecondition() throws CommandException, PreconditionException { 093 if (wfAction.getStatus() != WorkflowActionBean.Status.KILLED) { 094 throw new PreconditionException(ErrorCode.E0726, wfAction.getId()); 095 } 096 } 097 098 @Override 099 protected Void execute() throws CommandException { 100 LOG.debug("STARTED WorkflowActionKillXCommand for action " + actionId); 101 102 if (wfAction.isPending()) { 103 ActionExecutor executor = Services.get().get(ActionService.class).getExecutor(wfAction.getType()); 104 if (executor != null) { 105 try { 106 boolean isRetry = false; 107 ActionExecutorContext context = new ActionXCommand.ActionExecutorContext(wfJob, wfAction, 108 isRetry); 109 incrActionCounter(wfAction.getType(), 1); 110 111 Instrumentation.Cron cron = new Instrumentation.Cron(); 112 cron.start(); 113 executor.kill(context, wfAction); 114 cron.stop(); 115 addActionCron(wfAction.getType(), cron); 116 117 wfAction.resetPending(); 118 wfAction.setStatus(WorkflowActionBean.Status.KILLED); 119 120 jpaService.execute(new WorkflowActionUpdateJPAExecutor(wfAction)); 121 jpaService.execute(new WorkflowJobUpdateJPAExecutor(wfJob)); 122 // Add SLA status event (KILLED) for WF_ACTION 123 SLADbXOperations.writeStausEvent(wfAction.getSlaXml(), wfAction.getId(), Status.KILLED, 124 SlaAppType.WORKFLOW_ACTION); 125 queue(new NotificationXCommand(wfJob, wfAction)); 126 } 127 catch (ActionExecutorException ex) { 128 wfAction.resetPending(); 129 wfAction.setStatus(WorkflowActionBean.Status.FAILED); 130 wfAction.setErrorInfo(ex.getErrorCode().toString(), 131 "KILL COMMAND FAILED - exception while executing job kill"); 132 wfJob.setStatus(WorkflowJobBean.Status.KILLED); 133 try { 134 jpaService.execute(new WorkflowActionUpdateJPAExecutor(wfAction)); 135 jpaService.execute(new WorkflowJobUpdateJPAExecutor(wfJob)); 136 } 137 catch (JPAExecutorException je) { 138 throw new CommandException(je); 139 } 140 // What will happen to WF and COORD_ACTION, NOTIFICATION? 141 SLADbXOperations.writeStausEvent(wfAction.getSlaXml(), wfAction.getId(), Status.FAILED, 142 SlaAppType.WORKFLOW_ACTION); 143 LOG.warn("Exception while executing kill(). Error Code [{0}], Message[{1}]", 144 ex.getErrorCode(), ex.getMessage(), ex); 145 } 146 catch (JPAExecutorException je) { 147 throw new CommandException(je); 148 } 149 } 150 } 151 LOG.debug("ENDED WorkflowActionKillXCommand for action " + actionId); 152 return null; 153 } 154 155 }