001 /** 002 * Copyright (c) 2010 Yahoo! Inc. All rights reserved. 003 * Licensed under the Apache License, Version 2.0 (the "License"); 004 * you may not use this file except in compliance with the License. 005 * You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software 010 * distributed under the License is distributed on an "AS IS" BASIS, 011 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012 * See the License for the specific language governing permissions and 013 * limitations under the License. See accompanying LICENSE file. 014 */ 015 package org.apache.oozie; 016 017 import java.io.IOException; 018 import java.io.Writer; 019 import java.util.ArrayList; 020 import java.util.Date; 021 import java.util.HashMap; 022 import java.util.HashSet; 023 import java.util.List; 024 import java.util.Map; 025 import java.util.Set; 026 import java.util.StringTokenizer; 027 028 import org.apache.hadoop.conf.Configuration; 029 import org.apache.oozie.client.CoordinatorJob; 030 import org.apache.oozie.client.OozieClient; 031 import org.apache.oozie.client.WorkflowJob; 032 import org.apache.oozie.command.CommandException; 033 import org.apache.oozie.command.coord.CoordActionInfoCommand; 034 import org.apache.oozie.command.coord.CoordJobCommand; 035 import org.apache.oozie.command.coord.CoordJobsCommand; 036 import org.apache.oozie.command.coord.CoordKillCommand; 037 import org.apache.oozie.command.coord.CoordRerunCommand; 038 import org.apache.oozie.command.coord.CoordChangeCommand; 039 import org.apache.oozie.command.coord.CoordResumeCommand; 040 import org.apache.oozie.command.coord.CoordSubmitCommand; 041 import org.apache.oozie.command.coord.CoordSuspendCommand; 042 import org.apache.oozie.service.DagXLogInfoService; 043 import org.apache.oozie.service.Services; 044 import org.apache.oozie.service.XLogService; 045 import org.apache.oozie.util.ParamChecker; 046 import org.apache.oozie.util.XLog; 047 import org.apache.oozie.util.XLogStreamer; 048 049 public class CoordinatorEngine extends BaseEngine { 050 051 /** 052 * Create a system Coordinator engine, with no user and no group. 053 */ 054 public CoordinatorEngine() { 055 } 056 057 /** 058 * Create a Coordinator engine to perform operations on behave of a user. 059 * 060 * @param user user name. 061 * @param authToken the authentication token. 062 */ 063 public CoordinatorEngine(String user, String authToken) { 064 this.user = ParamChecker.notEmpty(user, "user"); 065 this.authToken = ParamChecker.notEmpty(authToken, "authToken"); 066 } 067 068 /* 069 * (non-Javadoc) 070 * 071 * @see org.apache.oozie.BaseEngine#getDefinition(java.lang.String) 072 */ 073 @Override 074 public String getDefinition(String jobId) throws BaseEngineException { 075 CoordinatorJobBean job = getCoordJobWithNoActionInfo(jobId); 076 return job.getOrigJobXml(); 077 } 078 079 /** 080 * @param jobId 081 * @return CoordinatorJobBean 082 * @throws BaseEngineException 083 */ 084 private CoordinatorJobBean getCoordJobWithNoActionInfo(String jobId) throws BaseEngineException { 085 try { 086 return new CoordJobCommand(jobId, false).call(); 087 } 088 catch (CommandException ex) { 089 throw new BaseEngineException(ex); 090 } 091 } 092 093 /** 094 * @param actionId 095 * @return CoordinatorActionBean 096 * @throws BaseEngineException 097 */ 098 public CoordinatorActionBean getCoordAction(String actionId) throws BaseEngineException { 099 try { 100 return new CoordActionInfoCommand(actionId).call(); 101 } 102 catch (CommandException ex) { 103 throw new BaseEngineException(ex); 104 } 105 } 106 107 /* 108 * (non-Javadoc) 109 * 110 * @see org.apache.oozie.BaseEngine#getCoordJob(java.lang.String) 111 */ 112 @Override 113 public CoordinatorJobBean getCoordJob(String jobId) throws BaseEngineException { 114 try { 115 return new CoordJobCommand(jobId).call(); 116 } 117 catch (CommandException ex) { 118 throw new BaseEngineException(ex); 119 } 120 } 121 122 /* 123 * (non-Javadoc) 124 * 125 * @see org.apache.oozie.BaseEngine#getCoordJob(java.lang.String, int, int) 126 */ 127 @Override 128 public CoordinatorJobBean getCoordJob(String jobId, int start, int length) throws BaseEngineException { 129 try { 130 return new CoordJobCommand(jobId, start, length).call(); 131 } 132 catch (CommandException ex) { 133 throw new BaseEngineException(ex); 134 } 135 } 136 137 /* 138 * (non-Javadoc) 139 * 140 * @see org.apache.oozie.BaseEngine#getJobIdForExternalId(java.lang.String) 141 */ 142 @Override 143 public String getJobIdForExternalId(String externalId) throws CoordinatorEngineException { 144 return null; 145 } 146 147 /* 148 * (non-Javadoc) 149 * 150 * @see org.apache.oozie.BaseEngine#kill(java.lang.String) 151 */ 152 @Override 153 public void kill(String jobId) throws CoordinatorEngineException { 154 try { 155 new CoordKillCommand(jobId).call(); 156 XLog.getLog(getClass()).info("User " + user + " killed the Coordinator job " + jobId); 157 } 158 catch (CommandException e) { 159 throw new CoordinatorEngineException(e); 160 } 161 } 162 163 /* (non-Javadoc) 164 * @see org.apache.oozie.BaseEngine#change(java.lang.String, java.lang.String) 165 */ 166 @Override 167 public void change(String jobId, String changeValue) throws CoordinatorEngineException { 168 try { 169 new CoordChangeCommand(jobId, changeValue).call(); 170 XLog.getLog(getClass()).info("User " + user + " changed the Coordinator job " + jobId + " to " + changeValue); 171 } 172 catch (CommandException e) { 173 throw new CoordinatorEngineException(e); 174 } 175 } 176 177 @Override 178 @Deprecated 179 public void reRun(String jobId, Configuration conf) throws BaseEngineException { 180 throw new BaseEngineException(new XException(ErrorCode.E0301)); 181 } 182 183 /** 184 * Rerun coordinator actions for given rerunType 185 * 186 * @param jobId 187 * @param rerunType 188 * @param scope 189 * @param refresh 190 * @param noCleanup 191 * @throws BaseEngineException 192 */ 193 public CoordinatorActionInfo reRun(String jobId, String rerunType, String scope, boolean refresh, boolean noCleanup) 194 throws BaseEngineException { 195 try { 196 return new CoordRerunCommand(jobId, rerunType, scope, refresh, noCleanup).call(); 197 } 198 catch (CommandException ex) { 199 throw new BaseEngineException(ex); 200 } 201 } 202 203 /* 204 * (non-Javadoc) 205 * 206 * @see org.apache.oozie.BaseEngine#resume(java.lang.String) 207 */ 208 @Override 209 public void resume(String jobId) throws CoordinatorEngineException { 210 try { 211 new CoordResumeCommand(jobId).call(); 212 } 213 catch (CommandException e) { 214 throw new CoordinatorEngineException(e); 215 } 216 } 217 218 @Override 219 @Deprecated 220 public void start(String jobId) throws BaseEngineException { 221 throw new BaseEngineException(new XException(ErrorCode.E0301)); 222 } 223 224 /* 225 * (non-Javadoc) 226 * 227 * @see org.apache.oozie.BaseEngine#streamLog(java.lang.String, 228 * java.io.Writer) 229 */ 230 @Override 231 public void streamLog(String jobId, Writer writer) throws IOException, BaseEngineException { 232 XLogStreamer.Filter filter = new XLogStreamer.Filter(); 233 filter.setParameter(DagXLogInfoService.JOB, jobId); 234 235 CoordinatorJobBean job = getCoordJobWithNoActionInfo(jobId); 236 Services.get().get(XLogService.class).streamLog(filter, job.getCreatedTime(), new Date(), writer); 237 238 } 239 240 /* 241 * (non-Javadoc) 242 * 243 * @see 244 * org.apache.oozie.BaseEngine#submitJob(org.apache.hadoop.conf.Configuration 245 * , boolean) 246 */ 247 @Override 248 public String submitJob(Configuration conf, boolean startJob) throws CoordinatorEngineException { 249 CoordSubmitCommand submit = new CoordSubmitCommand(conf, getAuthToken()); 250 try { 251 String jobId = submit.call(); 252 return jobId; 253 } 254 catch (CommandException ex) { 255 throw new CoordinatorEngineException(ex); 256 } 257 } 258 259 /* 260 * (non-Javadoc) 261 * 262 * @see 263 * org.apache.oozie.BaseEngine#dryrunSubmit(org.apache.hadoop.conf.Configuration 264 * , boolean) 265 */ 266 @Override 267 public String dryrunSubmit(Configuration conf, boolean startJob) throws CoordinatorEngineException { 268 CoordSubmitCommand submit = new CoordSubmitCommand(true, conf, getAuthToken()); 269 try { 270 String jobId = submit.call(); 271 return jobId; 272 } 273 catch (CommandException ex) { 274 throw new CoordinatorEngineException(ex); 275 } 276 } 277 278 /* 279 * (non-Javadoc) 280 * 281 * @see org.apache.oozie.BaseEngine#suspend(java.lang.String) 282 */ 283 @Override 284 public void suspend(String jobId) throws CoordinatorEngineException { 285 try { 286 new CoordSuspendCommand(jobId).call(); 287 } 288 catch (CommandException e) { 289 throw new CoordinatorEngineException(e); 290 } 291 292 } 293 294 /* 295 * (non-Javadoc) 296 * 297 * @see org.apache.oozie.BaseEngine#getJob(java.lang.String) 298 */ 299 @Override 300 public WorkflowJob getJob(String jobId) throws BaseEngineException { 301 throw new BaseEngineException(new XException(ErrorCode.E0301)); 302 } 303 304 /* 305 * (non-Javadoc) 306 * 307 * @see org.apache.oozie.BaseEngine#getJob(java.lang.String, int, int) 308 */ 309 @Override 310 public WorkflowJob getJob(String jobId, int start, int length) throws BaseEngineException { 311 throw new BaseEngineException(new XException(ErrorCode.E0301)); 312 } 313 314 private static final Set<String> FILTER_NAMES = new HashSet<String>(); 315 316 static { 317 FILTER_NAMES.add(OozieClient.FILTER_USER); 318 FILTER_NAMES.add(OozieClient.FILTER_NAME); 319 FILTER_NAMES.add(OozieClient.FILTER_GROUP); 320 FILTER_NAMES.add(OozieClient.FILTER_STATUS); 321 } 322 323 /** 324 * @param filterStr 325 * @param start 326 * @param len 327 * @return CoordinatorJobInfo 328 * @throws CoordinatorEngineException 329 */ 330 public CoordinatorJobInfo getCoordJobs(String filterStr, int start, int len) throws CoordinatorEngineException { 331 Map<String, List<String>> filter = parseFilter(filterStr); 332 333 try { 334 return new CoordJobsCommand(filter, start, len).call(); 335 } 336 catch (CommandException ex) { 337 throw new CoordinatorEngineException(ex); 338 } 339 } 340 341 /** 342 * @param filter 343 * @return Map<String, List<String>> 344 * @throws CoordinatorEngineException 345 */ 346 private Map<String, List<String>> parseFilter(String filter) throws CoordinatorEngineException { 347 Map<String, List<String>> map = new HashMap<String, List<String>>(); 348 if (filter != null) { 349 StringTokenizer st = new StringTokenizer(filter, ";"); 350 while (st.hasMoreTokens()) { 351 String token = st.nextToken(); 352 if (token.contains("=")) { 353 String[] pair = token.split("="); 354 if (pair.length != 2) { 355 throw new CoordinatorEngineException(ErrorCode.E0420, filter, 356 "elements must be name=value pairs"); 357 } 358 if (!FILTER_NAMES.contains(pair[0])) { 359 throw new CoordinatorEngineException(ErrorCode.E0420, filter, XLog.format("invalid name [{0}]", 360 pair[0])); 361 } 362 if (pair[0].equals("status")) { 363 try { 364 CoordinatorJob.Status.valueOf(pair[1]); 365 } 366 catch (IllegalArgumentException ex) { 367 throw new CoordinatorEngineException(ErrorCode.E0420, filter, XLog.format( 368 "invalid status [{0}]", pair[1])); 369 } 370 } 371 List<String> list = map.get(pair[0]); 372 if (list == null) { 373 list = new ArrayList<String>(); 374 map.put(pair[0], list); 375 } 376 list.add(pair[1]); 377 } 378 else { 379 throw new CoordinatorEngineException(ErrorCode.E0420, filter, "elements must be name=value pairs"); 380 } 381 } 382 } 383 return map; 384 } 385 }