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;
016
017 import java.io.IOException;
018 import java.io.Writer;
019 import java.util.ArrayList;
020 import java.util.Date;
021 import java.util.HashMap;
022 import java.util.HashSet;
023 import java.util.List;
024 import java.util.Map;
025 import java.util.Set;
026 import java.util.StringTokenizer;
027
028 import org.apache.hadoop.conf.Configuration;
029 import org.apache.oozie.client.CoordinatorJob;
030 import org.apache.oozie.client.OozieClient;
031 import org.apache.oozie.client.WorkflowJob;
032 import org.apache.oozie.command.CommandException;
033 import org.apache.oozie.command.coord.CoordActionInfoCommand;
034 import org.apache.oozie.command.coord.CoordJobCommand;
035 import org.apache.oozie.command.coord.CoordJobsCommand;
036 import org.apache.oozie.command.coord.CoordKillCommand;
037 import org.apache.oozie.command.coord.CoordRerunCommand;
038 import org.apache.oozie.command.coord.CoordChangeCommand;
039 import org.apache.oozie.command.coord.CoordResumeCommand;
040 import org.apache.oozie.command.coord.CoordSubmitCommand;
041 import org.apache.oozie.command.coord.CoordSuspendCommand;
042 import org.apache.oozie.service.DagXLogInfoService;
043 import org.apache.oozie.service.Services;
044 import org.apache.oozie.service.XLogService;
045 import org.apache.oozie.util.ParamChecker;
046 import org.apache.oozie.util.XLog;
047 import org.apache.oozie.util.XLogStreamer;
048
049 public class CoordinatorEngine extends BaseEngine {
050
051 /**
052 * Create a system Coordinator engine, with no user and no group.
053 */
054 public CoordinatorEngine() {
055 }
056
057 /**
058 * Create a Coordinator engine to perform operations on behave of a user.
059 *
060 * @param user user name.
061 * @param authToken the authentication token.
062 */
063 public CoordinatorEngine(String user, String authToken) {
064 this.user = ParamChecker.notEmpty(user, "user");
065 this.authToken = ParamChecker.notEmpty(authToken, "authToken");
066 }
067
068 /*
069 * (non-Javadoc)
070 *
071 * @see org.apache.oozie.BaseEngine#getDefinition(java.lang.String)
072 */
073 @Override
074 public String getDefinition(String jobId) throws BaseEngineException {
075 CoordinatorJobBean job = getCoordJobWithNoActionInfo(jobId);
076 return job.getOrigJobXml();
077 }
078
079 /**
080 * @param jobId
081 * @return CoordinatorJobBean
082 * @throws BaseEngineException
083 */
084 private CoordinatorJobBean getCoordJobWithNoActionInfo(String jobId) throws BaseEngineException {
085 try {
086 return new CoordJobCommand(jobId, false).call();
087 }
088 catch (CommandException ex) {
089 throw new BaseEngineException(ex);
090 }
091 }
092
093 /**
094 * @param actionId
095 * @return CoordinatorActionBean
096 * @throws BaseEngineException
097 */
098 public CoordinatorActionBean getCoordAction(String actionId) throws BaseEngineException {
099 try {
100 return new CoordActionInfoCommand(actionId).call();
101 }
102 catch (CommandException ex) {
103 throw new BaseEngineException(ex);
104 }
105 }
106
107 /*
108 * (non-Javadoc)
109 *
110 * @see org.apache.oozie.BaseEngine#getCoordJob(java.lang.String)
111 */
112 @Override
113 public CoordinatorJobBean getCoordJob(String jobId) throws BaseEngineException {
114 try {
115 return new CoordJobCommand(jobId).call();
116 }
117 catch (CommandException ex) {
118 throw new BaseEngineException(ex);
119 }
120 }
121
122 /*
123 * (non-Javadoc)
124 *
125 * @see org.apache.oozie.BaseEngine#getCoordJob(java.lang.String, int, int)
126 */
127 @Override
128 public CoordinatorJobBean getCoordJob(String jobId, int start, int length) throws BaseEngineException {
129 try {
130 return new CoordJobCommand(jobId, start, length).call();
131 }
132 catch (CommandException ex) {
133 throw new BaseEngineException(ex);
134 }
135 }
136
137 /*
138 * (non-Javadoc)
139 *
140 * @see org.apache.oozie.BaseEngine#getJobIdForExternalId(java.lang.String)
141 */
142 @Override
143 public String getJobIdForExternalId(String externalId) throws CoordinatorEngineException {
144 return null;
145 }
146
147 /*
148 * (non-Javadoc)
149 *
150 * @see org.apache.oozie.BaseEngine#kill(java.lang.String)
151 */
152 @Override
153 public void kill(String jobId) throws CoordinatorEngineException {
154 try {
155 new CoordKillCommand(jobId).call();
156 XLog.getLog(getClass()).info("User " + user + " killed the Coordinator job " + jobId);
157 }
158 catch (CommandException e) {
159 throw new CoordinatorEngineException(e);
160 }
161 }
162
163 /* (non-Javadoc)
164 * @see org.apache.oozie.BaseEngine#change(java.lang.String, java.lang.String)
165 */
166 @Override
167 public void change(String jobId, String changeValue) throws CoordinatorEngineException {
168 try {
169 new CoordChangeCommand(jobId, changeValue).call();
170 XLog.getLog(getClass()).info("User " + user + " changed the Coordinator job " + jobId + " to " + changeValue);
171 }
172 catch (CommandException e) {
173 throw new CoordinatorEngineException(e);
174 }
175 }
176
177 @Override
178 @Deprecated
179 public void reRun(String jobId, Configuration conf) throws BaseEngineException {
180 throw new BaseEngineException(new XException(ErrorCode.E0301));
181 }
182
183 /**
184 * Rerun coordinator actions for given rerunType
185 *
186 * @param jobId
187 * @param rerunType
188 * @param scope
189 * @param refresh
190 * @param noCleanup
191 * @throws BaseEngineException
192 */
193 public CoordinatorActionInfo reRun(String jobId, String rerunType, String scope, boolean refresh, boolean noCleanup)
194 throws BaseEngineException {
195 try {
196 return new CoordRerunCommand(jobId, rerunType, scope, refresh, noCleanup).call();
197 }
198 catch (CommandException ex) {
199 throw new BaseEngineException(ex);
200 }
201 }
202
203 /*
204 * (non-Javadoc)
205 *
206 * @see org.apache.oozie.BaseEngine#resume(java.lang.String)
207 */
208 @Override
209 public void resume(String jobId) throws CoordinatorEngineException {
210 try {
211 new CoordResumeCommand(jobId).call();
212 }
213 catch (CommandException e) {
214 throw new CoordinatorEngineException(e);
215 }
216 }
217
218 @Override
219 @Deprecated
220 public void start(String jobId) throws BaseEngineException {
221 throw new BaseEngineException(new XException(ErrorCode.E0301));
222 }
223
224 /*
225 * (non-Javadoc)
226 *
227 * @see org.apache.oozie.BaseEngine#streamLog(java.lang.String,
228 * java.io.Writer)
229 */
230 @Override
231 public void streamLog(String jobId, Writer writer) throws IOException, BaseEngineException {
232 XLogStreamer.Filter filter = new XLogStreamer.Filter();
233 filter.setParameter(DagXLogInfoService.JOB, jobId);
234
235 CoordinatorJobBean job = getCoordJobWithNoActionInfo(jobId);
236 Services.get().get(XLogService.class).streamLog(filter, job.getCreatedTime(), new Date(), writer);
237
238 }
239
240 /*
241 * (non-Javadoc)
242 *
243 * @see
244 * org.apache.oozie.BaseEngine#submitJob(org.apache.hadoop.conf.Configuration
245 * , boolean)
246 */
247 @Override
248 public String submitJob(Configuration conf, boolean startJob) throws CoordinatorEngineException {
249 CoordSubmitCommand submit = new CoordSubmitCommand(conf, getAuthToken());
250 try {
251 String jobId = submit.call();
252 return jobId;
253 }
254 catch (CommandException ex) {
255 throw new CoordinatorEngineException(ex);
256 }
257 }
258
259 /*
260 * (non-Javadoc)
261 *
262 * @see
263 * org.apache.oozie.BaseEngine#dryrunSubmit(org.apache.hadoop.conf.Configuration
264 * , boolean)
265 */
266 @Override
267 public String dryrunSubmit(Configuration conf, boolean startJob) throws CoordinatorEngineException {
268 CoordSubmitCommand submit = new CoordSubmitCommand(true, conf, getAuthToken());
269 try {
270 String jobId = submit.call();
271 return jobId;
272 }
273 catch (CommandException ex) {
274 throw new CoordinatorEngineException(ex);
275 }
276 }
277
278 /*
279 * (non-Javadoc)
280 *
281 * @see org.apache.oozie.BaseEngine#suspend(java.lang.String)
282 */
283 @Override
284 public void suspend(String jobId) throws CoordinatorEngineException {
285 try {
286 new CoordSuspendCommand(jobId).call();
287 }
288 catch (CommandException e) {
289 throw new CoordinatorEngineException(e);
290 }
291
292 }
293
294 /*
295 * (non-Javadoc)
296 *
297 * @see org.apache.oozie.BaseEngine#getJob(java.lang.String)
298 */
299 @Override
300 public WorkflowJob getJob(String jobId) throws BaseEngineException {
301 throw new BaseEngineException(new XException(ErrorCode.E0301));
302 }
303
304 /*
305 * (non-Javadoc)
306 *
307 * @see org.apache.oozie.BaseEngine#getJob(java.lang.String, int, int)
308 */
309 @Override
310 public WorkflowJob getJob(String jobId, int start, int length) throws BaseEngineException {
311 throw new BaseEngineException(new XException(ErrorCode.E0301));
312 }
313
314 private static final Set<String> FILTER_NAMES = new HashSet<String>();
315
316 static {
317 FILTER_NAMES.add(OozieClient.FILTER_USER);
318 FILTER_NAMES.add(OozieClient.FILTER_NAME);
319 FILTER_NAMES.add(OozieClient.FILTER_GROUP);
320 FILTER_NAMES.add(OozieClient.FILTER_STATUS);
321 }
322
323 /**
324 * @param filterStr
325 * @param start
326 * @param len
327 * @return CoordinatorJobInfo
328 * @throws CoordinatorEngineException
329 */
330 public CoordinatorJobInfo getCoordJobs(String filterStr, int start, int len) throws CoordinatorEngineException {
331 Map<String, List<String>> filter = parseFilter(filterStr);
332
333 try {
334 return new CoordJobsCommand(filter, start, len).call();
335 }
336 catch (CommandException ex) {
337 throw new CoordinatorEngineException(ex);
338 }
339 }
340
341 /**
342 * @param filter
343 * @return Map<String, List<String>>
344 * @throws CoordinatorEngineException
345 */
346 private Map<String, List<String>> parseFilter(String filter) throws CoordinatorEngineException {
347 Map<String, List<String>> map = new HashMap<String, List<String>>();
348 if (filter != null) {
349 StringTokenizer st = new StringTokenizer(filter, ";");
350 while (st.hasMoreTokens()) {
351 String token = st.nextToken();
352 if (token.contains("=")) {
353 String[] pair = token.split("=");
354 if (pair.length != 2) {
355 throw new CoordinatorEngineException(ErrorCode.E0420, filter,
356 "elements must be name=value pairs");
357 }
358 if (!FILTER_NAMES.contains(pair[0])) {
359 throw new CoordinatorEngineException(ErrorCode.E0420, filter, XLog.format("invalid name [{0}]",
360 pair[0]));
361 }
362 if (pair[0].equals("status")) {
363 try {
364 CoordinatorJob.Status.valueOf(pair[1]);
365 }
366 catch (IllegalArgumentException ex) {
367 throw new CoordinatorEngineException(ErrorCode.E0420, filter, XLog.format(
368 "invalid status [{0}]", pair[1]));
369 }
370 }
371 List<String> list = map.get(pair[0]);
372 if (list == null) {
373 list = new ArrayList<String>();
374 map.put(pair[0], list);
375 }
376 list.add(pair[1]);
377 }
378 else {
379 throw new CoordinatorEngineException(ErrorCode.E0420, filter, "elements must be name=value pairs");
380 }
381 }
382 }
383 return map;
384 }
385 }