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 org.apache.hadoop.conf.Configuration;
018    import org.apache.oozie.client.rest.RestConstants;
019    import org.apache.oozie.client.rest.JsonTags;
020    import org.apache.oozie.client.OozieClient;
021    import org.apache.oozie.util.XConfiguration;
022    import org.apache.oozie.service.Services;
023    import org.apache.oozie.service.DagEngineService;
024    import org.apache.oozie.service.WorkflowAppService;
025    import org.apache.oozie.DagEngine;
026    import org.apache.oozie.DagEngineException;
027    import org.apache.oozie.WorkflowsInfo;
028    import org.apache.oozie.WorkflowJobBean;
029    import org.apache.oozie.ErrorCode;
030    import org.json.simple.JSONObject;
031    
032    import javax.servlet.ServletException;
033    import javax.servlet.http.HttpServletRequest;
034    import javax.servlet.http.HttpServletResponse;
035    import java.io.IOException;
036    import java.util.Arrays;
037    import java.util.List;
038    
039    public class JobsServlet extends JsonRestServlet {
040        private static final String INSTRUMENTATION_NAME = "jobs";
041    
042        private static final JsonRestServlet.ResourceInfo RESOURCES_INFO[] = new JsonRestServlet.ResourceInfo[1];
043    
044        static {
045            RESOURCES_INFO[0] =
046                    new JsonRestServlet.ResourceInfo("", Arrays.asList("POST", "GET"), Arrays.asList(
047                            new JsonRestServlet.ParameterInfo(RestConstants.ACTION_PARAM, String.class, false, Arrays.asList("POST")),
048                            new JsonRestServlet.ParameterInfo(RestConstants.JOBS_FILTER_PARAM, String.class, false, Arrays.asList("GET")),
049                            new JsonRestServlet.ParameterInfo(RestConstants.JOBTYPE_PARAM, String.class, false, Arrays.asList("GET")),
050                            new JsonRestServlet.ParameterInfo(RestConstants.OFFSET_PARAM, String.class, false, Arrays.asList("GET")),
051                            new JsonRestServlet.ParameterInfo(RestConstants.LEN_PARAM, String.class, false, Arrays.asList("GET")),
052                            new JsonRestServlet.ParameterInfo(RestConstants.JOBS_EXTERNAL_ID_PARAM, String.class, false, Arrays.asList("GET"))));
053        }
054    
055        public JobsServlet() {
056            super(INSTRUMENTATION_NAME, RESOURCES_INFO);
057        }
058    
059        /**
060         * Create a job.
061         */
062        @SuppressWarnings("unchecked")
063        protected void doPost(HttpServletRequest request, HttpServletResponse response)
064                throws ServletException, IOException {
065    
066            validateContentType(request, RestConstants.XML_CONTENT_TYPE);
067    
068            request.setAttribute(AUDIT_OPERATION, request.getParameter(RestConstants.ACTION_PARAM));
069    
070            XConfiguration conf = new XConfiguration(request.getInputStream());
071    
072            stopCron();
073    
074            conf = conf.trim();
075            conf = conf.resolve();
076    
077            validateJobConfiguration(conf);
078    
079            JobServlet.checkAuthorizationForApp(getUser(request), conf);
080    
081            String action = request.getParameter(RestConstants.ACTION_PARAM);
082            if (action != null && !action.equals(RestConstants.JOB_ACTION_START)) {
083                throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0303, RestConstants.ACTION_PARAM,
084                                            action);
085            }
086            try {
087                boolean startJob = (action != null);
088                String user = conf.get(OozieClient.USER_NAME);
089                DagEngine dagEngine = Services.get().get(DagEngineService.class).getDagEngine(user, getAuthToken(request));
090                String id = dagEngine.submitJob(conf, startJob);
091                JSONObject json = new JSONObject();
092                json.put(JsonTags.JOB_ID, id);
093                startCron();
094                sendJsonResponse(response, HttpServletResponse.SC_CREATED, json);
095            }
096            catch (DagEngineException ex) {
097                throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
098            }
099        }
100    
101        static void validateJobConfiguration(Configuration conf) throws XServletException {
102            if (conf.get(OozieClient.USER_NAME) == null) {
103                throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0401,
104                                            OozieClient.USER_NAME);
105            }
106    
107            String localRealm = Services.get().getConf().get("local.realm");
108            
109            //if the job properties don't define JT/NN Kerberos principals, add default value
110            if (conf.get(WorkflowAppService.HADOOP_JT_KERBEROS_NAME) == null) {
111                conf.set(WorkflowAppService.HADOOP_JT_KERBEROS_NAME, "mapred/_HOST@" + localRealm);
112            }
113            if (conf.get(WorkflowAppService.HADOOP_NN_KERBEROS_NAME) == null) {
114                conf.set(WorkflowAppService.HADOOP_NN_KERBEROS_NAME, "hdfs/_HOST@" + localRealm);
115            }
116        }
117    
118        /**
119         * Return information about jobs.
120         */
121        @SuppressWarnings("unchecked")
122        public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
123            try {
124                String externalId = request.getParameter(RestConstants.JOBS_EXTERNAL_ID_PARAM);
125                if (externalId != null) {
126                    stopCron();
127                    DagEngine dagEngine = Services.get().get(DagEngineService.class)
128                            .getDagEngine(getUser(request), getAuthToken(request));
129                    String jobId = dagEngine.getJobIdForExternalId(externalId);
130                    JSONObject json = new JSONObject();
131                    json.put(JsonTags.JOB_ID, jobId);
132                    startCron();
133                    sendJsonResponse(response, HttpServletResponse.SC_OK, json);
134                }
135                else {
136                    String filter = request.getParameter(RestConstants.JOBS_FILTER_PARAM);
137                    String startStr = request.getParameter(RestConstants.OFFSET_PARAM);
138                    String lenStr = request.getParameter(RestConstants.LEN_PARAM);
139                    int start = (startStr != null) ? Integer.parseInt(startStr) : 1;
140                    start = (start < 1) ? 1 : start;
141                    int len = (lenStr != null) ? Integer.parseInt(lenStr) : 50;
142                    len = (len < 1) ? 50 : len;
143                    stopCron();
144                    DagEngine dagEngine = Services.get().get(DagEngineService.class)
145                            .getDagEngine(getUser(request), getAuthToken(request));
146                    WorkflowsInfo jobs = dagEngine.getJobs(filter, start, len);
147                    List<WorkflowJobBean> jsonWorkflows = jobs.getWorkflows();
148                    startCron();
149                    JSONObject json = new JSONObject();
150                    json.put(JsonTags.WORKFLOWS_JOBS, WorkflowJobBean.toJSONArray(jsonWorkflows));
151                    json.put(JsonTags.WORKFLOWS_TOTAL, jobs.getTotal());
152                    json.put(JsonTags.WORKFLOWS_OFFSET, jobs.getStart());
153                    json.put(JsonTags.WORKFLOWS_LEN, jobs.getLen());
154                    sendJsonResponse(response, HttpServletResponse.SC_OK, json);
155                }
156            }
157            catch (DagEngineException ex) {
158                throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ex);
159            }
160        }
161    
162    }