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 019 020package org.apache.oozie.action.hadoop; 021 022import java.util.List; 023 024import org.apache.hadoop.conf.Configuration; 025import org.apache.hadoop.fs.Path; 026import org.apache.oozie.action.ActionExecutorException; 027import org.apache.oozie.service.ConfigurationService; 028import org.jdom.Element; 029import org.jdom.Namespace; 030 031public class ShellActionExecutor extends JavaActionExecutor { 032 033 /** 034 * Config property name to set the child environment 035 */ 036 public String OOZIE_LAUNCHER_CHILD_ENV = "mapred.child.env"; 037 public String OOZIE_LAUNCHER_MAP_ENV = "mapreduce.map.env"; 038 039 public ShellActionExecutor() { 040 super("shell"); 041 } 042 043 @SuppressWarnings("rawtypes") 044 @Override 045 public List<Class> getLauncherClasses() { 046 return null; 047 } 048 049 @Override 050 protected String getLauncherMain(Configuration launcherConf, Element actionXml) { 051 return launcherConf.get(LauncherMapper.CONF_OOZIE_ACTION_MAIN_CLASS, ShellMain.class.getName()); 052 } 053 054 @SuppressWarnings("unchecked") 055 @Override 056 Configuration setupActionConf(Configuration actionConf, Context context, Element actionXml, Path appPath) 057 throws ActionExecutorException { 058 super.setupActionConf(actionConf, context, actionXml, appPath); 059 Namespace ns = actionXml.getNamespace(); 060 061 String exec = actionXml.getChild("exec", ns).getTextTrim(); 062 String execName = new Path(exec).getName(); 063 actionConf.set(ShellMain.CONF_OOZIE_SHELL_EXEC, execName); 064 065 // Setting Shell command's arguments 066 setListInConf("argument", actionXml, actionConf, ShellMain.CONF_OOZIE_SHELL_ARGS, false); 067 // Setting Shell command's environment variable key=value 068 setListInConf("env-var", actionXml, actionConf, ShellMain.CONF_OOZIE_SHELL_ENVS, true); 069 070 // Setting capture output flag 071 actionConf.setBoolean(ShellMain.CONF_OOZIE_SHELL_CAPTURE_OUTPUT, actionXml.getChild("capture-output", ns) != null); 072 073 // Setting if ShellMain should setup HADOOP_CONF_DIR 074 boolean setupHadoopConfDir = actionConf.getBoolean(ShellMain.CONF_OOZIE_SHELL_SETUP_HADOOP_CONF_DIR, 075 ConfigurationService.getBoolean(ShellMain.CONF_OOZIE_SHELL_SETUP_HADOOP_CONF_DIR)); 076 actionConf.setBoolean(ShellMain.CONF_OOZIE_SHELL_SETUP_HADOOP_CONF_DIR, setupHadoopConfDir); 077 // Setting to control if ShellMain should write log4j.properties 078 boolean writeL4J = actionConf.getBoolean(ShellMain.CONF_OOZIE_SHELL_SETUP_HADOOP_CONF_DIR_WRITE_LOG4J_PROPERTIES, 079 ConfigurationService.getBoolean(ShellMain.CONF_OOZIE_SHELL_SETUP_HADOOP_CONF_DIR_WRITE_LOG4J_PROPERTIES)); 080 actionConf.setBoolean(ShellMain.CONF_OOZIE_SHELL_SETUP_HADOOP_CONF_DIR_WRITE_LOG4J_PROPERTIES, writeL4J); 081 // Setting of content of log4j.properties, if to be written 082 if (writeL4J) { 083 String l4jContent = actionConf.get(ShellMain.CONF_OOZIE_SHELL_SETUP_HADOOP_CONF_DIR_LOG4J_CONTENT, 084 ConfigurationService.get(ShellMain.CONF_OOZIE_SHELL_SETUP_HADOOP_CONF_DIR_LOG4J_CONTENT)); 085 actionConf.set(ShellMain.CONF_OOZIE_SHELL_SETUP_HADOOP_CONF_DIR_LOG4J_CONTENT, l4jContent); 086 } 087 088 return actionConf; 089 } 090 091 /** 092 * This method read a list of tag from an XML element and set the 093 * Configuration accordingly 094 * 095 * @param tag 096 * @param actionXml 097 * @param actionConf 098 * @param key 099 * @param checkKeyValue 100 * @throws ActionExecutorException 101 */ 102 protected void setListInConf(String tag, Element actionXml, Configuration actionConf, String key, 103 boolean checkKeyValue) throws ActionExecutorException { 104 String[] strTagValue = null; 105 Namespace ns = actionXml.getNamespace(); 106 List<Element> eTags = actionXml.getChildren(tag, ns); 107 if (eTags != null && eTags.size() > 0) { 108 strTagValue = new String[eTags.size()]; 109 for (int i = 0; i < eTags.size(); i++) { 110 strTagValue[i] = eTags.get(i).getTextTrim(); 111 if (checkKeyValue) { 112 checkPair(strTagValue[i]); 113 } 114 } 115 } 116 MapReduceMain.setStrings(actionConf, key, strTagValue); 117 } 118 119 /** 120 * Check if the key=value pair is appropriately formatted 121 * @param pair 122 * @throws ActionExecutorException 123 */ 124 private void checkPair(String pair) throws ActionExecutorException { 125 String[] varValue = pair.split("="); 126 if (varValue == null || varValue.length <= 1) { 127 throw new ActionExecutorException(ActionExecutorException.ErrorType.FAILED, "JA010", 128 "Wrong ENV format [{0}] in <env-var> , key=value format expected ", pair); 129 } 130 } 131 132 @Override 133 protected Configuration setupLauncherConf(Configuration conf, Element actionXml, Path appPath, Context context) 134 throws ActionExecutorException { 135 super.setupLauncherConf(conf, actionXml, appPath, context); 136 addDefaultChildEnv(conf); 137 return conf; 138 } 139 140 /** 141 * This method sets the PATH to current working directory for the launched 142 * map task from where shell command will run. 143 * 144 * @param conf 145 */ 146 protected void addDefaultChildEnv(Configuration conf) { 147 String envValues = "PATH=.:$PATH"; 148 updateProperty(conf, OOZIE_LAUNCHER_MAP_ENV, envValues); 149 updateProperty(conf, OOZIE_LAUNCHER_CHILD_ENV, envValues); 150 } 151 152 /** 153 * Utility method to append the new value to any property. 154 * 155 * @param conf 156 * @param propertyName 157 * @param appendValue 158 */ 159 private void updateProperty(Configuration conf, String propertyName, String appendValue) { 160 if (conf != null) { 161 String val = conf.get(propertyName, ""); 162 if (val.length() > 0) { 163 val += ","; 164 } 165 val += appendValue; 166 conf.set(propertyName, val); 167 LOG.debug("action conf is updated with default value for property " + propertyName + ", old value :" 168 + conf.get(propertyName, "") + ", new value :" + val); 169 } 170 } 171 172}