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