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