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.List; 019 020 import javax.servlet.http.HttpServletRequest; 021 import javax.servlet.http.HttpServletResponse; 022 023 import org.apache.hadoop.conf.Configuration; 024 import org.apache.oozie.BundleJobBean; 025 import org.apache.oozie.BundleJobInfo; 026 import org.apache.oozie.CoordinatorEngine; 027 import org.apache.oozie.BundleEngine; 028 import org.apache.oozie.CoordinatorEngineException; 029 import org.apache.oozie.BundleEngineException; 030 import org.apache.oozie.CoordinatorJobBean; 031 import org.apache.oozie.CoordinatorJobInfo; 032 import org.apache.oozie.DagEngine; 033 import org.apache.oozie.DagEngineException; 034 import org.apache.oozie.ErrorCode; 035 import org.apache.oozie.WorkflowJobBean; 036 import org.apache.oozie.WorkflowsInfo; 037 import org.apache.oozie.client.OozieClient; 038 import org.apache.oozie.client.rest.JsonTags; 039 import org.apache.oozie.client.rest.RestConstants; 040 import org.apache.oozie.service.CoordinatorEngineService; 041 import org.apache.oozie.service.DagEngineService; 042 import org.apache.oozie.service.BundleEngineService; 043 import org.apache.oozie.service.Services; 044 import org.apache.oozie.util.XLog; 045 import org.apache.oozie.util.XmlUtils; 046 import org.json.simple.JSONObject; 047 048 public class V1JobsServlet extends BaseJobsServlet { 049 050 private static final String INSTRUMENTATION_NAME = "v1jobs"; 051 052 public V1JobsServlet() { 053 super(INSTRUMENTATION_NAME); 054 } 055 056 /** 057 * v1 service implementation to submit a job, either workflow or coordinator 058 */ 059 @Override 060 protected JSONObject submitJob(HttpServletRequest request, Configuration conf) throws XServletException, 061 IOException { 062 JSONObject json = null; 063 064 String jobType = request.getParameter(RestConstants.JOBTYPE_PARAM); 065 066 if (jobType == null) { 067 String wfPath = conf.get(OozieClient.APP_PATH); 068 String coordPath = conf.get(OozieClient.COORDINATOR_APP_PATH); 069 String bundlePath = conf.get(OozieClient.BUNDLE_APP_PATH); 070 071 ServletUtilities.ValidateAppPath(wfPath, coordPath, bundlePath); 072 073 if (wfPath != null) { 074 json = submitWorkflowJob(request, conf); 075 } 076 else if (coordPath != null) { 077 json = submitCoordinatorJob(request, conf); 078 } 079 else { 080 json = submitBundleJob(request, conf); 081 } 082 } 083 else { // This is a http submission job 084 if (jobType.equals("pig") || jobType.equals("mapreduce")) { 085 json = submitHttpJob(request, conf, jobType); 086 } 087 else { 088 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0303, 089 RestConstants.JOBTYPE_PARAM, jobType); 090 } 091 } 092 return json; 093 } 094 095 /** 096 * v1 service implementation to get a JSONObject representation of a job from its external ID 097 */ 098 @Override 099 protected JSONObject getJobIdForExternalId(HttpServletRequest request, String externalId) throws XServletException, 100 IOException { 101 JSONObject json = null; 102 /* 103 * Configuration conf = new XConfiguration(); String wfPath = 104 * conf.get(OozieClient.APP_PATH); String coordPath = 105 * conf.get(OozieClient.COORDINATOR_APP_PATH); 106 * 107 * ServletUtilities.ValidateAppPath(wfPath, coordPath); 108 */ 109 String jobtype = request.getParameter(RestConstants.JOBTYPE_PARAM); 110 jobtype = (jobtype != null) ? jobtype : "wf"; 111 if (jobtype.contains("wf")) { 112 json = getWorkflowJobIdForExternalId(request, externalId); 113 } 114 else { 115 json = getCoordinatorJobIdForExternalId(request, externalId); 116 } 117 return json; 118 } 119 120 /** 121 * v1 service implementation to get a list of workflows, coordinators, or bundles, with filtering or interested 122 * windows embedded in the request object 123 */ 124 @Override 125 protected JSONObject getJobs(HttpServletRequest request) throws XServletException, IOException { 126 JSONObject json = null; 127 String jobtype = request.getParameter(RestConstants.JOBTYPE_PARAM); 128 jobtype = (jobtype != null) ? jobtype : "wf"; 129 130 if (jobtype.contains("wf")) { 131 json = getWorkflowJobs(request); 132 } 133 else if (jobtype.contains("coord")) { 134 json = getCoordinatorJobs(request); 135 } 136 else if (jobtype.contains("bundle")) { 137 json = getBundleJobs(request); 138 } 139 return json; 140 } 141 142 /** 143 * v1 service implementation to submit a workflow job 144 */ 145 @SuppressWarnings("unchecked") 146 private JSONObject submitWorkflowJob(HttpServletRequest request, Configuration conf) throws XServletException { 147 148 JSONObject json = new JSONObject(); 149 150 try { 151 String action = request.getParameter(RestConstants.ACTION_PARAM); 152 if (action != null && !action.equals(RestConstants.JOB_ACTION_START)) { 153 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0303, 154 RestConstants.ACTION_PARAM, action); 155 } 156 boolean startJob = (action != null); 157 String user = conf.get(OozieClient.USER_NAME); 158 DagEngine dagEngine = Services.get().get(DagEngineService.class).getDagEngine(user, getAuthToken(request)); 159 String id = dagEngine.submitJob(conf, startJob); 160 json.put(JsonTags.JOB_ID, id); 161 } 162 catch (DagEngineException ex) { 163 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex); 164 } 165 166 return json; 167 } 168 169 /** 170 * v1 service implementation to submit a coordinator job 171 */ 172 @SuppressWarnings("unchecked") 173 private JSONObject submitCoordinatorJob(HttpServletRequest request, Configuration conf) throws XServletException { 174 175 JSONObject json = new JSONObject(); 176 XLog.getLog(getClass()).warn("submitCoordinatorJob " + XmlUtils.prettyPrint(conf).toString()); 177 try { 178 String action = request.getParameter(RestConstants.ACTION_PARAM); 179 if (action != null && !action.equals(RestConstants.JOB_ACTION_START) 180 && !action.equals(RestConstants.JOB_ACTION_DRYRUN)) { 181 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0303, 182 RestConstants.ACTION_PARAM, action); 183 } 184 boolean startJob = (action != null); 185 String user = conf.get(OozieClient.USER_NAME); 186 CoordinatorEngine coordEngine = Services.get().get(CoordinatorEngineService.class).getCoordinatorEngine( 187 user, getAuthToken(request)); 188 String id = null; 189 boolean dryrun = false; 190 if (action != null) { 191 dryrun = (action.equals(RestConstants.JOB_ACTION_DRYRUN)); 192 } 193 if (dryrun) { 194 id = coordEngine.dryrunSubmit(conf, startJob); 195 } 196 else { 197 id = coordEngine.submitJob(conf, startJob); 198 } 199 json.put(JsonTags.JOB_ID, id); 200 } 201 catch (CoordinatorEngineException ex) { 202 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex); 203 } 204 205 return json; 206 } 207 208 /** 209 * v1 service implementation to submit a bundle job 210 */ 211 @SuppressWarnings("unchecked") 212 private JSONObject submitBundleJob(HttpServletRequest request, Configuration conf) throws XServletException { 213 JSONObject json = new JSONObject(); 214 XLog.getLog(getClass()).warn("submitBundleJob " + XmlUtils.prettyPrint(conf).toString()); 215 try { 216 String action = request.getParameter(RestConstants.ACTION_PARAM); 217 if (action != null && !action.equals(RestConstants.JOB_ACTION_START) 218 && !action.equals(RestConstants.JOB_ACTION_DRYRUN)) { 219 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0303, 220 RestConstants.ACTION_PARAM, action); 221 } 222 boolean startJob = (action != null); 223 String user = conf.get(OozieClient.USER_NAME); 224 BundleEngine bundleEngine = Services.get().get(BundleEngineService.class).getBundleEngine(user, 225 getAuthToken(request)); 226 String id = null; 227 boolean dryrun = false; 228 if (action != null) { 229 dryrun = (action.equals(RestConstants.JOB_ACTION_DRYRUN)); 230 } 231 if (dryrun) { 232 id = bundleEngine.dryrunSubmit(conf, startJob); 233 } 234 else { 235 id = bundleEngine.submitJob(conf, startJob); 236 } 237 json.put(JsonTags.JOB_ID, id); 238 } 239 catch (BundleEngineException ex) { 240 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex); 241 } 242 243 return json; 244 } 245 246 /** 247 * v1 service implementation to get a JSONObject representation of a job from its external ID 248 */ 249 @SuppressWarnings("unchecked") 250 private JSONObject getWorkflowJobIdForExternalId(HttpServletRequest request, String externalId) 251 throws XServletException { 252 JSONObject json = new JSONObject(); 253 try { 254 DagEngine dagEngine = Services.get().get(DagEngineService.class).getDagEngine(getUser(request), 255 getAuthToken(request)); 256 String jobId = dagEngine.getJobIdForExternalId(externalId); 257 json.put(JsonTags.JOB_ID, jobId); 258 } 259 catch (DagEngineException ex) { 260 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex); 261 } 262 return json; 263 } 264 265 /** 266 * v1 service implementation to get a JSONObject representation of a job from its external ID 267 */ 268 private JSONObject getCoordinatorJobIdForExternalId(HttpServletRequest request, String externalId) 269 throws XServletException { 270 JSONObject json = new JSONObject(); 271 return json; 272 } 273 274 /** 275 * v1 service implementation to get a list of workflows, with filtering or interested windows embedded in the 276 * request object 277 */ 278 private JSONObject getWorkflowJobs(HttpServletRequest request) throws XServletException { 279 JSONObject json = new JSONObject(); 280 try { 281 String filter = request.getParameter(RestConstants.JOBS_FILTER_PARAM); 282 String startStr = request.getParameter(RestConstants.OFFSET_PARAM); 283 String lenStr = request.getParameter(RestConstants.LEN_PARAM); 284 int start = (startStr != null) ? Integer.parseInt(startStr) : 1; 285 start = (start < 1) ? 1 : start; 286 int len = (lenStr != null) ? Integer.parseInt(lenStr) : 50; 287 len = (len < 1) ? 50 : len; 288 DagEngine dagEngine = Services.get().get(DagEngineService.class).getDagEngine(getUser(request), 289 getAuthToken(request)); 290 WorkflowsInfo jobs = dagEngine.getJobs(filter, start, len); 291 List<WorkflowJobBean> jsonWorkflows = jobs.getWorkflows(); 292 json.put(JsonTags.WORKFLOWS_JOBS, WorkflowJobBean.toJSONArray(jsonWorkflows)); 293 json.put(JsonTags.WORKFLOWS_TOTAL, jobs.getTotal()); 294 json.put(JsonTags.WORKFLOWS_OFFSET, jobs.getStart()); 295 json.put(JsonTags.WORKFLOWS_LEN, jobs.getLen()); 296 297 } 298 catch (DagEngineException ex) { 299 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex); 300 } 301 302 return json; 303 } 304 305 /** 306 * v1 service implementation to get a list of workflows, with filtering or interested windows embedded in the 307 * request object 308 */ 309 @SuppressWarnings("unchecked") 310 private JSONObject getCoordinatorJobs(HttpServletRequest request) throws XServletException { 311 JSONObject json = new JSONObject(); 312 try { 313 String filter = request.getParameter(RestConstants.JOBS_FILTER_PARAM); 314 String startStr = request.getParameter(RestConstants.OFFSET_PARAM); 315 String lenStr = request.getParameter(RestConstants.LEN_PARAM); 316 int start = (startStr != null) ? Integer.parseInt(startStr) : 1; 317 start = (start < 1) ? 1 : start; 318 int len = (lenStr != null) ? Integer.parseInt(lenStr) : 50; 319 len = (len < 1) ? 50 : len; 320 CoordinatorEngine coordEngine = Services.get().get(CoordinatorEngineService.class).getCoordinatorEngine( 321 getUser(request), getAuthToken(request)); 322 CoordinatorJobInfo jobs = coordEngine.getCoordJobs(filter, start, len); 323 List<CoordinatorJobBean> jsonJobs = jobs.getCoordJobs(); 324 json.put(JsonTags.COORDINATOR_JOBS, CoordinatorJobBean.toJSONArray(jsonJobs)); 325 json.put(JsonTags.COORD_JOB_TOTAL, jobs.getTotal()); 326 json.put(JsonTags.COORD_JOB_OFFSET, jobs.getStart()); 327 json.put(JsonTags.COORD_JOB_LEN, jobs.getLen()); 328 329 } 330 catch (CoordinatorEngineException ex) { 331 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex); 332 } 333 return json; 334 } 335 336 @SuppressWarnings("unchecked") 337 private JSONObject getBundleJobs(HttpServletRequest request) throws XServletException { 338 JSONObject json = new JSONObject(); 339 try { 340 String filter = request.getParameter(RestConstants.JOBS_FILTER_PARAM); 341 String startStr = request.getParameter(RestConstants.OFFSET_PARAM); 342 String lenStr = request.getParameter(RestConstants.LEN_PARAM); 343 int start = (startStr != null) ? Integer.parseInt(startStr) : 1; 344 start = (start < 1) ? 1 : start; 345 int len = (lenStr != null) ? Integer.parseInt(lenStr) : 50; 346 len = (len < 1) ? 50 : len; 347 348 BundleEngine bundleEngine = Services.get().get(BundleEngineService.class).getBundleEngine(getUser(request), 349 getAuthToken(request)); 350 BundleJobInfo jobs = bundleEngine.getBundleJobs(filter, start, len); 351 List<BundleJobBean> jsonJobs = jobs.getBundleJobs(); 352 353 json.put(JsonTags.BUNDLE_JOBS, BundleJobBean.toJSONArray(jsonJobs)); 354 json.put(JsonTags.BUNDLE_JOB_TOTAL, jobs.getTotal()); 355 json.put(JsonTags.BUNDLE_JOB_OFFSET, jobs.getStart()); 356 json.put(JsonTags.BUNDLE_JOB_LEN, jobs.getLen()); 357 358 } 359 catch (BundleEngineException ex) { 360 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex); 361 } 362 return json; 363 } 364 365 /** 366 * service implementation to submit a http job 367 */ 368 private JSONObject submitHttpJob(HttpServletRequest request, Configuration conf, String jobType) 369 throws XServletException { 370 JSONObject json = new JSONObject(); 371 372 try { 373 String user = conf.get(OozieClient.USER_NAME); 374 DagEngine dagEngine = Services.get().get(DagEngineService.class).getDagEngine(user, getAuthToken(request)); 375 String id = dagEngine.submitHttpJob(conf, jobType); 376 json.put(JsonTags.JOB_ID, id); 377 } 378 catch (DagEngineException ex) { 379 throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex); 380 } 381 382 return json; 383 } 384 }