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 }