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    }