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 019package org.apache.oozie.cli; 020 021import com.google.common.annotations.VisibleForTesting; 022import org.apache.commons.cli.CommandLine; 023import org.apache.commons.cli.Option; 024import org.apache.commons.cli.OptionBuilder; 025import org.apache.commons.cli.OptionGroup; 026import org.apache.commons.cli.Options; 027import org.apache.commons.cli.ParseException; 028import org.apache.oozie.BuildInfo; 029import org.apache.oozie.client.AuthOozieClient; 030import org.apache.oozie.client.BulkResponse; 031import org.apache.oozie.client.BundleJob; 032import org.apache.oozie.client.CoordinatorAction; 033import org.apache.oozie.client.CoordinatorJob; 034import org.apache.oozie.client.OozieClient; 035import org.apache.oozie.client.OozieClient.SYSTEM_MODE; 036import org.apache.oozie.client.OozieClientException; 037import org.apache.oozie.client.WorkflowAction; 038import org.apache.oozie.client.WorkflowJob; 039import org.apache.oozie.client.XOozieClient; 040import org.apache.oozie.client.rest.JsonTags; 041import org.apache.oozie.client.rest.JsonToBean; 042import org.apache.oozie.client.rest.RestConstants; 043import org.json.simple.JSONArray; 044import org.json.simple.JSONObject; 045import org.w3c.dom.DOMException; 046import org.w3c.dom.Document; 047import org.w3c.dom.Element; 048import org.w3c.dom.Node; 049import org.w3c.dom.NodeList; 050import org.w3c.dom.Text; 051import org.xml.sax.SAXException; 052 053import javax.xml.XMLConstants; 054import javax.xml.parsers.DocumentBuilder; 055import javax.xml.parsers.DocumentBuilderFactory; 056import javax.xml.parsers.ParserConfigurationException; 057import javax.xml.transform.stream.StreamSource; 058import javax.xml.validation.Schema; 059import javax.xml.validation.SchemaFactory; 060import javax.xml.validation.Validator; 061import java.io.File; 062import java.io.FileInputStream; 063import java.io.FileReader; 064import java.io.IOException; 065import java.io.InputStream; 066import java.io.PrintStream; 067import java.text.SimpleDateFormat; 068import java.util.ArrayList; 069import java.util.Date; 070import java.util.List; 071import java.util.Locale; 072import java.util.Map; 073import java.util.Properties; 074import java.util.TimeZone; 075import java.util.TreeMap; 076import java.util.concurrent.Callable; 077import java.util.regex.Matcher; 078import java.util.regex.Pattern; 079 080/** 081 * Oozie command line utility. 082 */ 083public class OozieCLI { 084 public static final String ENV_OOZIE_URL = "OOZIE_URL"; 085 public static final String ENV_OOZIE_DEBUG = "OOZIE_DEBUG"; 086 public static final String ENV_OOZIE_TIME_ZONE = "OOZIE_TIMEZONE"; 087 public static final String ENV_OOZIE_AUTH = "OOZIE_AUTH"; 088 public static final String OOZIE_RETRY_COUNT = "oozie.connection.retry.count"; 089 public static final String WS_HEADER_PREFIX = "header:"; 090 091 public static final String HELP_CMD = "help"; 092 public static final String VERSION_CMD = "version"; 093 public static final String JOB_CMD = "job"; 094 public static final String JOBS_CMD = "jobs"; 095 public static final String ADMIN_CMD = "admin"; 096 public static final String VALIDATE_CMD = "validate"; 097 public static final String SLA_CMD = "sla"; 098 public static final String PIG_CMD = "pig"; 099 public static final String HIVE_CMD = "hive"; 100 public static final String SQOOP_CMD = "sqoop"; 101 public static final String MR_CMD = "mapreduce"; 102 public static final String INFO_CMD = "info"; 103 104 public static final String OOZIE_OPTION = "oozie"; 105 public static final String CONFIG_OPTION = "config"; 106 public static final String SUBMIT_OPTION = "submit"; 107 public static final String OFFSET_OPTION = "offset"; 108 public static final String START_OPTION = "start"; 109 public static final String RUN_OPTION = "run"; 110 public static final String DRYRUN_OPTION = "dryrun"; 111 public static final String SUSPEND_OPTION = "suspend"; 112 public static final String RESUME_OPTION = "resume"; 113 public static final String KILL_OPTION = "kill"; 114 public static final String CHANGE_OPTION = "change"; 115 public static final String CHANGE_VALUE_OPTION = "value"; 116 public static final String RERUN_OPTION = "rerun"; 117 public static final String INFO_OPTION = "info"; 118 public static final String LOG_OPTION = "log"; 119 public static final String ACTION_OPTION = "action"; 120 public static final String DEFINITION_OPTION = "definition"; 121 public static final String CONFIG_CONTENT_OPTION = "configcontent"; 122 public static final String SQOOP_COMMAND_OPTION = "command"; 123 public static final String SHOWDIFF_OPTION = "diff"; 124 public static final String UPDATE_OPTION = "update"; 125 public static final String IGNORE_OPTION = "ignore"; 126 public static final String POLL_OPTION = "poll"; 127 public static final String TIMEOUT_OPTION = "timeout"; 128 public static final String INTERVAL_OPTION = "interval"; 129 130 public static final String DO_AS_OPTION = "doas"; 131 132 public static final String LEN_OPTION = "len"; 133 public static final String FILTER_OPTION = "filter"; 134 public static final String JOBTYPE_OPTION = "jobtype"; 135 public static final String SYSTEM_MODE_OPTION = "systemmode"; 136 public static final String VERSION_OPTION = "version"; 137 public static final String STATUS_OPTION = "status"; 138 public static final String LOCAL_TIME_OPTION = "localtime"; 139 public static final String TIME_ZONE_OPTION = "timezone"; 140 public static final String QUEUE_DUMP_OPTION = "queuedump"; 141 public static final String RERUN_COORD_OPTION = "coordinator"; 142 public static final String DATE_OPTION = "date"; 143 public static final String RERUN_REFRESH_OPTION = "refresh"; 144 public static final String RERUN_NOCLEANUP_OPTION = "nocleanup"; 145 public static final String RERUN_FAILED_OPTION = "failed"; 146 public static final String ORDER_OPTION = "order"; 147 148 public static final String UPDATE_SHARELIB_OPTION = "sharelibupdate"; 149 150 public static final String LIST_SHARELIB_LIB_OPTION = "shareliblist"; 151 152 public static final String SERVER_CONFIGURATION_OPTION = "configuration"; 153 public static final String SERVER_OS_ENV_OPTION = "osenv"; 154 public static final String SERVER_JAVA_SYSTEM_PROPERTIES_OPTION = "javasysprops"; 155 156 public static final String METRICS_OPTION = "metrics"; 157 public static final String INSTRUMENTATION_OPTION = "instrumentation"; 158 159 public static final String AUTH_OPTION = "auth"; 160 161 public static final String VERBOSE_OPTION = "verbose"; 162 public static final String VERBOSE_DELIMITER = "\t"; 163 public static final String DEBUG_OPTION = "debug"; 164 165 public static final String SCRIPTFILE_OPTION = "file"; 166 167 public static final String INFO_TIME_ZONES_OPTION = "timezones"; 168 169 public static final String BULK_OPTION = "bulk"; 170 171 public static final String AVAILABLE_SERVERS_OPTION = "servers"; 172 173 public static final String ALL_WORKFLOWS_FOR_COORD_ACTION = "allruns"; 174 175 private static final String[] OOZIE_HELP = { 176 "the env variable '" + ENV_OOZIE_URL + "' is used as default value for the '-" + OOZIE_OPTION + "' option", 177 "the env variable '" + ENV_OOZIE_TIME_ZONE + "' is used as default value for the '-" + TIME_ZONE_OPTION + "' option", 178 "the env variable '" + ENV_OOZIE_AUTH + "' is used as default value for the '-" + AUTH_OPTION + "' option", 179 "custom headers for Oozie web services can be specified using '-D" + WS_HEADER_PREFIX + "NAME=VALUE'" }; 180 181 private static final String RULER; 182 private static final int LINE_WIDTH = 132; 183 184 private static final int RETRY_COUNT = 4; 185 186 private boolean used; 187 188 private static final String INSTANCE_SEPARATOR = "#"; 189 190 private static final String MAPRED_MAPPER = "mapred.mapper.class"; 191 private static final String MAPRED_MAPPER_2 = "mapreduce.map.class"; 192 private static final String MAPRED_REDUCER = "mapred.reducer.class"; 193 private static final String MAPRED_REDUCER_2 = "mapreduce.reduce.class"; 194 private static final String MAPRED_INPUT = "mapred.input.dir"; 195 private static final String MAPRED_OUTPUT = "mapred.output.dir"; 196 197 private static final Pattern GMT_OFFSET_SHORTEN_PATTERN = Pattern.compile("(.* )GMT((?:-|\\+)\\d{2}:\\d{2})"); 198 199 static { 200 StringBuilder sb = new StringBuilder(); 201 for (int i = 0; i < LINE_WIDTH; i++) { 202 sb.append("-"); 203 } 204 RULER = sb.toString(); 205 } 206 207 /** 208 * Entry point for the Oozie CLI when invoked from the command line. 209 * <p/> 210 * Upon completion this method exits the JVM with '0' (success) or '-1' (failure). 211 * 212 * @param args options and arguments for the Oozie CLI. 213 */ 214 public static void main(String[] args) { 215 if (!System.getProperties().containsKey(AuthOozieClient.USE_AUTH_TOKEN_CACHE_SYS_PROP)) { 216 System.setProperty(AuthOozieClient.USE_AUTH_TOKEN_CACHE_SYS_PROP, "true"); 217 } 218 System.exit(new OozieCLI().run(args)); 219 } 220 221 /** 222 * Create an Oozie CLI instance. 223 */ 224 public OozieCLI() { 225 used = false; 226 } 227 228 /** 229 * Return Oozie CLI top help lines. 230 * 231 * @return help lines. 232 */ 233 protected String[] getCLIHelp() { 234 return OOZIE_HELP; 235 } 236 237 /** 238 * Add authentication specific options to oozie cli 239 * 240 * @param options the collection of options to add auth options 241 */ 242 protected void addAuthOptions(Options options) { 243 Option auth = new Option(AUTH_OPTION, true, "select authentication type [SIMPLE|KERBEROS]"); 244 options.addOption(auth); 245 } 246 247 /** 248 * Create option for command line option 'admin' 249 * @return admin options 250 */ 251 protected Options createAdminOptions() { 252 Option oozie = new Option(OOZIE_OPTION, true, "Oozie URL"); 253 Option system_mode = new Option(SYSTEM_MODE_OPTION, true, 254 "Supported in Oozie-2.0 or later versions ONLY. Change oozie system mode [NORMAL|NOWEBSERVICE|SAFEMODE]"); 255 Option status = new Option(STATUS_OPTION, false, "show the current system status"); 256 Option version = new Option(VERSION_OPTION, false, "show Oozie server build version"); 257 Option queuedump = new Option(QUEUE_DUMP_OPTION, false, "show Oozie server queue elements"); 258 Option doAs = new Option(DO_AS_OPTION, true, "doAs user, impersonates as the specified user"); 259 Option availServers = new Option(AVAILABLE_SERVERS_OPTION, false, "list available Oozie servers" 260 + " (more than one only if HA is enabled)"); 261 Option sharelibUpdate = new Option(UPDATE_SHARELIB_OPTION, false, "Update server to use a newer version of sharelib"); 262 Option serverConfiguration = new Option(SERVER_CONFIGURATION_OPTION, false, "show Oozie system configuration"); 263 Option osEnv = new Option(SERVER_OS_ENV_OPTION, false, "show Oozie system OS environment"); 264 Option javaSysProps = new Option(SERVER_JAVA_SYSTEM_PROPERTIES_OPTION, false, "show Oozie Java system properties"); 265 Option metrics = new Option(METRICS_OPTION, false, "show Oozie system metrics"); 266 Option instrumentation = new Option(INSTRUMENTATION_OPTION, false, "show Oozie system instrumentation"); 267 268 Option sharelib = new Option(LIST_SHARELIB_LIB_OPTION, false, 269 "List available sharelib that can be specified in a workflow action"); 270 sharelib.setOptionalArg(true); 271 272 Options adminOptions = new Options(); 273 adminOptions.addOption(oozie); 274 adminOptions.addOption(doAs); 275 OptionGroup group = new OptionGroup(); 276 group.addOption(system_mode); 277 group.addOption(status); 278 group.addOption(version); 279 group.addOption(queuedump); 280 group.addOption(availServers); 281 group.addOption(sharelibUpdate); 282 group.addOption(sharelib); 283 group.addOption(serverConfiguration); 284 group.addOption(osEnv); 285 group.addOption(javaSysProps); 286 group.addOption(metrics); 287 group.addOption(instrumentation); 288 adminOptions.addOptionGroup(group); 289 addAuthOptions(adminOptions); 290 return adminOptions; 291 } 292 293 /** 294 * Create option for command line option 'job' 295 * @return job options 296 */ 297 protected Options createJobOptions() { 298 Option oozie = new Option(OOZIE_OPTION, true, "Oozie URL"); 299 Option config = new Option(CONFIG_OPTION, true, "job configuration file '.xml' or '.properties'"); 300 Option submit = new Option(SUBMIT_OPTION, false, "submit a job"); 301 Option run = new Option(RUN_OPTION, false, "run a job"); 302 Option debug = new Option(DEBUG_OPTION, false, "Use debug mode to see debugging statements on stdout"); 303 Option rerun = new Option(RERUN_OPTION, true, 304 "rerun a job (coordinator requires -action or -date, bundle requires -coordinator or -date)"); 305 Option dryrun = new Option(DRYRUN_OPTION, false, "Dryrun a workflow (since 3.3.2) or coordinator (since 2.0) job without" 306 + " actually executing it"); 307 Option update = new Option(UPDATE_OPTION, true, "Update coord definition and properties"); 308 Option showdiff = new Option(SHOWDIFF_OPTION, true, 309 "Show diff of the new coord definition and properties with the existing one (default true)"); 310 Option start = new Option(START_OPTION, true, "start a job"); 311 Option suspend = new Option(SUSPEND_OPTION, true, "suspend a job"); 312 Option resume = new Option(RESUME_OPTION, true, "resume a job"); 313 Option kill = new Option(KILL_OPTION, true, "kill a job (coordinator can mention -action or -date)"); 314 Option change = new Option(CHANGE_OPTION, true, "change a coordinator or bundle job"); 315 Option changeValue = new Option(CHANGE_VALUE_OPTION, true, 316 "new endtime/concurrency/pausetime value for changing a coordinator job"); 317 Option info = new Option(INFO_OPTION, true, "info of a job"); 318 Option poll = new Option(POLL_OPTION, true, "poll Oozie until a job reaches a terminal state or a timeout occurs"); 319 Option offset = new Option(OFFSET_OPTION, true, "job info offset of actions (default '1', requires -info)"); 320 Option len = new Option(LEN_OPTION, true, "number of actions (default TOTAL ACTIONS, requires -info)"); 321 Option filter = new Option(FILTER_OPTION, true, 322 "<key><comparator><value>[;<key><comparator><value>]*\n" 323 + "(All Coordinator actions satisfying the filters will be retreived).\n" 324 + "key: status or nominaltime\n" 325 + "comparator: =, !=, <, <=, >, >=. = is used as OR and others as AND\n" 326 + "status: values are valid status like SUCCEEDED, KILLED etc. Only = and != apply for status\n" 327 + "nominaltime: time of format yyyy-MM-dd'T'HH:mm'Z'"); 328 Option order = new Option(ORDER_OPTION, true, 329 "order to show coord actions (default ascending order, 'desc' for descending order, requires -info)"); 330 Option localtime = new Option(LOCAL_TIME_OPTION, false, "use local time (same as passing your time zone to -" + 331 TIME_ZONE_OPTION + "). Overrides -" + TIME_ZONE_OPTION + " option"); 332 Option timezone = new Option(TIME_ZONE_OPTION, true, 333 "use time zone with the specified ID (default GMT).\nSee 'oozie info -timezones' for a list"); 334 Option log = new Option(LOG_OPTION, true, "job log"); 335 Option logFilter = new Option( 336 RestConstants.LOG_FILTER_OPTION, true, 337 "job log search parameter. Can be specified as -logfilter opt1=val1;opt2=val1;opt3=val1. " 338 + "Supported options are recent, start, end, loglevel, text, limit and debug"); 339 Option definition = new Option(DEFINITION_OPTION, true, "job definition"); 340 Option config_content = new Option(CONFIG_CONTENT_OPTION, true, "job configuration"); 341 Option verbose = new Option(VERBOSE_OPTION, false, "verbose mode"); 342 Option action = new Option(ACTION_OPTION, true, 343 "coordinator rerun/kill on action ids (requires -rerun/-kill); coordinator log retrieval on action ids" 344 + "(requires -log)"); 345 Option date = new Option(DATE_OPTION, true, 346 "coordinator/bundle rerun on action dates (requires -rerun); coordinator log retrieval on action dates (requires -log)"); 347 Option rerun_coord = new Option(RERUN_COORD_OPTION, true, "bundle rerun on coordinator names (requires -rerun)"); 348 Option rerun_refresh = new Option(RERUN_REFRESH_OPTION, false, 349 "re-materialize the coordinator rerun actions (requires -rerun)"); 350 Option rerun_nocleanup = new Option(RERUN_NOCLEANUP_OPTION, false, 351 "do not clean up output-events of the coordiantor rerun actions (requires -rerun)"); 352 Option rerun_failed = new Option(RERUN_FAILED_OPTION, false, 353 "runs the failed workflow actions of the coordinator actions (requires -rerun)"); 354 Option property = OptionBuilder.withArgName("property=value").hasArgs(2).withValueSeparator().withDescription( 355 "set/override value for given property").create("D"); 356 Option getAllWorkflows = new Option(ALL_WORKFLOWS_FOR_COORD_ACTION, false, 357 "Get workflow jobs corresponding to a coordinator action including all the reruns"); 358 Option ignore = new Option(IGNORE_OPTION, true, 359 "change status of a coordinator job or action to IGNORED" 360 + " (-action required to ignore coord actions)"); 361 Option timeout = new Option(TIMEOUT_OPTION, true, "timeout in minutes (default is 30, negative values indicate no " 362 + "timeout, requires -poll)"); 363 timeout.setType(Integer.class); 364 Option interval = new Option(INTERVAL_OPTION, true, "polling interval in minutes (default is 5, requires -poll)"); 365 interval.setType(Integer.class); 366 367 Option doAs = new Option(DO_AS_OPTION, true, "doAs user, impersonates as the specified user"); 368 369 OptionGroup actions = new OptionGroup(); 370 actions.addOption(submit); 371 actions.addOption(start); 372 actions.addOption(run); 373 actions.addOption(dryrun); 374 actions.addOption(suspend); 375 actions.addOption(resume); 376 actions.addOption(kill); 377 actions.addOption(change); 378 actions.addOption(update); 379 actions.addOption(info); 380 actions.addOption(rerun); 381 actions.addOption(log); 382 actions.addOption(definition); 383 actions.addOption(config_content); 384 actions.addOption(ignore); 385 actions.addOption(poll); 386 actions.setRequired(true); 387 Options jobOptions = new Options(); 388 jobOptions.addOption(oozie); 389 jobOptions.addOption(doAs); 390 jobOptions.addOption(config); 391 jobOptions.addOption(property); 392 jobOptions.addOption(changeValue); 393 jobOptions.addOption(localtime); 394 jobOptions.addOption(timezone); 395 jobOptions.addOption(verbose); 396 jobOptions.addOption(debug); 397 jobOptions.addOption(offset); 398 jobOptions.addOption(len); 399 jobOptions.addOption(filter); 400 jobOptions.addOption(order); 401 jobOptions.addOption(action); 402 jobOptions.addOption(date); 403 jobOptions.addOption(rerun_coord); 404 jobOptions.addOption(rerun_refresh); 405 jobOptions.addOption(rerun_nocleanup); 406 jobOptions.addOption(rerun_failed); 407 jobOptions.addOption(getAllWorkflows); 408 jobOptions.addOptionGroup(actions); 409 jobOptions.addOption(logFilter); 410 jobOptions.addOption(timeout); 411 jobOptions.addOption(interval); 412 addAuthOptions(jobOptions); 413 jobOptions.addOption(showdiff); 414 415 //Needed to make dryrun and update mutually exclusive options 416 OptionGroup updateOption = new OptionGroup(); 417 updateOption.addOption(dryrun); 418 jobOptions.addOptionGroup(updateOption); 419 return jobOptions; 420 } 421 422 /** 423 * Create option for command line option 'jobs' 424 * @return jobs options 425 */ 426 protected Options createJobsOptions() { 427 Option oozie = new Option(OOZIE_OPTION, true, "Oozie URL"); 428 Option start = new Option(OFFSET_OPTION, true, "jobs offset (default '1')"); 429 Option jobtype = new Option(JOBTYPE_OPTION, true, 430 "job type ('Supported in Oozie-2.0 or later versions ONLY - 'coordinator' or 'bundle' or 'wf'(default))"); 431 Option len = new Option(LEN_OPTION, true, "number of jobs (default '100')"); 432 Option filter = new Option(FILTER_OPTION, true, 433 "user=<U>\\;name=<N>\\;group=<G>\\;status=<S>\\;frequency=<F>\\;unit=<M>" + 434 "\\;startcreatedtime=<SC>\\;endcreatedtime=<EC> " + 435 "(valid unit values are 'months', 'days', 'hours' or 'minutes'. " + 436 "startcreatedtime, endcreatedtime: time of format yyyy-MM-dd'T'HH:mm'Z')"); 437 Option localtime = new Option(LOCAL_TIME_OPTION, false, "use local time (same as passing your time zone to -" + 438 TIME_ZONE_OPTION + "). Overrides -" + TIME_ZONE_OPTION + " option"); 439 Option kill = new Option(KILL_OPTION, false, "bulk kill operation"); 440 Option suspend = new Option(SUSPEND_OPTION, false, "bulk suspend operation"); 441 Option resume = new Option(RESUME_OPTION, false, "bulk resume operation"); 442 Option timezone = new Option(TIME_ZONE_OPTION, true, 443 "use time zone with the specified ID (default GMT).\nSee 'oozie info -timezones' for a list"); 444 Option verbose = new Option(VERBOSE_OPTION, false, "verbose mode"); 445 Option doAs = new Option(DO_AS_OPTION, true, "doAs user, impersonates as the specified user"); 446 Option bulkMonitor = new Option(BULK_OPTION, true, "key-value pairs to filter bulk jobs response. e.g. bundle=<B>\\;" + 447 "coordinators=<C>\\;actionstatus=<S>\\;startcreatedtime=<SC>\\;endcreatedtime=<EC>\\;" + 448 "startscheduledtime=<SS>\\;endscheduledtime=<ES>\\; bundle, coordinators and actionstatus can be multiple comma separated values" + 449 "bundle and coordinators can be id(s) or appName(s) of those jobs. Specifying bundle is mandatory, other params are optional"); 450 start.setType(Integer.class); 451 len.setType(Integer.class); 452 Options jobsOptions = new Options(); 453 jobsOptions.addOption(oozie); 454 jobsOptions.addOption(doAs); 455 jobsOptions.addOption(localtime); 456 jobsOptions.addOption(kill); 457 jobsOptions.addOption(suspend); 458 jobsOptions.addOption(resume); 459 jobsOptions.addOption(timezone); 460 jobsOptions.addOption(start); 461 jobsOptions.addOption(len); 462 jobsOptions.addOption(oozie); 463 jobsOptions.addOption(filter); 464 jobsOptions.addOption(jobtype); 465 jobsOptions.addOption(verbose); 466 jobsOptions.addOption(bulkMonitor); 467 addAuthOptions(jobsOptions); 468 return jobsOptions; 469 } 470 471 /** 472 * Create option for command line option 'sla' 473 * 474 * @return sla options 475 */ 476 protected Options createSlaOptions() { 477 Option oozie = new Option(OOZIE_OPTION, true, "Oozie URL"); 478 Option start = new Option(OFFSET_OPTION, true, "start offset (default '0')"); 479 Option len = new Option(LEN_OPTION, true, "number of results (default '100', max '1000')"); 480 Option filter = new Option(FILTER_OPTION, true, "filter of SLA events. e.g., jobid=<J>\\;appname=<A>"); 481 start.setType(Integer.class); 482 len.setType(Integer.class); 483 Options slaOptions = new Options(); 484 slaOptions.addOption(start); 485 slaOptions.addOption(len); 486 slaOptions.addOption(filter); 487 slaOptions.addOption(oozie); 488 addAuthOptions(slaOptions); 489 return slaOptions; 490 } 491 492 /** 493 * Create option for command line option 'validate' 494 * 495 * @return validate options 496 */ 497 protected Options createValidateOptions() { 498 Option oozie = new Option(OOZIE_OPTION, true, "Oozie URL"); 499 Options validateOption = new Options(); 500 validateOption.addOption(oozie); 501 addAuthOptions(validateOption); 502 return validateOption; 503 } 504 505 /** 506 * Create option for command line option 'pig' or 'hive' 507 * @return pig or hive options 508 */ 509 @SuppressWarnings("static-access") 510 protected Options createScriptLanguageOptions(String jobType) { 511 Option oozie = new Option(OOZIE_OPTION, true, "Oozie URL"); 512 Option config = new Option(CONFIG_OPTION, true, "job configuration file '.properties'"); 513 Option file = new Option(SCRIPTFILE_OPTION, true, jobType + " script"); 514 Option property = OptionBuilder.withArgName("property=value").hasArgs(2).withValueSeparator().withDescription( 515 "set/override value for given property").create("D"); 516 Option params = OptionBuilder.withArgName("property=value").hasArgs(2).withValueSeparator().withDescription( 517 "set parameters for script").create("P"); 518 Option doAs = new Option(DO_AS_OPTION, true, "doAs user, impersonates as the specified user"); 519 Options Options = new Options(); 520 Options.addOption(oozie); 521 Options.addOption(doAs); 522 Options.addOption(config); 523 Options.addOption(property); 524 Options.addOption(params); 525 Options.addOption(file); 526 addAuthOptions(Options); 527 return Options; 528 } 529 530 /** 531 * Create option for command line option 'sqoop' 532 * @return sqoop options 533 */ 534 @SuppressWarnings("static-access") 535 protected Options createSqoopCLIOptions() { 536 Option oozie = new Option(OOZIE_OPTION, true, "Oozie URL"); 537 Option config = new Option(CONFIG_OPTION, true, "job configuration file '.properties'"); 538 Option command = OptionBuilder.withArgName(SQOOP_COMMAND_OPTION).hasArgs().withValueSeparator().withDescription( 539 "sqoop command").create(SQOOP_COMMAND_OPTION); 540 Option property = OptionBuilder.withArgName("property=value").hasArgs(2).withValueSeparator().withDescription( 541 "set/override value for given property").create("D"); 542 Option doAs = new Option(DO_AS_OPTION, true, "doAs user, impersonates as the specified user"); 543 Options Options = new Options(); 544 Options.addOption(oozie); 545 Options.addOption(doAs); 546 Options.addOption(config); 547 Options.addOption(property); 548 Options.addOption(command); 549 addAuthOptions(Options); 550 return Options; 551 } 552 553 /** 554 * Create option for command line option 'info' 555 * @return info options 556 */ 557 protected Options createInfoOptions() { 558 Option timezones = new Option(INFO_TIME_ZONES_OPTION, false, "display a list of available time zones"); 559 Options infoOptions = new Options(); 560 infoOptions.addOption(timezones); 561 return infoOptions; 562 } 563 564 /** 565 * Create option for command line option 'mapreduce' 566 * @return mapreduce options 567 */ 568 @SuppressWarnings("static-access") 569 protected Options createMROptions() { 570 Option oozie = new Option(OOZIE_OPTION, true, "Oozie URL"); 571 Option config = new Option(CONFIG_OPTION, true, "job configuration file '.properties'"); 572 Option property = OptionBuilder.withArgName("property=value").hasArgs(2).withValueSeparator().withDescription( 573 "set/override value for given property").create("D"); 574 Option doAs = new Option(DO_AS_OPTION, true, "doAs user, impersonates as the specified user"); 575 Options mrOptions = new Options(); 576 mrOptions.addOption(oozie); 577 mrOptions.addOption(doAs); 578 mrOptions.addOption(config); 579 mrOptions.addOption(property); 580 addAuthOptions(mrOptions); 581 return mrOptions; 582 } 583 584 /** 585 * Run a CLI programmatically. 586 * <p/> 587 * It does not exit the JVM. 588 * <p/> 589 * A CLI instance can be used only once. 590 * 591 * @param args options and arguments for the Oozie CLI. 592 * @return '0' (success), '-1' (failure). 593 */ 594 public synchronized int run(String[] args) { 595 if (used) { 596 throw new IllegalStateException("CLI instance already used"); 597 } 598 used = true; 599 final CLIParser parser = getCLIParser(); 600 try { 601 final CLIParser.Command command = parser.parse(args); 602 603 String doAsUser = command.getCommandLine().getOptionValue(DO_AS_OPTION); 604 605 if (doAsUser != null) { 606 OozieClient.doAs(doAsUser, new Callable<Void>() { 607 @Override 608 public Void call() throws Exception { 609 processCommand(parser, command); 610 return null; 611 } 612 }); 613 } 614 else { 615 processCommand(parser, command); 616 } 617 return 0; 618 } 619 catch (OozieCLIException ex) { 620 System.err.println("Error: " + ex.getMessage()); 621 return -1; 622 } 623 catch (ParseException ex) { 624 System.err.println("Invalid sub-command: " + ex.getMessage()); 625 System.err.println(); 626 System.err.println(parser.shortHelp()); 627 return -1; 628 } 629 catch (Exception ex) { 630 ex.printStackTrace(); 631 System.err.println(ex.getMessage()); 632 return -1; 633 } 634 } 635 636 @VisibleForTesting 637 public CLIParser getCLIParser(){ 638 CLIParser parser = new CLIParser(OOZIE_OPTION, getCLIHelp()); 639 parser.addCommand(HELP_CMD, "", "display usage for all commands or specified command", new Options(), false); 640 parser.addCommand(VERSION_CMD, "", "show client version", new Options(), false); 641 parser.addCommand(JOB_CMD, "", "job operations", createJobOptions(), false); 642 parser.addCommand(JOBS_CMD, "", "jobs status", createJobsOptions(), false); 643 parser.addCommand(ADMIN_CMD, "", "admin operations", createAdminOptions(), false); 644 parser.addCommand(VALIDATE_CMD, "", "validate a workflow, coordinator, bundle XML file", createValidateOptions(), true); 645 parser.addCommand(SLA_CMD, "", "sla operations (Deprecated with Oozie 4.0)", createSlaOptions(), false); 646 parser.addCommand(PIG_CMD, "-X ", "submit a pig job, everything after '-X' are pass-through parameters to pig, any '-D' " 647 + "arguments after '-X' are put in <configuration>", createScriptLanguageOptions(PIG_CMD), true); 648 parser.addCommand(HIVE_CMD, "-X ", "submit a hive job, everything after '-X' are pass-through parameters to hive, any '-D' " 649 + "arguments after '-X' are put in <configuration>", createScriptLanguageOptions(HIVE_CMD), true); 650 parser.addCommand(SQOOP_CMD, "-X ", "submit a sqoop job, everything after '-X' are pass-through parameters " + 651 "to sqoop, any '-D' arguments after '-X' are put in <configuration>", createSqoopCLIOptions(), true); 652 parser.addCommand(INFO_CMD, "", "get more detailed info about specific topics", createInfoOptions(), false); 653 parser.addCommand(MR_CMD, "", "submit a mapreduce job", createMROptions(), false); 654 return parser; 655 } 656 657 public void processCommand(CLIParser parser, CLIParser.Command command) throws Exception { 658 if (command.getName().equals(HELP_CMD)) { 659 parser.showHelp(command.getCommandLine()); 660 } 661 else if (command.getName().equals(JOB_CMD)) { 662 jobCommand(command.getCommandLine()); 663 } 664 else if (command.getName().equals(JOBS_CMD)) { 665 jobsCommand(command.getCommandLine()); 666 } 667 else if (command.getName().equals(ADMIN_CMD)) { 668 adminCommand(command.getCommandLine()); 669 } 670 else if (command.getName().equals(VERSION_CMD)) { 671 versionCommand(); 672 } 673 else if (command.getName().equals(VALIDATE_CMD)) { 674 validateCommand(command.getCommandLine()); 675 } 676 else if (command.getName().equals(SLA_CMD)) { 677 slaCommand(command.getCommandLine()); 678 } 679 else if (command.getName().equals(PIG_CMD)) { 680 scriptLanguageCommand(command.getCommandLine(), PIG_CMD); 681 } 682 else if (command.getName().equals(HIVE_CMD)) { 683 scriptLanguageCommand(command.getCommandLine(), HIVE_CMD); 684 } 685 else if (command.getName().equals(SQOOP_CMD)) { 686 sqoopCommand(command.getCommandLine()); 687 } 688 else if (command.getName().equals(INFO_CMD)) { 689 infoCommand(command.getCommandLine()); 690 } 691 else if (command.getName().equals(MR_CMD)){ 692 mrCommand(command.getCommandLine()); 693 } 694 } 695 protected String getOozieUrl(CommandLine commandLine) { 696 String url = commandLine.getOptionValue(OOZIE_OPTION); 697 if (url == null) { 698 url = System.getenv(ENV_OOZIE_URL); 699 if (url == null) { 700 throw new IllegalArgumentException( 701 "Oozie URL is not available neither in command option or in the environment"); 702 } 703 } 704 return url; 705 } 706 707 private String getTimeZoneId(CommandLine commandLine) 708 { 709 if (commandLine.hasOption(LOCAL_TIME_OPTION)) { 710 return null; 711 } 712 if (commandLine.hasOption(TIME_ZONE_OPTION)) { 713 return commandLine.getOptionValue(TIME_ZONE_OPTION); 714 } 715 String timeZoneId = System.getenv(ENV_OOZIE_TIME_ZONE); 716 if (timeZoneId != null) { 717 return timeZoneId; 718 } 719 return "GMT"; 720 } 721 722 // Canibalized from Hadoop <code>Configuration.loadResource()</code>. 723 private Properties parse(InputStream is, Properties conf) throws IOException { 724 try { 725 DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); 726 // ignore all comments inside the xml file 727 docBuilderFactory.setIgnoringComments(true); 728 DocumentBuilder builder = docBuilderFactory.newDocumentBuilder(); 729 Document doc = builder.parse(is); 730 return parseDocument(doc, conf); 731 } 732 catch (SAXException e) { 733 throw new IOException(e); 734 } 735 catch (ParserConfigurationException e) { 736 throw new IOException(e); 737 } 738 } 739 740 // Canibalized from Hadoop <code>Configuration.loadResource()</code>. 741 private Properties parseDocument(Document doc, Properties conf) throws IOException { 742 try { 743 Element root = doc.getDocumentElement(); 744 if (!"configuration".equals(root.getTagName())) { 745 throw new RuntimeException("bad conf file: top-level element not <configuration>"); 746 } 747 NodeList props = root.getChildNodes(); 748 for (int i = 0; i < props.getLength(); i++) { 749 Node propNode = props.item(i); 750 if (!(propNode instanceof Element)) { 751 continue; 752 } 753 Element prop = (Element) propNode; 754 if (!"property".equals(prop.getTagName())) { 755 throw new RuntimeException("bad conf file: element not <property>"); 756 } 757 NodeList fields = prop.getChildNodes(); 758 String attr = null; 759 String value = null; 760 for (int j = 0; j < fields.getLength(); j++) { 761 Node fieldNode = fields.item(j); 762 if (!(fieldNode instanceof Element)) { 763 continue; 764 } 765 Element field = (Element) fieldNode; 766 if ("name".equals(field.getTagName()) && field.hasChildNodes()) { 767 attr = ((Text) field.getFirstChild()).getData(); 768 } 769 if ("value".equals(field.getTagName()) && field.hasChildNodes()) { 770 value = ((Text) field.getFirstChild()).getData(); 771 } 772 } 773 774 if (attr != null && value != null) { 775 conf.setProperty(attr, value); 776 } 777 } 778 return conf; 779 } 780 catch (DOMException e) { 781 throw new IOException(e); 782 } 783 } 784 785 private Properties getConfiguration(OozieClient wc, CommandLine commandLine) throws IOException { 786 if (!isConfigurationSpecified(wc, commandLine)) { 787 throw new IOException("configuration is not specified"); 788 } 789 Properties conf = wc.createConfiguration(); 790 String configFile = commandLine.getOptionValue(CONFIG_OPTION); 791 if (configFile != null) { 792 File file = new File(configFile); 793 if (!file.exists()) { 794 throw new IOException("configuration file [" + configFile + "] not found"); 795 } 796 if (configFile.endsWith(".properties")) { 797 conf.load(new FileReader(file)); 798 } 799 else if (configFile.endsWith(".xml")) { 800 parse(new FileInputStream(configFile), conf); 801 } 802 else { 803 throw new IllegalArgumentException("configuration must be a '.properties' or a '.xml' file"); 804 } 805 } 806 if (commandLine.hasOption("D")) { 807 Properties commandLineProperties = commandLine.getOptionProperties("D"); 808 conf.putAll(commandLineProperties); 809 } 810 return conf; 811 } 812 813 /** 814 * Check if configuration has specified 815 * @param wc 816 * @param commandLine 817 * @return 818 * @throws IOException 819 */ 820 private boolean isConfigurationSpecified(OozieClient wc, CommandLine commandLine) throws IOException { 821 boolean isConf = false; 822 String configFile = commandLine.getOptionValue(CONFIG_OPTION); 823 if (configFile == null) { 824 isConf = false; 825 } 826 else { 827 isConf = new File(configFile).exists(); 828 } 829 if (commandLine.hasOption("D")) { 830 isConf = true; 831 } 832 return isConf; 833 } 834 835 /** 836 * @param commandLine command line string. 837 * @return change value specified by -value. 838 * @throws OozieCLIException 839 */ 840 private String getChangeValue(CommandLine commandLine) throws OozieCLIException { 841 String changeValue = commandLine.getOptionValue(CHANGE_VALUE_OPTION); 842 843 if (changeValue == null) { 844 throw new OozieCLIException("-value option needs to be specified for -change option"); 845 } 846 847 return changeValue; 848 } 849 850 protected void addHeader(OozieClient wc) { 851 for (Map.Entry entry : System.getProperties().entrySet()) { 852 String key = (String) entry.getKey(); 853 if (key.startsWith(WS_HEADER_PREFIX)) { 854 String header = key.substring(WS_HEADER_PREFIX.length()); 855 wc.setHeader(header, (String) entry.getValue()); 856 } 857 } 858 } 859 860 /** 861 * Get auth option from command line 862 * 863 * @param commandLine the command line object 864 * @return auth option 865 */ 866 protected String getAuthOption(CommandLine commandLine) { 867 String authOpt = commandLine.getOptionValue(AUTH_OPTION); 868 if (authOpt == null) { 869 authOpt = System.getenv(ENV_OOZIE_AUTH); 870 } 871 if (commandLine.hasOption(DEBUG_OPTION)) { 872 System.out.println(" Auth type : " + authOpt); 873 } 874 return authOpt; 875 } 876 877 /** 878 * Create a OozieClient. 879 * <p/> 880 * It injects any '-Dheader:' as header to the the {@link org.apache.oozie.client.OozieClient}. 881 * 882 * @param commandLine the parsed command line options. 883 * @return a pre configured eXtended workflow client. 884 * @throws OozieCLIException thrown if the OozieClient could not be configured. 885 */ 886 protected OozieClient createOozieClient(CommandLine commandLine) throws OozieCLIException { 887 return createXOozieClient(commandLine); 888 } 889 890 /** 891 * Create a XOozieClient. 892 * <p/> 893 * It injects any '-Dheader:' as header to the the {@link org.apache.oozie.client.OozieClient}. 894 * 895 * @param commandLine the parsed command line options. 896 * @return a pre configured eXtended workflow client. 897 * @throws OozieCLIException thrown if the XOozieClient could not be configured. 898 */ 899 protected XOozieClient createXOozieClient(CommandLine commandLine) throws OozieCLIException { 900 XOozieClient wc = new AuthOozieClient(getOozieUrl(commandLine), getAuthOption(commandLine)); 901 addHeader(wc); 902 setDebugMode(wc,commandLine.hasOption(DEBUG_OPTION)); 903 setRetryCount(wc); 904 return wc; 905 } 906 907 protected void setDebugMode(OozieClient wc, boolean debugOpt) { 908 909 String debug = System.getenv(ENV_OOZIE_DEBUG); 910 if (debug != null && !debug.isEmpty()) { 911 int debugVal = 0; 912 try { 913 debugVal = Integer.parseInt(debug.trim()); 914 } 915 catch (Exception ex) { 916 System.out.println("Unable to parse the debug settings. May be not an integer [" + debug + "]"); 917 ex.printStackTrace(); 918 } 919 wc.setDebugMode(debugVal); 920 } 921 else if(debugOpt){ // CLI argument "-debug" used 922 wc.setDebugMode(1); 923 } 924 } 925 926 protected void setRetryCount(OozieClient wc) { 927 String retryCount = System.getProperty(OOZIE_RETRY_COUNT); 928 if (retryCount != null && !retryCount.isEmpty()) { 929 try { 930 int retry = Integer.parseInt(retryCount.trim()); 931 wc.setRetryCount(retry); 932 } 933 catch (Exception ex) { 934 System.err.println("Unable to parse the retry settings. May be not an integer [" + retryCount + "]"); 935 ex.printStackTrace(); 936 } 937 } 938 } 939 940 private static String JOB_ID_PREFIX = "job: "; 941 942 private void jobCommand(CommandLine commandLine) throws IOException, OozieCLIException { 943 XOozieClient wc = createXOozieClient(commandLine); 944 945 List<String> options = new ArrayList<String>(); 946 for (Option option : commandLine.getOptions()) { 947 options.add(option.getOpt()); 948 } 949 950 try { 951 if (options.contains(SUBMIT_OPTION)) { 952 System.out.println(JOB_ID_PREFIX + wc.submit(getConfiguration(wc, commandLine))); 953 } 954 else if (options.contains(START_OPTION)) { 955 wc.start(commandLine.getOptionValue(START_OPTION)); 956 } 957 else if (options.contains(DRYRUN_OPTION) && !options.contains(UPDATE_OPTION)) { 958 String dryrunStr = wc.dryrun(getConfiguration(wc, commandLine)); 959 if (dryrunStr.equals("OK")) { // workflow 960 System.out.println("OK"); 961 } else { // coordinator 962 String[] dryrunStrs = dryrunStr.split("action for new instance"); 963 int arraysize = dryrunStrs.length; 964 System.out.println("***coordJob after parsing: ***"); 965 System.out.println(dryrunStrs[0]); 966 int aLen = dryrunStrs.length - 1; 967 if (aLen < 0) { 968 aLen = 0; 969 } 970 System.out.println("***total coord actions is " + aLen + " ***"); 971 for (int i = 1; i <= arraysize - 1; i++) { 972 System.out.println(RULER); 973 System.out.println("coordAction instance: " + i + ":"); 974 System.out.println(dryrunStrs[i]); 975 } 976 } 977 } 978 else if (options.contains(SUSPEND_OPTION)) { 979 wc.suspend(commandLine.getOptionValue(SUSPEND_OPTION)); 980 } 981 else if (options.contains(RESUME_OPTION)) { 982 wc.resume(commandLine.getOptionValue(RESUME_OPTION)); 983 } 984 else if (options.contains(IGNORE_OPTION)) { 985 String ignoreScope = null; 986 if (options.contains(ACTION_OPTION)) { 987 ignoreScope = commandLine.getOptionValue(ACTION_OPTION); 988 if (ignoreScope == null || ignoreScope.isEmpty()) { 989 throw new OozieCLIException("-" + ACTION_OPTION + " is empty"); 990 } 991 } 992 printCoordActionsStatus(wc.ignore(commandLine.getOptionValue(IGNORE_OPTION), ignoreScope)); 993 } 994 else if (options.contains(KILL_OPTION)) { 995 if (commandLine.getOptionValue(KILL_OPTION).contains("-C") 996 && (options.contains(DATE_OPTION) || options.contains(ACTION_OPTION))) { 997 String coordJobId = commandLine.getOptionValue(KILL_OPTION); 998 String scope = null; 999 String rangeType = null; 1000 if (options.contains(DATE_OPTION) && options.contains(ACTION_OPTION)) { 1001 throw new OozieCLIException("Invalid options provided for rerun: either" + DATE_OPTION + " or " 1002 + ACTION_OPTION + " expected. Don't use both at the same time."); 1003 } 1004 if (options.contains(DATE_OPTION)) { 1005 rangeType = RestConstants.JOB_COORD_SCOPE_DATE; 1006 scope = commandLine.getOptionValue(DATE_OPTION); 1007 } 1008 else if (options.contains(ACTION_OPTION)) { 1009 rangeType = RestConstants.JOB_COORD_SCOPE_ACTION; 1010 scope = commandLine.getOptionValue(ACTION_OPTION); 1011 } 1012 else { 1013 throw new OozieCLIException("Invalid options provided for rerun: " + DATE_OPTION + " or " 1014 + ACTION_OPTION + " expected."); 1015 } 1016 printCoordActions(wc.kill(coordJobId, rangeType, scope)); 1017 } 1018 else { 1019 wc.kill(commandLine.getOptionValue(KILL_OPTION)); 1020 } 1021 } 1022 else if (options.contains(CHANGE_OPTION)) { 1023 wc.change(commandLine.getOptionValue(CHANGE_OPTION), getChangeValue(commandLine)); 1024 } 1025 else if (options.contains(RUN_OPTION)) { 1026 System.out.println(JOB_ID_PREFIX + wc.run(getConfiguration(wc, commandLine))); 1027 } 1028 else if (options.contains(RERUN_OPTION)) { 1029 if (commandLine.getOptionValue(RERUN_OPTION).contains("-W")) { 1030 if (isConfigurationSpecified(wc, commandLine)) { 1031 wc.reRun(commandLine.getOptionValue(RERUN_OPTION), getConfiguration(wc, commandLine)); 1032 } 1033 else { 1034 wc.reRun(commandLine.getOptionValue(RERUN_OPTION), new Properties()); 1035 } 1036 } 1037 else if (commandLine.getOptionValue(RERUN_OPTION).contains("-B")) { 1038 String bundleJobId = commandLine.getOptionValue(RERUN_OPTION); 1039 String coordScope = null; 1040 String dateScope = null; 1041 boolean refresh = false; 1042 boolean noCleanup = false; 1043 if (options.contains(ACTION_OPTION)) { 1044 throw new OozieCLIException("Invalid options provided for bundle rerun. " + ACTION_OPTION 1045 + " is not valid for bundle rerun"); 1046 } 1047 if (options.contains(DATE_OPTION)) { 1048 dateScope = commandLine.getOptionValue(DATE_OPTION); 1049 } 1050 1051 if (options.contains(RERUN_COORD_OPTION)) { 1052 coordScope = commandLine.getOptionValue(RERUN_COORD_OPTION); 1053 } 1054 1055 if (options.contains(RERUN_REFRESH_OPTION)) { 1056 refresh = true; 1057 } 1058 if (options.contains(RERUN_NOCLEANUP_OPTION)) { 1059 noCleanup = true; 1060 } 1061 wc.reRunBundle(bundleJobId, coordScope, dateScope, refresh, noCleanup); 1062 if (coordScope != null && !coordScope.isEmpty()) { 1063 System.out.println("Coordinators [" + coordScope + "] of bundle " + bundleJobId 1064 + " are scheduled to rerun on date ranges [" + dateScope + "]."); 1065 } 1066 else { 1067 System.out.println("All coordinators of bundle " + bundleJobId 1068 + " are scheduled to rerun on the date ranges [" + dateScope + "]."); 1069 } 1070 } 1071 else { 1072 String coordJobId = commandLine.getOptionValue(RERUN_OPTION); 1073 String scope = null; 1074 String rerunType = null; 1075 boolean refresh = false; 1076 boolean noCleanup = false; 1077 if (options.contains(DATE_OPTION) && options.contains(ACTION_OPTION)) { 1078 throw new OozieCLIException("Invalid options provided for rerun: either" + DATE_OPTION + " or " 1079 + ACTION_OPTION + " expected. Don't use both at the same time."); 1080 } 1081 if (options.contains(DATE_OPTION)) { 1082 rerunType = RestConstants.JOB_COORD_SCOPE_DATE; 1083 scope = commandLine.getOptionValue(DATE_OPTION); 1084 } 1085 else if (options.contains(ACTION_OPTION)) { 1086 rerunType = RestConstants.JOB_COORD_SCOPE_ACTION; 1087 scope = commandLine.getOptionValue(ACTION_OPTION); 1088 } 1089 else { 1090 throw new OozieCLIException("Invalid options provided for rerun: " + DATE_OPTION + " or " 1091 + ACTION_OPTION + " expected."); 1092 } 1093 if (options.contains(RERUN_REFRESH_OPTION)) { 1094 refresh = true; 1095 } 1096 if (options.contains(RERUN_NOCLEANUP_OPTION)) { 1097 noCleanup = true; 1098 } 1099 if (options.contains(RERUN_FAILED_OPTION)) { 1100 printCoordActions(wc.reRunCoord(coordJobId, rerunType, scope, refresh, noCleanup, true)); 1101 } else { 1102 printCoordActions(wc.reRunCoord(coordJobId, rerunType, scope, refresh, noCleanup)); 1103 } 1104 } 1105 } 1106 else if (options.contains(INFO_OPTION)) { 1107 String timeZoneId = getTimeZoneId(commandLine); 1108 final String optionValue = commandLine.getOptionValue(INFO_OPTION); 1109 if (optionValue.endsWith("-B")) { 1110 String filter = commandLine.getOptionValue(FILTER_OPTION); 1111 if (filter != null) { 1112 throw new OozieCLIException("Filter option is currently not supported for a Bundle job"); 1113 } 1114 printBundleJob(wc.getBundleJobInfo(optionValue), timeZoneId, 1115 options.contains(VERBOSE_OPTION)); 1116 } 1117 else if (optionValue.endsWith("-C")) { 1118 String s = commandLine.getOptionValue(OFFSET_OPTION); 1119 int start = Integer.parseInt((s != null) ? s : "-1"); 1120 s = commandLine.getOptionValue(LEN_OPTION); 1121 int len = Integer.parseInt((s != null) ? s : "-1"); 1122 String filter = commandLine.getOptionValue(FILTER_OPTION); 1123 String order = commandLine.getOptionValue(ORDER_OPTION); 1124 printCoordJob(wc.getCoordJobInfo(optionValue, filter, start, len, order), timeZoneId, 1125 options.contains(VERBOSE_OPTION)); 1126 } 1127 else if (optionValue.contains("-C@")) { 1128 if (options.contains(ALL_WORKFLOWS_FOR_COORD_ACTION)) { 1129 printWfsForCoordAction(wc.getWfsForCoordAction(optionValue), timeZoneId); 1130 } 1131 else { 1132 String filter = commandLine.getOptionValue(FILTER_OPTION); 1133 if (filter != null) { 1134 throw new OozieCLIException("Filter option is not supported for a Coordinator action"); 1135 } 1136 printCoordAction(wc.getCoordActionInfo(optionValue), timeZoneId); 1137 } 1138 } 1139 else if (optionValue.contains("-W@")) { 1140 String filter = commandLine.getOptionValue(FILTER_OPTION); 1141 if (filter != null) { 1142 throw new OozieCLIException("Filter option is not supported for a Workflow action"); 1143 } 1144 printWorkflowAction(wc.getWorkflowActionInfo(optionValue), timeZoneId, 1145 options.contains(VERBOSE_OPTION)); 1146 } 1147 else { 1148 String filter = commandLine.getOptionValue(FILTER_OPTION); 1149 if (filter != null) { 1150 throw new OozieCLIException("Filter option is currently not supported for a Workflow job"); 1151 } 1152 String s = commandLine.getOptionValue(OFFSET_OPTION); 1153 int start = Integer.parseInt((s != null) ? s : "0"); 1154 s = commandLine.getOptionValue(LEN_OPTION); 1155 String jobtype = commandLine.getOptionValue(JOBTYPE_OPTION); 1156 jobtype = (jobtype != null) ? jobtype : "wf"; 1157 int len = Integer.parseInt((s != null) ? s : "0"); 1158 printJob(wc.getJobInfo(optionValue, start, len), timeZoneId, 1159 options.contains(VERBOSE_OPTION)); 1160 } 1161 } 1162 else if (options.contains(LOG_OPTION)) { 1163 PrintStream ps = System.out; 1164 String logFilter = null; 1165 if (options.contains(RestConstants.LOG_FILTER_OPTION)) { 1166 logFilter = commandLine.getOptionValue(RestConstants.LOG_FILTER_OPTION); 1167 } 1168 if (commandLine.getOptionValue(LOG_OPTION).contains("-C")) { 1169 String logRetrievalScope = null; 1170 String logRetrievalType = null; 1171 if (options.contains(ACTION_OPTION)) { 1172 logRetrievalType = RestConstants.JOB_LOG_ACTION; 1173 logRetrievalScope = commandLine.getOptionValue(ACTION_OPTION); 1174 } 1175 if (options.contains(DATE_OPTION)) { 1176 logRetrievalType = RestConstants.JOB_LOG_DATE; 1177 logRetrievalScope = commandLine.getOptionValue(DATE_OPTION); 1178 } 1179 try { 1180 wc.getJobLog(commandLine.getOptionValue(LOG_OPTION), logRetrievalType, logRetrievalScope, 1181 logFilter, ps); 1182 } 1183 finally { 1184 ps.close(); 1185 } 1186 } 1187 else { 1188 if (!options.contains(ACTION_OPTION) && !options.contains(DATE_OPTION)) { 1189 wc.getJobLog(commandLine.getOptionValue(LOG_OPTION), null, null, logFilter, ps); 1190 } 1191 else { 1192 throw new OozieCLIException("Invalid options provided for log retrieval. " + ACTION_OPTION 1193 + " and " + DATE_OPTION + " are valid only for coordinator job log retrieval"); 1194 } 1195 } 1196 } 1197 else if (options.contains(DEFINITION_OPTION)) { 1198 System.out.println(wc.getJobDefinition(commandLine.getOptionValue(DEFINITION_OPTION))); 1199 } 1200 else if (options.contains(CONFIG_CONTENT_OPTION)) { 1201 if (commandLine.getOptionValue(CONFIG_CONTENT_OPTION).endsWith("-C")) { 1202 System.out.println(wc.getCoordJobInfo(commandLine.getOptionValue(CONFIG_CONTENT_OPTION)).getConf()); 1203 } 1204 else if (commandLine.getOptionValue(CONFIG_CONTENT_OPTION).endsWith("-W")) { 1205 System.out.println(wc.getJobInfo(commandLine.getOptionValue(CONFIG_CONTENT_OPTION)).getConf()); 1206 } 1207 else if (commandLine.getOptionValue(CONFIG_CONTENT_OPTION).endsWith("-B")) { 1208 System.out 1209 .println(wc.getBundleJobInfo(commandLine.getOptionValue(CONFIG_CONTENT_OPTION)).getConf()); 1210 } 1211 else { 1212 System.out.println("ERROR: job id [" + commandLine.getOptionValue(CONFIG_CONTENT_OPTION) 1213 + "] doesn't end with either C or W or B"); 1214 } 1215 } 1216 else if (options.contains(UPDATE_OPTION)) { 1217 String coordJobId = commandLine.getOptionValue(UPDATE_OPTION); 1218 Properties conf = null; 1219 1220 String dryrun = ""; 1221 String showdiff = ""; 1222 1223 if (commandLine.getOptionValue(CONFIG_OPTION) != null) { 1224 conf = getConfiguration(wc, commandLine); 1225 } 1226 if (options.contains(DRYRUN_OPTION)) { 1227 dryrun = "true"; 1228 } 1229 if (commandLine.getOptionValue(SHOWDIFF_OPTION) != null) { 1230 showdiff = commandLine.getOptionValue(SHOWDIFF_OPTION); 1231 } 1232 if (conf == null) { 1233 System.out.println(wc.updateCoord(coordJobId, dryrun, showdiff)); 1234 } 1235 else { 1236 System.out.println(wc.updateCoord(coordJobId, conf, dryrun, showdiff)); 1237 } 1238 } 1239 else if (options.contains(POLL_OPTION)) { 1240 String jobId = commandLine.getOptionValue(POLL_OPTION); 1241 int timeout = 30; 1242 int interval = 5; 1243 String timeoutS = commandLine.getOptionValue(TIMEOUT_OPTION); 1244 if (timeoutS != null) { 1245 timeout = Integer.parseInt(timeoutS); 1246 } 1247 String intervalS = commandLine.getOptionValue(INTERVAL_OPTION); 1248 if (intervalS != null) { 1249 interval = Integer.parseInt(intervalS); 1250 } 1251 boolean verbose = commandLine.hasOption(VERBOSE_OPTION); 1252 wc.pollJob(jobId, timeout, interval, verbose); 1253 } 1254 } 1255 catch (OozieClientException ex) { 1256 throw new OozieCLIException(ex.toString(), ex); 1257 } 1258 } 1259 1260 @VisibleForTesting 1261 void printCoordJob(CoordinatorJob coordJob, String timeZoneId, boolean verbose) { 1262 System.out.println("Job ID : " + coordJob.getId()); 1263 1264 System.out.println(RULER); 1265 1266 List<CoordinatorAction> actions = coordJob.getActions(); 1267 System.out.println("Job Name : " + maskIfNull(coordJob.getAppName())); 1268 System.out.println("App Path : " + maskIfNull(coordJob.getAppPath())); 1269 System.out.println("Status : " + coordJob.getStatus()); 1270 System.out.println("Start Time : " + maskDate(coordJob.getStartTime(), timeZoneId, false)); 1271 System.out.println("End Time : " + maskDate(coordJob.getEndTime(), timeZoneId, false)); 1272 System.out.println("Pause Time : " + maskDate(coordJob.getPauseTime(), timeZoneId, false)); 1273 System.out.println("Concurrency : " + coordJob.getConcurrency()); 1274 System.out.println(RULER); 1275 1276 if (verbose) { 1277 System.out.println("ID" + VERBOSE_DELIMITER + "Action Number" + VERBOSE_DELIMITER + "Console URL" 1278 + VERBOSE_DELIMITER + "Error Code" + VERBOSE_DELIMITER + "Error Message" + VERBOSE_DELIMITER 1279 + "External ID" + VERBOSE_DELIMITER + "External Status" + VERBOSE_DELIMITER + "Job ID" 1280 + VERBOSE_DELIMITER + "Tracker URI" + VERBOSE_DELIMITER + "Created" + VERBOSE_DELIMITER 1281 + "Nominal Time" + VERBOSE_DELIMITER + "Status" + VERBOSE_DELIMITER + "Last Modified" 1282 + VERBOSE_DELIMITER + "Missing Dependencies"); 1283 System.out.println(RULER); 1284 1285 for (CoordinatorAction action : actions) { 1286 System.out.println(maskIfNull(action.getId()) + VERBOSE_DELIMITER + action.getActionNumber() 1287 + VERBOSE_DELIMITER + maskIfNull(action.getConsoleUrl()) + VERBOSE_DELIMITER 1288 + maskIfNull(action.getErrorCode()) + VERBOSE_DELIMITER + maskIfNull(action.getErrorMessage()) 1289 + VERBOSE_DELIMITER + maskIfNull(action.getExternalId()) + VERBOSE_DELIMITER 1290 + maskIfNull(action.getExternalStatus()) + VERBOSE_DELIMITER + maskIfNull(action.getJobId()) 1291 + VERBOSE_DELIMITER + maskIfNull(action.getTrackerUri()) + VERBOSE_DELIMITER 1292 + maskDate(action.getCreatedTime(), timeZoneId, verbose) + VERBOSE_DELIMITER 1293 + maskDate(action.getNominalTime(), timeZoneId, verbose) + action.getStatus() + VERBOSE_DELIMITER 1294 + maskDate(action.getLastModifiedTime(), timeZoneId, verbose) + VERBOSE_DELIMITER 1295 + maskIfNull(getFirstMissingDependencies(action))); 1296 1297 System.out.println(RULER); 1298 } 1299 } 1300 else { 1301 System.out.println(String.format(COORD_ACTION_FORMATTER, "ID", "Status", "Ext ID", "Err Code", "Created", 1302 "Nominal Time", "Last Mod")); 1303 1304 for (CoordinatorAction action : actions) { 1305 System.out.println(String.format(COORD_ACTION_FORMATTER, maskIfNull(action.getId()), 1306 action.getStatus(), maskIfNull(action.getExternalId()), maskIfNull(action.getErrorCode()), 1307 maskDate(action.getCreatedTime(), timeZoneId, verbose), maskDate(action.getNominalTime(), timeZoneId, verbose), 1308 maskDate(action.getLastModifiedTime(), timeZoneId, verbose))); 1309 1310 System.out.println(RULER); 1311 } 1312 } 1313 } 1314 1315 @VisibleForTesting 1316 void printBundleJob(BundleJob bundleJob, String timeZoneId, boolean verbose) { 1317 System.out.println("Job ID : " + bundleJob.getId()); 1318 1319 System.out.println(RULER); 1320 1321 List<CoordinatorJob> coordinators = bundleJob.getCoordinators(); 1322 System.out.println("Job Name : " + maskIfNull(bundleJob.getAppName())); 1323 System.out.println("App Path : " + maskIfNull(bundleJob.getAppPath())); 1324 System.out.println("Status : " + bundleJob.getStatus()); 1325 System.out.println("Kickoff time : " + bundleJob.getKickoffTime()); 1326 System.out.println(RULER); 1327 1328 System.out.println(String.format(BUNDLE_COORD_JOBS_FORMATTER, "Job ID", "Status", "Freq", "Unit", "Started", 1329 "Next Materialized")); 1330 System.out.println(RULER); 1331 1332 for (CoordinatorJob job : coordinators) { 1333 System.out.println(String.format(BUNDLE_COORD_JOBS_FORMATTER, maskIfNull(job.getId()), job.getStatus(), 1334 job.getFrequency(), job.getTimeUnit(), maskDate(job.getStartTime(), timeZoneId, verbose), 1335 maskDate(job.getNextMaterializedTime(), timeZoneId, verbose))); 1336 1337 System.out.println(RULER); 1338 } 1339 } 1340 1341 @VisibleForTesting 1342 void printCoordAction(CoordinatorAction coordAction, String timeZoneId) { 1343 System.out.println("ID : " + maskIfNull(coordAction.getId())); 1344 1345 System.out.println(RULER); 1346 1347 System.out.println("Action Number : " + coordAction.getActionNumber()); 1348 System.out.println("Console URL : " + maskIfNull(coordAction.getConsoleUrl())); 1349 System.out.println("Error Code : " + maskIfNull(coordAction.getErrorCode())); 1350 System.out.println("Error Message : " + maskIfNull(coordAction.getErrorMessage())); 1351 System.out.println("External ID : " + maskIfNull(coordAction.getExternalId())); 1352 System.out.println("External Status : " + maskIfNull(coordAction.getExternalStatus())); 1353 System.out.println("Job ID : " + maskIfNull(coordAction.getJobId())); 1354 System.out.println("Tracker URI : " + maskIfNull(coordAction.getTrackerUri())); 1355 System.out.println("Created : " + maskDate(coordAction.getCreatedTime(), timeZoneId, false)); 1356 System.out.println("Nominal Time : " + maskDate(coordAction.getNominalTime(), timeZoneId, false)); 1357 System.out.println("Status : " + coordAction.getStatus()); 1358 System.out.println("Last Modified : " + maskDate(coordAction.getLastModifiedTime(), timeZoneId, false)); 1359 System.out.println("First Missing Dependency : " + maskIfNull(getFirstMissingDependencies(coordAction))); 1360 1361 System.out.println(RULER); 1362 } 1363 1364 private void printCoordActions(List<CoordinatorAction> actions) { 1365 if (actions != null && actions.size() > 0) { 1366 System.out.println("Action ID" + VERBOSE_DELIMITER + "Nominal Time"); 1367 System.out.println(RULER); 1368 for (CoordinatorAction action : actions) { 1369 System.out.println(maskIfNull(action.getId()) + VERBOSE_DELIMITER 1370 + maskDate(action.getNominalTime(), null,false)); 1371 } 1372 } 1373 else { 1374 System.out.println("No Actions match your criteria!"); 1375 } 1376 } 1377 1378 private void printCoordActionsStatus(List<CoordinatorAction> actions) { 1379 if (actions != null && actions.size() > 0) { 1380 System.out.println("Action ID" + VERBOSE_DELIMITER + "Nominal Time" + VERBOSE_DELIMITER + "Status"); 1381 System.out.println(RULER); 1382 for (CoordinatorAction action : actions) { 1383 System.out.println(maskIfNull(action.getId()) + VERBOSE_DELIMITER 1384 + maskDate(action.getNominalTime(), null, false) + VERBOSE_DELIMITER 1385 + maskIfNull(action.getStatus().name())); 1386 } 1387 } 1388 } 1389 1390 @VisibleForTesting 1391 void printWorkflowAction(WorkflowAction action, String timeZoneId, boolean verbose) { 1392 1393 System.out.println("ID : " + maskIfNull(action.getId())); 1394 1395 System.out.println(RULER); 1396 1397 System.out.println("Console URL : " + maskIfNull(action.getConsoleUrl())); 1398 System.out.println("Error Code : " + maskIfNull(action.getErrorCode())); 1399 System.out.println("Error Message : " + maskIfNull(action.getErrorMessage())); 1400 System.out.println("External ID : " + maskIfNull(action.getExternalId())); 1401 System.out.println("External Status : " + maskIfNull(action.getExternalStatus())); 1402 System.out.println("Name : " + maskIfNull(action.getName())); 1403 System.out.println("Retries : " + action.getRetries()); 1404 System.out.println("Tracker URI : " + maskIfNull(action.getTrackerUri())); 1405 System.out.println("Type : " + maskIfNull(action.getType())); 1406 System.out.println("Started : " + maskDate(action.getStartTime(), timeZoneId, verbose)); 1407 System.out.println("Status : " + action.getStatus()); 1408 System.out.println("Ended : " + maskDate(action.getEndTime(), timeZoneId, verbose)); 1409 1410 if (verbose) { 1411 System.out.println("External Stats : " + action.getStats()); 1412 System.out.println("External ChildIDs : " + action.getExternalChildIDs()); 1413 } 1414 1415 System.out.println(RULER); 1416 } 1417 1418 private static final String WORKFLOW_JOBS_FORMATTER = "%-41s%-13s%-10s%-10s%-10s%-24s%-24s"; 1419 private static final String COORD_JOBS_FORMATTER = "%-41s%-15s%-10s%-5s%-13s%-24s%-24s"; 1420 private static final String BUNDLE_JOBS_FORMATTER = "%-41s%-15s%-10s%-20s%-20s%-13s%-13s"; 1421 private static final String BUNDLE_COORD_JOBS_FORMATTER = "%-41s%-15s%-5s%-13s%-24s%-24s"; 1422 1423 private static final String WORKFLOW_ACTION_FORMATTER = "%-78s%-10s%-23s%-11s%-10s"; 1424 private static final String COORD_ACTION_FORMATTER = "%-43s%-10s%-37s%-10s%-21s%-21s"; 1425 private static final String BULK_RESPONSE_FORMATTER = "%-13s%-38s%-13s%-41s%-10s%-38s%-21s%-38s"; 1426 1427 @VisibleForTesting 1428 void printJob(WorkflowJob job, String timeZoneId, boolean verbose) throws IOException { 1429 System.out.println("Job ID : " + maskIfNull(job.getId())); 1430 1431 System.out.println(RULER); 1432 1433 System.out.println("Workflow Name : " + maskIfNull(job.getAppName())); 1434 System.out.println("App Path : " + maskIfNull(job.getAppPath())); 1435 System.out.println("Status : " + job.getStatus()); 1436 System.out.println("Run : " + job.getRun()); 1437 System.out.println("User : " + maskIfNull(job.getUser())); 1438 System.out.println("Group : " + maskIfNull(job.getGroup())); 1439 System.out.println("Created : " + maskDate(job.getCreatedTime(), timeZoneId, verbose)); 1440 System.out.println("Started : " + maskDate(job.getStartTime(), timeZoneId, verbose)); 1441 System.out.println("Last Modified : " + maskDate(job.getLastModifiedTime(), timeZoneId, verbose)); 1442 System.out.println("Ended : " + maskDate(job.getEndTime(), timeZoneId, verbose)); 1443 System.out.println("CoordAction ID: " + maskIfNull(job.getParentId())); 1444 1445 List<WorkflowAction> actions = job.getActions(); 1446 1447 if (actions != null && actions.size() > 0) { 1448 System.out.println(); 1449 System.out.println("Actions"); 1450 System.out.println(RULER); 1451 1452 if (verbose) { 1453 System.out.println("ID" + VERBOSE_DELIMITER + "Console URL" + VERBOSE_DELIMITER + "Error Code" 1454 + VERBOSE_DELIMITER + "Error Message" + VERBOSE_DELIMITER + "External ID" + VERBOSE_DELIMITER 1455 + "External Status" + VERBOSE_DELIMITER + "Name" + VERBOSE_DELIMITER + "Retries" 1456 + VERBOSE_DELIMITER + "Tracker URI" + VERBOSE_DELIMITER + "Type" + VERBOSE_DELIMITER 1457 + "Started" + VERBOSE_DELIMITER + "Status" + VERBOSE_DELIMITER + "Ended"); 1458 System.out.println(RULER); 1459 1460 for (WorkflowAction action : job.getActions()) { 1461 System.out.println(maskIfNull(action.getId()) + VERBOSE_DELIMITER 1462 + maskIfNull(action.getConsoleUrl()) + VERBOSE_DELIMITER 1463 + maskIfNull(action.getErrorCode()) + VERBOSE_DELIMITER 1464 + maskIfNull(action.getErrorMessage()) + VERBOSE_DELIMITER 1465 + maskIfNull(action.getExternalId()) + VERBOSE_DELIMITER 1466 + maskIfNull(action.getExternalStatus()) + VERBOSE_DELIMITER + maskIfNull(action.getName()) 1467 + VERBOSE_DELIMITER + action.getRetries() + VERBOSE_DELIMITER 1468 + maskIfNull(action.getTrackerUri()) + VERBOSE_DELIMITER + maskIfNull(action.getType()) 1469 + VERBOSE_DELIMITER + maskDate(action.getStartTime(), timeZoneId, verbose) 1470 + VERBOSE_DELIMITER + action.getStatus() + VERBOSE_DELIMITER 1471 + maskDate(action.getEndTime(), timeZoneId, verbose)); 1472 1473 System.out.println(RULER); 1474 } 1475 } 1476 else { 1477 System.out.println(String.format(WORKFLOW_ACTION_FORMATTER, "ID", "Status", "Ext ID", "Ext Status", 1478 "Err Code")); 1479 1480 System.out.println(RULER); 1481 1482 for (WorkflowAction action : job.getActions()) { 1483 System.out.println(String.format(WORKFLOW_ACTION_FORMATTER, maskIfNull(action.getId()), action 1484 .getStatus(), maskIfNull(action.getExternalId()), maskIfNull(action.getExternalStatus()), 1485 maskIfNull(action.getErrorCode()))); 1486 1487 System.out.println(RULER); 1488 } 1489 } 1490 } 1491 else { 1492 System.out.println(RULER); 1493 } 1494 1495 System.out.println(); 1496 } 1497 1498 private void jobsCommand(CommandLine commandLine) throws IOException, OozieCLIException { 1499 XOozieClient wc = createXOozieClient(commandLine); 1500 1501 List<String> options = new ArrayList<String>(); 1502 for (Option option : commandLine.getOptions()) { 1503 options.add(option.getOpt()); 1504 } 1505 1506 String filter = commandLine.getOptionValue(FILTER_OPTION); 1507 String s = commandLine.getOptionValue(OFFSET_OPTION); 1508 int start = Integer.parseInt((s != null) ? s : "0"); 1509 s = commandLine.getOptionValue(LEN_OPTION); 1510 String jobtype = commandLine.getOptionValue(JOBTYPE_OPTION); 1511 String timeZoneId = getTimeZoneId(commandLine); 1512 jobtype = (jobtype != null) ? jobtype : "wf"; 1513 int len = Integer.parseInt((s != null) ? s : "0"); 1514 String bulkFilterString = commandLine.getOptionValue(BULK_OPTION); 1515 1516 try { 1517 if (options.contains(KILL_OPTION)) { 1518 printBulkModifiedJobs(wc.killJobs(filter, jobtype, start, len), timeZoneId, "killed"); 1519 } 1520 else if (options.contains(SUSPEND_OPTION)) { 1521 printBulkModifiedJobs(wc.suspendJobs(filter, jobtype, start, len), timeZoneId, "suspended"); 1522 } 1523 else if (options.contains(RESUME_OPTION)) { 1524 printBulkModifiedJobs(wc.resumeJobs(filter, jobtype, start, len), timeZoneId, "resumed"); 1525 } 1526 else if (bulkFilterString != null) { 1527 printBulkJobs(wc.getBulkInfo(bulkFilterString, start, len), timeZoneId, commandLine.hasOption(VERBOSE_OPTION)); 1528 } 1529 else if (jobtype.toLowerCase().contains("wf")) { 1530 printJobs(wc.getJobsInfo(filter, start, len), timeZoneId, commandLine.hasOption(VERBOSE_OPTION)); 1531 } 1532 else if (jobtype.toLowerCase().startsWith("coord")) { 1533 printCoordJobs(wc.getCoordJobsInfo(filter, start, len), timeZoneId, commandLine.hasOption(VERBOSE_OPTION)); 1534 } 1535 else if (jobtype.toLowerCase().startsWith("bundle")) { 1536 printBundleJobs(wc.getBundleJobsInfo(filter, start, len), timeZoneId, commandLine.hasOption(VERBOSE_OPTION)); 1537 } 1538 1539 } 1540 catch (OozieClientException ex) { 1541 throw new OozieCLIException(ex.toString(), ex); 1542 } 1543 } 1544 1545 @VisibleForTesting 1546 void printBulkModifiedJobs(JSONObject json, String timeZoneId, String action) throws IOException { 1547 if (json.containsKey(JsonTags.WORKFLOWS_JOBS)) { 1548 JSONArray workflows = (JSONArray) json.get(JsonTags.WORKFLOWS_JOBS); 1549 if (workflows == null) { 1550 workflows = new JSONArray(); 1551 } 1552 List<WorkflowJob> wfs = JsonToBean.createWorkflowJobList(workflows); 1553 if (wfs.isEmpty()) { 1554 System.out.println("bulk modify command did not modify any jobs"); 1555 } 1556 else { 1557 System.out.println("the following jobs have been " + action); 1558 printJobs(wfs, timeZoneId, false); 1559 } 1560 } 1561 else if (json.containsKey(JsonTags.COORDINATOR_JOBS)) { 1562 JSONArray coordinators = (JSONArray) json.get(JsonTags.COORDINATOR_JOBS); 1563 if (coordinators == null) { 1564 coordinators = new JSONArray(); 1565 } 1566 List<CoordinatorJob> coords = JsonToBean.createCoordinatorJobList(coordinators); 1567 if (coords.isEmpty()) { 1568 System.out.println("bulk modify command did not modify any jobs"); 1569 } 1570 else { 1571 System.out.println("the following jobs have been " + action); 1572 printCoordJobs(coords, timeZoneId, false); 1573 } 1574 } 1575 else { 1576 JSONArray bundles = (JSONArray) json.get(JsonTags.BUNDLE_JOBS); 1577 if (bundles == null) { 1578 bundles = new JSONArray(); 1579 } 1580 List<BundleJob> bundleJobs = JsonToBean.createBundleJobList(bundles); 1581 if (bundleJobs.isEmpty()) { 1582 System.out.println("bulk modify command did not modify any jobs"); 1583 } 1584 else { 1585 System.out.println("the following jobs have been " + action); 1586 printBundleJobs(bundleJobs, timeZoneId, false); 1587 } 1588 } 1589 } 1590 1591 @VisibleForTesting 1592 void printCoordJobs(List<CoordinatorJob> jobs, String timeZoneId, boolean verbose) throws IOException { 1593 if (jobs != null && jobs.size() > 0) { 1594 if (verbose) { 1595 System.out.println("Job ID" + VERBOSE_DELIMITER + "App Name" + VERBOSE_DELIMITER + "App Path" 1596 + VERBOSE_DELIMITER + "Console URL" + VERBOSE_DELIMITER + "User" + VERBOSE_DELIMITER + "Group" 1597 + VERBOSE_DELIMITER + "Concurrency" + VERBOSE_DELIMITER + "Frequency" + VERBOSE_DELIMITER 1598 + "Time Unit" + VERBOSE_DELIMITER + "Time Zone" + VERBOSE_DELIMITER + "Time Out" 1599 + VERBOSE_DELIMITER + "Started" + VERBOSE_DELIMITER + "Next Materialize" + VERBOSE_DELIMITER 1600 + "Status" + VERBOSE_DELIMITER + "Last Action" + VERBOSE_DELIMITER + "Ended"); 1601 System.out.println(RULER); 1602 1603 for (CoordinatorJob job : jobs) { 1604 System.out.println(maskIfNull(job.getId()) + VERBOSE_DELIMITER + maskIfNull(job.getAppName()) 1605 + VERBOSE_DELIMITER + maskIfNull(job.getAppPath()) + VERBOSE_DELIMITER 1606 + maskIfNull(job.getConsoleUrl()) + VERBOSE_DELIMITER + maskIfNull(job.getUser()) 1607 + VERBOSE_DELIMITER + maskIfNull(job.getGroup()) + VERBOSE_DELIMITER + job.getConcurrency() 1608 + VERBOSE_DELIMITER + job.getFrequency() + VERBOSE_DELIMITER + job.getTimeUnit() 1609 + VERBOSE_DELIMITER + maskIfNull(job.getTimeZone()) + VERBOSE_DELIMITER + job.getTimeout() 1610 + VERBOSE_DELIMITER + maskDate(job.getStartTime(), timeZoneId, verbose) + VERBOSE_DELIMITER 1611 + maskDate(job.getNextMaterializedTime(), timeZoneId, verbose) + VERBOSE_DELIMITER 1612 + job.getStatus() + VERBOSE_DELIMITER 1613 + maskDate(job.getLastActionTime(), timeZoneId, verbose) + VERBOSE_DELIMITER 1614 + maskDate(job.getEndTime(), timeZoneId, verbose)); 1615 1616 System.out.println(RULER); 1617 } 1618 } 1619 else { 1620 System.out.println(String.format(COORD_JOBS_FORMATTER, "Job ID", "App Name", "Status", "Freq", "Unit", 1621 "Started", "Next Materialized")); 1622 System.out.println(RULER); 1623 1624 for (CoordinatorJob job : jobs) { 1625 System.out.println(String.format(COORD_JOBS_FORMATTER, maskIfNull(job.getId()), maskIfNull(job 1626 .getAppName()), job.getStatus(), job.getFrequency(), job.getTimeUnit(), maskDate(job 1627 .getStartTime(), timeZoneId, verbose), maskDate(job.getNextMaterializedTime(), timeZoneId, verbose))); 1628 1629 System.out.println(RULER); 1630 } 1631 } 1632 } 1633 else { 1634 System.out.println("No Jobs match your criteria!"); 1635 } 1636 } 1637 1638 @VisibleForTesting 1639 void printBulkJobs(List<BulkResponse> jobs, String timeZoneId, boolean verbose) throws IOException { 1640 if (jobs != null && jobs.size() > 0) { 1641 for (BulkResponse response : jobs) { 1642 BundleJob bundle = response.getBundle(); 1643 CoordinatorJob coord = response.getCoordinator(); 1644 CoordinatorAction action = response.getAction(); 1645 if (verbose) { 1646 System.out.println(); 1647 System.out.println("Bundle Name : " + maskIfNull(bundle.getAppName())); 1648 1649 System.out.println(RULER); 1650 1651 System.out.println("Bundle ID : " + maskIfNull(bundle.getId())); 1652 System.out.println("Coordinator Name : " + maskIfNull(coord.getAppName())); 1653 System.out.println("Coord Action ID : " + maskIfNull(action.getId())); 1654 System.out.println("Action Status : " + action.getStatus()); 1655 System.out.println("External ID : " + maskIfNull(action.getExternalId())); 1656 System.out.println("Created Time : " + maskDate(action.getCreatedTime(), timeZoneId, false)); 1657 System.out.println("User : " + maskIfNull(bundle.getUser())); 1658 System.out.println("Error Message : " + maskIfNull(action.getErrorMessage())); 1659 System.out.println(RULER); 1660 } 1661 else { 1662 System.out.println(String.format(BULK_RESPONSE_FORMATTER, "Bundle Name", "Bundle ID", "Coord Name", 1663 "Coord Action ID", "Status", "External ID", "Created Time", "Error Message")); 1664 System.out.println(RULER); 1665 System.out 1666 .println(String.format(BULK_RESPONSE_FORMATTER, maskIfNull(bundle.getAppName()), 1667 maskIfNull(bundle.getId()), maskIfNull(coord.getAppName()), 1668 maskIfNull(action.getId()), action.getStatus(), maskIfNull(action.getExternalId()), 1669 maskDate(action.getCreatedTime(), timeZoneId, false), 1670 maskIfNull(action.getErrorMessage()))); 1671 System.out.println(RULER); 1672 } 1673 } 1674 } 1675 else { 1676 System.out.println("Bulk request criteria did not match any coordinator actions"); 1677 } 1678 } 1679 1680 @VisibleForTesting 1681 void printBundleJobs(List<BundleJob> jobs, String timeZoneId, boolean verbose) throws IOException { 1682 if (jobs != null && jobs.size() > 0) { 1683 if (verbose) { 1684 System.out.println("Job ID" + VERBOSE_DELIMITER + "Bundle Name" + VERBOSE_DELIMITER + "Bundle Path" 1685 + VERBOSE_DELIMITER + "User" + VERBOSE_DELIMITER + "Group" + VERBOSE_DELIMITER + "Status" 1686 + VERBOSE_DELIMITER + "Kickoff" + VERBOSE_DELIMITER + "Pause" + VERBOSE_DELIMITER + "Created" 1687 + VERBOSE_DELIMITER + "Console URL"); 1688 System.out.println(RULER); 1689 1690 for (BundleJob job : jobs) { 1691 System.out.println(maskIfNull(job.getId()) + VERBOSE_DELIMITER + maskIfNull(job.getAppName()) 1692 + VERBOSE_DELIMITER + maskIfNull(job.getAppPath()) + VERBOSE_DELIMITER 1693 + maskIfNull(job.getUser()) + VERBOSE_DELIMITER + maskIfNull(job.getGroup()) 1694 + VERBOSE_DELIMITER + job.getStatus() + VERBOSE_DELIMITER 1695 + maskDate(job.getKickoffTime(), timeZoneId, verbose) + VERBOSE_DELIMITER 1696 + maskDate(job.getPauseTime(), timeZoneId, verbose) + VERBOSE_DELIMITER 1697 + maskDate(job.getCreatedTime(), timeZoneId, verbose) + VERBOSE_DELIMITER 1698 + maskIfNull(job.getConsoleUrl())); 1699 1700 System.out.println(RULER); 1701 } 1702 } 1703 else { 1704 System.out.println(String.format(BUNDLE_JOBS_FORMATTER, "Job ID", "Bundle Name", "Status", "Kickoff", 1705 "Created", "User", "Group")); 1706 System.out.println(RULER); 1707 1708 for (BundleJob job : jobs) { 1709 System.out.println(String.format(BUNDLE_JOBS_FORMATTER, maskIfNull(job.getId()), 1710 maskIfNull(job.getAppName()), job.getStatus(), 1711 maskDate(job.getKickoffTime(), timeZoneId, verbose), 1712 maskDate(job.getCreatedTime(), timeZoneId, verbose), maskIfNull(job.getUser()), 1713 maskIfNull(job.getGroup()))); 1714 System.out.println(RULER); 1715 } 1716 } 1717 } 1718 else { 1719 System.out.println("No Jobs match your criteria!"); 1720 } 1721 } 1722 1723 private void slaCommand(CommandLine commandLine) throws IOException, OozieCLIException { 1724 XOozieClient wc = createXOozieClient(commandLine); 1725 List<String> options = new ArrayList<String>(); 1726 for (Option option : commandLine.getOptions()) { 1727 options.add(option.getOpt()); 1728 } 1729 1730 String s = commandLine.getOptionValue(OFFSET_OPTION); 1731 int start = Integer.parseInt((s != null) ? s : "0"); 1732 s = commandLine.getOptionValue(LEN_OPTION); 1733 int len = Integer.parseInt((s != null) ? s : "100"); 1734 String filter = commandLine.getOptionValue(FILTER_OPTION); 1735 1736 try { 1737 wc.getSlaInfo(start, len, filter); 1738 } 1739 catch (OozieClientException ex) { 1740 throw new OozieCLIException(ex.toString(), ex); 1741 } 1742 } 1743 1744 private void adminCommand(CommandLine commandLine) throws OozieCLIException { 1745 XOozieClient wc = createXOozieClient(commandLine); 1746 1747 List<String> options = new ArrayList<String>(); 1748 for (Option option : commandLine.getOptions()) { 1749 options.add(option.getOpt()); 1750 } 1751 1752 try { 1753 SYSTEM_MODE status = SYSTEM_MODE.NORMAL; 1754 if (options.contains(VERSION_OPTION)) { 1755 System.out.println("Oozie server build version: " + wc.getServerBuildVersion()); 1756 } 1757 else if (options.contains(SYSTEM_MODE_OPTION)) { 1758 String systemModeOption = commandLine.getOptionValue(SYSTEM_MODE_OPTION).toUpperCase(); 1759 try { 1760 status = SYSTEM_MODE.valueOf(systemModeOption); 1761 } 1762 catch (Exception e) { 1763 throw new OozieCLIException("Invalid input provided for option: " + SYSTEM_MODE_OPTION 1764 + " value given :" + systemModeOption 1765 + " Expected values are: NORMAL/NOWEBSERVICE/SAFEMODE "); 1766 } 1767 wc.setSystemMode(status); 1768 System.out.println("System mode: " + status); 1769 } 1770 else if (options.contains(STATUS_OPTION)) { 1771 status = wc.getSystemMode(); 1772 System.out.println("System mode: " + status); 1773 } 1774 1775 else if (options.contains(UPDATE_SHARELIB_OPTION)) { 1776 System.out.println(wc.updateShareLib()); 1777 } 1778 1779 else if (options.contains(LIST_SHARELIB_LIB_OPTION)) { 1780 String sharelibKey = null; 1781 if (commandLine.getArgList().size() > 0) { 1782 sharelibKey = (String) commandLine.getArgList().get(0); 1783 } 1784 System.out.println(wc.listShareLib(sharelibKey)); 1785 } 1786 1787 else if (options.contains(QUEUE_DUMP_OPTION)) { 1788 1789 List<String> list = wc.getQueueDump(); 1790 if (list != null && list.size() != 0) { 1791 for (String str : list) { 1792 System.out.println(str); 1793 } 1794 } 1795 else { 1796 System.out.println("QueueDump is null!"); 1797 } 1798 } 1799 else if (options.contains(AVAILABLE_SERVERS_OPTION)) { 1800 Map<String, String> availableOozieServers = new TreeMap<String, String>(wc.getAvailableOozieServers()); 1801 for (Map.Entry<String, String> ent : availableOozieServers.entrySet()) { 1802 System.out.println(ent.getKey() + " : " + ent.getValue()); 1803 } 1804 } else if (options.contains(SERVER_CONFIGURATION_OPTION)) { 1805 Map<String, String> serverConfig = new TreeMap<String, String>(wc.getServerConfiguration()); 1806 for (Map.Entry<String, String> ent : serverConfig.entrySet()) { 1807 System.out.println(ent.getKey() + " : " + ent.getValue()); 1808 } 1809 } else if (options.contains(SERVER_OS_ENV_OPTION)) { 1810 Map<String, String> osEnv = new TreeMap<String, String>(wc.getOSEnv()); 1811 for (Map.Entry<String, String> ent : osEnv.entrySet()) { 1812 System.out.println(ent.getKey() + " : " + ent.getValue()); 1813 } 1814 } else if (options.contains(SERVER_JAVA_SYSTEM_PROPERTIES_OPTION)) { 1815 Map<String, String> javaSysProps = new TreeMap<String, String>(wc.getJavaSystemProperties()); 1816 for (Map.Entry<String, String> ent : javaSysProps.entrySet()) { 1817 System.out.println(ent.getKey() + " : " + ent.getValue()); 1818 } 1819 } else if (options.contains(METRICS_OPTION)) { 1820 OozieClient.Metrics metrics = wc.getMetrics(); 1821 if (metrics == null) { 1822 System.out.println("Metrics are unavailable. Try Instrumentation (-" + INSTRUMENTATION_OPTION + ") instead"); 1823 } else { 1824 printMetrics(metrics); 1825 } 1826 } else if (options.contains(INSTRUMENTATION_OPTION)) { 1827 OozieClient.Instrumentation instrumentation = wc.getInstrumentation(); 1828 if (instrumentation == null) { 1829 System.out.println("Instrumentation is unavailable. Try Metrics (-" + METRICS_OPTION + ") instead"); 1830 } else { 1831 printInstrumentation(instrumentation); 1832 } 1833 } 1834 } 1835 catch (OozieClientException ex) { 1836 throw new OozieCLIException(ex.toString(), ex); 1837 } 1838 } 1839 1840 private void versionCommand() throws OozieCLIException { 1841 System.out.println("Oozie client build version: " 1842 + BuildInfo.getBuildInfo().getProperty(BuildInfo.BUILD_VERSION)); 1843 } 1844 1845 @VisibleForTesting 1846 void printJobs(List<WorkflowJob> jobs, String timeZoneId, boolean verbose) throws IOException { 1847 if (jobs != null && jobs.size() > 0) { 1848 if (verbose) { 1849 System.out.println("Job ID" + VERBOSE_DELIMITER + "App Name" + VERBOSE_DELIMITER + "App Path" 1850 + VERBOSE_DELIMITER + "Console URL" + VERBOSE_DELIMITER + "User" + VERBOSE_DELIMITER + "Group" 1851 + VERBOSE_DELIMITER + "Run" + VERBOSE_DELIMITER + "Created" + VERBOSE_DELIMITER + "Started" 1852 + VERBOSE_DELIMITER + "Status" + VERBOSE_DELIMITER + "Last Modified" + VERBOSE_DELIMITER 1853 + "Ended"); 1854 System.out.println(RULER); 1855 1856 for (WorkflowJob job : jobs) { 1857 System.out.println(maskIfNull(job.getId()) + VERBOSE_DELIMITER + maskIfNull(job.getAppName()) 1858 + VERBOSE_DELIMITER + maskIfNull(job.getAppPath()) + VERBOSE_DELIMITER 1859 + maskIfNull(job.getConsoleUrl()) + VERBOSE_DELIMITER + maskIfNull(job.getUser()) 1860 + VERBOSE_DELIMITER + maskIfNull(job.getGroup()) + VERBOSE_DELIMITER + job.getRun() 1861 + VERBOSE_DELIMITER + maskDate(job.getCreatedTime(), timeZoneId, verbose) 1862 + VERBOSE_DELIMITER + maskDate(job.getStartTime(), timeZoneId, verbose) + VERBOSE_DELIMITER 1863 + job.getStatus() + VERBOSE_DELIMITER 1864 + maskDate(job.getLastModifiedTime(), timeZoneId, verbose) + VERBOSE_DELIMITER 1865 + maskDate(job.getEndTime(), timeZoneId, verbose)); 1866 1867 System.out.println(RULER); 1868 } 1869 } 1870 else { 1871 System.out.println(String.format(WORKFLOW_JOBS_FORMATTER, "Job ID", "App Name", "Status", "User", 1872 "Group", "Started", "Ended")); 1873 System.out.println(RULER); 1874 1875 for (WorkflowJob job : jobs) { 1876 System.out.println(String.format(WORKFLOW_JOBS_FORMATTER, maskIfNull(job.getId()), 1877 maskIfNull(job.getAppName()), job.getStatus(), maskIfNull(job.getUser()), 1878 maskIfNull(job.getGroup()), maskDate(job.getStartTime(), timeZoneId, verbose), 1879 maskDate(job.getEndTime(), timeZoneId, verbose))); 1880 1881 System.out.println(RULER); 1882 } 1883 } 1884 } 1885 else { 1886 System.out.println("No Jobs match your criteria!"); 1887 } 1888 } 1889 1890 void printWfsForCoordAction(List<WorkflowJob> jobs, String timeZoneId) throws IOException { 1891 if (jobs != null && jobs.size() > 0) { 1892 System.out.println(String.format("%-41s%-10s%-24s%-24s", "Job ID", "Status", "Started", "Ended")); 1893 System.out.println(RULER); 1894 1895 for (WorkflowJob job : jobs) { 1896 System.out 1897 .println(String.format("%-41s%-10s%-24s%-24s", maskIfNull(job.getId()), job.getStatus(), 1898 maskDate(job.getStartTime(), timeZoneId, false), 1899 maskDate(job.getEndTime(), timeZoneId, false))); 1900 System.out.println(RULER); 1901 } 1902 } 1903 } 1904 1905 private String maskIfNull(String value) { 1906 if (value != null && value.length() > 0) { 1907 return value; 1908 } 1909 return "-"; 1910 } 1911 1912 private String maskDate(Date date, String timeZoneId, boolean verbose) { 1913 if (date == null) { 1914 return "-"; 1915 } 1916 1917 SimpleDateFormat dateFormater = null; 1918 if (verbose) { 1919 dateFormater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss zzz", Locale.US); 1920 } 1921 else { 1922 dateFormater = new SimpleDateFormat("yyyy-MM-dd HH:mm zzz", Locale.US); 1923 } 1924 1925 if (timeZoneId != null) { 1926 dateFormater.setTimeZone(TimeZone.getTimeZone(timeZoneId)); 1927 } 1928 String dateString = dateFormater.format(date); 1929 // 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 1930 // to fit better 1931 Matcher m = GMT_OFFSET_SHORTEN_PATTERN.matcher(dateString); 1932 if (m.matches() && m.groupCount() == 2) { 1933 dateString = m.group(1) + m.group(2); 1934 } 1935 return dateString; 1936 } 1937 1938 private void validateCommand(CommandLine commandLine) throws OozieCLIException { 1939 String[] args = commandLine.getArgs(); 1940 if (args.length != 1) { 1941 throw new OozieCLIException("One file must be specified"); 1942 } 1943 try { 1944 XOozieClient wc = createXOozieClient(commandLine); 1945 String result = wc.validateXML(args[0].toString()); 1946 if (result == null) { 1947 // TODO This is only for backward compatibility. Need to remove after 4.2.0 higher version. 1948 System.out.println("Using client-side validation. Check out Oozie server version."); 1949 validateCommandV41(commandLine); 1950 return; 1951 } 1952 System.out.println(result); 1953 } catch (OozieClientException e) { 1954 throw new OozieCLIException(e.getMessage(), e); 1955 } 1956 } 1957 1958 /** 1959 * Validate on client-side. This is only for backward compatibility. Need to removed after <tt>4.2.0</tt> higher version. 1960 * @param commandLine 1961 * @throws OozieCLIException 1962 */ 1963 @Deprecated 1964 @VisibleForTesting 1965 void validateCommandV41(CommandLine commandLine) throws OozieCLIException { 1966 String[] args = commandLine.getArgs(); 1967 if (args.length != 1) { 1968 throw new OozieCLIException("One file must be specified"); 1969 } 1970 File file = new File(args[0]); 1971 if (file.exists()) { 1972 try { 1973 List<StreamSource> sources = new ArrayList<StreamSource>(); 1974 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 1975 "oozie-workflow-0.1.xsd"))); 1976 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 1977 "shell-action-0.1.xsd"))); 1978 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 1979 "shell-action-0.2.xsd"))); 1980 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 1981 "shell-action-0.3.xsd"))); 1982 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 1983 "email-action-0.1.xsd"))); 1984 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 1985 "email-action-0.2.xsd"))); 1986 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 1987 "distcp-action-0.1.xsd"))); 1988 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 1989 "distcp-action-0.2.xsd"))); 1990 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 1991 "oozie-workflow-0.2.xsd"))); 1992 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 1993 "oozie-workflow-0.2.5.xsd"))); 1994 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 1995 "oozie-workflow-0.3.xsd"))); 1996 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 1997 "oozie-workflow-0.4.xsd"))); 1998 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 1999 "oozie-workflow-0.4.5.xsd"))); 2000 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 2001 "oozie-workflow-0.5.xsd"))); 2002 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 2003 "oozie-coordinator-0.1.xsd"))); 2004 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 2005 "oozie-coordinator-0.2.xsd"))); 2006 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 2007 "oozie-coordinator-0.3.xsd"))); 2008 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 2009 "oozie-coordinator-0.4.xsd"))); 2010 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 2011 "oozie-bundle-0.1.xsd"))); 2012 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 2013 "oozie-bundle-0.2.xsd"))); 2014 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 2015 "oozie-sla-0.1.xsd"))); 2016 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 2017 "oozie-sla-0.2.xsd"))); 2018 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 2019 "hive-action-0.2.xsd"))); 2020 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 2021 "hive-action-0.3.xsd"))); 2022 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 2023 "hive-action-0.4.xsd"))); 2024 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 2025 "hive-action-0.5.xsd"))); 2026 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 2027 "hive-action-0.6.xsd"))); 2028 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 2029 "sqoop-action-0.2.xsd"))); 2030 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 2031 "sqoop-action-0.3.xsd"))); 2032 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 2033 "sqoop-action-0.4.xsd"))); 2034 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 2035 "ssh-action-0.1.xsd"))); 2036 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 2037 "ssh-action-0.2.xsd"))); 2038 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 2039 "hive2-action-0.1.xsd"))); 2040 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 2041 "hive2-action-0.2.xsd"))); 2042 sources.add(new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream( 2043 "spark-action-0.1.xsd"))); 2044 SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 2045 Schema schema = factory.newSchema(sources.toArray(new StreamSource[sources.size()])); 2046 Validator validator = schema.newValidator(); 2047 validator.validate(new StreamSource(new FileReader(file))); 2048 System.out.println("Valid workflow-app"); 2049 } 2050 catch (Exception ex) { 2051 throw new OozieCLIException("Invalid app definition, " + ex.toString(), ex); 2052 } 2053 } 2054 else { 2055 throw new OozieCLIException("File does not exists"); 2056 } 2057 } 2058 2059 private void scriptLanguageCommand(CommandLine commandLine, String jobType) throws IOException, OozieCLIException { 2060 List<String> args = commandLine.getArgList(); 2061 if (args.size() > 0) { 2062 // checking if args starts with -X (because CLIParser cannot check this) 2063 if (!args.get(0).equals("-X")) { 2064 throw new OozieCLIException("Unrecognized option: " + args.get(0) + " Expecting -X"); 2065 } 2066 args.remove(0); 2067 } 2068 2069 if (!commandLine.hasOption(SCRIPTFILE_OPTION)) { 2070 throw new OozieCLIException("Need to specify -file <scriptfile>"); 2071 } 2072 2073 if (!commandLine.hasOption(CONFIG_OPTION)) { 2074 throw new OozieCLIException("Need to specify -config <configfile>"); 2075 } 2076 2077 try { 2078 XOozieClient wc = createXOozieClient(commandLine); 2079 Properties conf = getConfiguration(wc, commandLine); 2080 String script = commandLine.getOptionValue(SCRIPTFILE_OPTION); 2081 List<String> paramsList = new ArrayList<String>(); 2082 if (commandLine.hasOption("P")) { 2083 Properties params = commandLine.getOptionProperties("P"); 2084 for (String key : params.stringPropertyNames()) { 2085 paramsList.add(key + "=" + params.getProperty(key)); 2086 } 2087 } 2088 System.out.println(JOB_ID_PREFIX + wc.submitScriptLanguage(conf, script, args.toArray(new String[args.size()]), 2089 paramsList.toArray(new String[paramsList.size()]), jobType)); 2090 } 2091 catch (OozieClientException ex) { 2092 throw new OozieCLIException(ex.toString(), ex); 2093 } 2094 } 2095 2096 private void sqoopCommand(CommandLine commandLine) throws IOException, OozieCLIException { 2097 List<String> args = commandLine.getArgList(); 2098 if (args.size() > 0) { 2099 // checking if args starts with -X (because CLIParser cannot check this) 2100 if (!args.get(0).equals("-X")) { 2101 throw new OozieCLIException("Unrecognized option: " + args.get(0) + " Expecting -X"); 2102 } 2103 args.remove(0); 2104 } 2105 2106 if (!commandLine.hasOption(SQOOP_COMMAND_OPTION)) { 2107 throw new OozieCLIException("Need to specify -command"); 2108 } 2109 2110 if (!commandLine.hasOption(CONFIG_OPTION)) { 2111 throw new OozieCLIException("Need to specify -config <configfile>"); 2112 } 2113 2114 try { 2115 XOozieClient wc = createXOozieClient(commandLine); 2116 Properties conf = getConfiguration(wc, commandLine); 2117 String[] command = commandLine.getOptionValues(SQOOP_COMMAND_OPTION); 2118 System.out.println(JOB_ID_PREFIX + wc.submitSqoop(conf, command, args.toArray(new String[args.size()]))); 2119 } 2120 catch (OozieClientException ex) { 2121 throw new OozieCLIException(ex.toString(), ex); 2122 } 2123 } 2124 2125 private void infoCommand(CommandLine commandLine) throws OozieCLIException { 2126 for (Option option : commandLine.getOptions()) { 2127 String opt = option.getOpt(); 2128 if (opt.equals(INFO_TIME_ZONES_OPTION)) { 2129 printAvailableTimeZones(); 2130 } 2131 } 2132 } 2133 2134 private void printAvailableTimeZones() { 2135 System.out.println("The format is \"SHORT_NAME (ID)\"\nGive the ID to the -timezone argument"); 2136 System.out.println("GMT offsets can also be used (e.g. GMT-07:00, GMT-0700, GMT+05:30, GMT+0530)"); 2137 System.out.println("Available Time Zones:"); 2138 for (String tzId : TimeZone.getAvailableIDs()) { 2139 // skip id's that are like "Etc/GMT+01:00" because their display names are like "GMT-01:00", which is confusing 2140 if (!tzId.startsWith("Etc/GMT")) { 2141 TimeZone tZone = TimeZone.getTimeZone(tzId); 2142 System.out.println(" " + tZone.getDisplayName(false, TimeZone.SHORT) + " (" + tzId + ")"); 2143 } 2144 } 2145 } 2146 2147 2148 private void mrCommand(CommandLine commandLine) throws IOException, OozieCLIException { 2149 try { 2150 XOozieClient wc = createXOozieClient(commandLine); 2151 Properties conf = getConfiguration(wc, commandLine); 2152 2153 String mapper = conf.getProperty(MAPRED_MAPPER, conf.getProperty(MAPRED_MAPPER_2)); 2154 if (mapper == null) { 2155 throw new OozieCLIException("mapper (" + MAPRED_MAPPER + " or " + MAPRED_MAPPER_2 + ") must be specified in conf"); 2156 } 2157 2158 String reducer = conf.getProperty(MAPRED_REDUCER, conf.getProperty(MAPRED_REDUCER_2)); 2159 if (reducer == null) { 2160 throw new OozieCLIException("reducer (" + MAPRED_REDUCER + " or " + MAPRED_REDUCER_2 2161 + ") must be specified in conf"); 2162 } 2163 2164 String inputDir = conf.getProperty(MAPRED_INPUT); 2165 if (inputDir == null) { 2166 throw new OozieCLIException("input dir (" + MAPRED_INPUT +") must be specified in conf"); 2167 } 2168 2169 String outputDir = conf.getProperty(MAPRED_OUTPUT); 2170 if (outputDir == null) { 2171 throw new OozieCLIException("output dir (" + MAPRED_OUTPUT +") must be specified in conf"); 2172 } 2173 2174 System.out.println(JOB_ID_PREFIX + wc.submitMapReduce(conf)); 2175 } 2176 catch (OozieClientException ex) { 2177 throw new OozieCLIException(ex.toString(), ex); 2178 } 2179 } 2180 2181 private String getFirstMissingDependencies(CoordinatorAction action) { 2182 StringBuilder allDeps = new StringBuilder(); 2183 String missingDep = action.getMissingDependencies(); 2184 boolean depExists = false; 2185 if (missingDep != null && !missingDep.isEmpty()) { 2186 allDeps.append(missingDep.split(INSTANCE_SEPARATOR)[0]); 2187 depExists = true; 2188 } 2189 String pushDeps = action.getPushMissingDependencies(); 2190 if (pushDeps != null && !pushDeps.isEmpty()) { 2191 if(depExists) { 2192 allDeps.append(INSTANCE_SEPARATOR); 2193 } 2194 allDeps.append(pushDeps.split(INSTANCE_SEPARATOR)[0]); 2195 } 2196 return allDeps.toString(); 2197 } 2198 2199 private void printMetrics(OozieClient.Metrics metrics) { 2200 System.out.println("COUNTERS"); 2201 System.out.println("--------"); 2202 Map<String, Long> counters = new TreeMap<String, Long>(metrics.getCounters()); 2203 for (Map.Entry<String, Long> ent : counters.entrySet()) { 2204 System.out.println(ent.getKey() + " : " + ent.getValue()); 2205 } 2206 System.out.println("\nGAUGES"); 2207 System.out.println("------"); 2208 Map<String, Object> gauges = new TreeMap<String, Object>(metrics.getGauges()); 2209 for (Map.Entry<String, Object> ent : gauges.entrySet()) { 2210 System.out.println(ent.getKey() + " : " + ent.getValue()); 2211 } 2212 System.out.println("\nTIMERS"); 2213 System.out.println("------"); 2214 Map<String, OozieClient.Metrics.Timer> timers = new TreeMap<String, OozieClient.Metrics.Timer>(metrics.getTimers()); 2215 for (Map.Entry<String, OozieClient.Metrics.Timer> ent : timers.entrySet()) { 2216 System.out.println(ent.getKey()); 2217 System.out.println(ent.getValue()); 2218 } 2219 System.out.println("\nHISTOGRAMS"); 2220 System.out.println("----------"); 2221 Map<String, OozieClient.Metrics.Histogram> histograms = 2222 new TreeMap<String, OozieClient.Metrics.Histogram>(metrics.getHistograms()); 2223 for (Map.Entry<String, OozieClient.Metrics.Histogram> ent : histograms.entrySet()) { 2224 System.out.println(ent.getKey()); 2225 System.out.println(ent.getValue()); 2226 } 2227 } 2228 2229 private void printInstrumentation(OozieClient.Instrumentation instrumentation) { 2230 System.out.println("COUNTERS"); 2231 System.out.println("--------"); 2232 Map<String, Long> counters = new TreeMap<String, Long>(instrumentation.getCounters()); 2233 for (Map.Entry<String, Long> ent : counters.entrySet()) { 2234 System.out.println(ent.getKey() + " : " + ent.getValue()); 2235 } 2236 System.out.println("\nVARIABLES"); 2237 System.out.println("---------"); 2238 Map<String, Object> variables = new TreeMap<String, Object>(instrumentation.getVariables()); 2239 for (Map.Entry<String, Object> ent : variables.entrySet()) { 2240 System.out.println(ent.getKey() + " : " + ent.getValue()); 2241 } 2242 System.out.println("\nSAMPLERS"); 2243 System.out.println("---------"); 2244 Map<String, Double> samplers = new TreeMap<String, Double>(instrumentation.getSamplers()); 2245 for (Map.Entry<String, Double> ent : samplers.entrySet()) { 2246 System.out.println(ent.getKey() + " : " + ent.getValue()); 2247 } 2248 System.out.println("\nTIMERS"); 2249 System.out.println("---------"); 2250 Map<String, OozieClient.Instrumentation.Timer> timers = 2251 new TreeMap<String, OozieClient.Instrumentation.Timer>(instrumentation.getTimers()); 2252 for (Map.Entry<String, OozieClient.Instrumentation.Timer> ent : timers.entrySet()) { 2253 System.out.println(ent.getKey()); 2254 System.out.println(ent.getValue()); 2255 } 2256 } 2257}