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.action.hadoop;
020
021import java.io.IOException;
022import java.io.StringReader;
023import java.util.Iterator;
024import java.util.Map;
025import java.util.Map.Entry;
026
027import org.apache.hadoop.conf.Configuration;
028import org.apache.oozie.action.ActionExecutor.Context;
029import org.apache.oozie.action.oozie.SubWorkflowActionExecutor;
030import org.apache.oozie.client.OozieClient;
031import org.apache.oozie.client.WorkflowAction;
032import org.apache.oozie.service.ConfigurationService;
033import org.apache.oozie.util.XConfiguration;
034
035import com.google.common.annotations.VisibleForTesting;
036
037public class OozieJobInfo {
038
039    public static final String BUNDLE_ID = "bundle.id";
040    public static final String BUNDLE_NAME = "bundle.name";
041    public static final String COORD_NAME = "coord.name";
042    public static final String COORD_ID = "coord.id";
043    public static final String COORD_NOMINAL_TIME = "coord.nominal.time";
044    public static final String WORKFLOW_ID = "wf.id";
045    public static final String WORKFLOW_NAME = "wf.name";
046    public static final String WORKFLOW_DEPTH = "wf.depth";
047    public static final String WORKFLOW_SUPER_PARENT = "wf.superparent.id";
048    public static final String ACTION_TYPE = "action.type";
049    public static final String ACTION_NAME = "action.name";
050    public static final String JOB_INFO_KEY = "oozie.job.info";
051    public static final String CONF_JOB_INFO = "oozie.action.jobinfo.enable";
052    public final static String SEPARATOR = ",";
053
054    private Context context;
055    XConfiguration contextConf;
056    private WorkflowAction action;
057    private Configuration actionConf;
058    private static boolean jobInfo = ConfigurationService.getBoolean(OozieJobInfo.CONF_JOB_INFO);
059
060    /**
061     * Instantiates a new oozie job info.
062     *
063     * @param actionConf the action conf
064     * @param context the context
065     * @param action the action
066     * @throws IOException
067     */
068    public OozieJobInfo(Configuration actionConf, Context context, WorkflowAction action) throws IOException {
069        this.context = context;
070        contextConf = new XConfiguration(new StringReader(context.getWorkflow().getConf()));
071        this.action = action;
072        this.actionConf = actionConf;
073    }
074
075    public static boolean isJobInfoEnabled() {
076        return jobInfo;
077    }
078
079    @VisibleForTesting
080    public static void setJobInfo(boolean jobInfo) {
081        OozieJobInfo.jobInfo = jobInfo;
082    }
083
084    /**
085     * Get the job info.
086     *
087     * @return job info
088     * @throws IOException Signals that an I/O exception has occurred.
089     */
090    public String getJobInfo() throws IOException {
091        StringBuffer sb = new StringBuffer();
092        addBundleInfo(sb);
093        addCoordInfo(sb);
094        addWorkflowInfo(sb);
095        addActionInfo(sb);
096        addCustomInfo(sb);
097        return sb.toString();
098
099    }
100
101    private void addBundleInfo(StringBuffer sb) throws IOException {
102        addJobInfo(sb, BUNDLE_ID, contextConf.get(OozieClient.BUNDLE_ID));
103        addJobInfo(sb, BUNDLE_NAME, contextConf.get(OozieJobInfo.BUNDLE_NAME));
104
105    }
106
107    private void addCoordInfo(StringBuffer sb) throws IOException {
108        addJobInfo(sb, COORD_NAME, contextConf.get(OozieJobInfo.COORD_NAME));
109        addJobInfo(sb, COORD_NOMINAL_TIME, contextConf.get(OozieJobInfo.COORD_NOMINAL_TIME));
110        addJobInfo(sb, COORD_ID, contextConf.get(OozieJobInfo.COORD_ID));
111    }
112
113    private void addWorkflowInfo(StringBuffer sb) {
114        addJobInfo(sb, WORKFLOW_ID, context.getWorkflow().getId());
115        addJobInfo(sb, WORKFLOW_NAME, context.getWorkflow().getAppName());
116        addJobInfo(sb, WORKFLOW_DEPTH, contextConf.get(SubWorkflowActionExecutor.SUBWORKFLOW_DEPTH, "0"));
117        addJobInfo(sb, WORKFLOW_SUPER_PARENT, computeSuperParent());
118    }
119
120    private void addActionInfo(StringBuffer sb) {
121        addJobInfo(sb, ACTION_NAME, action.getName());
122        addJobInfo(sb, ACTION_TYPE, action.getType());
123    }
124
125    private void addCustomInfo(StringBuffer sb) throws IOException {
126        addfromConf(actionConf, sb);
127    }
128
129    public void addfromConf(Configuration conf, StringBuffer sb) {
130        Iterator<Map.Entry<String, String>> it = conf.iterator();
131        while (it.hasNext()) {
132            Entry<String, String> entry = it.next();
133            if (entry.getKey().startsWith("oozie.job.info.")) {
134                addJobInfo(sb, entry.getKey().substring("oozie.job.info.".length()), entry.getValue());
135            }
136        }
137    }
138
139    private void addJobInfo(StringBuffer sb, String key, String value) {
140        if (value != null) {
141            sb.append(key).append("=").append(value).append(OozieJobInfo.SEPARATOR);
142        }
143
144    }
145
146    private String computeSuperParent() {
147        String superParentId = contextConf.get(SubWorkflowActionExecutor.SUPER_PARENT_ID);
148        if (superParentId == null) {
149            // Not a sub-workflow
150            if (context.getWorkflow().getParentId() != null) {
151                // return coord id as the super parent id
152                return context.getWorkflow().getParentId();
153            } else {
154                // return the current workflow id as the super parent id.
155                return context.getWorkflow().getId();
156            }
157        }
158        return superParentId;
159    }
160}