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