You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@oozie.apache.org by mo...@apache.org on 2013/05/20 18:51:39 UTC

svn commit: r1484523 [5/5] - in /oozie/trunk: ./ client/src/main/java/org/apache/oozie/ client/src/main/java/org/apache/oozie/cli/ client/src/main/java/org/apache/oozie/client/ client/src/main/java/org/apache/oozie/client/event/ client/src/main/java/or...

Added: oozie/trunk/core/src/test/java/org/apache/oozie/sla/TestSLAEventGeneration.java
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/test/java/org/apache/oozie/sla/TestSLAEventGeneration.java?rev=1484523&view=auto
==============================================================================
--- oozie/trunk/core/src/test/java/org/apache/oozie/sla/TestSLAEventGeneration.java (added)
+++ oozie/trunk/core/src/test/java/org/apache/oozie/sla/TestSLAEventGeneration.java Mon May 20 16:51:37 2013
@@ -0,0 +1,290 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.oozie.sla;
+
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashSet;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.Path;
+import org.apache.oozie.AppType;
+import org.apache.oozie.CoordinatorActionBean;
+import org.apache.oozie.client.CoordinatorAction;
+import org.apache.oozie.client.OozieClient;
+import org.apache.oozie.client.WorkflowJob;
+import org.apache.oozie.client.event.SLAEvent.SLAStatus;
+import org.apache.oozie.client.event.SLAEvent.EventStatus;
+import org.apache.oozie.command.CommandException;
+import org.apache.oozie.command.coord.CoordActionStartXCommand;
+import org.apache.oozie.command.coord.CoordKillXCommand;
+import org.apache.oozie.command.coord.CoordSubmitXCommand;
+import org.apache.oozie.command.wf.KillXCommand;
+import org.apache.oozie.command.wf.StartXCommand;
+import org.apache.oozie.command.wf.SubmitXCommand;
+import org.apache.oozie.event.listener.JobEventListener;
+import org.apache.oozie.executor.jpa.CoordActionGetJPAExecutor;
+import org.apache.oozie.executor.jpa.CoordActionUpdateJPAExecutor;
+import org.apache.oozie.service.EventHandlerService;
+import org.apache.oozie.service.JPAService;
+import org.apache.oozie.service.Services;
+import org.apache.oozie.sla.listener.SLAJobEventListener;
+import org.apache.oozie.sla.service.SLAService;
+import org.apache.oozie.test.XDataTestCase;
+import org.apache.oozie.util.DateUtils;
+import org.apache.oozie.util.IOUtils;
+import org.apache.oozie.util.XConfiguration;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestSLAEventGeneration extends XDataTestCase {
+    Services services;
+    JPAService jpa;
+    Calendar cal;
+    String alert_events = "START_MISS,END_MET,END_MISS";
+
+    private static final String SLA_XML_1 = "<workflow-app xmlns=\"uri:oozie:workflow:0.2\" "
+            + "xmlns:sla=\"uri:oozie:sla:0.1\" name=\"test-wf-job-sla\">" + "<start to=\"myjava\"/>"
+            + "<action name=\"myjava\"> <java>" + "<job-tracker>jt</job-tracker>" + "<name-node>nn</name-node>"
+            + "<main-class>org.apache.oozie.example.DemoJavaMain</main-class>" + "</java> <ok to=\"end\"/>"
+            + "<error to=\"end\"/>" + "</action>" + "<end name=\"end\"/> " + "<sla:info>"
+            + "<sla:app-name>test-wf-job-sla</sla:app-name>" + "<sla:nominal-time>${nominal_time}</sla:nominal-time>"
+            + "<sla:should-start>${10 * MINUTES}</sla:should-start>"
+            + "<sla:should-end>${30 * MINUTES}</sla:should-end>"
+            + "<sla:notification-msg>My Notification Message</sla:notification-msg>"
+            + "<sla:alert-contact>alert@example.com</sla:alert-contact>"
+            + "<sla:dev-contact>dev@example.com</sla:dev-contact>" + "<sla:qa-contact>qa@example.com</sla:qa-contact>"
+            + "<sla:se-contact>se@example.com</sla:se-contact>"
+            + "<sla:alert-frequency>LAST_HOUR</sla:alert-frequency>"
+            + "<sla:alert-percentage>10</sla:alert-percentage>" + "<sla:upstream-apps>upstream-job</sla:upstream-apps>"
+            + "</sla:info>" + "</workflow-app>";
+
+    @Override
+    @Before
+    protected void setUp() throws Exception {
+        super.setUp();
+        services = new Services();
+        Configuration conf = services.getConf();
+        conf.set(Services.CONF_SERVICE_EXT_CLASSES,
+                EventHandlerService.class.getName() + "," + SLAService.class.getName());
+        conf.setClass(EventHandlerService.CONF_LISTENERS, SLAJobEventListener.class, JobEventListener.class);
+        conf.setInt(EventHandlerService.CONF_WORKER_INTERVAL, 10000);
+        conf.setInt(EventHandlerService.CONF_BATCH_SIZE, 1);
+        services.init();
+        jpa = services.get(JPAService.class);
+        cal = Calendar.getInstance();
+        cleanUpDBTables();
+    }
+
+    @Override
+    @After
+    protected void tearDown() throws Exception {
+        services.destroy();
+        super.tearDown();
+    }
+
+    /**
+     * Test for SLA Events generated through Workflow Job Commands
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testWorkflowJobSLANew() throws Exception {
+        EventHandlerService ehs = services.get(EventHandlerService.class);
+        assertNotNull(ehs);
+        SLAService slas = services.get(SLAService.class);
+        assertNotNull(slas);
+
+        String wfXml = IOUtils.getResourceAsString("wf-job-sla.xml", -1);
+        Path appPath = getFsTestCaseDir();
+        writeToFile(wfXml, appPath, "workflow.xml");
+        Configuration conf = new XConfiguration();
+        conf.set(OozieClient.APP_PATH, appPath.toString());
+        conf.set(OozieClient.USER_NAME, getTestUser());
+        _testWorkflowJobCommands(conf, ehs, slas, true);
+    }
+
+    @Test
+    public void testSLASchema1BackwardCompatibility() throws Exception {
+        EventHandlerService ehs = services.get(EventHandlerService.class);
+        assertNotNull(ehs);
+        SLAService slas = services.get(SLAService.class);
+        assertNotNull(slas);
+
+        Path appPath = getFsTestCaseDir();
+        writeToFile(SLA_XML_1, appPath, "workflow.xml");
+        Configuration conf = new XConfiguration();
+        conf.set(OozieClient.APP_PATH, appPath.toString());
+        conf.set(OozieClient.USER_NAME, getTestUser());
+        cal.setTime(new Date());
+        cal.add(Calendar.MINUTE, -20); // for start_miss
+        Date nominal = cal.getTime();
+        String nominalTime = DateUtils.formatDateOozieTZ(nominal);
+        conf.set("nominal_time", nominalTime);
+        _testWorkflowJobCommands(conf, ehs, slas, false);
+    }
+
+    private void _testWorkflowJobCommands(Configuration conf, EventHandlerService ehs, SLAService slas, boolean isNew)
+            throws CommandException, InterruptedException {
+        cal.setTime(new Date());
+        cal.add(Calendar.MINUTE, -20); // for start_miss
+        Date nominal = cal.getTime();
+        String nominalTime = DateUtils.formatDateOozieTZ(nominal);
+        conf.set("nominal_time", nominalTime);
+        cal.setTime(nominal);
+        cal.add(Calendar.MINUTE, 10); // as per the sla xml
+        String expectedStart = DateUtils.formatDateOozieTZ(cal.getTime());
+        cal.setTime(nominal);
+        cal.add(Calendar.MINUTE, 30); // as per the sla xml
+        String expectedEnd = DateUtils.formatDateOozieTZ(cal.getTime());
+
+        // testing creation of new sla registration via Submit command
+        SubmitXCommand sc = new SubmitXCommand(conf, "UNIT_TESTING");
+        String jobId = sc.call();
+        SLACalcStatus slaEvent = slas.getSLACalculator().get(jobId);
+        assertEquals(jobId, slaEvent.getJobId());
+        assertEquals("test-wf-job-sla", slaEvent.getAppName());
+        assertEquals(AppType.WORKFLOW_JOB, slaEvent.getAppType());
+        assertEquals(nominalTime, DateUtils.formatDateOozieTZ(slaEvent.getNominalTime()));
+        assertEquals(expectedStart, DateUtils.formatDateOozieTZ(slaEvent.getExpectedStart()));
+        assertEquals(expectedEnd, DateUtils.formatDateOozieTZ(slaEvent.getExpectedEnd()));
+        if (isNew) {
+            assertEquals(30 * 60 * 1000, slaEvent.getExpectedDuration());
+            assertEquals(alert_events, slaEvent.getAlertEvents());
+        }
+        slas.runSLAWorker();
+        slaEvent = (SLACalcStatus) ehs.getEventQueue().poll();
+        assertEquals(SLAStatus.NOT_STARTED, slaEvent.getSLAStatus());
+        assertEquals(EventStatus.START_MISS, slaEvent.getEventStatus());
+
+        // test that sla processes the Job Event from Start command
+        new StartXCommand(jobId).call();
+        slaEvent = slas.getSLACalculator().get(jobId);
+        slaEvent.setStartProcessed(false); //resetting flag for testing sla event
+        ehs.new EventWorker().run();
+        Thread.sleep(300); //time for event listeners to run
+        slaEvent = (SLACalcStatus) ehs.getEventQueue().poll();
+        assertEquals(jobId, slaEvent.getJobId());
+        assertNotNull(slaEvent.getActualStart());
+        assertEquals(SLAStatus.IN_PROCESS, slaEvent.getSLAStatus());
+        assertEquals(WorkflowJob.Status.RUNNING.name(), slaEvent.getJobStatus());
+        ehs.getEventQueue().clear();
+
+        // test that sla processes the Job Event from Kill command
+        new KillXCommand(jobId).call();
+        ehs.new EventWorker().run();
+        Thread.sleep(300);
+        slaEvent = (SLACalcStatus) ehs.getEventQueue().poll();
+        assertEquals(jobId, slaEvent.getJobId());
+        assertNotNull(slaEvent.getActualEnd());
+        assertEquals(EventStatus.END_MISS, slaEvent.getEventStatus());
+        assertEquals(SLAStatus.MISS, slaEvent.getSLAStatus());
+        assertEquals(WorkflowJob.Status.KILLED.name(), slaEvent.getJobStatus());
+    }
+
+    /**
+     * Test for SLA Events generated through Coordinator Action commands
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testCoordinatorActionCommands() throws Exception {
+        EventHandlerService ehs = services.get(EventHandlerService.class);
+        assertNotNull(ehs);
+        // reduce noise from WF Job events (also default) by setting it to only
+        // coord action
+        ehs.setAppTypes(new HashSet<String>(Arrays.asList(new String[] { "coordinator_action" })));
+        SLAService slas = services.get(SLAService.class);
+        assertNotNull(slas);
+
+        String coordXml = IOUtils.getResourceAsString("coord-action-sla.xml", -1);
+        Path appPath = getFsTestCaseDir();
+        writeToFile(coordXml, appPath, "coordinator.xml");
+        Configuration conf = new XConfiguration();
+        conf.set(OozieClient.COORDINATOR_APP_PATH, appPath.toString());
+        String wfXml = IOUtils.getResourceAsString("wf-credentials.xml", -1);
+        writeToFile(wfXml, appPath, "workflow.xml");
+        conf.set("wfAppPath", appPath.toString());
+        conf.set(OozieClient.USER_NAME, getTestUser());
+
+        cal.setTime(new Date());
+        cal.add(Calendar.MINUTE, -20); // for start_miss
+        Date nominal = cal.getTime();
+        String nominalTime = DateUtils.formatDateOozieTZ(nominal);
+        conf.set("nominal_time", nominalTime);
+        cal.setTime(nominal);
+        cal.add(Calendar.MINUTE, 10); // as per the sla xml
+        String expectedStart = DateUtils.formatDateOozieTZ(cal.getTime());
+        cal.setTime(nominal);
+        cal.add(Calendar.MINUTE, 30); // as per the sla xml
+        String expectedEnd = DateUtils.formatDateOozieTZ(cal.getTime());
+        String appName = "test-coord-sla";
+
+        // testing creation of new sla registration via Submit+Materialize
+        // command
+        CoordSubmitXCommand sc = new CoordSubmitXCommand(conf, "UNIT_TESTING");
+        String jobId = sc.call();
+        Thread.sleep(500); // waiting for materialize command to run
+        final CoordActionGetJPAExecutor getCmd = new CoordActionGetJPAExecutor(jobId + "@1");
+        CoordinatorActionBean action = jpa.execute(getCmd);
+        String actionId = action.getId();
+        SLACalcStatus slaEvent = slas.getSLACalculator().get(actionId);
+        assertEquals(actionId, slaEvent.getJobId());
+        assertEquals(appName, slaEvent.getAppName());
+        assertEquals(AppType.COORDINATOR_ACTION, slaEvent.getAppType());
+        assertEquals(nominalTime, DateUtils.formatDateOozieTZ(slaEvent.getNominalTime()));
+        assertEquals(expectedStart, DateUtils.formatDateOozieTZ(slaEvent.getExpectedStart()));
+        assertEquals(expectedEnd, DateUtils.formatDateOozieTZ(slaEvent.getExpectedEnd()));
+        assertEquals(30 * 60 * 1000, slaEvent.getExpectedDuration());
+        assertEquals(alert_events, slaEvent.getAlertEvents());
+        ehs.getEventQueue().clear(); //clear the coord-action WAITING event generated
+        slas.runSLAWorker();
+        slaEvent = (SLACalcStatus) ehs.getEventQueue().poll();
+        assertEquals(SLAStatus.NOT_STARTED, slaEvent.getSLAStatus());
+        assertEquals(EventStatus.START_MISS, slaEvent.getEventStatus());
+
+        // test that sla processes the Job Event from Start command
+        action.setStatus(CoordinatorAction.Status.SUBMITTED);
+        final CoordActionUpdateJPAExecutor writeCmd = new CoordActionUpdateJPAExecutor(action);
+        jpa.execute(writeCmd);
+        new CoordActionStartXCommand(actionId, getTestUser(), appName, "authtoken", jobId).call();
+        slaEvent = slas.getSLACalculator().get(actionId);
+        slaEvent.setStartProcessed(false); //resetting flag for testing sla event
+        ehs.new EventWorker().run();
+        Thread.sleep(300); //time for event listeners to run
+        slaEvent = (SLACalcStatus) ehs.getEventQueue().poll();
+        assertEquals(actionId, slaEvent.getJobId());
+        assertNotNull(slaEvent.getActualStart());
+        assertEquals(SLAStatus.IN_PROCESS, slaEvent.getSLAStatus());
+        assertEquals(WorkflowJob.Status.RUNNING.name(), slaEvent.getJobStatus());
+
+        // test that sla processes the Job Event from Kill command
+        new CoordKillXCommand(jobId).call();
+        ehs.new EventWorker().run();
+        Thread.sleep(300); //time for event listeners to run
+        slaEvent = (SLACalcStatus) ehs.getEventQueue().poll();
+        assertEquals(actionId, slaEvent.getJobId());
+        assertNotNull(slaEvent.getActualEnd());
+        assertEquals(EventStatus.END_MISS, slaEvent.getEventStatus());
+        assertEquals(SLAStatus.MISS, slaEvent.getSLAStatus());
+        assertEquals(WorkflowJob.Status.KILLED.name(), slaEvent.getJobStatus());
+    }
+
+}

Added: oozie/trunk/core/src/test/java/org/apache/oozie/sla/TestSLAJobEventListener.java
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/test/java/org/apache/oozie/sla/TestSLAJobEventListener.java?rev=1484523&view=auto
==============================================================================
--- oozie/trunk/core/src/test/java/org/apache/oozie/sla/TestSLAJobEventListener.java (added)
+++ oozie/trunk/core/src/test/java/org/apache/oozie/sla/TestSLAJobEventListener.java Mon May 20 16:51:37 2013
@@ -0,0 +1,144 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.oozie.sla;
+
+import java.util.Date;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.oozie.AppType;
+import org.apache.oozie.client.CoordinatorAction;
+import org.apache.oozie.client.CoordinatorJob;
+import org.apache.oozie.client.WorkflowAction;
+import org.apache.oozie.client.WorkflowJob;
+import org.apache.oozie.client.event.SLAEvent.EventStatus;
+import org.apache.oozie.event.CoordinatorActionEvent;
+import org.apache.oozie.event.CoordinatorJobEvent;
+import org.apache.oozie.event.WorkflowActionEvent;
+import org.apache.oozie.event.WorkflowJobEvent;
+import org.apache.oozie.executor.jpa.sla.SLACalculatorGetJPAExecutor;
+import org.apache.oozie.executor.jpa.sla.SLASummaryGetJPAExecutor;
+import org.apache.oozie.service.EventHandlerService;
+import org.apache.oozie.service.JPAService;
+import org.apache.oozie.service.Services;
+import org.apache.oozie.sla.listener.SLAJobEventListener;
+import org.apache.oozie.sla.service.SLAService;
+import org.apache.oozie.test.XTestCase;
+import org.apache.oozie.util.DateUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestSLAJobEventListener extends XTestCase {
+    Services services;
+    static StringBuilder output = new StringBuilder();
+
+    @Override
+    @Before
+    protected void setUp() throws Exception {
+        super.setUp();
+        services = new Services();
+        Configuration conf = services.getConf();
+        conf.set(Services.CONF_SERVICE_EXT_CLASSES, "org.apache.oozie.service.EventHandlerService,"
+                + "org.apache.oozie.sla.service.SLAService");
+        services.init();
+    }
+
+    @Override
+    @After
+    protected void tearDown() throws Exception {
+        services.destroy();
+        super.tearDown();
+    }
+
+    @Test
+    public void testListenerConfigured() throws Exception {
+        EventHandlerService ehs = services.get(EventHandlerService.class);
+        assertNotNull(ehs);
+        assertTrue(SLAService.isEnabled());
+        assertTrue(ehs.listEventListeners().contains(SLAJobEventListener.class.getCanonicalName()));
+    }
+
+    @Test
+    public void testOnJobEvent() throws Exception {
+        SLAService slas = services.get(SLAService.class);
+        SLAJobEventListener listener = new SLAJobEventListener();
+        listener.init(services.getConf());
+        // add dummy registration events to the SLAService map
+        SLARegistrationBean job = _createSLARegBean("wf1", AppType.WORKFLOW_JOB);
+        job.setExpectedStart(DateUtils.parseDateUTC("2012-07-22T00:00Z"));
+        slas.addRegistrationEvent(job);
+        assertEquals(1, slas.getSLACalculator().size());
+        Date actualStart = DateUtils.parseDateUTC("2012-07-22T01:00Z");
+        WorkflowJobEvent wfe = new WorkflowJobEvent("wf1", "caId1", WorkflowJob.Status.RUNNING, "user1",
+                "wf-app-name1", actualStart, null);
+        listener.onWorkflowJobEvent(wfe);
+        SLACalcStatus serviceObj = slas.getSLACalculator().get("wf1");
+        // check that start sla has been calculated
+        assertTrue(serviceObj.isStartProcessed());
+        assertEquals(EventStatus.START_MISS, serviceObj.getEventStatus());
+
+        job = _createSLARegBean("wa1", AppType.WORKFLOW_ACTION);
+        slas.addRegistrationEvent(job);
+        assertEquals(2, slas.getSLACalculator().size());
+        job.setExpectedStart(DateUtils.parseDateUTC("2012-07-22T00:00Z"));
+        WorkflowActionEvent wae = new WorkflowActionEvent("wa1", "wfId1", WorkflowAction.Status.RUNNING, "user1",
+                "wf-app-name1", actualStart, null);
+        listener.onWorkflowActionEvent(wae);
+        serviceObj = slas.getSLACalculator().get("wa1");
+        // check that start sla has been calculated
+        assertTrue(serviceObj.isStartProcessed());
+        assertEquals(EventStatus.START_MISS, serviceObj.getEventStatus());
+
+        job = _createSLARegBean("cj1", AppType.COORDINATOR_JOB);
+        job.setExpectedEnd(DateUtils.parseDateUTC("2012-07-22T01:00Z"));
+        slas.addRegistrationEvent(job);
+        assertEquals(3, slas.getSLACalculator().size());
+        Date actualEnd = DateUtils.parseDateUTC("2012-07-22T00:00Z");
+        CoordinatorJobEvent cje = new CoordinatorJobEvent("cj1", "bj1", CoordinatorJob.Status.SUCCEEDED, "user1",
+                "coord-app-name1", actualStart, actualEnd);
+        listener.onCoordinatorJobEvent(cje);
+
+        // Since serviceObj is removed from memory after END stage
+        SLACalculatorBean calc = Services.get().get(JPAService.class).execute(new SLACalculatorGetJPAExecutor("cj1"));
+        SLASummaryBean summary = Services.get().get(JPAService.class).execute(new SLASummaryGetJPAExecutor("cj1"));
+        // check that end sla has been calculated
+        assertTrue(calc.isEndProcessed());
+        assertEquals(EventStatus.END_MET, summary.getEventStatus());
+
+        job = _createSLARegBean("ca1", AppType.COORDINATOR_ACTION);
+        actualEnd = DateUtils.parseDateUTC("2012-07-22T02:00Z");
+        slas.addRegistrationEvent(job);
+        assertEquals(3, slas.getSLACalculator().size());
+        CoordinatorActionEvent cae = new CoordinatorActionEvent("ca1", "cj1", CoordinatorAction.Status.KILLED, "user1",
+                "coord-app-name1", null, actualEnd, null);
+        listener.onCoordinatorActionEvent(cae);
+        calc = Services.get().get(JPAService.class).execute(new SLACalculatorGetJPAExecutor("ca1"));
+        summary = Services.get().get(JPAService.class).execute(new SLASummaryGetJPAExecutor("ca1"));
+        // check that start sla has been calculated
+        assertTrue(calc.isEndProcessed());
+        assertEquals(EventStatus.END_MISS, summary.getEventStatus());
+
+    }
+
+    private SLARegistrationBean _createSLARegBean(String jobId, AppType appType) {
+        SLARegistrationBean reg = new SLARegistrationBean();
+        reg.setJobId(jobId);
+        reg.setAppType(appType);
+        return reg;
+    }
+}

Added: oozie/trunk/core/src/test/java/org/apache/oozie/sla/TestSLARegistrationGetJPAExecutor.java
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/test/java/org/apache/oozie/sla/TestSLARegistrationGetJPAExecutor.java?rev=1484523&view=auto
==============================================================================
--- oozie/trunk/core/src/test/java/org/apache/oozie/sla/TestSLARegistrationGetJPAExecutor.java (added)
+++ oozie/trunk/core/src/test/java/org/apache/oozie/sla/TestSLARegistrationGetJPAExecutor.java Mon May 20 16:51:37 2013
@@ -0,0 +1,92 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.oozie.sla;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.oozie.AppType;
+import org.apache.oozie.client.rest.JsonBean;
+import org.apache.oozie.executor.jpa.JPAExecutorException;
+import org.apache.oozie.executor.jpa.sla.SLACalculationInsertUpdateJPAExecutor;
+import org.apache.oozie.executor.jpa.sla.SLARegistrationGetJPAExecutor;
+import org.apache.oozie.service.JPAService;
+import org.apache.oozie.service.Services;
+import org.apache.oozie.sla.SLARegistrationBean;
+import org.apache.oozie.test.XDataTestCase;
+
+public class TestSLARegistrationGetJPAExecutor extends XDataTestCase {
+    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 testSLARegistrationGet() throws Exception {
+        Date current = new Date();
+        final String jobId = "0000000-" + current.getTime() + "-TestSLARegGetJPAExecutor-W";
+        _addRecordToSLARegistrationTable(jobId, AppType.WORKFLOW_JOB, current, new Date(), "END_MISS",
+                "alert@example.com");
+        JPAService jpaService = Services.get().get(JPAService.class);
+        assertNotNull(jpaService);
+
+        SLARegistrationGetJPAExecutor readCmd = new SLARegistrationGetJPAExecutor(jobId);
+        SLARegistrationBean bean = jpaService.execute(readCmd);
+        assertEquals(jobId, bean.getJobId());
+        assertEquals(AppType.WORKFLOW_JOB, bean.getAppType());
+        assertEquals(current, bean.getExpectedStart());
+        assertEquals(2, bean.getSlaConfigMap().size());
+        assertEquals("END_MISS", bean.getAlertEvents());
+        assertEquals("alert@example.com", bean.getAlertContact());
+    }
+
+    private void _addRecordToSLARegistrationTable(String jobId, AppType appType, Date start, Date end,
+            String alertEvent, String alertContact) throws Exception {
+        SLARegistrationBean reg = new SLARegistrationBean();
+        reg.setJobId(jobId);
+        reg.setAppType(appType);
+        reg.setExpectedStart(start);
+        reg.setExpectedEnd(end);
+        reg.setAlertEvents(alertEvent);
+        reg.setAlertContact(alertContact);
+        try {
+            JPAService jpaService = Services.get().get(JPAService.class);
+            assertNotNull(jpaService);
+            List<JsonBean> insert = new ArrayList<JsonBean>();
+            insert.add(reg);
+            SLACalculationInsertUpdateJPAExecutor slaInsertCmd = new SLACalculationInsertUpdateJPAExecutor(insert, null);
+            jpaService.execute(slaInsertCmd);
+        }
+        catch (JPAExecutorException je) {
+            fail("Unable to insert the test sla registration record to table");
+            throw je;
+        }
+    }
+
+}

Added: oozie/trunk/core/src/test/java/org/apache/oozie/sla/TestSLAService.java
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/test/java/org/apache/oozie/sla/TestSLAService.java?rev=1484523&view=auto
==============================================================================
--- oozie/trunk/core/src/test/java/org/apache/oozie/sla/TestSLAService.java (added)
+++ oozie/trunk/core/src/test/java/org/apache/oozie/sla/TestSLAService.java Mon May 20 16:51:37 2013
@@ -0,0 +1,197 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.oozie.sla;
+
+import java.util.Date;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.oozie.AppType;
+import org.apache.oozie.client.CoordinatorAction;
+import org.apache.oozie.client.CoordinatorJob;
+import org.apache.oozie.client.WorkflowJob;
+import org.apache.oozie.client.event.JobEvent.EventStatus;
+import org.apache.oozie.client.event.SLAEvent;
+import org.apache.oozie.service.EventHandlerService;
+import org.apache.oozie.service.Services;
+import org.apache.oozie.sla.listener.SLAEventListener;
+import org.apache.oozie.sla.service.SLAService;
+import org.apache.oozie.test.XDataTestCase;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestSLAService extends XDataTestCase {
+
+    static StringBuilder output = new StringBuilder();
+
+    @Override
+    @Before
+    protected void setUp() throws Exception {
+        super.setUp();
+        Services services = new Services();
+        Configuration conf = services.getConf();
+        conf.set(Services.CONF_SERVICE_EXT_CLASSES, "org.apache.oozie.service.EventHandlerService,"
+                + "org.apache.oozie.sla.service.SLAService");
+        conf.setClass(EventHandlerService.CONF_LISTENERS, DummySLAEventListener.class, SLAEventListener.class);
+        services.init();
+        cleanUpDBTables();
+    }
+
+    @Override
+    @After
+    protected void tearDown() throws Exception {
+        Services.get().destroy();
+        super.tearDown();
+    }
+
+    @Test
+    public void testBasicService() throws Exception {
+        Services services = Services.get();
+        SLAService slas = services.get(SLAService.class);
+        assertNotNull(slas);
+        assertTrue(SLAService.isEnabled());
+
+        services.destroy();
+        services = new Services();
+        Configuration conf = services.getConf();
+        conf.set(Services.CONF_SERVICE_EXT_CLASSES, "");
+        services.init();
+        assertFalse(SLAService.isEnabled());
+    }
+
+    @Test
+    public void testUpdateSLA() throws Exception {
+        SLAService slas = Services.get().get(SLAService.class);
+        assertNotNull(slas);
+        assertTrue(SLAService.isEnabled());
+
+        EventHandlerService ehs = Services.get().get(EventHandlerService.class);
+        // test start-miss
+        SLARegistrationBean sla1 = _createSLARegistration("job-1", AppType.WORKFLOW_JOB);
+        sla1.setExpectedStart(new Date(System.currentTimeMillis() - 1 * 1 * 3600 * 1000)); //1 hour back
+        sla1.setExpectedEnd(new Date(System.currentTimeMillis() + 1 * 1 * 3600 * 1000)); //1 hour ahead
+        slas.addRegistrationEvent(sla1);
+        assertEquals(1, slas.getSLACalculator().size());
+        slas.runSLAWorker();
+        ehs.new EventWorker().run();
+        assertTrue(output.toString().contains("Sla START - MISS!!!"));
+        output.setLength(0);
+
+        // test different jobs and events start-met and end-miss
+        sla1 = _createSLARegistration("job-2", AppType.WORKFLOW_JOB);
+        sla1.setExpectedStart(new Date(System.currentTimeMillis() + 1 * 3600 * 1000)); //1 hour ahead
+        sla1.setExpectedEnd(new Date(System.currentTimeMillis() + 2 * 3600 * 1000)); //2 hours ahead
+        slas.addRegistrationEvent(sla1);
+        slas.addStatusEvent(sla1.getJobId(), WorkflowJob.Status.RUNNING.name(), EventStatus.STARTED, new Date(),
+                new Date());
+        SLARegistrationBean sla2 = _createSLARegistration("job-3", AppType.COORDINATOR_JOB);
+        sla2.setExpectedStart(new Date(System.currentTimeMillis() + 1 * 3600 * 1000)); //1 hour ahead only for testing
+        sla2.setExpectedEnd(new Date(System.currentTimeMillis() - 2 * 3600 * 1000)); //2 hours back
+        slas.addRegistrationEvent(sla2);
+        assertEquals(3, slas.getSLACalculator().size());
+        slas.addStatusEvent(sla2.getJobId(), CoordinatorJob.Status.SUCCEEDED.name(), EventStatus.SUCCESS, new Date(),
+                new Date());
+        slas.runSLAWorker();
+        ehs.new EventWorker().run();
+        assertTrue(output.toString().contains(sla1.getJobId() + " Sla START - MET!!!"));
+        assertTrue(output.toString().contains(sla2.getJobId() + " Sla END - MISS!!!"));
+        output.setLength(0);
+
+        // test same job multiple events (start-miss, end-miss) through regular check
+        sla2 = _createSLARegistration("job-4", AppType.WORKFLOW_JOB);
+        sla2.setExpectedStart(new Date(System.currentTimeMillis() - 2 * 3600 * 1000)); //2 hours back
+        sla2.setExpectedEnd(new Date(System.currentTimeMillis() - 1 * 3600 * 1000)); //1 hour back
+        slas.addRegistrationEvent(sla2);
+        assertEquals(3, slas.getSLACalculator().size()); // remains same as before since
+                                                         // sla-END stage job is removed from map
+        slas.runSLAWorker();
+        assertEquals(2, ehs.getEventQueue().size());
+        ehs.new EventWorker().run();
+        System.out.println(output);
+        assertTrue(output.toString().contains(sla2.getJobId() + " Sla START - MISS!!!"));
+        assertTrue(output.toString().contains(sla2.getJobId() + " Sla END - MISS!!!"));
+        output.setLength(0);
+
+        // test same job multiple events (start-met, end-met) through job status event
+        sla1 = _createSLARegistration("action-1", AppType.COORDINATOR_ACTION);
+        sla1.setExpectedStart(new Date(System.currentTimeMillis() + 1 * 3600 * 1000)); //1 hour ahead
+        sla1.setExpectedEnd(new Date(System.currentTimeMillis() + 2 * 3600 * 1000)); //2 hours ahead
+        slas.addRegistrationEvent(sla1);
+        assertEquals(3, slas.getSLACalculator().size());
+        slas.addStatusEvent(sla1.getJobId(), CoordinatorAction.Status.RUNNING.name(), EventStatus.STARTED, new Date(),
+                new Date());
+        slas.addStatusEvent(sla1.getJobId(), CoordinatorAction.Status.SUCCEEDED.name(), EventStatus.SUCCESS,
+                new Date(), new Date());
+        slas.runSLAWorker();
+        assertEquals(3, ehs.getEventQueue().size());
+        ehs.new EventWorker().run();
+        System.out.println(output);
+        assertTrue(output.toString().contains(sla1.getJobId() + " Sla START - MET!!!"));
+        assertTrue(output.toString().contains(sla1.getJobId() + " Sla END - MET!!!"));
+    }
+
+    private SLARegistrationBean _createSLARegistration(String jobId, AppType appType) {
+        SLARegistrationBean bean = new SLARegistrationBean();
+        bean.setJobId(jobId);
+        bean.setAppType(appType);
+        return bean;
+    }
+
+    public static class DummySLAEventListener extends SLAEventListener {
+
+        @Override
+        public void onStartMet(SLAEvent sla) {
+            output.append(sla.getJobId() + " Sla START - MET!!!");
+        }
+
+        @Override
+        public void onStartMiss(SLAEvent sla) {
+            output.append(sla.getJobId() + " Sla START - MISS!!!");
+        }
+
+        @Override
+        public void onEndMet(SLAEvent sla) {
+            output.append(sla.getJobId() + " Sla END - MET!!!");
+        }
+
+        @Override
+        public void onEndMiss(SLAEvent sla) {
+            output.append(sla.getJobId() + " Sla END - MISS!!!");
+        }
+
+        @Override
+        public void onDurationMet(SLAEvent sla) {
+            output.append(sla.getJobId() + " Sla DURATION - MET!!!");
+        }
+
+        @Override
+        public void onDurationMiss(SLAEvent sla) {
+            output.append(sla.getJobId() + " Sla DURATION - MISS!!!");
+        }
+
+        @Override
+        public void init(Configuration conf) {
+        }
+
+        @Override
+        public void destroy() {
+        }
+
+    }
+
+}

Modified: oozie/trunk/core/src/test/java/org/apache/oozie/test/XDataTestCase.java
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/test/java/org/apache/oozie/test/XDataTestCase.java?rev=1484523&r1=1484522&r2=1484523&view=diff
==============================================================================
--- oozie/trunk/core/src/test/java/org/apache/oozie/test/XDataTestCase.java (original)
+++ oozie/trunk/core/src/test/java/org/apache/oozie/test/XDataTestCase.java Mon May 20 16:51:37 2013
@@ -43,13 +43,13 @@ import org.apache.oozie.action.hadoop.Ma
 import org.apache.oozie.client.BundleJob;
 import org.apache.oozie.client.CoordinatorAction;
 import org.apache.oozie.client.CoordinatorJob;
+import org.apache.oozie.client.CoordinatorJob.Execution;
+import org.apache.oozie.client.CoordinatorJob.Timeunit;
 import org.apache.oozie.client.Job;
 import org.apache.oozie.client.OozieClient;
 import org.apache.oozie.client.SLAEvent;
 import org.apache.oozie.client.WorkflowAction;
 import org.apache.oozie.client.WorkflowJob;
-import org.apache.oozie.client.CoordinatorJob.Execution;
-import org.apache.oozie.client.CoordinatorJob.Timeunit;
 import org.apache.oozie.executor.jpa.BundleActionInsertJPAExecutor;
 import org.apache.oozie.executor.jpa.BundleJobInsertJPAExecutor;
 import org.apache.oozie.executor.jpa.CoordActionGetJPAExecutor;
@@ -68,9 +68,9 @@ import org.apache.oozie.service.JPAServi
 import org.apache.oozie.service.LiteWorkflowStoreService;
 import org.apache.oozie.service.Services;
 import org.apache.oozie.service.UUIDService;
+import org.apache.oozie.service.UUIDService.ApplicationType;
 import org.apache.oozie.service.WorkflowAppService;
 import org.apache.oozie.service.WorkflowStoreService;
-import org.apache.oozie.service.UUIDService.ApplicationType;
 import org.apache.oozie.util.DateUtils;
 import org.apache.oozie.util.IOUtils;
 import org.apache.oozie.util.XConfiguration;
@@ -726,6 +726,7 @@ public abstract class XDataTestCase exte
      * @param status sla status
      * @throws Exception thrown if unable to create sla bean
      */
+    @Deprecated
     protected void addRecordToSLAEventTable(String slaId, SLAEvent.Status status, Date today) throws Exception {
         addRecordToSLAEventTable(slaId, "app-name", status, today);
     }
@@ -738,7 +739,9 @@ public abstract class XDataTestCase exte
      * @param status sla status
      * @throws Exception thrown if unable to create sla bean
      */
-    protected void addRecordToSLAEventTable(String slaId, String appName, SLAEvent.Status status, Date today) throws Exception {
+    @Deprecated
+    protected void addRecordToSLAEventTable(String slaId, String appName, SLAEvent.Status status, Date today)
+            throws Exception {
         SLAEventBean sla = new SLAEventBean();
         sla.setSlaId(slaId);
         sla.setAppName(appName);
@@ -773,8 +776,6 @@ public abstract class XDataTestCase exte
         }
     }
 
-
-
     /**
      * Insert bundle job for testing.
      *
@@ -1463,4 +1464,13 @@ public abstract class XDataTestCase exte
         action.setMissingDependencies(missingDependencies);
         jpaService.execute(new CoordActionUpdateJPAExecutor(action));
     }
+
+    protected void modifyCoordForRunning(CoordinatorJobBean coord) throws Exception {
+        String wfXml = IOUtils.getResourceAsString("wf-credentials.xml", -1);
+        writeToFile(wfXml, getFsTestCaseDir(), "workflow.xml");
+        String coordXml = coord.getJobXml();
+        coord.setJobXml(coordXml.replace("hdfs:///tmp/workflows/", getFsTestCaseDir() + "/workflow.xml"));
+        Services.get().get(JPAService.class).execute(new CoordJobUpdateJPAExecutor(coord));
+    }
+
 }

Modified: oozie/trunk/core/src/test/java/org/apache/oozie/test/XTestCase.java
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/test/java/org/apache/oozie/test/XTestCase.java?rev=1484523&r1=1484522&r2=1484523&view=diff
==============================================================================
--- oozie/trunk/core/src/test/java/org/apache/oozie/test/XTestCase.java (original)
+++ oozie/trunk/core/src/test/java/org/apache/oozie/test/XTestCase.java Mon May 20 16:51:37 2013
@@ -65,6 +65,9 @@ import org.apache.oozie.service.Partitio
 import org.apache.oozie.service.ServiceException;
 import org.apache.oozie.service.Services;
 import org.apache.oozie.service.URIHandlerService;
+import org.apache.oozie.sla.SLACalculatorBean;
+import org.apache.oozie.sla.SLARegistrationBean;
+import org.apache.oozie.sla.SLASummaryBean;
 import org.apache.oozie.store.CoordinatorStore;
 import org.apache.oozie.store.StoreException;
 import org.apache.oozie.test.MiniHCatServer.RUNMODE;
@@ -712,6 +715,27 @@ public abstract class XTestCase extends 
             entityManager.remove(w);
         }
 
+        q = entityManager.createQuery("select OBJECT(w) from SLARegistrationBean w");
+        List<SLARegistrationBean> slaRegBeans = q.getResultList();
+        int slaRegSize = slaRegBeans.size();
+        for (SLARegistrationBean w : slaRegBeans) {
+            entityManager.remove(w);
+        }
+
+        q = entityManager.createQuery("select OBJECT(w) from SLACalculatorBean w");
+        List<SLACalculatorBean> scBeans = q.getResultList();
+        int scSize = scBeans.size();
+        for (SLACalculatorBean w : scBeans) {
+            entityManager.remove(w);
+        }
+
+        q = entityManager.createQuery("select OBJECT(w) from SLASummaryBean w");
+        List<SLASummaryBean> sdBeans = q.getResultList();
+        int ssSize = sdBeans.size();
+        for (SLASummaryBean w : sdBeans) {
+            entityManager.remove(w);
+        }
+
         store.commitTrx();
         store.closeTrx();
         log.info(wfjSize + " entries in WF_JOBS removed from DB!");
@@ -721,6 +745,10 @@ public abstract class XTestCase extends 
         log.info(bjSize + " entries in BUNDLE_JOBS removed from DB!");
         log.info(baSize + " entries in BUNDLE_ACTIONS removed from DB!");
         log.info(slaSize + " entries in SLA_EVENTS removed from DB!");
+        log.info(slaRegSize + " entries in SLA_REGISTRATION removed from DB!");
+        log.info(scSize + " entries in SLA_CALCULATOR removed from DB!");
+        log.info(ssSize + " entries in SLA_SUMMARY removed from DB!");
+
     }
 
     private static MiniDFSCluster dfsCluster = null;

Added: oozie/trunk/core/src/test/resources/coord-action-sla.xml
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/test/resources/coord-action-sla.xml?rev=1484523&view=auto
==============================================================================
--- oozie/trunk/core/src/test/resources/coord-action-sla.xml (added)
+++ oozie/trunk/core/src/test/resources/coord-action-sla.xml Mon May 20 16:51:37 2013
@@ -0,0 +1,37 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you 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.
+-->
+<coordinator-app name="test-coord-sla" frequency="${coord:days(1)}"
+                 start="2009-01-02T08:01Z" end="2010-01-01T08:01Z"
+                 timezone="America/Los_Angeles"
+                 xmlns="uri:oozie:coordinator:0.4"
+                 xmlns:sla="uri:oozie:sla:0.2">
+    <action>
+        <workflow>
+            <app-path>${wfAppPath}</app-path>
+        </workflow>
+        <sla:info>
+            <sla:nominal-time>${nominal_time}</sla:nominal-time>
+            <sla:should-start>${10 * MINUTES}</sla:should-start>
+            <sla:should-end>${30 * MINUTES}</sla:should-end>
+            <sla:max-duration>${30 * MINUTES}</sla:max-duration>
+            <sla:alert-events>start_miss,end_met,end_miss</sla:alert-events>
+            <sla:alert-contact>joe@example.com</sla:alert-contact>
+        </sla:info>
+    </action>
+</coordinator-app>
+

Added: oozie/trunk/core/src/test/resources/wf-action-sla.xml
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/test/resources/wf-action-sla.xml?rev=1484523&view=auto
==============================================================================
--- oozie/trunk/core/src/test/resources/wf-action-sla.xml (added)
+++ oozie/trunk/core/src/test/resources/wf-action-sla.xml Mon May 20 16:51:37 2013
@@ -0,0 +1,50 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you 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.
+-->
+<workflow-app name="test-wf-action-sla"
+              xmlns="uri:oozie:workflow:0.5"
+              xmlns:sla="uri:oozie:sla:0.2">
+    <start to="grouper"/>
+    <action name="grouper">
+        <map-reduce>
+            <job-tracker>jt</job-tracker>
+            <name-node>nn</name-node>
+            <configuration>
+                <property>
+                    <name>mapred.input.dir</name>
+                    <value>input</value>
+                </property>
+                <property>
+                    <name>mapred.output.dir</name>
+                    <value>output</value>
+                </property>
+            </configuration>
+        </map-reduce>
+        <ok to="end"/>
+        <error to="end"/>
+        <sla:info>
+        <sla:nominal-time>${nominal_time}</sla:nominal-time>
+        <sla:should-start>${10 * MINUTES}</sla:should-start>
+        <sla:should-end>${30 * MINUTES}</sla:should-end>
+        <sla:max-duration>${30 * MINUTES}</sla:max-duration>
+        <sla:alert-events>start_miss,end_met,end_miss</sla:alert-events>
+        <sla:alert-contact>joe@example.com</sla:alert-contact>
+    </sla:info>
+    </action>
+    <end name="end"/>
+</workflow-app>
+

Added: oozie/trunk/core/src/test/resources/wf-job-sla.xml
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/test/resources/wf-job-sla.xml?rev=1484523&view=auto
==============================================================================
--- oozie/trunk/core/src/test/resources/wf-job-sla.xml (added)
+++ oozie/trunk/core/src/test/resources/wf-job-sla.xml Mon May 20 16:51:37 2013
@@ -0,0 +1,50 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you 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.
+-->
+<workflow-app name="test-wf-job-sla"
+              xmlns="uri:oozie:workflow:0.5"
+              xmlns:sla="uri:oozie:sla:0.2">
+    <start to="grouper"/>
+    <action name="grouper">
+        <map-reduce>
+            <job-tracker>jt</job-tracker>
+            <name-node>nn</name-node>
+            <configuration>
+                <property>
+                    <name>mapred.input.dir</name>
+                    <value>input</value>
+                </property>
+                <property>
+                    <name>mapred.output.dir</name>
+                    <value>output</value>
+                </property>
+            </configuration>
+        </map-reduce>
+        <ok to="end"/>
+        <error to="end"/>
+    </action>
+    <end name="end"/>
+    <sla:info>
+        <sla:nominal-time>${nominal_time}</sla:nominal-time>
+        <sla:should-start>${10 * MINUTES}</sla:should-start>
+        <sla:should-end>${30 * MINUTES}</sla:should-end>
+        <sla:max-duration>${30 * MINUTES}</sla:max-duration>
+        <sla:alert-events>start_miss,end_met,end_miss</sla:alert-events>
+        <sla:alert-contact>joe@example.com</sla:alert-contact>
+    </sla:info>
+</workflow-app>
+

Modified: oozie/trunk/examples/src/main/apps/sla/coordinator.xml
URL: http://svn.apache.org/viewvc/oozie/trunk/examples/src/main/apps/sla/coordinator.xml?rev=1484523&r1=1484522&r2=1484523&view=diff
==============================================================================
--- oozie/trunk/examples/src/main/apps/sla/coordinator.xml (original)
+++ oozie/trunk/examples/src/main/apps/sla/coordinator.xml Mon May 20 16:51:37 2013
@@ -16,7 +16,7 @@
   limitations under the License.
 -->
 <coordinator-app name="aggregator-coord" frequency="${coord:hours(1)}" start="${start}" end="${end}" timezone="UTC"
-                 xmlns="uri:oozie:coordinator:0.2" xmlns:sla="uri:oozie:sla:0.1">
+                 xmlns="uri:oozie:coordinator:0.4" xmlns:sla="uri:oozie:sla:0.2">
     <controls>
         <concurrency>1</concurrency>
     </controls>
@@ -67,23 +67,22 @@
                     <name>outputData</name>
                     <value>${coord:dataOut('output')}</value>
                 </property>
+                <property>
+                    <name>nominalTime</name>
+                    <value>${coord:nominalTime()}</value>
+                </property>
             </configuration>
         </workflow>
 
       <sla:info>
-              <sla:app-name>${appName}</sla:app-name>
-              <sla:nominal-time>${coord:nominalTime()}</sla:nominal-time>
-              <sla:should-start>${shouldStart}</sla:should-start>
-              <sla:should-end>${shouldEnd}</sla:should-end>
-              <sla:notification-msg>${notificationMsg}</sla:notification-msg>
-              <sla:alert-contact>${alertContact}</sla:alert-contact>
-              <sla:dev-contact>${devContact}</sla:dev-contact>
-              <sla:qa-contact>${qaContact}</sla:qa-contact>
-              <sla:se-contact>${seContact}</sla:se-contact>
-              <sla:alert-frequency>${alertFrequency}</sla:alert-frequency>
-              <sla:alert-percentage>${alertPercentage}</sla:alert-percentage>
-              <sla:upstream-apps>${upstreamApps}</sla:upstream-apps>
-    </sla:info>
+          <sla:nominal-time>${coord:nominalTime()}</sla:nominal-time>
+          <sla:should-start>${shouldStart}</sla:should-start>
+          <sla:should-end>${shouldEnd}</sla:should-end>
+          <sla:max-duration>${duration}</sla:max-duration>
+          <sla:alert-contact>${alertContact}</sla:alert-contact>
+          <sla:notification-msg>${notificationMsg}</sla:notification-msg>
+          <sla:upstream-apps>${upstreamApps}</sla:upstream-apps>
+      </sla:info>
 </action>
 </coordinator-app>
 

Modified: oozie/trunk/examples/src/main/apps/sla/job.properties
URL: http://svn.apache.org/viewvc/oozie/trunk/examples/src/main/apps/sla/job.properties?rev=1484523&r1=1484522&r2=1484523&view=diff
==============================================================================
--- oozie/trunk/examples/src/main/apps/sla/job.properties (original)
+++ oozie/trunk/examples/src/main/apps/sla/job.properties Mon May 20 16:51:37 2013
@@ -25,16 +25,11 @@ oozie.coord.application.path=${nameNode}
 start=2010-01-01T01:00Z
 end=2010-01-01T03:00Z
 
-appName=sla-app
 # shouldStart in minutes, expected start time defined as coord action's nominal time + shouldStart
 shouldStart=1
 # shouldEnd in minutes, expected end time defined as coord action's nominal time + shouldEnd
-shouldEnd=5
+shouldEnd=10
+duration=5
 notificationMsg=Notification Message
 alertContact=alert@oozie.com
-devContact=dev@oozie.com
-qaContact=qa@oozie.com
-seContact=se@oozie.com
-alertFrequency=LAST_HOUR
-alertPercentage=80
-upstreamApps=applicaion-a,application-b
+upstreamApps=application-a,application-b

Modified: oozie/trunk/examples/src/main/apps/sla/workflow.xml
URL: http://svn.apache.org/viewvc/oozie/trunk/examples/src/main/apps/sla/workflow.xml?rev=1484523&r1=1484522&r2=1484523&view=diff
==============================================================================
--- oozie/trunk/examples/src/main/apps/sla/workflow.xml (original)
+++ oozie/trunk/examples/src/main/apps/sla/workflow.xml Mon May 20 16:51:37 2013
@@ -15,7 +15,16 @@
   See the License for the specific language governing permissions and
   limitations under the License.
 -->
-<workflow-app xmlns="uri:oozie:workflow:0.2" name="no-op-wf">
+<workflow-app xmlns="uri:oozie:workflow:0.5" xmlns:sla="uri:oozie:sla:0.2" name="no-op-wf">
     <start to="end"/>
     <end name="end"/>
+    <sla:info>
+          <sla:nominal-time>${nominalTime}</sla:nominal-time>
+          <sla:should-start>${shouldStart}</sla:should-start>
+          <sla:should-end>${shouldEnd}</sla:should-end>
+          <sla:max-duration>${duration}</sla:max-duration>
+          <sla:alert-contact>${alertContact}</sla:alert-contact>
+          <sla:notification-msg>${notificationMsg}</sla:notification-msg>
+          <sla:upstream-apps>${upstreamApps}</sla:upstream-apps>
+    </sla:info>
 </workflow-app>

Modified: oozie/trunk/release-log.txt
URL: http://svn.apache.org/viewvc/oozie/trunk/release-log.txt?rev=1484523&r1=1484522&r2=1484523&view=diff
==============================================================================
--- oozie/trunk/release-log.txt (original)
+++ oozie/trunk/release-log.txt Mon May 20 16:51:37 2013
@@ -1,5 +1,6 @@
 -- Oozie 4.1.0 release (trunk - unreleased)
 
+OOZIE-1244 SLA Support in Oozie (mona)
 OOZIE-1371 oozie.coord.action.notification.url has no documentation (rkanter)
 OOZIE-1328 Cover package org.apache.oozie.cli with unit tests (vbondarev via virag)
 OOZIE-1327 enhance unit-test coverage of package org.apache.oozie (iveselovsky via rkanter)
@@ -12,7 +13,6 @@ OOZIE-1183 Update WebServices API docume
 OOZIE-1368 Error message when using an incorrect oozie url with kerberos is misleading (rkanter)
 OOZIE-1352 Write documentation for OOzie Hive CLI (rkanter)
 OOZIE-1353 hive CLI fails with -X argument (rkanter)
-OOZIE-1303 CLI API for Bulk Monitoring (mona)
 OOZIE-611 distcp action does not have documentation (rkanter)
 OOZIE-1318 Action Main classes should be overridable via action configuration settings (rkanter)
 OOZIE-1347 Additions to JMS topic API (virag)
@@ -55,6 +55,7 @@ OOZIE-1239 Bump up trunk to 4.1.0-SNAPSH
 
 -- Oozie 4.0.0 (unreleased)
 
+OOZIE-1303 CLI API for Bulk Monitoring (mona)
 OOZIE-1350 Improve client debug output information (rkanter)
 OOZIE-1343 Sqoop sharelib should have hsqldb jar (rkanter)
 OOZIE-1344 We should use Sqoop 1.4.3 instead of 1.5.0-incubating-SNAPSHOT (rkanter)

Modified: oozie/trunk/tools/src/main/java/org/apache/oozie/tools/OozieDBCLI.java
URL: http://svn.apache.org/viewvc/oozie/trunk/tools/src/main/java/org/apache/oozie/tools/OozieDBCLI.java?rev=1484523&r1=1484522&r2=1484523&view=diff
==============================================================================
--- oozie/trunk/tools/src/main/java/org/apache/oozie/tools/OozieDBCLI.java (original)
+++ oozie/trunk/tools/src/main/java/org/apache/oozie/tools/OozieDBCLI.java Mon May 20 16:51:37 2013
@@ -788,9 +788,13 @@ public class OozieDBCLI {
         args.add("org.apache.oozie.CoordinatorActionBean");
         args.add("org.apache.oozie.client.rest.JsonSLAEvent");
         args.add("org.apache.oozie.SLAEventBean");
+        args.add("org.apache.oozie.client.rest.sla.JsonSLARegistrationEvent");
+        args.add("org.apache.oozie.sla.SLARegistrationBean");
         args.add("org.apache.oozie.client.rest.JsonBundleJob");
         args.add("org.apache.oozie.BundleJobBean");
         args.add("org.apache.oozie.BundleActionBean");
+        args.add("org.apache.oozie.sla.SLACalculatorBean");
+        args.add("org.apache.oozie.sla.SLASummaryBean");
         args.add("org.apache.oozie.util.db.ValidateConnectionBean");
         return args.toArray(new String[args.size()]);
     }