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 078 return actionConf; 079 } 080 081 /** 082 * This method read a list of tag from an XML element and set the 083 * Configuration accordingly 084 * 085 * @param tag 086 * @param actionXml 087 * @param actionConf 088 * @param key 089 * @param checkKeyValue 090 * @throws ActionExecutorException 091 */ 092 protected void setListInConf(String tag, Element actionXml, Configuration actionConf, String key, 093 boolean checkKeyValue) throws ActionExecutorException { 094 String[] strTagValue = null; 095 Namespace ns = actionXml.getNamespace(); 096 List<Element> eTags = actionXml.getChildren(tag, ns); 097 if (eTags != null && eTags.size() > 0) { 098 strTagValue = new String[eTags.size()]; 099 for (int i = 0; i < eTags.size(); i++) { 100 strTagValue[i] = eTags.get(i).getTextTrim(); 101 if (checkKeyValue) { 102 checkPair(strTagValue[i]); 103 } 104 } 105 } 106 MapReduceMain.setStrings(actionConf, key, strTagValue); 107 } 108 109 /** 110 * Check if the key=value pair is appropriately formatted 111 * @param pair 112 * @throws ActionExecutorException 113 */ 114 private void checkPair(String pair) throws ActionExecutorException { 115 String[] varValue = pair.split("="); 116 if (varValue == null || varValue.length <= 1) { 117 throw new ActionExecutorException(ActionExecutorException.ErrorType.FAILED, "JA010", 118 "Wrong ENV format [{0}] in <env-var> , key=value format expected ", pair); 119 } 120 } 121 122 @Override 123 protected Configuration setupLauncherConf(Configuration conf, Element actionXml, Path appPath, Context context) 124 throws ActionExecutorException { 125 super.setupLauncherConf(conf, actionXml, appPath, context); 126 addDefaultChildEnv(conf); 127 return conf; 128 } 129 130 /** 131 * This method sets the PATH to current working directory for the launched 132 * map task from where shell command will run. 133 * 134 * @param conf 135 */ 136 protected void addDefaultChildEnv(Configuration conf) { 137 String envValues = "PATH=.:$PATH"; 138 updateProperty(conf, OOZIE_LAUNCHER_MAP_ENV, envValues); 139 updateProperty(conf, OOZIE_LAUNCHER_CHILD_ENV, envValues); 140 } 141 142 /** 143 * Utility method to append the new value to any property. 144 * 145 * @param conf 146 * @param propertyName 147 * @param appendValue 148 */ 149 private void updateProperty(Configuration conf, String propertyName, String appendValue) { 150 if (conf != null) { 151 String val = conf.get(propertyName, ""); 152 if (val.length() > 0) { 153 val += ","; 154 } 155 val += appendValue; 156 conf.set(propertyName, val); 157 LOG.debug("action conf is updated with default value for property " + propertyName + ", old value :" 158 + conf.get(propertyName, "") + ", new value :" + val); 159 } 160 } 161 162}