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