/**
* Copyright (c) 2010 Yahoo! Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License. See accompanying LICENSE file.
*/
package org.apache.oozie.command.coord;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.oozie.CoordinatorActionBean;
import org.apache.oozie.CoordinatorJobBean;
import org.apache.oozie.ErrorCode;
import org.apache.oozie.client.CoordinatorAction;
import org.apache.oozie.client.CoordinatorJob;
import org.apache.oozie.client.OozieClient;
import org.apache.oozie.client.OozieClientException;
import org.apache.oozie.client.CoordinatorJob.Execution;
import org.apache.oozie.client.rest.RestConstants;
import org.apache.oozie.coord.CoordELFunctions;
import org.apache.oozie.local.LocalOozie;
import org.apache.oozie.service.Services;
import org.apache.oozie.service.StoreService;
import org.apache.oozie.store.CoordinatorStore;
import org.apache.oozie.store.StoreException;
import org.apache.oozie.test.XFsTestCase;
import org.apache.oozie.util.DateUtils;
import org.apache.oozie.util.IOUtils;
import org.apache.oozie.util.XLog;
import org.apache.oozie.util.XmlUtils;
import org.jdom.Element;
import org.jdom.JDOMException;
public class TestCoordRerunCommand extends XFsTestCase {
private Services services;
@Override
protected void setUp() throws Exception {
super.setUp();
services = new Services();
services.init();
cleanUpDBTables();
services.destroy();
LocalOozie.start();
}
@Override
protected void tearDown() throws Exception {
LocalOozie.stop();
super.tearDown();
}
/**
* Test : rerun <jobId> -action 1 -nocleanup
*
* @throws Exception
*/
public void testCoordRerunActions1() throws Exception {
final String jobId = "0000000-" + new Date().getTime() + "-testCoordRerun-C";
final int actionNum = 1;
final String actionId = jobId + "@" + actionNum;
CoordinatorStore store = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store.beginTrx();
try {
addRecordToJobTable(jobId, store, CoordinatorJob.Status.SUCCEEDED);
addRecordToActionTable(jobId, actionNum, actionId, store, CoordinatorAction.Status.SUCCEEDED,
"coord-rerun-action1.xml");
store.commitTrx();
}
catch (Exception e) {
e.printStackTrace();
fail("Could not update db.");
}
finally {
store.closeTrx();
}
CoordinatorStore store1 = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store1.beginTrx();
CoordinatorActionBean action1 = store1.getCoordinatorAction(actionId, false);
assertEquals(action1.getStatus(), CoordinatorAction.Status.SUCCEEDED);
store1.commitTrx();
store1.closeTrx();
final OozieClient coordClient = LocalOozie.getCoordClient();
coordClient.reRunCoord(jobId, RestConstants.JOB_COORD_RERUN_ACTION, Integer.toString(actionNum), false, true);
CoordinatorStore store2 = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store2.beginTrx();
CoordinatorActionBean action2 = store2.getCoordinatorAction(actionId, false);
assertNotSame(action2.getStatus(), CoordinatorAction.Status.SUCCEEDED);
store2.commitTrx();
store2.closeTrx();
}
/**
* Test : rerun <jobId> -action 1-2 -nocleanup
*
* @throws Exception
*/
public void testCoordRerunActions2() throws Exception {
final String jobId = "0000000-" + new Date().getTime() + "-testCoordRerun-C";
final int actionNum1 = 1;
final int actionNum2 = 2;
final String actionId1 = jobId + "@" + actionNum1;
final String actionId2 = jobId + "@" + actionNum2;
CoordinatorStore store = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store.beginTrx();
try {
addRecordToJobTable(jobId, store, CoordinatorJob.Status.SUCCEEDED);
addRecordToActionTable(jobId, actionNum1, actionId1, store, CoordinatorAction.Status.SUCCEEDED,
"coord-rerun-action1.xml");
addRecordToActionTable(jobId, actionNum2, actionId2, store, CoordinatorAction.Status.SUCCEEDED,
"coord-rerun-action2.xml");
store.commitTrx();
}
catch (Exception e) {
e.printStackTrace();
fail("Could not update db.");
}
finally {
store.closeTrx();
}
String rerunScope = Integer.toString(actionNum1) + "-" + Integer.toString(actionNum2);
final OozieClient coordClient = LocalOozie.getCoordClient();
coordClient.reRunCoord(jobId, RestConstants.JOB_COORD_RERUN_ACTION, rerunScope, false, true);
CoordinatorStore store1 = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store1.beginTrx();
CoordinatorActionBean action1 = store1.getCoordinatorAction(actionId1, false);
assertNotSame(action1.getStatus(), CoordinatorAction.Status.SUCCEEDED);
CoordinatorActionBean action2 = store1.getCoordinatorAction(actionId2, false);
assertNotSame(action2.getStatus(), CoordinatorAction.Status.SUCCEEDED);
store1.commitTrx();
store1.closeTrx();
}
/**
* Test : rerun <jobId> -action 1,2 -nocleanup
*
* @throws Exception
*/
public void testCoordRerunActions3() throws Exception {
final String jobId = "0000000-" + new Date().getTime() + "-testCoordRerun-C";
final int actionNum1 = 1;
final int actionNum2 = 2;
final String actionId1 = jobId + "@" + actionNum1;
final String actionId2 = jobId + "@" + actionNum2;
CoordinatorStore store = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store.beginTrx();
try {
addRecordToJobTable(jobId, store, CoordinatorJob.Status.SUCCEEDED);
addRecordToActionTable(jobId, actionNum1, actionId1, store, CoordinatorAction.Status.SUCCEEDED,
"coord-rerun-action1.xml");
addRecordToActionTable(jobId, actionNum2, actionId2, store, CoordinatorAction.Status.SUCCEEDED,
"coord-rerun-action2.xml");
store.commitTrx();
}
catch (Exception e) {
e.printStackTrace();
fail("Could not update db.");
}
finally {
store.closeTrx();
}
String rerunScope = Integer.toString(actionNum1) + "," + Integer.toString(actionNum2);
final OozieClient coordClient = LocalOozie.getCoordClient();
coordClient.reRunCoord(jobId, RestConstants.JOB_COORD_RERUN_ACTION, rerunScope, false, true);
CoordinatorStore store1 = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store1.beginTrx();
CoordinatorActionBean action1 = store1.getCoordinatorAction(actionId1, false);
assertNotSame(action1.getStatus(), CoordinatorAction.Status.SUCCEEDED);
CoordinatorActionBean action2 = store1.getCoordinatorAction(actionId2, false);
assertNotSame(action2.getStatus(), CoordinatorAction.Status.SUCCEEDED);
store1.commitTrx();
store1.closeTrx();
}
/**
* Negative Test : rerun <jobId> -action 1-3 -nocleanup. Only 2 actions is
* in db.
*
* @throws Exception
*/
public void testCoordRerunActionsNeg1() throws Exception {
final String jobId = "0000000-" + new Date().getTime() + "-testCoordRerun-C";
final int actionNum1 = 1;
final int actionNum2 = 2;
final String actionId1 = jobId + "@" + actionNum1;
final String actionId2 = jobId + "@" + actionNum2;
CoordinatorStore store = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store.beginTrx();
try {
addRecordToJobTable(jobId, store, CoordinatorJob.Status.SUCCEEDED);
addRecordToActionTable(jobId, actionNum1, actionId1, store, CoordinatorAction.Status.SUCCEEDED,
"coord-rerun-action1.xml");
addRecordToActionTable(jobId, actionNum2, actionId2, store, CoordinatorAction.Status.SUCCEEDED,
"coord-rerun-action2.xml");
store.commitTrx();
}
catch (Exception e) {
e.printStackTrace();
fail("Could not update db.");
}
finally {
store.closeTrx();
}
String rerunScope = "1-3";
try {
final OozieClient coordClient = LocalOozie.getCoordClient();
coordClient.reRunCoord(jobId, RestConstants.JOB_COORD_RERUN_ACTION, rerunScope, false, true);
fail("Exception expected because one action is missing from db.");
}
catch (OozieClientException ex) {
}
}
/**
* Negative Test : rerun <jobId> -action 1 -nocleanup. Action is not in
* terminal state.
*
* @throws Exception
*/
public void testCoordRerunActionsNeg2() throws Exception {
final String jobId = "0000000-" + new Date().getTime() + "-testCoordRerun-C";
final int actionNum = 1;
final String actionId = jobId + "@" + actionNum;
CoordinatorStore store = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store.beginTrx();
try {
addRecordToJobTable(jobId, store, CoordinatorJob.Status.SUCCEEDED);
addRecordToActionTable(jobId, actionNum, actionId, store, CoordinatorAction.Status.RUNNING,
"coord-rerun-action1.xml");
store.commitTrx();
}
catch (Exception e) {
e.printStackTrace();
fail("Could not update db.");
}
finally {
store.closeTrx();
}
try {
final OozieClient coordClient = LocalOozie.getCoordClient();
coordClient.reRunCoord(jobId, RestConstants.JOB_COORD_RERUN_ACTION, Integer.toString(actionNum), false,
true);
fail("Exception expected because action is not in terminal state.");
}
catch (OozieClientException ex) {
if (!ex.getErrorCode().equals(ErrorCode.E1018.toString())) {
fail("Error code should be E1018 when action is not in terminal state.");
}
}
CoordinatorStore store2 = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store2.beginTrx();
CoordinatorActionBean action2 = store2.getCoordinatorAction(actionId, false);
assertEquals(action2.getStatus(), CoordinatorAction.Status.RUNNING);
store2.commitTrx();
store2.closeTrx();
}
/**
* Test : rerun <jobId> -date 2009-12-15T17:00Z -nocleanup
*
* @throws Exception
*/
public void testCoordRerunDate1() throws Exception {
final String jobId = "0000000-" + new Date().getTime() + "-testCoordRerun-C";
final int actionNum = 1;
final String actionId = jobId + "@" + actionNum;
CoordinatorStore store = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store.beginTrx();
try {
addRecordToJobTable(jobId, store, CoordinatorJob.Status.SUCCEEDED);
addRecordToActionTable(jobId, actionNum, actionId, store, CoordinatorAction.Status.SUCCEEDED,
"coord-rerun-action1.xml");
store.commitTrx();
}
catch (Exception e) {
e.printStackTrace();
fail("Could not update db.");
}
finally {
store.closeTrx();
}
CoordinatorStore store1 = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store1.beginTrx();
CoordinatorActionBean action1 = store1.getCoordinatorAction(actionId, false);
assertEquals(action1.getStatus(), CoordinatorAction.Status.SUCCEEDED);
store1.commitTrx();
store1.closeTrx();
final OozieClient coordClient = LocalOozie.getCoordClient();
coordClient.reRunCoord(jobId, RestConstants.JOB_COORD_RERUN_DATE, "2009-12-15T01:00Z", false, true);
CoordinatorStore store2 = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store2.beginTrx();
CoordinatorActionBean action2 = store2.getCoordinatorAction(actionId, false);
assertNotSame(action2.getStatus(), CoordinatorAction.Status.SUCCEEDED);
store2.commitTrx();
store2.closeTrx();
}
/**
* Test : rerun <jobId> -date 2009-12-15T01:00Z::2009-12-16T01:00Z -nocleanup
*
* @throws Exception
*/
public void testCoordRerunDate2() throws Exception {
final String jobId = "0000000-" + new Date().getTime() + "-testCoordRerun-C";
final int actionNum1 = 1;
final int actionNum2 = 2;
final String actionId1 = jobId + "@" + actionNum1;
final String actionId2 = jobId + "@" + actionNum2;
CoordinatorStore store = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store.beginTrx();
try {
addRecordToJobTable(jobId, store, CoordinatorJob.Status.SUCCEEDED);
addRecordToActionTable(jobId, actionNum1, actionId1, store, CoordinatorAction.Status.SUCCEEDED,
"coord-rerun-action1.xml");
addRecordToActionTable(jobId, actionNum2, actionId2, store, CoordinatorAction.Status.SUCCEEDED,
"coord-rerun-action2.xml");
store.commitTrx();
}
catch (Exception e) {
e.printStackTrace();
fail("Could not update db.");
}
finally {
store.closeTrx();
}
String rerunScope = "2009-12-15T01:00Z" + "::" + "2009-12-16T01:00Z";
final OozieClient coordClient = LocalOozie.getCoordClient();
coordClient.reRunCoord(jobId, RestConstants.JOB_COORD_RERUN_DATE, rerunScope, false, true);
CoordinatorStore store1 = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store1.beginTrx();
CoordinatorActionBean action1 = store1.getCoordinatorAction(actionId1, false);
assertNotSame(action1.getStatus(), CoordinatorAction.Status.SUCCEEDED);
CoordinatorActionBean action2 = store1.getCoordinatorAction(actionId2, false);
assertNotSame(action2.getStatus(), CoordinatorAction.Status.SUCCEEDED);
store1.commitTrx();
store1.closeTrx();
}
/**
* Test : rerun <jobId> -date 2009-12-15T01:00Z,2009-12-16T01:00Z -nocleanup
*
* @throws Exception
*/
public void testCoordRerunDate3() throws Exception {
final String jobId = "0000000-" + new Date().getTime() + "-testCoordRerun-C";
final int actionNum1 = 1;
final int actionNum2 = 2;
final String actionId1 = jobId + "@" + actionNum1;
final String actionId2 = jobId + "@" + actionNum2;
CoordinatorStore store = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store.beginTrx();
try {
addRecordToJobTable(jobId, store, CoordinatorJob.Status.SUCCEEDED);
addRecordToActionTable(jobId, actionNum1, actionId1, store, CoordinatorAction.Status.SUCCEEDED,
"coord-rerun-action1.xml");
addRecordToActionTable(jobId, actionNum2, actionId2, store, CoordinatorAction.Status.SUCCEEDED,
"coord-rerun-action2.xml");
store.commitTrx();
}
catch (Exception e) {
e.printStackTrace();
fail("Could not update db.");
}
finally {
store.closeTrx();
}
String rerunScope = "2009-12-15T01:00Z" + "," + "2009-12-16T01:00Z";
final OozieClient coordClient = LocalOozie.getCoordClient();
coordClient.reRunCoord(jobId, RestConstants.JOB_COORD_RERUN_DATE, rerunScope, false, true);
CoordinatorStore store1 = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store1.beginTrx();
CoordinatorActionBean action1 = store1.getCoordinatorAction(actionId1, false);
assertNotSame(action1.getStatus(), CoordinatorAction.Status.SUCCEEDED);
CoordinatorActionBean action2 = store1.getCoordinatorAction(actionId2, false);
assertNotSame(action2.getStatus(), CoordinatorAction.Status.SUCCEEDED);
store1.commitTrx();
store1.closeTrx();
}
/**
* Test : rerun <jobId> -date 2009-12-15T01:00Z::2009-12-17T01:00Z -nocleanup
* 2009-12-17T01:00Z is not in the action list, but Oozie will tolerate this.
*
* @throws Exception
*/
public void testCoordRerunDate4() throws Exception {
final String jobId = "0000000-" + new Date().getTime() + "-testCoordRerun-C";
final int actionNum1 = 1;
final int actionNum2 = 2;
final String actionId1 = jobId + "@" + actionNum1;
final String actionId2 = jobId + "@" + actionNum2;
CoordinatorStore store = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store.beginTrx();
try {
addRecordToJobTable(jobId, store, CoordinatorJob.Status.SUCCEEDED);
addRecordToActionTable(jobId, actionNum1, actionId1, store, CoordinatorAction.Status.SUCCEEDED,
"coord-rerun-action1.xml");
addRecordToActionTable(jobId, actionNum2, actionId2, store, CoordinatorAction.Status.SUCCEEDED,
"coord-rerun-action2.xml");
store.commitTrx();
}
catch (Exception e) {
e.printStackTrace();
fail("Could not update db.");
}
finally {
store.closeTrx();
}
String rerunScope = "2009-12-15T01:00Z" + "::" + "2009-12-17T01:00Z";
final OozieClient coordClient = LocalOozie.getCoordClient();
coordClient.reRunCoord(jobId, RestConstants.JOB_COORD_RERUN_DATE, rerunScope, false, true);
CoordinatorStore store1 = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store1.beginTrx();
CoordinatorActionBean action1 = store1.getCoordinatorAction(actionId1, false);
assertNotSame(action1.getStatus(), CoordinatorAction.Status.SUCCEEDED);
CoordinatorActionBean action2 = store1.getCoordinatorAction(actionId2, false);
assertNotSame(action2.getStatus(), CoordinatorAction.Status.SUCCEEDED);
store1.commitTrx();
store1.closeTrx();
}
/**
* Test : rerun <jobId> -date 2009-12-15T01:00Z,2009-12-16T01:00Z,2009-12-17T01:00Z -nocleanup
* 2009-12-17T01:00Z is not in the action list, Oozie will not tolerate this when comma is used.
*
* @throws Exception
*/
public void testCoordRerunDateNeg() throws Exception {
final String jobId = "0000000-" + new Date().getTime() + "-testCoordRerun-C";
final int actionNum1 = 1;
final int actionNum2 = 2;
final String actionId1 = jobId + "@" + actionNum1;
final String actionId2 = jobId + "@" + actionNum2;
CoordinatorStore store = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store.beginTrx();
try {
addRecordToJobTable(jobId, store, CoordinatorJob.Status.SUCCEEDED);
addRecordToActionTable(jobId, actionNum1, actionId1, store, CoordinatorAction.Status.SUCCEEDED,
"coord-rerun-action1.xml");
addRecordToActionTable(jobId, actionNum2, actionId2, store, CoordinatorAction.Status.SUCCEEDED,
"coord-rerun-action2.xml");
store.commitTrx();
}
catch (Exception e) {
e.printStackTrace();
fail("Could not update db.");
}
finally {
store.closeTrx();
}
String rerunScope = "2009-12-15T01:00Z,2009-12-16T01:00Z,2009-12-17T01:00Z";
try {
final OozieClient coordClient = LocalOozie.getCoordClient();
coordClient.reRunCoord(jobId, RestConstants.JOB_COORD_RERUN_DATE, rerunScope, false, true);
fail("Exception expected because one action is missing from db.");
}
catch (OozieClientException ex) {
}
}
/**
* Test : rerun <jobId> -action 1 -nocleanup -refresh
*
* @throws Exception
*/
public void testCoordRerunRefresh() throws Exception {
final String jobId = "0000000-" + new Date().getTime() + "-testCoordRerun-C";
final int actionNum = 1;
final String actionId = jobId + "@" + actionNum;
CoordinatorStore store = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store.beginTrx();
try {
addRecordToJobTable(jobId, store, CoordinatorJob.Status.SUCCEEDED);
addRecordToActionTable(jobId, actionNum, actionId, store, CoordinatorAction.Status.SUCCEEDED,
"coord-rerun-action1.xml");
store.commitTrx();
}
catch (Exception e) {
e.printStackTrace();
fail("Could not update db.");
}
finally {
store.closeTrx();
}
Path appPath = new Path(getFsTestCaseDir(), "coord");
String inputDir = appPath.toString() + "/coord-input/2010/07/09/01/00";
FileSystem fs = getFileSystem();
fs.mkdirs(new Path(inputDir));
fs.create(new Path(inputDir, "_SUCCESS"), true);
final OozieClient coordClient = LocalOozie.getCoordClient();
coordClient.reRunCoord(jobId, RestConstants.JOB_COORD_RERUN_ACTION, Integer.toString(actionNum), true, true);
CoordinatorStore store2 = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store2.beginTrx();
CoordinatorActionBean action2 = store2.getCoordinatorAction(actionId, false);
assertNotSame(action2.getStatus(), CoordinatorAction.Status.SUCCEEDED);
store2.commitTrx();
store2.closeTrx();
waitFor(120 * 1000, new Predicate() {
public boolean evaluate() throws Exception {
CoordinatorAction bean = coordClient.getCoordActionInfo(actionId);
return (bean.getStatus() == CoordinatorAction.Status.READY || bean.getStatus() == CoordinatorAction.Status.SUBMITTED);
}
});
CoordinatorStore store3 = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store3.beginTrx();
CoordinatorActionBean action3 = store3.getCoordinatorAction(actionId, false);
String actionXml = action3.getActionXml();
System.out.println("After refresh, action xml= " + actionXml);
Element eAction = XmlUtils.parseXml(actionXml);
String[] urls = getActionXmlUrls(eAction, getTestUser(), getTestGroup());
store3.commitTrx();
store3.closeTrx();
if (urls != null) {
assertEquals(inputDir, urls[0]);
}
else {
fail("After refresh, latest() should get the inputDir:" + inputDir);
}
}
/**
* Test : rerun <jobId> -action 1
*
* @throws Exception
*/
public void testCoordRerunCleanup() throws Exception {
final String jobId = "0000000-" + new Date().getTime() + "-testCoordRerun-C";
final int actionNum = 1;
final String actionId = jobId + "@" + actionNum;
CoordinatorStore store = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store.beginTrx();
try {
addRecordToJobTable(jobId, store, CoordinatorJob.Status.SUCCEEDED);
addRecordToActionTable(jobId, actionNum, actionId, store, CoordinatorAction.Status.SUCCEEDED,
"coord-rerun-action1.xml");
store.commitTrx();
}
catch (Exception e) {
e.printStackTrace();
fail("Could not update db.");
}
finally {
store.closeTrx();
}
Path appPath = new Path(getFsTestCaseDir(), "coord");
String outputDir = appPath.toString() + "/coord-input/2009/12/14/11/00";
Path success = new Path(outputDir, "_SUCCESS");
FileSystem fs = getFileSystem();
fs.mkdirs(new Path(outputDir));
fs.create(success, true);
// before cleanup
assertTrue(fs.exists(success));
final OozieClient coordClient = LocalOozie.getCoordClient();
coordClient.reRunCoord(jobId, RestConstants.JOB_COORD_RERUN_ACTION, Integer.toString(actionNum), false, false);
CoordinatorStore store2 = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store2.beginTrx();
CoordinatorActionBean action2 = store2.getCoordinatorAction(actionId, false);
assertNotSame(action2.getStatus(), CoordinatorAction.Status.SUCCEEDED);
store2.commitTrx();
store2.closeTrx();
waitFor(120 * 1000, new Predicate() {
public boolean evaluate() throws Exception {
CoordinatorAction bean = coordClient.getCoordActionInfo(actionId);
return (bean.getStatus() == CoordinatorAction.Status.WAITING || bean.getStatus() == CoordinatorAction.Status.READY);
}
});
// after cleanup
assertFalse(fs.exists(success));
}
/**
* Test : rerun <jobId> -action 1 with no output-event
*
* @throws Exception
*/
public void testCoordRerunCleanupNoOutputEvents() throws Exception {
final String jobId = "0000000-" + new Date().getTime() + "-testCoordRerun-C";
final int actionNum = 1;
final String actionId = jobId + "@" + actionNum;
CoordinatorStore store = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store.beginTrx();
try {
addRecordToJobTable(jobId, store, CoordinatorJob.Status.SUCCEEDED);
addRecordToActionTable(jobId, actionNum, actionId, store, CoordinatorAction.Status.SUCCEEDED,
"coord-rerun-action3.xml");
store.commitTrx();
}
catch (Exception e) {
e.printStackTrace();
fail("Could not update db.");
}
finally {
store.closeTrx();
}
final OozieClient coordClient = LocalOozie.getCoordClient();
coordClient.reRunCoord(jobId, RestConstants.JOB_COORD_RERUN_ACTION, Integer.toString(actionNum), false, false);
CoordinatorStore store2 = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store2.beginTrx();
CoordinatorActionBean action2 = store2.getCoordinatorAction(actionId, false);
assertNotSame(action2.getStatus(), CoordinatorAction.Status.SUCCEEDED);
store2.commitTrx();
store2.closeTrx();
waitFor(120 * 1000, new Predicate() {
public boolean evaluate() throws Exception {
CoordinatorAction bean = coordClient.getCoordActionInfo(actionId);
return (bean.getStatus() == CoordinatorAction.Status.WAITING || bean.getStatus() == CoordinatorAction.Status.READY);
}
});
CoordinatorAction bean = coordClient.getCoordActionInfo(actionId);
assertTrue(bean.getStatus() == CoordinatorAction.Status.WAITING
|| bean.getStatus() == CoordinatorAction.Status.READY);
}
/**
* Negative Test : rerun <jobId> -action 1 -nocleanup.
* Coordiantor job is killed, so no actions are able to rerun.
*
* @throws Exception
*/
public void testCoordRerunNeg() throws Exception {
final String jobId = "0000000-" + new Date().getTime() + "-testCoordRerun-C";
final int actionNum = 1;
final String actionId = jobId + "@" + actionNum;
CoordinatorStore store = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store.beginTrx();
try {
addRecordToJobTable(jobId, store, CoordinatorJob.Status.KILLED);
addRecordToActionTable(jobId, actionNum, actionId, store, CoordinatorAction.Status.SUCCEEDED,
"coord-rerun-action1.xml");
store.commitTrx();
}
catch (Exception e) {
e.printStackTrace();
fail("Could not update db.");
}
finally {
store.closeTrx();
}
try {
final OozieClient coordClient = LocalOozie.getCoordClient();
coordClient.reRunCoord(jobId, RestConstants.JOB_COORD_RERUN_ACTION, Integer.toString(actionNum), false,
true);
fail("Exception expected because action is not in terminal state.");
}
catch (OozieClientException ex) {
if (!ex.getErrorCode().equals(ErrorCode.E1018.toString())) {
fail("Error code should be E1018 when job is killed or failed.");
}
}
CoordinatorStore store2 = Services.get().get(StoreService.class).getStore(CoordinatorStore.class);
store2.beginTrx();
CoordinatorActionBean action2 = store2.getCoordinatorAction(actionId, false);
assertEquals(action2.getStatus(), CoordinatorAction.Status.SUCCEEDED);
store2.commitTrx();
store2.closeTrx();
}
private void addRecordToJobTable(String jobId, CoordinatorStore store, CoordinatorJob.Status status)
throws StoreException,
IOException {
Path appPath = new Path(getFsTestCaseDir(), "coord");
String appXml = getCoordJobXml(appPath);
FileSystem fs = getFileSystem();
Writer writer = new OutputStreamWriter(fs.create(new Path(appPath + "/coordinator.xml")));
byte[] bytes = appXml.getBytes("UTF-8");
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
Reader reader2 = new InputStreamReader(bais);
IOUtils.copyCharStream(reader2, writer);
CoordinatorJobBean coordJob = new CoordinatorJobBean();
coordJob.setId(jobId);
coordJob.setAppName("COORD-TEST");
coordJob.setAppPath(appPath.toString());
coordJob.setStatus(status);
coordJob.setCreatedTime(new Date());
coordJob.setLastModifiedTime(new Date());
coordJob.setUser(getTestUser());
coordJob.setGroup(getTestGroup());
coordJob.setAuthToken("notoken");
Properties conf = getCoordConf(appPath);
String confStr = XmlUtils.writePropToString(conf);
coordJob.setConf(confStr);
coordJob.setJobXml(appXml);
coordJob.setLastActionNumber(0);
coordJob.setFrequency(1);
coordJob.setExecution(Execution.FIFO);
coordJob.setConcurrency(1);
try {
coordJob.setStartTime(DateUtils.parseDateUTC("2009-12-15T01:00Z"));
coordJob.setEndTime(DateUtils.parseDateUTC("2009-12-17T01:00Z"));
}
catch (Exception e) {
e.printStackTrace();
fail("Could not set Date/time");
}
try {
store.insertCoordinatorJob(coordJob);
}
catch (StoreException se) {
se.printStackTrace();
store.rollbackTrx();
fail("Unable to insert the test job record to table");
throw se;
}
}
private void addRecordToActionTable(String jobId, int actionNum, String actionId, CoordinatorStore store,
CoordinatorAction.Status status, String resourceXmlName)
throws StoreException, IOException {
Path appPath = new Path(getFsTestCaseDir(), "coord");
String actionXml = getCoordActionXml(appPath, resourceXmlName);
String actionNomialTime = getActionNomialTime(actionXml);
CoordinatorActionBean action = new CoordinatorActionBean();
action.setJobId(jobId);
action.setId(actionId);
action.setActionNumber(actionNum);
try {
action.setNominalTime(DateUtils.parseDateUTC(actionNomialTime));
}
catch (Exception e) {
e.printStackTrace();
fail("Unable to get action nominal time");
throw new IOException(e);
}
action.setLastModifiedTime(new Date());
action.setStatus(status);
action.setActionXml(actionXml);
Properties conf = getCoordConf(appPath);
String createdConf = XmlUtils.writePropToString(conf);
action.setCreatedConf(createdConf);
try {
store.insertCoordinatorAction(action);
}
catch (StoreException se) {
se.printStackTrace();
store.rollbackTrx();
fail("Unable to insert the test job record to table");
throw se;
}
}
private Properties getCoordConf(Path appPath) throws IOException {
Path wfAppPath = new Path(getFsTestCaseDir(), "workflow");
final OozieClient coordClient = LocalOozie.getCoordClient();
Properties conf = coordClient.createConfiguration();
conf.setProperty(OozieClient.COORDINATOR_APP_PATH, appPath.toString());
conf.setProperty("jobTracker", getJobTrackerUri());
conf.setProperty("nameNode", getNameNodeUri());
conf.setProperty("wfAppPath", wfAppPath.toString());
conf.remove("user.name");
conf.setProperty("user.name", getTestUser());
injectKerberosInfo(conf);
String content = "<workflow-app xmlns='uri:oozie:workflow:0.1' xmlns:sla='uri:oozie:sla:0.1' name='no-op-wf'>";
content += "<start to='end' />";
content += "<end name='end' /></workflow-app>";
writeToFile(content, wfAppPath, "workflow.xml");
return conf;
}
private void writeToFile(String content, Path appPath, String fileName) throws IOException {
FileSystem fs = getFileSystem();
Writer writer = new OutputStreamWriter(fs.create(new Path(appPath, fileName), true));
writer.write(content);
writer.close();
}
@SuppressWarnings("unchecked")
private String[] getActionXmlUrls(Element eAction, String user, String group) {
Element outputList = eAction.getChild("input-events", eAction.getNamespace());
for (Element data : (List<Element>) outputList.getChildren("data-in", eAction.getNamespace())) {
if (data.getChild("uris", data.getNamespace()) != null) {
String uris = data.getChild("uris", data.getNamespace()).getTextTrim();
if (uris != null) {
String[] uriArr = uris.split(CoordELFunctions.INSTANCE_SEPARATOR);
return uriArr;
}
}
}
return null;
}
@Override
protected String getTestCaseDir() {
String testCaseDir = "/tmp/TestCoordRerunCommand/";
System.out.println(XLog.format("Setting testcase work dir[{0}]", testCaseDir));
try {
delete(new File(testCaseDir));
}
catch (IOException ioe) {
ioe.printStackTrace();
throw new RuntimeException(XLog.format("Could not delete testcase dir[{0}]", testCaseDir));
}
File dir = new File(testCaseDir);
if (!dir.mkdirs()) {
throw new RuntimeException(XLog.format("Could not create testcase dir[{0}]", testCaseDir));
}
return testCaseDir;
}
private String getCoordJobXml(Path appPath) {
String inputTemplate = appPath + "/coord-input/${YEAR}/${MONTH}/${DAY}/${HOUR}/${MINUTE}";
inputTemplate = Matcher.quoteReplacement(inputTemplate);
String outputTemplate = appPath + "/coord-input/${YEAR}/${MONTH}/${DAY}/${HOUR}/${MINUTE}";
outputTemplate = Matcher.quoteReplacement(outputTemplate);
try {
Reader reader = IOUtils.getResourceAsReader("coord-rerun-job.xml", -1);
String appXml = IOUtils.getReaderAsString(reader, -1);
appXml = appXml.replaceAll("#inputTemplate", inputTemplate);
appXml = appXml.replaceAll("#outputTemplate", outputTemplate);
return appXml;
}
catch (IOException ioe) {
throw new RuntimeException(XLog.format("Could not get coord-rerun-job.xml", ioe));
}
}
private String getCoordActionXml(Path appPath, String resourceXmlName) {
String inputTemplate = appPath + "/coord-input/${YEAR}/${MONTH}/${DAY}/${HOUR}/${MINUTE}";
inputTemplate = Matcher.quoteReplacement(inputTemplate);
String outputTemplate = appPath + "/coord-input/${YEAR}/${MONTH}/${DAY}/${HOUR}/${MINUTE}";
outputTemplate = Matcher.quoteReplacement(outputTemplate);
String inputDir = appPath + "/coord-input/2010/07/05/01/00";
inputDir = Matcher.quoteReplacement(inputDir);
String outputDir = appPath + "/coord-input/2009/12/14/11/00";
outputDir = Matcher.quoteReplacement(outputDir);
try {
Reader reader = IOUtils.getResourceAsReader(resourceXmlName, -1);
String appXml = IOUtils.getReaderAsString(reader, -1);
appXml = appXml.replaceAll("#inputTemplate", inputTemplate);
appXml = appXml.replaceAll("#outputTemplate", outputTemplate);
appXml = appXml.replaceAll("#inputDir", inputDir);
appXml = appXml.replaceAll("#outputDir", outputDir);
return appXml;
}
catch (IOException ioe) {
throw new RuntimeException(XLog.format("Could not get " + resourceXmlName, ioe));
}
}
private String getActionNomialTime(String actionXml) {
Element eAction;
try {
eAction = XmlUtils.parseXml(actionXml);
}
catch (JDOMException je) {
throw new RuntimeException(XLog.format("Could not parse actionXml :" + actionXml, je));
}
String actionNomialTime = eAction.getAttributeValue("action-nominal-time");
return actionNomialTime;
}
}