This project has retired. For details please refer to its
Attic page.
001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 package org.apache.oozie.cli;
019
020 import java.io.File;
021 import java.io.FileInputStream;
022 import java.io.FileReader;
023 import java.io.IOException;
024 import java.io.InputStream;
025 import java.io.PrintStream;
026 import java.text.SimpleDateFormat;
027 import java.util.ArrayList;
028 import java.util.Date;
029 import java.util.List;
030 import java.util.Locale;
031 import java.util.Map;
032 import java.util.Properties;
033 import java.util.TimeZone;
034 import java.util.concurrent.Callable;
035 import java.util.regex.Matcher;
036 import java.util.regex.Pattern;
037
038 import javax.xml.XMLConstants;
039 import javax.xml.parsers.DocumentBuilder;
040 import javax.xml.parsers.DocumentBuilderFactory;
041 import javax.xml.parsers.ParserConfigurationException;
042 import javax.xml.transform.stream.StreamSource;
043 import javax.xml.validation.Schema;
044 import javax.xml.validation.SchemaFactory;
045 import javax.xml.validation.Validator;
046
047 import org.apache.commons.cli.CommandLine;
048 import org.apache.commons.cli.Option;
049 import org.apache.commons.cli.OptionBuilder;
050 import org.apache.commons.cli.OptionGroup;
051 import org.apache.commons.cli.Options;
052 import org.apache.commons.cli.ParseException;
053 import org.apache.oozie.BuildInfo;
054 import org.apache.oozie.client.AuthOozieClient;
055 import org.apache.oozie.client.BulkResponse;
056 import org.apache.oozie.client.BundleJob;
057 import org.apache.oozie.client.CoordinatorAction;
058 import org.apache.oozie.client.CoordinatorJob;
059 import org.apache.oozie.client.OozieClient;
060 import org.apache.oozie.client.OozieClient.SYSTEM_MODE;
061 import org.apache.oozie.client.OozieClientException;
062 import org.apache.oozie.client.WorkflowAction;
063 import org.apache.oozie.client.WorkflowJob;
064 import org.apache.oozie.client.XOozieClient;
065 import org.apache.oozie.client.rest.RestConstants;
066 import org.w3c.dom.DOMException;
067 import org.w3c.dom.Document;
068 import org.w3c.dom.Element;
069 import org.w3c.dom.Node;
070 import org.w3c.dom.NodeList;
071 import org.w3c.dom.Text;
072 import org.xml.sax.SAXException;
073
074 import com.google.common.annotations.VisibleForTesting;
075
076 /**
077 * Oozie command line utility.
078 */
079 public class OozieCLI {
080 public static final String ENV_OOZIE_URL = "OOZIE_URL";
081 public static final String ENV_OOZIE_DEBUG = "OOZIE_DEBUG";
082 public static final String ENV_OOZIE_TIME_ZONE = "OOZIE_TIMEZONE";
083 public static final String WS_HEADER_PREFIX = "header:";
084
085 public static final String HELP_CMD = "help";
086 public static final String VERSION_CMD = "version";
087 public static final String JOB_CMD = "job";
088 public static final String JOBS_CMD = "jobs";
089 public static final String ADMIN_CMD = "admin";
090 public static final String VALIDATE_CMD = "validate";
091 public static final String SLA_CMD = "sla";
092 public static final String PIG_CMD = "pig";
093 public static final String HIVE_CMD = "hive";
094 public static final String MR_CMD = "mapreduce";
095 public static final String INFO_CMD = "info";
096
097 public static final String OOZIE_OPTION = "oozie";
098 public static final String CONFIG_OPTION = "config";
099 public static final String SUBMIT_OPTION = "submit";
100 public static final String OFFSET_OPTION = "offset";
101 public static final String START_OPTION = "start";
102 public static final String RUN_OPTION = "run";
103 public static final String DRYRUN_OPTION = "dryrun";
104 public static final String SUSPEND_OPTION = "suspend";
105 public static final String RESUME_OPTION = "resume";
106 public static final String KILL_OPTION = "kill";
107 public static final String CHANGE_OPTION = "change";
108 public static final String CHANGE_VALUE_OPTION = "value";
109 public static final String RERUN_OPTION = "rerun";
110 public static final String INFO_OPTION = "info";
111 public static final String LOG_OPTION = "log";
112 public static final String ACTION_OPTION = "action";
113 public static final String DEFINITION_OPTION = "definition";
114 public static final String CONFIG_CONTENT_OPTION = "configcontent";
115
116 public static final String DO_AS_OPTION = "doas";
117
118 public static final String LEN_OPTION = "len";
119 public static final String FILTER_OPTION = "filter";
120 public static final String JOBTYPE_OPTION = "jobtype";
121 public static final String SYSTEM_MODE_OPTION = "systemmode";
122 public static final String VERSION_OPTION = "version";
123 public static final String STATUS_OPTION = "status";
124 public static final String LOCAL_TIME_OPTION = "localtime";
125 public static final String TIME_ZONE_OPTION = "timezone";
126 public static final String QUEUE_DUMP_OPTION = "queuedump";
127 public static final String RERUN_COORD_OPTION = "coordinator";
128 public static final String DATE_OPTION = "date";
129 public static final String RERUN_REFRESH_OPTION = "refresh";
130 public static final String RERUN_NOCLEANUP_OPTION = "nocleanup";
131
132 public static final String AUTH_OPTION = "auth";
133
134 public static final String VERBOSE_OPTION = "verbose";
135 public static final String VERBOSE_DELIMITER = "\t";
136 public static final String DEBUG_OPTION = "debug";
137
138 public static final String SCRIPTFILE_OPTION = "file";
139
140 public static final String INFO_TIME_ZONES_OPTION = "timezones";
141
142 public static final String BULK_OPTION = "bulk";
143
144 private static final String[] OOZIE_HELP = {
145 "the env variable '" + ENV_OOZIE_URL + "' is used as default value for the '-" + OOZIE_OPTION + "' option",
146 "the env variable '" + ENV_OOZIE_TIME_ZONE + "' is used as default value for the '-" + TIME_ZONE_OPTION + "' option",
147 "custom headers for Oozie web services can be specified using '-D" + WS_HEADER_PREFIX + "NAME=VALUE'" };
148
149 private static final String RULER;
150 private static final int LINE_WIDTH = 132;
151
152 private boolean used;
153
154 private static final String INSTANCE_SEPARATOR = "#";
155
156 private static final String MAPRED_MAPPER = "mapred.mapper.class";
157 private static final String MAPRED_MAPPER_2 = "mapreduce.map.class";
158 private static final String MAPRED_REDUCER = "mapred.reducer.class";
159 private static final String MAPRED_REDUCER_2 = "mapreduce.reduce.class";
160 private static final String MAPRED_INPUT = "mapred.input.dir";
161 private static final String MAPRED_OUTPUT = "mapred.output.dir";
162
163 private static final Pattern GMT_OFFSET_SHORTEN_PATTERN = Pattern.compile("(.* )GMT((?:-|\\+)\\d{2}:\\d{2})");
164
165 static {
166 StringBuilder sb = new StringBuilder();
167 for (int i = 0; i < LINE_WIDTH; i++) {
168 sb.append("-");
169 }
170 RULER = sb.toString();
171 }
172
173 /**
174 * Entry point for the Oozie CLI when invoked from the command line.
175 * <p/>
176 * Upon completion this method exits the JVM with '0' (success) or '-1' (failure).
177 *
178 * @param args options and arguments for the Oozie CLI.
179 */
180 public static void main(String[] args) {
181 if (!System.getProperties().containsKey(AuthOozieClient.USE_AUTH_TOKEN_CACHE_SYS_PROP)) {
182 System.setProperty(AuthOozieClient.USE_AUTH_TOKEN_CACHE_SYS_PROP, "true");
183 }
184 System.exit(new OozieCLI().run(args));
185 }
186
187 /**
188 * Create an Oozie CLI instance.
189 */
190 public OozieCLI() {
191 used = false;
192 }
193
194 /**
195 * Return Oozie CLI top help lines.
196 *
197 * @return help lines.
198 */
199 protected String[] getCLIHelp() {
200 return OOZIE_HELP;
201 }
202
203 /**
204 * Add authentication specific options to oozie cli
205 *
206 * @param options the collection of options to add auth options
207 */
208 protected void addAuthOptions(Options options) {
209 Option auth = new Option(AUTH_OPTION, true, "select authentication type [SIMPLE|KERBEROS]");
210 options.addOption(auth);
211 }
212
213 /**
214 * Create option for command line option 'admin'
215 * @return admin options
216 */
217 protected Options createAdminOptions() {
218 Option oozie = new Option(OOZIE_OPTION, true, "Oozie URL");
219 Option system_mode = new Option(SYSTEM_MODE_OPTION, true,
220 "Supported in Oozie-2.0 or later versions ONLY. Change oozie system mode [NORMAL|NOWEBSERVICE|SAFEMODE]");
221 Option status = new Option(STATUS_OPTION, false, "show the current system status");
222 Option version = new Option(VERSION_OPTION, false, "show Oozie server build version");
223 Option queuedump = new Option(QUEUE_DUMP_OPTION, false, "show Oozie server queue elements");
224 Option doAs = new Option(DO_AS_OPTION, true, "doAs user, impersonates as the specified user");
225 Options adminOptions = new Options();
226 adminOptions.addOption(oozie);
227 adminOptions.addOption(doAs);
228 OptionGroup group = new OptionGroup();
229 group.addOption(system_mode);
230 group.addOption(status);
231 group.addOption(version);
232 group.addOption(queuedump);
233 adminOptions.addOptionGroup(group);
234 addAuthOptions(adminOptions);
235 return adminOptions;
236 }
237
238 /**
239 * Create option for command line option 'job'
240 * @return job options
241 */
242 protected Options createJobOptions() {
243 Option oozie = new Option(OOZIE_OPTION, true, "Oozie URL");
244 Option config = new Option(CONFIG_OPTION, true, "job configuration file '.xml' or '.properties'");
245 Option submit = new Option(SUBMIT_OPTION, false, "submit a job");
246 Option run = new Option(RUN_OPTION, false, "run a job");
247 Option debug = new Option(DEBUG_OPTION, false, "Use debug mode to see debugging statements on stdout");
248 Option rerun = new Option(RERUN_OPTION, true,
249 "rerun a job (coordinator requires -action or -date, bundle requires -coordinator or -date)");
250 Option dryrun = new Option(DRYRUN_OPTION, false, "Dryrun a workflow (since 3.3.2) or coordinator (since 2.0) job without"
251 + " actually executing it");
252 Option start = new Option(START_OPTION, true, "start a job");
253 Option suspend = new Option(SUSPEND_OPTION, true, "suspend a job");
254 Option resume = new Option(RESUME_OPTION, true, "resume a job");
255 Option kill = new Option(KILL_OPTION, true, "kill a job");
256 Option change = new Option(CHANGE_OPTION, true, "change a coordinator job");
257 Option changeValue = new Option(CHANGE_VALUE_OPTION, true,
258 "new endtime/concurrency/pausetime value for changing a coordinator job");
259 Option info = new Option(INFO_OPTION, true, "info of a job");
260 Option offset = new Option(OFFSET_OPTION, true, "job info offset of actions (default '1', requires -info)");
261 Option len = new Option(LEN_OPTION, true, "number of actions (default TOTAL ACTIONS, requires -info)");
262 Option filter = new Option(FILTER_OPTION, true,
263 "status=<S1>[;status=<S2>]* (All Coordinator actions satisfying any one of the status filters will be retreived. Currently, only supported for Coordinator job)");
264 Option localtime = new Option(LOCAL_TIME_OPTION, false, "use local time (same as passing your time zone to -" +
265 TIME_ZONE_OPTION + "). Overrides -" + TIME_ZONE_OPTION + " option");
266 Option timezone = new Option(TIME_ZONE_OPTION, true,
267 "use time zone with the specified ID (default GMT).\nSee 'oozie info -timezones' for a list");
268 Option log = new Option(LOG_OPTION, true, "job log");
269 Option definition = new Option(DEFINITION_OPTION, true, "job definition");
270 Option config_content = new Option(CONFIG_CONTENT_OPTION, true, "job configuration");
271 Option verbose = new Option(VERBOSE_OPTION, false, "verbose mode");
272 Option action = new Option(ACTION_OPTION, true,
273 "coordinator rerun on action ids (requires -rerun); coordinator log retrieval on action ids (requires -log)");
274 Option date = new Option(DATE_OPTION, true,
275 "coordinator/bundle rerun on action dates (requires -rerun); coordinator log retrieval on action dates (requires -log)");
276 Option rerun_coord = new Option(RERUN_COORD_OPTION, true, "bundle rerun on coordinator names (requires -rerun)");
277 Option rerun_refresh = new Option(RERUN_REFRESH_OPTION, false,
278 "re-materialize the coordinator rerun actions (requires -rerun)");
279 Option rerun_nocleanup = new Option(RERUN_NOCLEANUP_OPTION, false,
280 "do not clean up output-events of the coordiantor rerun actions (requires -rerun)");
281 Option property = OptionBuilder.withArgName("property=value").hasArgs(2).withValueSeparator().withDescription(
282 "set/override value for given property").create("D");
283
284 Option doAs = new Option(DO_AS_OPTION, true, "doAs user, impersonates as the specified user");
285
286 OptionGroup actions = new OptionGroup();
287 actions.addOption(submit);
288 actions.addOption(start);
289 actions.addOption(run);
290 actions.addOption(dryrun);
291 actions.addOption(suspend);
292 actions.addOption(resume);
293 actions.addOption(kill);
294 actions.addOption(change);
295 actions.addOption(info);
296 actions.addOption(rerun);
297 actions.addOption(log);
298 actions.addOption(definition);
299 actions.addOption(config_content);
300 actions.setRequired(true);
301 Options jobOptions = new Options();
302 jobOptions.addOption(oozie);
303 jobOptions.addOption(doAs);
304 jobOptions.addOption(config);
305 jobOptions.addOption(property);
306 jobOptions.addOption(changeValue);
307 jobOptions.addOption(localtime);
308 jobOptions.addOption(timezone);
309 jobOptions.addOption(verbose);
310 jobOptions.addOption(debug);
311 jobOptions.addOption(offset);
312 jobOptions.addOption(len);
313 jobOptions.addOption(filter);
314 jobOptions.addOption(action);
315 jobOptions.addOption(date);
316 jobOptions.addOption(rerun_coord);
317 jobOptions.addOption(rerun_refresh);
318 jobOptions.addOption(rerun_nocleanup);
319 jobOptions.addOptionGroup(actions);
320 addAuthOptions(jobOptions);
321 return jobOptions;
322 }
323
324 /**
325 * Create option for command line option 'jobs'
326 * @return jobs options
327 */
328 protected Options createJobsOptions() {
329 Option oozie = new Option(OOZIE_OPTION, true, "Oozie URL");
330 Option start = new Option(OFFSET_OPTION, true, "jobs offset (default '1')");
331 Option jobtype = new Option(JOBTYPE_OPTION, true,
332 "job type ('Supported in Oozie-2.0 or later versions ONLY - 'coordinator' or 'bundle' or 'wf'(default))");
333 Option len = new Option(LEN_OPTION, true, "number of jobs (default '100')");
334 Option filter = new Option(FILTER_OPTION, true, "user=<U>\\;name=<N>\\;group=<G>\\;status=<S>\\;frequency=<F>\\;unit=<M> " +
335 "(Valid unit values are 'months', 'days', 'hours' or 'minutes'.)");
336 Option localtime = new Option(LOCAL_TIME_OPTION, false, "use local time (same as passing your time zone to -" +
337 TIME_ZONE_OPTION + "). Overrides -" + TIME_ZONE_OPTION + " option");
338 Option timezone = new Option(TIME_ZONE_OPTION, true,
339 "use time zone with the specified ID (default GMT).\nSee 'oozie info -timezones' for a list");
340 Option verbose = new Option(VERBOSE_OPTION, false, "verbose mode");
341 Option doAs = new Option(DO_AS_OPTION, true, "doAs user, impersonates as the specified user");
342 Option bulkMonitor = new Option(BULK_OPTION, true, "key-value pairs to filter bulk jobs response. e.g. bundle=<B>\\;" +
343 "coordinators=<C>\\;actionstatus=<S>\\;startcreatedtime=<SC>\\;endcreatedtime=<EC>\\;" +
344 "startscheduledtime=<SS>\\;endscheduledtime=<ES>\\; coordinators and actionstatus can be multiple comma separated values" +
345 "bundle and coordinators are 'names' of those jobs. Bundle name is mandatory, other params are optional");
346 start.setType(Integer.class);
347 len.setType(Integer.class);
348 Options jobsOptions = new Options();
349 jobsOptions.addOption(oozie);
350 jobsOptions.addOption(doAs);
351 jobsOptions.addOption(localtime);
352 jobsOptions.addOption(timezone);
353 jobsOptions.addOption(start);
354 jobsOptions.addOption(len);
355 jobsOptions.addOption(oozie);
356 jobsOptions.addOption(filter);
357 jobsOptions.addOption(jobtype);
358 jobsOptions.addOption(verbose);
359 jobsOptions.addOption(bulkMonitor);
360 addAuthOptions(jobsOptions);
361 return jobsOptions;
362 }
363
364 /**
365 * Create option for command line option 'sla'
366 *
367 * @return sla options
368 */
369 protected Options createSlaOptions() {
370 Option oozie = new Option(OOZIE_OPTION, true, "Oozie URL");
371 Option start = new Option(OFFSET_OPTION, true, "start offset (default '0')");
372 Option len = new Option(LEN_OPTION, true, "number of results (default '100', max '1000')");
373 Option filter = new Option(FILTER_OPTION, true, "filter of SLA events. e.g., jobid=<J>\\;appname=<A>");
374 start.setType(Integer.class);
375 len.setType(Integer.class);
376 Options slaOptions = new Options();
377 slaOptions.addOption(start);
378 slaOptions.addOption(len);
379 slaOptions.addOption(filter);
380 slaOptions.addOption(oozie);
381 addAuthOptions(slaOptions);
382 return slaOptions;
383 }
384
385 /**
386 * Create option for command line option 'pig' or 'hive'
387 * @return pig or hive options
388 */
389 @SuppressWarnings("static-access")
390 protected Options createScriptLanguageOptions(String jobType) {
391 Option oozie = new Option(OOZIE_OPTION, true, "Oozie URL");
392 Option config = new Option(CONFIG_OPTION, true, "job configuration file '.properties'");
393 Option file = new Option(SCRIPTFILE_OPTION, true, jobType + " script");
394 Option property = OptionBuilder.withArgName("property=value").hasArgs(2).withValueSeparator().withDescription(
395 "set/override value for given property").create("D");
396 Option params = OptionBuilder.withArgName("property=value").hasArgs(2).withValueSeparator().withDescription(
397 "set parameters for script").create("P");
398 Option doAs = new Option(DO_AS_OPTION, true, "doAs user, impersonates as the specified user");
399 Options Options = new Options();
400 Options.addOption(oozie);
401 Options.addOption(doAs);
402 Options.addOption(config);
403 Options.addOption(property);
404 Options.addOption(params);
405 Options.addOption(file);
406 addAuthOptions(Options);
407 return Options;
408 }
409
410 /**
411 * Create option for command line option 'info'
412 * @return info options
413 */
414 protected Options createInfoOptions() {
415 Option timezones = new Option(INFO_TIME_ZONES_OPTION, false, "display a list of available time zones");
416 Options infoOptions = new Options();
417 infoOptions.addOption(timezones);
418 return infoOptions;
419 }
420
421 /**
422 * Create option for command line option 'mapreduce'
423 * @return mapreduce options
424 */
425 @SuppressWarnings("static-access")
426 protected Options createMROptions() {
427 Option oozie = new Option(OOZIE_OPTION, true, "Oozie URL");
428 Option config = new Option(CONFIG_OPTION, true, "job configuration file '.properties'");
429 Option property = OptionBuilder.withArgName("property=value").hasArgs(2).withValueSeparator().withDescription(
430 "set/override value for given property").create("D");
431 Option doAs = new Option(DO_AS_OPTION, true, "doAs user, impersonates as the specified user");
432 Options mrOptions = new Options();
433 mrOptions.addOption(oozie);
434 mrOptions.addOption(doAs);
435 mrOptions.addOption(config);
436 mrOptions.addOption(property);
437 addAuthOptions(mrOptions);
438 return mrOptions;
439 }
440
441 /**
442 * Run a CLI programmatically.
443 * <p/>
444 * It does not exit the JVM.
445 * <p/>
446 * A CLI instance can be used only once.
447 *
448 * @param args options and arguments for the Oozie CLI.
449 * @return '0' (success), '-1' (failure).
450 */
451 public synchronized int run(String[] args) {
452 if (used) {
453 throw new IllegalStateException("CLI instance already used");
454 }
455 used = true;
456
457 final CLIParser parser = new CLIParser(OOZIE_OPTION, getCLIHelp());
458 parser.addCommand(HELP_CMD, "", "display usage for all commands or specified command", new Options(), false);
459 parser.addCommand(VERSION_CMD, "", "show client version", new Options(), false);
460 parser.addCommand(JOB_CMD, "", "job operations", createJobOptions(), false);
461 parser.addCommand(JOBS_CMD, "", "jobs status", createJobsOptions(), false);
462 parser.addCommand(ADMIN_CMD, "", "admin operations", createAdminOptions(), false);
463 parser.addCommand(VALIDATE_CMD, "", "validate a workflow XML file", new Options(), true);
464 parser.addCommand(SLA_CMD, "", "sla operations (Deprecated with Oozie 4.0)", createSlaOptions(), false);
465 parser.addCommand(PIG_CMD, "-X ", "submit a pig job, everything after '-X' are pass-through parameters to pig, any '-D' "
466 + "arguments after '-X' are put in <configuration>", createScriptLanguageOptions(PIG_CMD), true);
467 parser.addCommand(HIVE_CMD, "-X ", "submit a hive job, everything after '-X' are pass-through parameters to hive, any '-D' "
468 + "arguments after '-X' are put in <configuration>", createScriptLanguageOptions(HIVE_CMD), true);
469 parser.addCommand(INFO_CMD, "", "get more detailed info about specific topics", createInfoOptions(), false);
470 parser.addCommand(MR_CMD, "", "submit a mapreduce job", createMROptions(), false);
471
472 try {
473 final CLIParser.Command command = parser.parse(args);
474
475 String doAsUser = command.getCommandLine().getOptionValue(DO_AS_OPTION);
476
477 if (doAsUser != null) {
478 OozieClient.doAs(doAsUser, new Callable<Void>() {
479 @Override
480 public Void call() throws Exception {
481 processCommand(parser, command);
482 return null;
483 }
484 });
485 }
486 else {
487 processCommand(parser, command);
488 }
489
490 return 0;
491 }
492 catch (OozieCLIException ex) {
493 System.err.println("Error: " + ex.getMessage());
494 return -1;
495 }
496 catch (ParseException ex) {
497 System.err.println("Invalid sub-command: " + ex.getMessage());
498 System.err.println();
499 System.err.println(parser.shortHelp());
500 return -1;
501 }
502 catch (Exception ex) {
503 ex.printStackTrace();
504 System.err.println(ex.getMessage());
505 return -1;
506 }
507 }
508
509 private void processCommand(CLIParser parser, CLIParser.Command command) throws Exception {
510 if (command.getName().equals(HELP_CMD)) {
511 parser.showHelp(command.getCommandLine());
512 }
513 else if (command.getName().equals(JOB_CMD)) {
514 jobCommand(command.getCommandLine());
515 }
516 else if (command.getName().equals(JOBS_CMD)) {
517 jobsCommand(command.getCommandLine());
518 }
519 else if (command.getName().equals(ADMIN_CMD)) {
520 adminCommand(command.getCommandLine());
521 }
522 else if (command.getName().equals(VERSION_CMD)) {
523 versionCommand();
524 }
525 else if (command.getName().equals(VALIDATE_CMD)) {
526 validateCommand(command.getCommandLine());
527 }
528 else if (command.getName().equals(SLA_CMD)) {
529 slaCommand(command.getCommandLine());
530 }
531 else if (command.getName().equals(PIG_CMD)) {
532 scriptLanguageCommand(command.getCommandLine(), PIG_CMD);
533 }
534 else if (command.getName().equals(HIVE_CMD)) {
535 scriptLanguageCommand(command.getCommandLine(), HIVE_CMD);
536 }
537 else if (command.getName().equals(INFO_CMD)) {
538 infoCommand(command.getCommandLine());
539 }
540 else if (command.getName().equals(MR_CMD)){
541 mrCommand(command.getCommandLine());
542 }
543 }
544 protected String getOozieUrl(CommandLine commandLine) {
545 String url = commandLine.getOptionValue(OOZIE_OPTION);
546 if (url == null) {
547 url = System.getenv(ENV_OOZIE_URL);
548 if (url == null) {
549 throw new IllegalArgumentException(
550 "Oozie URL is not available neither in command option or in the environment");
551 }
552 }
553 return url;
554 }
555
556 private String getTimeZoneId(CommandLine commandLine)
557 {
558 if (commandLine.hasOption(LOCAL_TIME_OPTION)) {
559 return null;
560 }
561 if (commandLine.hasOption(TIME_ZONE_OPTION)) {
562 return commandLine.getOptionValue(TIME_ZONE_OPTION);
563 }
564 String timeZoneId = System.getenv(ENV_OOZIE_TIME_ZONE);
565 if (timeZoneId != null) {
566 return timeZoneId;
567 }
568 return "GMT";
569 }
570
571 // Canibalized from Hadoop <code>Configuration.loadResource()</code>.
572 private Properties parse(InputStream is, Properties conf) throws IOException {
573 try {
574 DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
575 // ignore all comments inside the xml file
576 docBuilderFactory.setIgnoringComments(true);
577 DocumentBuilder builder = docBuilderFactory.newDocumentBuilder();
578 Document doc = builder.parse(is);
579 return parseDocument(doc, conf);
580 }
581 catch (SAXException e) {
582 throw new IOException(e);
583 }
584 catch (ParserConfigurationException e) {
585 throw new IOException(e);
586 }
587 }
588
589 // Canibalized from Hadoop <code>Configuration.loadResource()</code>.
590 private Properties parseDocument(Document doc, Properties conf) throws IOException {
591 try {
592 Element root = doc.getDocumentElement();
593 if (!"configuration".equals(root.getTagName())) {
594 throw new RuntimeException("bad conf file: top-level element not <configuration>");
595 }
596 NodeList props = root.getChildNodes();
597 for (int i = 0; i < props.getLength(); i++) {
598 Node propNode = props.item(i);
599 if (!(propNode instanceof Element)) {
600 continue;
601 }
602 Element prop = (Element) propNode;
603 if (!"property".equals(prop.getTagName())) {
604 throw new RuntimeException("bad conf file: element not <property>");
605 }
606 NodeList fields = prop.getChildNodes();
607 String attr = null;
608 String value = null;
609 for (int j = 0; j < fields.getLength(); j++) {
610 Node fieldNode = fields.item(j);
611 if (!(fieldNode instanceof Element)) {
612 continue;
613 }
614 Element field = (Element) fieldNode;
615 if ("name".equals(field.getTagName()) && field.hasChildNodes()) {
616 attr = ((Text) field.getFirstChild()).getData();
617 }
618 if ("value".equals(field.getTagName()) && field.hasChildNodes()) {
619 value = ((Text) field.getFirstChild()).getData();
620 }
621 }
622
623 if (attr != null && value != null) {
624 conf.setProperty(attr, value);
625 }
626 }
627 return conf;
628 }
629 catch (DOMException e) {
630 throw new IOException(e);
631 }
632 }
633
634 private Properties getConfiguration(OozieClient wc, CommandLine commandLine) throws IOException {
635 Properties conf = wc.createConfiguration();
636 String configFile = commandLine.getOptionValue(CONFIG_OPTION);
637 if (configFile == null) {
638 throw new IOException("configuration file not specified");
639 }
640 else {
641 File file = new File(configFile);
642 if (!file.exists()) {
643 throw new IOException("configuration file [" + configFile + "] not found");
644 }
645 if (configFile.endsWith(".properties")) {
646 conf.load(new FileReader(file));
647 }
648 else if (configFile.endsWith(".xml")) {
649 parse(new FileInputStream(configFile), conf);
650 }
651 else {
652 throw new IllegalArgumentException("configuration must be a '.properties' or a '.xml' file");
653 }
654 }
655 if (commandLine.hasOption("D")) {
656 Properties commandLineProperties = commandLine.getOptionProperties("D");
657 conf.putAll(commandLineProperties);
658 }
659 return conf;
660 }
661
662 /**
663 * @param commandLine command line string.
664 * @return change value specified by -value.
665 * @throws OozieCLIException
666 */
667 private String getChangeValue(CommandLine commandLine) throws OozieCLIException {
668 String changeValue = commandLine.getOptionValue(CHANGE_VALUE_OPTION);
669
670 if (changeValue == null) {
671 throw new OozieCLIException("-value option needs to be specified for -change option");
672 }
673
674 return changeValue;
675 }
676
677 protected void addHeader(OozieClient wc) {
678 for (Map.Entry entry : System.getProperties().entrySet()) {
679 String key = (String) entry.getKey();
680 if (key.startsWith(WS_HEADER_PREFIX)) {
681 String header = key.substring(WS_HEADER_PREFIX.length());
682 wc.setHeader(header, (String) entry.getValue());
683 }
684 }
685 }
686
687 /**
688 * Get auth option from command line
689 *
690 * @param commandLine the command line object
691 * @return auth option
692 */
693 protected String getAuthOption(CommandLine commandLine) {
694 String authOpt = commandLine.getOptionValue(AUTH_OPTION);
695 return authOpt;
696 }
697
698 /**
699 * Create a OozieClient.
700 * <p/>
701 * It injects any '-Dheader:' as header to the the {@link org.apache.oozie.client.OozieClient}.
702 *
703 * @param commandLine the parsed command line options.
704 * @return a pre configured eXtended workflow client.
705 * @throws OozieCLIException thrown if the OozieClient could not be configured.
706 */
707 protected OozieClient createOozieClient(CommandLine commandLine) throws OozieCLIException {
708 return createXOozieClient(commandLine);
709 }
710
711 /**
712 * Create a XOozieClient.
713 * <p/>
714 * It injects any '-Dheader:' as header to the the {@link org.apache.oozie.client.OozieClient}.
715 *
716 * @param commandLine the parsed command line options.
717 * @return a pre configured eXtended workflow client.
718 * @throws OozieCLIException thrown if the XOozieClient could not be configured.
719 */
720 protected XOozieClient createXOozieClient(CommandLine commandLine) throws OozieCLIException {
721 XOozieClient wc = new AuthOozieClient(getOozieUrl(commandLine), getAuthOption(commandLine));
722 addHeader(wc);
723 setDebugMode(wc,commandLine.hasOption(DEBUG_OPTION));
724 return wc;
725 }
726
727 protected void setDebugMode(OozieClient wc, boolean debugOpt) {
728
729 String debug = System.getenv(ENV_OOZIE_DEBUG);
730 if (debug != null && !debug.isEmpty()) {
731 int debugVal = 0;
732 try {
733 debugVal = Integer.parseInt(debug.trim());
734 }
735 catch (Exception ex) {
736 System.out.println("Unable to parse the debug settings. May be not an integer [" + debug + "]");
737 ex.printStackTrace();
738 }
739 wc.setDebugMode(debugVal);
740 }
741 else if(debugOpt){ // CLI argument "-debug" used
742 wc.setDebugMode(1);
743 }
744 }
745
746 private static String JOB_ID_PREFIX = "job: ";
747
748 private void jobCommand(CommandLine commandLine) throws IOException, OozieCLIException {
749 XOozieClient wc = createXOozieClient(commandLine);
750
751 List<String> options = new ArrayList<String>();
752 for (Option option : commandLine.getOptions()) {
753 options.add(option.getOpt());
754 }
755
756 try {
757 if (options.contains(SUBMIT_OPTION)) {
758 System.out.println(JOB_ID_PREFIX + wc.submit(getConfiguration(wc, commandLine)));
759 }
760 else if (options.contains(START_OPTION)) {
761 wc.start(commandLine.getOptionValue(START_OPTION));
762 }
763 else if (options.contains(DRYRUN_OPTION)) {
764 String dryrunStr = wc.dryrun(getConfiguration(wc, commandLine));
765 if (dryrunStr.equals("OK")) { // workflow
766 System.out.println("OK");
767 } else { // coordinator
768 String[] dryrunStrs = dryrunStr.split("action for new instance");
769 int arraysize = dryrunStrs.length;
770 System.out.println("***coordJob after parsing: ***");
771 System.out.println(dryrunStrs[0]);
772 int aLen = dryrunStrs.length - 1;
773 if (aLen < 0) {
774 aLen = 0;
775 }
776 System.out.println("***total coord actions is " + aLen + " ***");
777 for (int i = 1; i <= arraysize - 1; i++) {
778 System.out.println(RULER);
779 System.out.println("coordAction instance: " + i + ":");
780 System.out.println(dryrunStrs[i]);
781 }
782 }
783 }
784 else if (options.contains(SUSPEND_OPTION)) {
785 wc.suspend(commandLine.getOptionValue(SUSPEND_OPTION));
786 }
787 else if (options.contains(RESUME_OPTION)) {
788 wc.resume(commandLine.getOptionValue(RESUME_OPTION));
789 }
790 else if (options.contains(KILL_OPTION)) {
791 wc.kill(commandLine.getOptionValue(KILL_OPTION));
792 }
793 else if (options.contains(CHANGE_OPTION)) {
794 wc.change(commandLine.getOptionValue(CHANGE_OPTION), getChangeValue(commandLine));
795 }
796 else if (options.contains(RUN_OPTION)) {
797 System.out.println(JOB_ID_PREFIX + wc.run(getConfiguration(wc, commandLine)));
798 }
799 else if (options.contains(RERUN_OPTION)) {
800 if (commandLine.getOptionValue(RERUN_OPTION).contains("-W")) {
801 wc.reRun(commandLine.getOptionValue(RERUN_OPTION), getConfiguration(wc, commandLine));
802 }
803 else if (commandLine.getOptionValue(RERUN_OPTION).contains("-B")) {
804 String bundleJobId = commandLine.getOptionValue(RERUN_OPTION);
805 String coordScope = null;
806 String dateScope = null;
807 boolean refresh = false;
808 boolean noCleanup = false;
809 if (options.contains(ACTION_OPTION)) {
810 throw new OozieCLIException("Invalid options provided for bundle rerun. " + ACTION_OPTION
811 + " is not valid for bundle rerun");
812 }
813 if (options.contains(DATE_OPTION)) {
814 dateScope = commandLine.getOptionValue(DATE_OPTION);
815 }
816
817 if (options.contains(RERUN_COORD_OPTION)) {
818 coordScope = commandLine.getOptionValue(RERUN_COORD_OPTION);
819 }
820
821 if (options.contains(RERUN_REFRESH_OPTION)) {
822 refresh = true;
823 }
824 if (options.contains(RERUN_NOCLEANUP_OPTION)) {
825 noCleanup = true;
826 }
827 wc.reRunBundle(bundleJobId, coordScope, dateScope, refresh, noCleanup);
828 if (coordScope != null && !coordScope.isEmpty()) {
829 System.out.println("Coordinators [" + coordScope + "] of bundle " + bundleJobId
830 + " are scheduled to rerun on date ranges [" + dateScope + "].");
831 }
832 else {
833 System.out.println("All coordinators of bundle " + bundleJobId
834 + " are scheduled to rerun on the date ranges [" + dateScope + "].");
835 }
836 }
837 else {
838 String coordJobId = commandLine.getOptionValue(RERUN_OPTION);
839 String scope = null;
840 String rerunType = null;
841 boolean refresh = false;
842 boolean noCleanup = false;
843 if (options.contains(DATE_OPTION) && options.contains(ACTION_OPTION)) {
844 throw new OozieCLIException("Invalid options provided for rerun: either" + DATE_OPTION + " or "
845 + ACTION_OPTION + " expected. Don't use both at the same time.");
846 }
847 if (options.contains(DATE_OPTION)) {
848 rerunType = RestConstants.JOB_COORD_RERUN_DATE;
849 scope = commandLine.getOptionValue(DATE_OPTION);
850 }
851 else if (options.contains(ACTION_OPTION)) {
852 rerunType = RestConstants.JOB_COORD_RERUN_ACTION;
853 scope = commandLine.getOptionValue(ACTION_OPTION);
854 }
855 else {
856 throw new OozieCLIException("Invalid options provided for rerun: " + DATE_OPTION + " or "
857 + ACTION_OPTION + " expected.");
858 }
859 if (options.contains(RERUN_REFRESH_OPTION)) {
860 refresh = true;
861 }
862 if (options.contains(RERUN_NOCLEANUP_OPTION)) {
863 noCleanup = true;
864 }
865 printRerunCoordActions(wc.reRunCoord(coordJobId, rerunType, scope, refresh, noCleanup));
866 }
867 }
868 else if (options.contains(INFO_OPTION)) {
869 String timeZoneId = getTimeZoneId(commandLine);
870 final String optionValue = commandLine.getOptionValue(INFO_OPTION);
871 if (optionValue.endsWith("-B")) {
872 String filter = commandLine.getOptionValue(FILTER_OPTION);
873 if (filter != null) {
874 throw new OozieCLIException("Filter option is currently not supported for a Bundle job");
875 }
876 printBundleJob(wc.getBundleJobInfo(optionValue), timeZoneId,
877 options.contains(VERBOSE_OPTION));
878 }
879 else if (optionValue.endsWith("-C")) {
880 String s = commandLine.getOptionValue(OFFSET_OPTION);
881 int start = Integer.parseInt((s != null) ? s : "-1");
882 s = commandLine.getOptionValue(LEN_OPTION);
883 int len = Integer.parseInt((s != null) ? s : "-1");
884 String filter = commandLine.getOptionValue(FILTER_OPTION);
885 printCoordJob(wc.getCoordJobInfo(optionValue, filter, start, len), timeZoneId,
886 options.contains(VERBOSE_OPTION));
887 }
888 else if (optionValue.contains("-C@")) {
889 String filter = commandLine.getOptionValue(FILTER_OPTION);
890 if (filter != null) {
891 throw new OozieCLIException("Filter option is not supported for a Coordinator action");
892 }
893 printCoordAction(wc.getCoordActionInfo(optionValue), timeZoneId);
894 }
895 else if (optionValue.contains("-W@")) {
896 String filter = commandLine.getOptionValue(FILTER_OPTION);
897 if (filter != null) {
898 throw new OozieCLIException("Filter option is not supported for a Workflow action");
899 }
900 printWorkflowAction(wc.getWorkflowActionInfo(optionValue), timeZoneId,
901 options.contains(VERBOSE_OPTION));
902 }
903 else {
904 String filter = commandLine.getOptionValue(FILTER_OPTION);
905 if (filter != null) {
906 throw new OozieCLIException("Filter option is currently not supported for a Workflow job");
907 }
908 String s = commandLine.getOptionValue(OFFSET_OPTION);
909 int start = Integer.parseInt((s != null) ? s : "0");
910 s = commandLine.getOptionValue(LEN_OPTION);
911 String jobtype = commandLine.getOptionValue(JOBTYPE_OPTION);
912 jobtype = (jobtype != null) ? jobtype : "wf";
913 int len = Integer.parseInt((s != null) ? s : "0");
914 printJob(wc.getJobInfo(optionValue, start, len), timeZoneId,
915 options.contains(VERBOSE_OPTION));
916 }
917 }
918 else if (options.contains(LOG_OPTION)) {
919 PrintStream ps = System.out;
920 if (commandLine.getOptionValue(LOG_OPTION).contains("-C")) {
921 String logRetrievalScope = null;
922 String logRetrievalType = null;
923 if (options.contains(ACTION_OPTION)) {
924 logRetrievalType = RestConstants.JOB_LOG_ACTION;
925 logRetrievalScope = commandLine.getOptionValue(ACTION_OPTION);
926 }
927 if (options.contains(DATE_OPTION)) {
928 logRetrievalType = RestConstants.JOB_LOG_DATE;
929 logRetrievalScope = commandLine.getOptionValue(DATE_OPTION);
930 }
931 try {
932 wc.getJobLog(commandLine.getOptionValue(LOG_OPTION), logRetrievalType, logRetrievalScope, ps);
933 }
934 finally {
935 ps.close();
936 }
937 }
938 else {
939 if (!options.contains(ACTION_OPTION) && !options.contains(DATE_OPTION)) {
940 wc.getJobLog(commandLine.getOptionValue(LOG_OPTION), null, null, ps);
941 }
942 else {
943 throw new OozieCLIException("Invalid options provided for log retrieval. " + ACTION_OPTION
944 + " and " + DATE_OPTION + " are valid only for coordinator job log retrieval");
945 }
946 }
947 }
948 else if (options.contains(DEFINITION_OPTION)) {
949 System.out.println(wc.getJobDefinition(commandLine.getOptionValue(DEFINITION_OPTION)));
950 }
951 else if (options.contains(CONFIG_CONTENT_OPTION)) {
952 if (commandLine.getOptionValue(CONFIG_CONTENT_OPTION).endsWith("-C")) {
953 System.out.println(wc.getCoordJobInfo(commandLine.getOptionValue(CONFIG_CONTENT_OPTION)).getConf());
954 }
955 else if (commandLine.getOptionValue(CONFIG_CONTENT_OPTION).endsWith("-W")) {
956 System.out.println(wc.getJobInfo(commandLine.getOptionValue(CONFIG_CONTENT_OPTION)).getConf());
957 }
958 else if (commandLine.getOptionValue(CONFIG_CONTENT_OPTION).endsWith("-B")) {
959 System.out
960 .println(wc.getBundleJobInfo(commandLine.getOptionValue(CONFIG_CONTENT_OPTION)).getConf());
961 }
962 else {
963 System.out.println("ERROR: job id [" + commandLine.getOptionValue(CONFIG_CONTENT_OPTION)
964 + "] doesn't end with either C or W or B");
965 }
966 }
967 }
968 catch (OozieClientException ex) {
969 throw new OozieCLIException(ex.toString(), ex);
970 }
971 }
972
973 @VisibleForTesting
974 void printCoordJob(CoordinatorJob coordJob, String timeZoneId, boolean verbose) {
975 System.out.println("Job ID : " + coordJob.getId());
976
977 System.out.println(RULER);
978
979 List<CoordinatorAction> actions = coordJob.getActions();
980 System.out.println("Job Name : " + maskIfNull(coordJob.getAppName()));
981 System.out.println("App Path : " + maskIfNull(coordJob.getAppPath()));
982 System.out.println("Status : " + coordJob.getStatus());
983 System.out.println("Start Time : " + maskDate(coordJob.getStartTime(), timeZoneId, false));
984 System.out.println("End Time : " + maskDate(coordJob.getEndTime(), timeZoneId, false));
985 System.out.println("Pause Time : " + maskDate(coordJob.getPauseTime(), timeZoneId, false));
986 System.out.println("Concurrency : " + coordJob.getConcurrency());
987 System.out.println(RULER);
988
989 if (verbose) {
990 System.out.println("ID" + VERBOSE_DELIMITER + "Action Number" + VERBOSE_DELIMITER + "Console URL"
991 + VERBOSE_DELIMITER + "Error Code" + VERBOSE_DELIMITER + "Error Message" + VERBOSE_DELIMITER
992 + "External ID" + VERBOSE_DELIMITER + "External Status" + VERBOSE_DELIMITER + "Job ID"
993 + VERBOSE_DELIMITER + "Tracker URI" + VERBOSE_DELIMITER + "Created" + VERBOSE_DELIMITER
994 + "Nominal Time" + VERBOSE_DELIMITER + "Status" + VERBOSE_DELIMITER + "Last Modified"
995 + VERBOSE_DELIMITER + "Missing Dependencies");
996 System.out.println(RULER);
997
998 for (CoordinatorAction action : actions) {
999 System.out.println(maskIfNull(action.getId()) + VERBOSE_DELIMITER + action.getActionNumber()
1000 + VERBOSE_DELIMITER + maskIfNull(action.getConsoleUrl()) + VERBOSE_DELIMITER
1001 + maskIfNull(action.getErrorCode()) + VERBOSE_DELIMITER + maskIfNull(action.getErrorMessage())
1002 + VERBOSE_DELIMITER + maskIfNull(action.getExternalId()) + VERBOSE_DELIMITER
1003 + maskIfNull(action.getExternalStatus()) + VERBOSE_DELIMITER + maskIfNull(action.getJobId())
1004 + VERBOSE_DELIMITER + maskIfNull(action.getTrackerUri()) + VERBOSE_DELIMITER
1005 + maskDate(action.getCreatedTime(), timeZoneId, verbose) + VERBOSE_DELIMITER
1006 + maskDate(action.getNominalTime(), timeZoneId, verbose) + action.getStatus() + VERBOSE_DELIMITER
1007 + maskDate(action.getLastModifiedTime(), timeZoneId, verbose) + VERBOSE_DELIMITER
1008 + maskIfNull(getFirstMissingDependencies(action)));
1009
1010 System.out.println(RULER);
1011 }
1012 }
1013 else {
1014 System.out.println(String.format(COORD_ACTION_FORMATTER, "ID", "Status", "Ext ID", "Err Code", "Created",
1015 "Nominal Time", "Last Mod"));
1016
1017 for (CoordinatorAction action : actions) {
1018 System.out.println(String.format(COORD_ACTION_FORMATTER, maskIfNull(action.getId()),
1019 action.getStatus(), maskIfNull(action.getExternalId()), maskIfNull(action.getErrorCode()),
1020 maskDate(action.getCreatedTime(), timeZoneId, verbose), maskDate(action.getNominalTime(), timeZoneId, verbose),
1021 maskDate(action.getLastModifiedTime(), timeZoneId, verbose)));
1022
1023 System.out.println(RULER);
1024 }
1025 }
1026 }
1027
1028 @VisibleForTesting
1029 void printBundleJob(BundleJob bundleJob, String timeZoneId, boolean verbose) {
1030 System.out.println("Job ID : " + bundleJob.getId());
1031
1032 System.out.println(RULER);
1033
1034 List<CoordinatorJob> coordinators = bundleJob.getCoordinators();
1035 System.out.println("Job Name : " + maskIfNull(bundleJob.getAppName()));
1036 System.out.println("App Path : " + maskIfNull(bundleJob.getAppPath()));
1037 System.out.println("Status : " + bundleJob.getStatus());
1038 System.out.println("Kickoff time : " + bundleJob.getKickoffTime());
1039 System.out.println(RULER);
1040
1041 System.out.println(String.format(BUNDLE_COORD_JOBS_FORMATTER, "Job ID", "Status", "Freq", "Unit", "Started",
1042 "Next Materialized"));
1043 System.out.println(RULER);
1044
1045 for (CoordinatorJob job : coordinators) {
1046 System.out.println(String.format(BUNDLE_COORD_JOBS_FORMATTER, maskIfNull(job.getId()), job.getStatus(),
1047 job.getFrequency(), job.getTimeUnit(), maskDate(job.getStartTime(), timeZoneId, verbose),
1048 maskDate(job.getNextMaterializedTime(), timeZoneId, verbose)));
1049
1050 System.out.println(RULER);
1051 }
1052 }
1053
1054 @VisibleForTesting
1055 void printCoordAction(CoordinatorAction coordAction, String timeZoneId) {
1056 System.out.println("ID : " + maskIfNull(coordAction.getId()));
1057
1058 System.out.println(RULER);
1059
1060 System.out.println("Action Number : " + coordAction.getActionNumber());
1061 System.out.println("Console URL : " + maskIfNull(coordAction.getConsoleUrl()));
1062 System.out.println("Error Code : " + maskIfNull(coordAction.getErrorCode()));
1063 System.out.println("Error Message : " + maskIfNull(coordAction.getErrorMessage()));
1064 System.out.println("External ID : " + maskIfNull(coordAction.getExternalId()));
1065 System.out.println("External Status : " + maskIfNull(coordAction.getExternalStatus()));
1066 System.out.println("Job ID : " + maskIfNull(coordAction.getJobId()));
1067 System.out.println("Tracker URI : " + maskIfNull(coordAction.getTrackerUri()));
1068 System.out.println("Created : " + maskDate(coordAction.getCreatedTime(), timeZoneId, false));
1069 System.out.println("Nominal Time : " + maskDate(coordAction.getNominalTime(), timeZoneId, false));
1070 System.out.println("Status : " + coordAction.getStatus());
1071 System.out.println("Last Modified : " + maskDate(coordAction.getLastModifiedTime(), timeZoneId, false));
1072 System.out.println("First Missing Dependency : " + maskIfNull(getFirstMissingDependencies(coordAction)));
1073
1074 System.out.println(RULER);
1075 }
1076
1077 private void printRerunCoordActions(List<CoordinatorAction> actions) {
1078 if (actions != null && actions.size() > 0) {
1079 System.out.println("Action ID" + VERBOSE_DELIMITER + "Nominal Time");
1080 System.out.println(RULER);
1081 for (CoordinatorAction action : actions) {
1082 System.out.println(maskIfNull(action.getId()) + VERBOSE_DELIMITER
1083 + maskDate(action.getNominalTime(), null,false));
1084 }
1085 }
1086 else {
1087 System.out.println("No Actions match your rerun criteria!");
1088 }
1089 }
1090
1091
1092 @VisibleForTesting
1093 void printWorkflowAction(WorkflowAction action, String timeZoneId, boolean verbose) {
1094
1095 System.out.println("ID : " + maskIfNull(action.getId()));
1096
1097 System.out.println(RULER);
1098
1099 System.out.println("Console URL : " + maskIfNull(action.getConsoleUrl()));
1100 System.out.println("Error Code : " + maskIfNull(action.getErrorCode()));
1101 System.out.println("Error Message : " + maskIfNull(action.getErrorMessage()));
1102 System.out.println("External ID : " + maskIfNull(action.getExternalId()));
1103 System.out.println("External Status : " + maskIfNull(action.getExternalStatus()));
1104 System.out.println("Name : " + maskIfNull(action.getName()));
1105 System.out.println("Retries : " + action.getRetries());
1106 System.out.println("Tracker URI : " + maskIfNull(action.getTrackerUri()));
1107 System.out.println("Type : " + maskIfNull(action.getType()));
1108 System.out.println("Started : " + maskDate(action.getStartTime(), timeZoneId, verbose));
1109 System.out.println("Status : " + action.getStatus());
1110 System.out.println("Ended : " + maskDate(action.getEndTime(), timeZoneId, verbose));
1111
1112 if (verbose) {
1113 System.out.println("External Stats : " + action.getStats());
1114 System.out.println("External ChildIDs : " + action.getExternalChildIDs());
1115 }
1116
1117 System.out.println(RULER);
1118 }
1119
1120 private static final String WORKFLOW_JOBS_FORMATTER = "%-41s%-13s%-10s%-10s%-10s%-24s%-24s";
1121 private static final String COORD_JOBS_FORMATTER = "%-41s%-15s%-10s%-5s%-13s%-24s%-24s";
1122 private static final String BUNDLE_JOBS_FORMATTER = "%-41s%-15s%-10s%-20s%-20s%-13s%-13s";
1123 private static final String BUNDLE_COORD_JOBS_FORMATTER = "%-41s%-15s%-5s%-13s%-24s%-24s";
1124
1125 private static final String WORKFLOW_ACTION_FORMATTER = "%-78s%-10s%-23s%-11s%-10s";
1126 private static final String COORD_ACTION_FORMATTER = "%-43s%-10s%-37s%-10s%-21s%-21s";
1127 private static final String BULK_RESPONSE_FORMATTER = "%-13s%-38s%-13s%-41s%-10s%-38s%-21s%-38s";
1128
1129 @VisibleForTesting
1130 void printJob(WorkflowJob job, String timeZoneId, boolean verbose) throws IOException {
1131 System.out.println("Job ID : " + maskIfNull(job.getId()));
1132
1133 System.out.println(RULER);
1134
1135 System.out.println("Workflow Name : " + maskIfNull(job.getAppName()));
1136 System.out.println("App Path : " + maskIfNull(job.getAppPath()));
1137 System.out.println("Status : " + job.getStatus());
1138 System.out.println("Run : " + job.getRun());
1139 System.out.println("User : " + maskIfNull(job.getUser()));
1140 System.out.println("Group : " + maskIfNull(job.getGroup()));
1141 System.out.println("Created : " + maskDate(job.getCreatedTime(), timeZoneId, verbose));
1142 System.out.println("Started : " + maskDate(job.getStartTime(), timeZoneId, verbose));
1143 System.out.println("Last Modified : " + maskDate(job.getLastModifiedTime(), timeZoneId, verbose));
1144 System.out.println("Ended : " + maskDate(job.getEndTime(), timeZoneId, verbose));
1145 System.out.println("CoordAction ID: " + maskIfNull(job.getParentId()));
1146
1147 List<WorkflowAction> actions = job.getActions();
1148
1149 if (actions != null && actions.size() > 0) {
1150 System.out.println();
1151 System.out.println("Actions");
1152 System.out.println(RULER);
1153
1154 if (verbose) {
1155 System.out.println("ID" + VERBOSE_DELIMITER + "Console URL" + VERBOSE_DELIMITER + "Error Code"
1156 + VERBOSE_DELIMITER + "Error Message" + VERBOSE_DELIMITER + "External ID" + VERBOSE_DELIMITER
1157 + "External Status" + VERBOSE_DELIMITER + "Name" + VERBOSE_DELIMITER + "Retries"
1158 + VERBOSE_DELIMITER + "Tracker URI" + VERBOSE_DELIMITER + "Type" + VERBOSE_DELIMITER
1159 + "Started" + VERBOSE_DELIMITER + "Status" + VERBOSE_DELIMITER + "Ended");
1160 System.out.println(RULER);
1161
1162 for (WorkflowAction action : job.getActions()) {
1163 System.out.println(maskIfNull(action.getId()) + VERBOSE_DELIMITER
1164 + maskIfNull(action.getConsoleUrl()) + VERBOSE_DELIMITER
1165 + maskIfNull(action.getErrorCode()) + VERBOSE_DELIMITER
1166 + maskIfNull(action.getErrorMessage()) + VERBOSE_DELIMITER
1167 + maskIfNull(action.getExternalId()) + VERBOSE_DELIMITER
1168 + maskIfNull(action.getExternalStatus()) + VERBOSE_DELIMITER + maskIfNull(action.getName())
1169 + VERBOSE_DELIMITER + action.getRetries() + VERBOSE_DELIMITER
1170 + maskIfNull(action.getTrackerUri()) + VERBOSE_DELIMITER + maskIfNull(action.getType())
1171 + VERBOSE_DELIMITER + maskDate(action.getStartTime(), timeZoneId, verbose)
1172 + VERBOSE_DELIMITER + action.getStatus() + VERBOSE_DELIMITER
1173 + maskDate(action.getEndTime(), timeZoneId, verbose));
1174
1175 System.out.println(RULER);
1176 }
1177 }
1178 else {
1179 System.out.println(String.format(WORKFLOW_ACTION_FORMATTER, "ID", "Status", "Ext ID", "Ext Status",
1180 "Err Code"));
1181
1182 System.out.println(RULER);
1183
1184 for (WorkflowAction action : job.getActions()) {
1185 System.out.println(String.format(WORKFLOW_ACTION_FORMATTER, maskIfNull(action.getId()), action
1186 .getStatus(), maskIfNull(action.getExternalId()), maskIfNull(action.getExternalStatus()),
1187 maskIfNull(action.getErrorCode())));
1188
1189 System.out.println(RULER);
1190 }
1191 }
1192 }
1193 else {
1194 System.out.println(RULER);
1195 }
1196
1197 System.out.println();
1198 }
1199
1200 private void jobsCommand(CommandLine commandLine) throws IOException, OozieCLIException {
1201 XOozieClient wc = createXOozieClient(commandLine);
1202
1203 String filter = commandLine.getOptionValue(FILTER_OPTION);
1204 String s = commandLine.getOptionValue(OFFSET_OPTION);
1205 int start = Integer.parseInt((s != null) ? s : "0");
1206 s = commandLine.getOptionValue(LEN_OPTION);
1207 String jobtype = commandLine.getOptionValue(JOBTYPE_OPTION);
1208 String timeZoneId = getTimeZoneId(commandLine);
1209 jobtype = (jobtype != null) ? jobtype : "wf";
1210 int len = Integer.parseInt((s != null) ? s : "0");
1211 String bulkFilterString = commandLine.getOptionValue(BULK_OPTION);
1212
1213 try {
1214 if (bulkFilterString != null) {
1215 printBulkJobs(wc.getBulkInfo(bulkFilterString, start, len), timeZoneId, commandLine.hasOption(VERBOSE_OPTION));
1216 }
1217 else if (jobtype.toLowerCase().contains("wf")) {
1218 printJobs(wc.getJobsInfo(filter, start, len), timeZoneId, commandLine.hasOption(VERBOSE_OPTION));
1219 }
1220 else if (jobtype.toLowerCase().startsWith("coord")) {
1221 printCoordJobs(wc.getCoordJobsInfo(filter, start, len), timeZoneId, commandLine.hasOption(VERBOSE_OPTION));
1222 }
1223 else if (jobtype.toLowerCase().startsWith("bundle")) {
1224 printBundleJobs(wc.getBundleJobsInfo(filter, start, len), timeZoneId, commandLine.hasOption(VERBOSE_OPTION));
1225 }
1226
1227 }
1228 catch (OozieClientException ex) {
1229 throw new OozieCLIException(ex.toString(), ex);
1230 }
1231 }
1232
1233 @VisibleForTesting
1234 void printCoordJobs(List<CoordinatorJob> jobs, String timeZoneId, boolean verbose) throws IOException {
1235 if (jobs != null && jobs.size() > 0) {
1236 if (verbose) {
1237 System.out.println("Job ID" + VERBOSE_DELIMITER + "App Name" + VERBOSE_DELIMITER + "App Path"
1238 + VERBOSE_DELIMITER + "Console URL" + VERBOSE_DELIMITER + "User" + VERBOSE_DELIMITER + "Group"
1239 + VERBOSE_DELIMITER + "Concurrency" + VERBOSE_DELIMITER + "Frequency" + VERBOSE_DELIMITER
1240 + "Time Unit" + VERBOSE_DELIMITER + "Time Zone" + VERBOSE_DELIMITER + "Time Out"
1241 + VERBOSE_DELIMITER + "Started" + VERBOSE_DELIMITER + "Next Materialize" + VERBOSE_DELIMITER
1242 + "Status" + VERBOSE_DELIMITER + "Last Action" + VERBOSE_DELIMITER + "Ended");
1243 System.out.println(RULER);
1244
1245 for (CoordinatorJob job : jobs) {
1246 System.out.println(maskIfNull(job.getId()) + VERBOSE_DELIMITER + maskIfNull(job.getAppName())
1247 + VERBOSE_DELIMITER + maskIfNull(job.getAppPath()) + VERBOSE_DELIMITER
1248 + maskIfNull(job.getConsoleUrl()) + VERBOSE_DELIMITER + maskIfNull(job.getUser())
1249 + VERBOSE_DELIMITER + maskIfNull(job.getGroup()) + VERBOSE_DELIMITER + job.getConcurrency()
1250 + VERBOSE_DELIMITER + job.getFrequency() + VERBOSE_DELIMITER + job.getTimeUnit()
1251 + VERBOSE_DELIMITER + maskIfNull(job.getTimeZone()) + VERBOSE_DELIMITER + job.getTimeout()
1252 + VERBOSE_DELIMITER + maskDate(job.getStartTime(), timeZoneId, verbose) + VERBOSE_DELIMITER
1253 + maskDate(job.getNextMaterializedTime(), timeZoneId, verbose) + VERBOSE_DELIMITER
1254 + job.getStatus() + VERBOSE_DELIMITER
1255 + maskDate(job.getLastActionTime(), timeZoneId, verbose) + VERBOSE_DELIMITER
1256 + maskDate(job.getEndTime(), timeZoneId, verbose));
1257
1258 System.out.println(RULER);
1259 }
1260 }
1261 else {
1262 System.out.println(String.format(COORD_JOBS_FORMATTER, "Job ID", "App Name", "Status", "Freq", "Unit",
1263 "Started", "Next Materialized"));
1264 System.out.println(RULER);
1265
1266 for (CoordinatorJob job : jobs) {
1267 System.out.println(String.format(COORD_JOBS_FORMATTER, maskIfNull(job.getId()), maskIfNull(job
1268 .getAppName()), job.getStatus(), job.getFrequency(), job.getTimeUnit(), maskDate(job
1269 .getStartTime(), timeZoneId, verbose), maskDate(job.getNextMaterializedTime(), timeZoneId, verbose)));
1270
1271 System.out.println(RULER);
1272 }
1273 }
1274 }
1275 else {
1276 System.out.println("No Jobs match your criteria!");
1277 }
1278 }
1279
1280 @VisibleForTesting
1281 void printBulkJobs(List<BulkResponse> jobs, String timeZoneId, boolean verbose) throws IOException {
1282 if (jobs != null && jobs.size() > 0) {
1283 for (BulkResponse response : jobs) {
1284 BundleJob bundle = response.getBundle();
1285 CoordinatorJob coord = response.getCoordinator();
1286 CoordinatorAction action = response.getAction();
1287 if (verbose) {
1288 System.out.println();
1289 System.out.println("Bundle Name : " + maskIfNull(bundle.getAppName()));
1290
1291 System.out.println(RULER);
1292
1293 System.out.println("Bundle ID : " + maskIfNull(bundle.getId()));
1294 System.out.println("Coordinator Name : " + maskIfNull(coord.getAppName()));
1295 System.out.println("Coord Action ID : " + maskIfNull(action.getId()));
1296 System.out.println("Action Status : " + action.getStatus());
1297 System.out.println("External ID : " + maskIfNull(action.getExternalId()));
1298 System.out.println("Created Time : " + maskDate(action.getCreatedTime(), timeZoneId, false));
1299 System.out.println("User : " + maskIfNull(bundle.getUser()));
1300 System.out.println("Error Message : " + maskIfNull(action.getErrorMessage()));
1301 System.out.println(RULER);
1302 }
1303 else {
1304 System.out.println(String.format(BULK_RESPONSE_FORMATTER, "Bundle Name", "Bundle ID", "Coord Name",
1305 "Coord Action ID", "Status", "External ID", "Created Time", "Error Message"));
1306 System.out.println(RULER);
1307 System.out
1308 .println(String.format(BULK_RESPONSE_FORMATTER, maskIfNull(bundle.getAppName()),
1309 maskIfNull(bundle.getId()), maskIfNull(coord.getAppName()),
1310 maskIfNull(action.getId()), action.getStatus(), maskIfNull(action.getExternalId()),
1311 maskDate(action.getCreatedTime(), timeZoneId, false),
1312 maskIfNull(action.getErrorMessage())));
1313 System.out.println(RULER);
1314 }
1315 }
1316 }
1317 else {
1318 System.out.println("Bulk request criteria did not match any coordinator actions");
1319 }
1320 }
1321
1322 @VisibleForTesting
1323 void printBundleJobs(List<BundleJob> jobs, String timeZoneId, boolean verbose) throws IOException {
1324 if (jobs != null && jobs.size() > 0) {
1325 if (verbose) {
1326 System.out.println("Job ID" + VERBOSE_DELIMITER + "Bundle Name" + VERBOSE_DELIMITER + "Bundle Path"
1327 + VERBOSE_DELIMITER + "User" + VERBOSE_DELIMITER + "Group" + VERBOSE_DELIMITER + "Status"
1328 + VERBOSE_DELIMITER + "Kickoff" + VERBOSE_DELIMITER + "Pause" + VERBOSE_DELIMITER + "Created"
1329 + VERBOSE_DELIMITER + "Console URL");
1330 System.out.println(RULER);
1331
1332 for (BundleJob job : jobs) {
1333 System.out.println(maskIfNull(job.getId()) + VERBOSE_DELIMITER + maskIfNull(job.getAppName())
1334 + VERBOSE_DELIMITER + maskIfNull(job.getAppPath()) + VERBOSE_DELIMITER
1335 + maskIfNull(job.getUser()) + VERBOSE_DELIMITER + maskIfNull(job.getGroup())
1336 + VERBOSE_DELIMITER + job.getStatus() + VERBOSE_DELIMITER
1337 + maskDate(job.getKickoffTime(), timeZoneId, verbose) + VERBOSE_DELIMITER
1338 + maskDate(job.getPauseTime(), timeZoneId, verbose) + VERBOSE_DELIMITER
1339 + maskDate(job.getCreatedTime(), timeZoneId, verbose) + VERBOSE_DELIMITER
1340 + maskIfNull(job.getConsoleUrl()));
1341
1342 System.out.println(RULER);
1343 }
1344 }
1345 else {
1346 System.out.println(String.format(BUNDLE_JOBS_FORMATTER, "Job ID", "Bundle Name", "Status", "Kickoff",
1347 "Created", "User", "Group"));
1348 System.out.println(RULER);
1349
1350 for (BundleJob job : jobs) {
1351 System.out.println(String.format(BUNDLE_JOBS_FORMATTER, maskIfNull(job.getId()),
1352 maskIfNull(job.getAppName()), job.getStatus(),
1353 maskDate(job.getKickoffTime(), timeZoneId, verbose),
1354 maskDate(job.getCreatedTime(), timeZoneId, verbose), maskIfNull(job.getUser()),
1355 maskIfNull(job.getGroup())));
1356 System.out.println(RULER);
1357 }
1358 }
1359 }
1360 else {
1361 System.out.println("No Jobs match your criteria!");
1362 }
1363 }
1364
1365 private void slaCommand(CommandLine commandLine) throws IOException, OozieCLIException {
1366 XOozieClient wc = createXOozieClient(commandLine);
1367 List<String> options = new ArrayList<String>();
1368 for (Option option : commandLine.getOptions()) {
1369 options.add(option.getOpt());
1370 }
1371
1372 String s = commandLine.getOptionValue(OFFSET_OPTION);
1373 int start = Integer.parseInt((s != null) ? s : "0");
1374 s = commandLine.getOptionValue(LEN_OPTION);
1375 int len = Integer.parseInt((s != null) ? s : "100");
1376 String filter = commandLine.getOptionValue(FILTER_OPTION);
1377
1378 try {
1379 wc.getSlaInfo(start, len, filter);
1380 }
1381 catch (OozieClientException ex) {
1382 throw new OozieCLIException(ex.toString(), ex);
1383 }
1384 }
1385
1386 private void adminCommand(CommandLine commandLine) throws OozieCLIException {
1387 XOozieClient wc = createXOozieClient(commandLine);
1388
1389 List<String> options = new ArrayList<String>();
1390 for (Option option : commandLine.getOptions()) {
1391 options.add(option.getOpt());
1392 }
1393
1394 try {
1395 SYSTEM_MODE status = SYSTEM_MODE.NORMAL;
1396 if (options.contains(VERSION_OPTION)) {
1397 System.out.println("Oozie server build version: " + wc.getServerBuildVersion());
1398 }
1399 else if (options.contains(SYSTEM_MODE_OPTION)) {
1400 String systemModeOption = commandLine.getOptionValue(SYSTEM_MODE_OPTION).toUpperCase();
1401 try {
1402 status = SYSTEM_MODE.valueOf(systemModeOption);
1403 }
1404 catch (Exception e) {
1405 throw new OozieCLIException("Invalid input provided for option: " + SYSTEM_MODE_OPTION
1406 + " value given :" + systemModeOption
1407 + " Expected values are: NORMAL/NOWEBSERVICE/SAFEMODE ");
1408 }
1409 wc.setSystemMode(status);
1410 System.out.println("System mode: " + status);
1411 }
1412 else if (options.contains(STATUS_OPTION)) {
1413 status = wc.getSystemMode();
1414 System.out.println("System mode: " + status);
1415 }
1416 else if (options.contains(QUEUE_DUMP_OPTION)) {
1417
1418 List<String> list = wc.getQueueDump();
1419 if (list != null && list.size() != 0) {
1420 for (String str : list) {
1421 System.out.println(str);
1422 }
1423 }
1424 else {
1425 System.out.println("QueueDump is null!");
1426 }
1427 }
1428 }
1429 catch (OozieClientException ex) {
1430 throw new OozieCLIException(ex.toString(), ex);
1431 }
1432 }
1433
1434 private void versionCommand() throws OozieCLIException {
1435 System.out.println("Oozie client build version: "
1436 + BuildInfo.getBuildInfo().getProperty(BuildInfo.BUILD_VERSION));
1437 }
1438
1439 @VisibleForTesting
1440 void printJobs(List<WorkflowJob> jobs, String timeZoneId, boolean verbose) throws IOException {
1441 if (jobs != null && jobs.size() > 0) {
1442 if (verbose) {
1443 System.out.println("Job ID" + VERBOSE_DELIMITER + "App Name" + VERBOSE_DELIMITER + "App Path"
1444 + VERBOSE_DELIMITER + "Console URL" + VERBOSE_DELIMITER + "User" + VERBOSE_DELIMITER + "Group"
1445 + VERBOSE_DELIMITER + "Run" + VERBOSE_DELIMITER + "Created" + VERBOSE_DELIMITER + "Started"
1446 + VERBOSE_DELIMITER + "Status" + VERBOSE_DELIMITER + "Last Modified" + VERBOSE_DELIMITER
1447 + "Ended");
1448 System.out.println(RULER);
1449
1450 for (WorkflowJob job : jobs) {
1451 System.out.println(maskIfNull(job.getId()) + VERBOSE_DELIMITER + maskIfNull(job.getAppName())
1452 + VERBOSE_DELIMITER + maskIfNull(job.getAppPath()) + VERBOSE_DELIMITER
1453 + maskIfNull(job.getConsoleUrl()) + VERBOSE_DELIMITER + maskIfNull(job.getUser())
1454 + VERBOSE_DELIMITER + maskIfNull(job.getGroup()) + VERBOSE_DELIMITER + job.getRun()
1455 + VERBOSE_DELIMITER + maskDate(job.getCreatedTime(), timeZoneId, verbose)
1456 + VERBOSE_DELIMITER + maskDate(job.getStartTime(), timeZoneId, verbose) + VERBOSE_DELIMITER
1457 + job.getStatus() + VERBOSE_DELIMITER
1458 + maskDate(job.getLastModifiedTime(), timeZoneId, verbose) + VERBOSE_DELIMITER
1459 + maskDate(job.getEndTime(), timeZoneId, verbose));
1460
1461 System.out.println(RULER);
1462 }
1463 }
1464 else {
1465 System.out.println(String.format(WORKFLOW_JOBS_FORMATTER, "Job ID", "App Name", "Status", "User",
1466 "Group", "Started", "Ended"));
1467 System.out.println(RULER);
1468
1469 for (WorkflowJob job : jobs) {
1470 System.out.println(String.format(WORKFLOW_JOBS_FORMATTER, maskIfNull(job.getId()),
1471 maskIfNull(job.getAppName()), job.getStatus(), maskIfNull(job.getUser()),
1472 maskIfNull(job.getGroup()), maskDate(job.getStartTime(), timeZoneId, verbose),
1473 maskDate(job.getEndTime(), timeZoneId, verbose)));
1474
1475 System.out.println(RULER);
1476 }
1477 }
1478 }
1479 else {
1480 System.out.println("No Jobs match your criteria!");
1481 }
1482 }
1483
1484 private String maskIfNull(String value) {
1485 if (value != null && value.length() > 0) {
1486 return value;
1487 }
1488 return "-";
1489 }
1490
1491 private String maskDate(Date date, String timeZoneId, boolean verbose) {
1492 if (date == null) {
1493 return "-";
1494 }
1495
1496 SimpleDateFormat dateFormater = null;
1497 if (verbose) {
1498 dateFormater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss zzz", Locale.US);
1499 }
1500 else {
1501 dateFormater = new SimpleDateFormat("yyyy-MM-dd HH:mm zzz", Locale.US);
1502 }
1503
1504 if (timeZoneId != null) {
1505 dateFormater.setTimeZone(TimeZone.getTimeZone(timeZoneId));
1506 }
1507 String dateString = dateFormater.format(date);
1508 // Most TimeZones are 3 or 4 characters; GMT offsets (e.g. GMT-07:00) are 9, so lets remove the "GMT" part to make it 6
1509 // to fit better
1510 Matcher m = GMT_OFFSET_SHORTEN_PATTERN.matcher(dateString);
1511 if (m.matches() && m.groupCount() == 2) {
1512 dateString = m.group(1) + m.group(2);
1513 }
1514 return dateString;
1515 }
1516
1517 private void validateCommand(CommandLine commandLine) throws OozieCLIException {
1518 String[] args = commandLine.getArgs();
1519 if (args.length != 1) {
1520 throw new OozieCLIException("One file must be specified");
1521 }
1522 File file = new File(args[0]);
1523 if (file.exists()) {
1524 try {
1525 List<StreamSource> sources = new ArrayList<StreamSource>();
1526 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1527 "oozie-workflow-0.1.xsd")));
1528 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1529 "shell-action-0.1.xsd")));
1530 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1531 "shell-action-0.2.xsd")));
1532 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1533 "shell-action-0.3.xsd")));
1534 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1535 "email-action-0.1.xsd")));
1536 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1537 "distcp-action-0.1.xsd")));
1538 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1539 "distcp-action-0.2.xsd")));
1540 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1541 "oozie-workflow-0.2.xsd")));
1542 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1543 "oozie-workflow-0.2.5.xsd")));
1544 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1545 "oozie-workflow-0.3.xsd")));
1546 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1547 "oozie-workflow-0.4.xsd")));
1548 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1549 "oozie-workflow-0.5.xsd")));
1550 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1551 "oozie-coordinator-0.1.xsd")));
1552 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1553 "oozie-coordinator-0.2.xsd")));
1554 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1555 "oozie-coordinator-0.3.xsd")));
1556 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1557 "oozie-coordinator-0.4.xsd")));
1558 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1559 "oozie-bundle-0.1.xsd")));
1560 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1561 "oozie-bundle-0.2.xsd")));
1562 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1563 "oozie-sla-0.1.xsd")));
1564 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1565 "oozie-sla-0.2.xsd")));
1566 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1567 "hive-action-0.2.xsd")));
1568 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1569 "hive-action-0.3.xsd")));
1570 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1571 "hive-action-0.4.xsd")));
1572 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1573 "hive-action-0.5.xsd")));
1574 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1575 "sqoop-action-0.2.xsd")));
1576 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1577 "sqoop-action-0.3.xsd")));
1578 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1579 "sqoop-action-0.4.xsd")));
1580 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1581 "ssh-action-0.1.xsd")));
1582 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(
1583 "ssh-action-0.2.xsd")));
1584 SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
1585 Schema schema = factory.newSchema(sources.toArray(new StreamSource[sources.size()]));
1586 Validator validator = schema.newValidator();
1587 validator.validate(new StreamSource(new FileReader(file)));
1588 System.out.println("Valid workflow-app");
1589 }
1590 catch (Exception ex) {
1591 throw new OozieCLIException("Invalid app definition, " + ex.toString(), ex);
1592 }
1593 }
1594 else {
1595 throw new OozieCLIException("File does not exists");
1596 }
1597 }
1598
1599 private void scriptLanguageCommand(CommandLine commandLine, String jobType) throws IOException, OozieCLIException {
1600 List<String> args = commandLine.getArgList();
1601 if (args.size() > 0) {
1602 // checking if args starts with -X (because CLIParser cannot check this)
1603 if (!args.get(0).equals("-X")) {
1604 throw new OozieCLIException("Unrecognized option: " + args.get(0) + " Expecting -X");
1605 }
1606 args.remove(0);
1607 }
1608
1609 if (!commandLine.hasOption(SCRIPTFILE_OPTION)) {
1610 throw new OozieCLIException("Need to specify -file <scriptfile>");
1611 }
1612
1613 if (!commandLine.hasOption(CONFIG_OPTION)) {
1614 throw new OozieCLIException("Need to specify -config <configfile>");
1615 }
1616
1617 try {
1618 XOozieClient wc = createXOozieClient(commandLine);
1619 Properties conf = getConfiguration(wc, commandLine);
1620 String script = commandLine.getOptionValue(SCRIPTFILE_OPTION);
1621 List<String> paramsList = new ArrayList<String>();
1622 if (commandLine.hasOption("P")) {
1623 Properties params = commandLine.getOptionProperties("P");
1624 for (String key : params.stringPropertyNames()) {
1625 paramsList.add(key + "=" + params.getProperty(key));
1626 }
1627 }
1628 System.out.println(JOB_ID_PREFIX + wc.submitScriptLanguage(conf, script, args.toArray(new String[args.size()]),
1629 paramsList.toArray(new String[paramsList.size()]), jobType));
1630 }
1631 catch (OozieClientException ex) {
1632 throw new OozieCLIException(ex.toString(), ex);
1633 }
1634 }
1635
1636 private void infoCommand(CommandLine commandLine) throws OozieCLIException {
1637 for (Option option : commandLine.getOptions()) {
1638 String opt = option.getOpt();
1639 if (opt.equals(INFO_TIME_ZONES_OPTION)) {
1640 printAvailableTimeZones();
1641 }
1642 }
1643 }
1644
1645 private void printAvailableTimeZones() {
1646 System.out.println("The format is \"SHORT_NAME (ID)\"\nGive the ID to the -timezone argument");
1647 System.out.println("GMT offsets can also be used (e.g. GMT-07:00, GMT-0700, GMT+05:30, GMT+0530)");
1648 System.out.println("Available Time Zones:");
1649 for (String tzId : TimeZone.getAvailableIDs()) {
1650 // skip id's that are like "Etc/GMT+01:00" because their display names are like "GMT-01:00", which is confusing
1651 if (!tzId.startsWith("Etc/GMT")) {
1652 TimeZone tZone = TimeZone.getTimeZone(tzId);
1653 System.out.println(" " + tZone.getDisplayName(false, TimeZone.SHORT) + " (" + tzId + ")");
1654 }
1655 }
1656 }
1657
1658
1659 private void mrCommand(CommandLine commandLine) throws IOException, OozieCLIException {
1660 try {
1661 XOozieClient wc = createXOozieClient(commandLine);
1662 Properties conf = getConfiguration(wc, commandLine);
1663
1664 String mapper = conf.getProperty(MAPRED_MAPPER, conf.getProperty(MAPRED_MAPPER_2));
1665 if (mapper == null) {
1666 throw new OozieCLIException("mapper (" + MAPRED_MAPPER + " or " + MAPRED_MAPPER_2 + ") must be specified in conf");
1667 }
1668
1669 String reducer = conf.getProperty(MAPRED_REDUCER, conf.getProperty(MAPRED_REDUCER_2));
1670 if (reducer == null) {
1671 throw new OozieCLIException("reducer (" + MAPRED_REDUCER + " or " + MAPRED_REDUCER_2
1672 + ") must be specified in conf");
1673 }
1674
1675 String inputDir = conf.getProperty(MAPRED_INPUT);
1676 if (inputDir == null) {
1677 throw new OozieCLIException("input dir (" + MAPRED_INPUT +") must be specified in conf");
1678 }
1679
1680 String outputDir = conf.getProperty(MAPRED_OUTPUT);
1681 if (outputDir == null) {
1682 throw new OozieCLIException("output dir (" + MAPRED_OUTPUT +") must be specified in conf");
1683 }
1684
1685 System.out.println(JOB_ID_PREFIX + wc.submitMapReduce(conf));
1686 }
1687 catch (OozieClientException ex) {
1688 throw new OozieCLIException(ex.toString(), ex);
1689 }
1690 }
1691
1692 private String getFirstMissingDependencies(CoordinatorAction action) {
1693 StringBuilder allDeps = new StringBuilder();
1694 String missingDep = action.getMissingDependencies();
1695 boolean depExists = false;
1696 if (missingDep != null && !missingDep.isEmpty()) {
1697 allDeps.append(missingDep.split(INSTANCE_SEPARATOR)[0]);
1698 depExists = true;
1699 }
1700 String pushDeps = action.getPushMissingDependencies();
1701 if (pushDeps != null && !pushDeps.isEmpty()) {
1702 if(depExists) {
1703 allDeps.append(INSTANCE_SEPARATOR);
1704 }
1705 allDeps.append(pushDeps.split(INSTANCE_SEPARATOR)[0]);
1706 }
1707 return allDeps.toString();
1708 }
1709
1710 }