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