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 }