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.servlet; 016 017 import java.io.IOException; 018 import java.util.Arrays; 019 import java.util.List; 020 021 import javax.servlet.ServletException; 022 import javax.servlet.http.HttpServletRequest; 023 import javax.servlet.http.HttpServletResponse; 024 025 import org.apache.hadoop.conf.Configuration; 026 import org.apache.oozie.BaseEngineException; 027 import org.apache.oozie.CoordinatorActionBean; 028 import org.apache.oozie.CoordinatorActionInfo; 029 import org.apache.oozie.CoordinatorEngine; 030 import org.apache.oozie.DagEngine; 031 import org.apache.oozie.DagEngineException; 032 import org.apache.oozie.ErrorCode; 033 import org.apache.oozie.client.OozieClient; 034 import org.apache.oozie.client.rest.JsonTags; 035 import org.apache.oozie.client.rest.JsonWorkflowJob; 036 import org.apache.oozie.client.rest.RestConstants; 037 import org.apache.oozie.service.AuthorizationException; 038 import org.apache.oozie.service.AuthorizationService; 039 import org.apache.oozie.service.CoordinatorEngineService; 040 import org.apache.oozie.service.DagEngineService; 041 import org.apache.oozie.service.Services; 042 import org.apache.oozie.service.XLogService; 043 import org.apache.oozie.util.XConfiguration; 044 import org.apache.oozie.util.XLog; 045 import org.json.simple.JSONObject; 046 047 public class JobServlet extends JsonRestServlet { 048 private static final String INSTRUMENTATION_NAME = "job"; 049 050 private static final ResourceInfo RESOURCES_INFO[] = new ResourceInfo[1]; 051 052 static { 053 RESOURCES_INFO[0] = new ResourceInfo("*", Arrays.asList("PUT", "GET"), Arrays.asList(new ParameterInfo( 054 RestConstants.ACTION_PARAM, String.class, true, Arrays.asList("PUT")), new ParameterInfo( 055 RestConstants.JOB_SHOW_PARAM, String.class, false, Arrays.asList("GET")))); 056 } 057 058 public JobServlet() { 059 super(INSTRUMENTATION_NAME, RESOURCES_INFO); 060 } 061 062 /** 063 * Perform various job related actions - start, suspend, resume, kill, etc. 064 */ 065 @SuppressWarnings("unchecked") 066 @Override 067 protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 068 String jobId = getResourceName(request); 069 request.setAttribute(AUDIT_PARAM, jobId); 070 request.setAttribute(AUDIT_OPERATION, request.getParameter(RestConstants.ACTION_PARAM)); 071 try { 072 AuthorizationService auth = Services.get().get(AuthorizationService.class); 073 auth.authorizeForJob(getUser(request), jobId, true); 074 } 075 catch (AuthorizationException ex) { 076 throw new XServletException(HttpServletResponse.SC_UNAUTHORIZED, ex); 077 } 078 079 DagEngine dagEngine = Services.get().get(DagEngineService.class).getDagEngine(getUser(request), 080 getAuthToken(request)); 081 CoordinatorEngine coordEngine = Services.get().get(CoordinatorEngineService.class).getCoordinatorEngine( 082 getUser(request), getAuthToken(request)); 083 try { 084 String action = request.getParameter(RestConstants.ACTION_PARAM); 085 if (action.equals(RestConstants.JOB_ACTION_START)) { 086 stopCron(); 087 dagEngine.start(jobId); 088 startCron(); 089 response.setStatus(HttpServletResponse.SC_OK); 090 } 091 else if (action.equals(RestConstants.JOB_ACTION_RESUME)) { 092 stopCron(); 093 dagEngine.resume(jobId); 094 startCron(); 095 response.setStatus(HttpServletResponse.SC_OK); 096 } 097 else if (action.equals(RestConstants.JOB_ACTION_SUSPEND)) { 098 stopCron(); 099 dagEngine.suspend(jobId); 100 startCron(); 101 response.setStatus(HttpServletResponse.SC_OK); 102 } 103 else if (action.equals(RestConstants.JOB_ACTION_KILL)) { 104 stopCron(); 105 dagEngine.kill(jobId); 106 startCron(); 107 response.setStatus(HttpServletResponse.SC_OK); 108 } 109 else if (action.equals(RestConstants.JOB_ACTION_RERUN)) { 110 validateContentType(request, RestConstants.XML_CONTENT_TYPE); 111 XConfiguration conf = new XConfiguration(request.getInputStream()); 112 stopCron(); 113 conf = conf.trim(); 114 conf = conf.resolve(); 115 JobsServlet.validateJobConfiguration(conf); 116 checkAuthorizationForApp(getUser(request), conf); 117 dagEngine.reRun(jobId, conf); 118 startCron(); 119 response.setStatus(HttpServletResponse.SC_OK); 120 } 121 else if (action.equals(RestConstants.JOB_COORD_ACTION_RERUN)) { 122 validateContentType(request, RestConstants.XML_CONTENT_TYPE); 123 stopCron(); 124 String rerunType = request.getParameter(RestConstants.JOB_COORD_RERUN_TYPE_PARAM); 125 String scope = request.getParameter(RestConstants.JOB_COORD_RERUN_SCOPE_PARAM); 126 String refresh = request.getParameter(RestConstants.JOB_COORD_RERUN_REFRESH_PARAM); 127 String noCleanup = request.getParameter(RestConstants.JOB_COORD_RERUN_NOCLEANUP_PARAM); 128 CoordinatorActionInfo coordInfo = coordEngine.reRun(jobId, rerunType, scope, Boolean.valueOf(refresh), 129 Boolean.valueOf(noCleanup)); 130 List<CoordinatorActionBean> actions = coordInfo.getCoordActions(); 131 JSONObject json = new JSONObject(); 132 json.put(JsonTags.COORDINATOR_ACTIONS, CoordinatorActionBean.toJSONArray(actions)); 133 startCron(); 134 sendJsonResponse(response, HttpServletResponse.SC_OK, json); 135 } 136 else { 137 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0303, 138 RestConstants.ACTION_PARAM, action); 139 } 140 } 141 catch (DagEngineException ex) { 142 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex); 143 } 144 catch (BaseEngineException ex) { 145 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex); 146 } 147 } 148 149 /** 150 * Validate the configuration user/group. <p/> 151 * 152 * @param requestUser user in request. 153 * @param conf configuration. 154 * @throws XServletException thrown if the configuration does not have a property {@link 155 * org.apache.oozie.client.OozieClient#USER_NAME}. 156 */ 157 static void checkAuthorizationForApp(String requestUser, Configuration conf) throws XServletException { 158 String user = conf.get(OozieClient.USER_NAME); 159 String group = conf.get(OozieClient.GROUP_NAME); 160 try { 161 if (user == null) { 162 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0401, OozieClient.USER_NAME); 163 } 164 if (!requestUser.equals(UNDEF) && !user.equals(requestUser)) { 165 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0400, requestUser, user); 166 } 167 AuthorizationService auth = Services.get().get(AuthorizationService.class); 168 if (group == null) { 169 group = auth.getDefaultGroup(user); 170 conf.set(OozieClient.GROUP_NAME, group); 171 } 172 else { 173 auth.authorizeForGroup(user, group); 174 } 175 XLog.Info.get().setParameter(XLogService.GROUP, group); 176 auth.authorizeForApp(user, group, conf.get(OozieClient.APP_PATH), conf); 177 } 178 catch (AuthorizationException ex) { 179 throw new XServletException(HttpServletResponse.SC_UNAUTHORIZED, ex); 180 } 181 } 182 183 /** 184 * Return information about jobs. 185 */ 186 @Override 187 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 188 String jobId = getResourceName(request); 189 String show = request.getParameter(RestConstants.JOB_SHOW_PARAM); 190 191 try { 192 AuthorizationService auth = Services.get().get(AuthorizationService.class); 193 auth.authorizeForJob(getUser(request), jobId, false); 194 } 195 catch (AuthorizationException ex) { 196 throw new XServletException(HttpServletResponse.SC_UNAUTHORIZED, ex); 197 } 198 199 DagEngine dagEngine = Services.get().get(DagEngineService.class).getDagEngine(getUser(request), 200 getAuthToken(request)); 201 try { 202 if (show == null || show.equals(RestConstants.JOB_SHOW_INFO)) { 203 stopCron(); 204 JsonWorkflowJob job = (JsonWorkflowJob) dagEngine.getJob(jobId); 205 startCron(); 206 sendJsonResponse(response, HttpServletResponse.SC_OK, job); 207 } 208 else { 209 if (show.equals(RestConstants.JOB_SHOW_LOG)) { 210 response.setContentType(TEXT_UTF8); 211 dagEngine.streamLog(jobId, response.getWriter()); 212 } 213 else { 214 if (show.equals(RestConstants.JOB_SHOW_DEFINITION)) { 215 stopCron(); 216 response.setContentType(XML_UTF8); 217 String wfDefinition = dagEngine.getDefinition(jobId); 218 startCron(); 219 response.setStatus(HttpServletResponse.SC_OK); 220 response.getWriter().write(wfDefinition); 221 } 222 else { 223 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0303, 224 RestConstants.JOB_SHOW_PARAM, show); 225 } 226 } 227 } 228 } 229 catch (DagEngineException ex) { 230 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex); 231 } 232 } 233 234 }