/** * 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.util.Date; import java.util.List; import org.apache.oozie.CoordinatorActionBean; import org.apache.oozie.CoordinatorJobBean; import org.apache.oozie.SLAEventBean; import org.apache.oozie.client.CoordinatorJob; import org.apache.oozie.client.CoordinatorJob.Timeunit; import org.apache.oozie.service.Services; import org.apache.oozie.store.CoordinatorStore; import org.apache.oozie.store.SLAStore; import org.apache.oozie.store.StoreException; import org.apache.oozie.test.XTestCase; import org.apache.oozie.util.DateUtils; public class TestCoordActionMaterializeCommand extends XTestCase { private Services services; @Override protected void setUp() throws Exception { super.setUp(); services = new Services(); services.init(); cleanUpDBTables(); } @Override protected void tearDown() throws Exception { services.destroy(); super.tearDown(); } public void testActionMater() throws Exception { String jobId = "0000000-" + new Date().getTime() + "-testActionMater-C"; Date startTime = DateUtils.parseDateUTC("2009-03-06T010:00Z"); Date endTime = DateUtils.parseDateUTC("2009-03-11T10:00Z"); addRecordToJobTable(jobId, startTime, endTime); new CoordActionMaterializeCommand(jobId, startTime, endTime).call(); CoordinatorActionBean action = checkCoordAction(jobId + "@1"); } public void testActionMaterWithPauseTime1() throws Exception { String jobId = "0000000-" + new Date().getTime() + "-testActionMater-C"; Date startTime = DateUtils.parseDateUTC("2009-03-06T10:00Z"); Date endTime = DateUtils.parseDateUTC("2009-03-06T10:14Z"); Date pauseTime = DateUtils.parseDateUTC("2009-03-06T10:04Z"); addRecordToJobTable(jobId, startTime, endTime, pauseTime); new CoordActionMaterializeCommand(jobId, startTime, endTime).call(); checkCoordActions(jobId, 1, null); } public void testActionMaterWithPauseTime2() throws Exception { String jobId = "0000000-" + new Date().getTime() + "-testActionMater-C"; Date startTime = DateUtils.parseDateUTC("2009-03-06T10:00Z"); Date endTime = DateUtils.parseDateUTC("2009-03-06T10:14Z"); Date pauseTime = DateUtils.parseDateUTC("2009-03-06T10:08Z"); addRecordToJobTable(jobId, startTime, endTime, pauseTime); new CoordActionMaterializeCommand(jobId, startTime, endTime).call(); checkCoordActions(jobId, 2, null); } public void testActionMaterWithPauseTime3() throws Exception { String jobId = "0000000-" + new Date().getTime() + "-testActionMater-C"; Date startTime = DateUtils.parseDateUTC("2009-03-06T10:00Z"); Date endTime = DateUtils.parseDateUTC("2009-03-06T10:14Z"); Date pauseTime = DateUtils.parseDateUTC("2009-03-06T09:58Z"); addRecordToJobTable(jobId, startTime, endTime, pauseTime); new CoordActionMaterializeCommand(jobId, startTime, endTime).call(); checkCoordActions(jobId, 0, CoordinatorJob.Status.RUNNING); } private void addRecordToJobTable(String jobId, Date startTime, Date endTime) throws StoreException { CoordinatorStore store = new CoordinatorStore(false); CoordinatorJobBean coordJob = new CoordinatorJobBean(); coordJob.setId(jobId); coordJob.setAppName("testApp"); coordJob.setStartTime(startTime); coordJob.setEndTime(endTime); coordJob.setTimeUnit(Timeunit.DAY); coordJob.setAppPath("testAppPath"); coordJob.setStatus(CoordinatorJob.Status.PREMATER); coordJob.setCreatedTime(new Date()); // TODO: Do we need that? coordJob.setLastModifiedTime(new Date()); coordJob.setUser("testUser"); coordJob.setGroup("testGroup"); coordJob.setTimeZone("America/Los_Angeles"); String confStr = "<configuration></configuration>"; coordJob.setConf(confStr); String appXml = "<coordinator-app xmlns='uri:oozie:coordinator:0.1' xmlns:sla='uri:oozie:sla:0.1' name='NAME' frequency=\"1\" start='2009-03-06T010:00Z' end='2009-03-11T10:00Z' timezone='America/Los_Angeles' freq_timeunit='DAY' end_of_duration='NONE'>"; appXml += "<controls>"; appXml += "<timeout>10</timeout>"; appXml += "<concurrency>2</concurrency>"; appXml += "<execution>LIFO</execution>"; appXml += "</controls>"; appXml += "<input-events>"; appXml += "<data-in name='A' dataset='a'>"; appXml += "<dataset name='a' frequency='7' initial-instance='2009-02-01T01:00Z' timezone='UTC' freq_timeunit='DAY' end_of_duration='NONE'>"; appXml += "<uri-template>file:///tmp/coord/workflows/${YEAR}/${MONTH}/${DAY}</uri-template>"; appXml += "</dataset>"; appXml += "<instance>${coord:current(0)}</instance>"; appXml += "<instance>${coord:latest(-1)}</instance>"; //appXml += "<start-instance>${coord:current(-2)}</start-instance>"; //appXml += "<end-instance>${coord:current(0)}</end-instance>"; appXml += "</data-in>"; appXml += "</input-events>"; appXml += "<output-events>"; appXml += "<data-out name='LOCAL_A' dataset='local_a'>"; appXml += "<dataset name='local_a' frequency='7' initial-instance='2009-02-01T01:00Z' timezone='UTC' freq_timeunit='DAY' end_of_duration='NONE'>"; appXml += "<uri-template>file:///tmp/coord/workflows/${YEAR}/${DAY}</uri-template>"; appXml += "</dataset>"; appXml += "<instance>${coord:current(-1)}</instance>"; appXml += "</data-out>"; appXml += "</output-events>"; appXml += "<action>"; appXml += "<workflow>"; appXml += "<app-path>hdfs:///tmp/workflows/</app-path>"; appXml += "<configuration>"; appXml += "<property>"; appXml += "<name>inputA</name>"; appXml += "<value>${coord:dataIn('A')}</value>"; appXml += "</property>"; appXml += "<property>"; appXml += "<name>inputB</name>"; appXml += "<value>${coord:dataOut('LOCAL_A')}</value>"; appXml += "</property>"; appXml += "</configuration>"; appXml += "</workflow>"; appXml += " <sla:info>" // + " <sla:client-id>axonite-blue</sla:client-id>" + " <sla:app-name>test-app</sla:app-name>" + " <sla:nominal-time>${coord:nominalTime()}</sla:nominal-time>" + " <sla:should-start>5</sla:should-start>" + " <sla:should-end>120</sla:should-end>" + " <sla:notification-msg>Notifying User for ${coord:nominalTime()} nominal time </sla:notification-msg>" + " <sla:alert-contact>abc@yahoo.com</sla:alert-contact>" + " <sla:dev-contact>abc@yahoo.com</sla:dev-contact>" + " <sla:qa-contact>abc@yahoo.com</sla:qa-contact>" + " <sla:se-contact>abc@yahoo.com</sla:se-contact>" + "</sla:info>"; appXml += "</action>"; appXml += "</coordinator-app>"; /*try { System.out.println(XmlUtils.prettyPrint(XmlUtils.parseXml(appXml))); ; } catch (JDOMException e1) { // TODO Auto-generated catch block e1.printStackTrace(); }*/ coordJob.setJobXml(appXml); coordJob.setLastActionNumber(0); coordJob.setFrequency(1); try { coordJob.setEndTime(DateUtils.parseDateUTC("2009-03-11T10:00Z")); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); fail("Could not set end time"); } try { store.beginTrx(); store.insertCoordinatorJob(coordJob); store.commitTrx(); } catch (StoreException se) { se.printStackTrace(); store.rollbackTrx(); fail("Unable to insert the test job record to table"); throw se; } finally { store.closeTrx(); } } private CoordinatorActionBean checkCoordAction(String actionId) throws StoreException { CoordinatorStore store = new CoordinatorStore(false); try { CoordinatorActionBean action = store.getCoordinatorAction(actionId, false); SLAStore slaStore = new SLAStore(store); long lastSeqId[] = new long[1]; List<SLAEventBean> slaEvents = slaStore.getSLAEventListNewerSeqLimited(0, 10, lastSeqId); // System.out.println("AAA " + slaEvents.size() + " : " + // lastSeqId[0]); if (slaEvents.size() == 0) { fail("Unable to GET any record of sequence id greater than 0"); } return action; } catch (StoreException se) { se.printStackTrace(); fail("Action ID " + actionId + " was not stored properly in db"); } return null; } private void addRecordToJobTable(String jobId, Date startTime, Date endTime, Date pauseTime) throws StoreException { CoordinatorStore store = new CoordinatorStore(false); CoordinatorJobBean coordJob = new CoordinatorJobBean(); coordJob.setId(jobId); coordJob.setAppName("testApp"); coordJob.setStartTime(startTime); coordJob.setEndTime(endTime); coordJob.setPauseTime(pauseTime); coordJob.setTimeUnit(Timeunit.MINUTE); coordJob.setAppPath("testAppPath"); coordJob.setStatus(CoordinatorJob.Status.PREMATER); coordJob.setCreatedTime(new Date()); // TODO: Do we need that? coordJob.setLastModifiedTime(new Date()); coordJob.setUser("testUser"); coordJob.setGroup("testGroup"); coordJob.setTimeZone("America/Los_Angeles"); String confStr = "<configuration></configuration>"; coordJob.setConf(confStr); String appXml = "<coordinator-app xmlns='uri:oozie:coordinator:0.1' xmlns:sla='uri:oozie:sla:0.1' name='NAME' frequency=\"5\" start='2009-03-06T010:00Z' end='2009-03-06T10:14Z' timezone='America/Los_Angeles' freq_timeunit='MINUTE' end_of_duration='NONE'>"; appXml += "<controls>"; appXml += "<timeout>10</timeout>"; appXml += "<concurrency>2</concurrency>"; appXml += "<execution>LIFO</execution>"; appXml += "</controls>"; appXml += "<action>"; appXml += "<workflow>"; appXml += "<app-path>hdfs:///tmp/workflows/</app-path>"; appXml += "<configuration>"; appXml += "</configuration>"; appXml += "</workflow>"; appXml += " <sla:info>" // + " <sla:client-id>axonite-blue</sla:client-id>" + " <sla:app-name>test-app</sla:app-name>" + " <sla:nominal-time>${coord:nominalTime()}</sla:nominal-time>" + " <sla:should-start>5</sla:should-start>" + " <sla:should-end>120</sla:should-end>" + " <sla:notification-msg>Notifying User for ${coord:nominalTime()} nominal time </sla:notification-msg>" + " <sla:alert-contact>abc@yahoo.com</sla:alert-contact>" + " <sla:dev-contact>abc@yahoo.com</sla:dev-contact>" + " <sla:qa-contact>abc@yahoo.com</sla:qa-contact>" + " <sla:se-contact>abc@yahoo.com</sla:se-contact>" + "</sla:info>"; appXml += "</action>"; appXml += "</coordinator-app>"; coordJob.setJobXml(appXml); coordJob.setLastActionNumber(0); coordJob.setFrequency(5); try { store.beginTrx(); store.insertCoordinatorJob(coordJob); store.commitTrx(); } catch (StoreException se) { se.printStackTrace(); store.rollbackTrx(); fail("Unable to insert the test job record to table"); throw se; } finally { store.closeTrx(); } } private void checkCoordActions(String jobId, int number, CoordinatorJob.Status status) throws StoreException { CoordinatorStore store = new CoordinatorStore(false); try { List<CoordinatorActionBean> actions = store.getActionsForCoordinatorJob(jobId, false); if (actions.size() != number) { fail("Should have " + number + " actions created for job " + jobId); } if (status != null) { CoordinatorJob job = store.getCoordinatorJob(jobId, false); if (job.getStatus() != status) { fail("Job status " + job.getStatus() + " should be " + status); } } } catch (StoreException se) { se.printStackTrace(); fail("Job ID " + jobId + " was not stored properly in db"); } } }