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