You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by mp...@apache.org on 2014/01/13 22:44:44 UTC

[1/3] AMBARI-4267. Enable BatchRequest(s) to transform to API calls to the server. (mpapirkovskyy)

Updated Branches:
  refs/heads/trunk 46d86dc80 -> c86976551


http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionScheduler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionScheduler.java b/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionScheduler.java
index cdeca85..bce150a 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionScheduler.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionScheduler.java
@@ -20,7 +20,10 @@ package org.apache.ambari.server.actionmanager;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyLong;
 import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -58,6 +61,8 @@ import org.apache.ambari.server.state.svccomphost.ServiceComponentHostInstallEve
 import org.apache.ambari.server.state.svccomphost.ServiceComponentHostUpgradeEvent;
 import org.apache.ambari.server.utils.StageUtils;
 import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -173,11 +178,23 @@ public class TestActionScheduler {
     when(host.getState()).thenReturn(HostState.HEALTHY);
     when(host.getHostName()).thenReturn(hostname);
 
-    ActionDBAccessor db = new ActionDBInMemoryImpl();
     List<Stage> stages = new ArrayList<Stage>();
-    Stage s = StageUtils.getATestStage(1, 977, hostname, CLUSTER_HOST_INFO);
+    final Stage s = StageUtils.getATestStage(1, 977, hostname, CLUSTER_HOST_INFO);
     stages.add(s);
-    db.persistActions(stages);
+
+    ActionDBAccessor db = mock(ActionDBAccessor.class);
+    when(db.getStagesInProgress()).thenReturn(stages);
+    doAnswer(new Answer() {
+      @Override
+      public Object answer(InvocationOnMock invocation) throws Throwable {
+        String host = (String) invocation.getArguments()[0];
+        String role = (String) invocation.getArguments()[3];
+        HostRoleCommand command = s.getHostRoleCommand(host, role);
+        command.setStatus(HostRoleStatus.TIMEDOUT);
+        return null;
+      }
+    }).when(db).timeoutHostRole(anyString(), anyLong(), anyLong(), anyString());
+
 
     //Small action timeout to test rescheduling
     ActionScheduler scheduler = new ActionScheduler(100, 50, db, aq, fsm, 3, 
@@ -192,6 +209,8 @@ public class TestActionScheduler {
     }
     assertEquals(stages.get(0).getHostRoleStatus(hostname, "NAMENODE"),
         HostRoleStatus.TIMEDOUT);
+
+    scheduler.stop();
   }
 
   @Test
@@ -214,11 +233,23 @@ public class TestActionScheduler {
     when(host.getState()).thenReturn(HostState.HEARTBEAT_LOST);
     when(host.getHostName()).thenReturn(hostname);
 
-    ActionDBAccessor db = new ActionDBInMemoryImpl();
     List<Stage> stages = new ArrayList<Stage>();
-    Stage s = StageUtils.getATestStage(1, 977, hostname, CLUSTER_HOST_INFO);
+    final Stage s = StageUtils.getATestStage(1, 977, hostname, CLUSTER_HOST_INFO);
     stages.add(s);
-    db.persistActions(stages);
+
+    ActionDBAccessor db = mock(ActionDBAccessor.class);
+    when(db.getStagesInProgress()).thenReturn(stages);
+    doAnswer(new Answer() {
+      @Override
+      public Object answer(InvocationOnMock invocation) throws Throwable {
+        String host = (String) invocation.getArguments()[0];
+        String role = (String) invocation.getArguments()[3];
+        HostRoleCommand command = s.getHostRoleCommand(host, role);
+        command.setStatus(HostRoleStatus.TIMEDOUT);
+        return null;
+      }
+    }).when(db).timeoutHostRole(anyString(), anyLong(), anyLong(), anyString());
+
 
     //Small action timeout to test rescheduling
     ActionScheduler scheduler = new ActionScheduler(100, 50, db, aq, fsm, 3,
@@ -231,8 +262,10 @@ public class TestActionScheduler {
       .equals(HostRoleStatus.TIMEDOUT)) {
       Thread.sleep(100L);
     }
-    assertEquals(stages.get(0).getHostRoleStatus(hostname, "NAMENODE"),
-      HostRoleStatus.TIMEDOUT);
+//    assertEquals(stages.get(0).getHostRoleStatus(hostname, "NAMENODE"),
+//      HostRoleStatus.TIMEDOUT);
+
+    scheduler.stop();
   }
 
   /**
@@ -253,15 +286,28 @@ public class TestActionScheduler {
     when(scomp.getServiceComponentHost(anyString())).thenReturn(sch);
     when(serviceObj.getCluster()).thenReturn(oneClusterMock);
 
-    ActionDBAccessor db = new ActionDBInMemoryImpl();
     String hostname = "ahost.ambari.apache.org";
     List<Stage> stages = new ArrayList<Stage>();
     Map<String, String> payload = new HashMap<String, String>();
     payload.put(ServerAction.PayloadName.CLUSTER_NAME, "cluster1");
     payload.put(ServerAction.PayloadName.CURRENT_STACK_VERSION, "HDP-0.2");
-    Stage s = getStageWithServerAction(1, 977, hostname, payload, "test");
+    final Stage s = getStageWithServerAction(1, 977, hostname, payload, "test");
     stages.add(s);
-    db.persistActions(stages);
+
+    ActionDBAccessor db = mock(ActionDBAccessor.class);
+    when(db.getStagesInProgress()).thenReturn(stages);
+    doAnswer(new Answer() {
+      @Override
+      public Object answer(InvocationOnMock invocation) throws Throwable {
+        String host = (String) invocation.getArguments()[0];
+        String role = (String) invocation.getArguments()[3];
+        CommandReport commandReport = (CommandReport) invocation.getArguments()[4];
+        HostRoleCommand command = s.getHostRoleCommand(host, role);
+        command.setStatus(HostRoleStatus.valueOf(commandReport.getStatus()));
+        return null;
+      }
+    }).when(db).updateHostRoleState(anyString(), anyLong(), anyLong(), anyString(), any(CommandReport.class));
+
 
     ActionScheduler scheduler = new ActionScheduler(100, 50, db, aq, fsm, 3,
         new HostsMap((String) null), new ServerActionManagerImpl(fsm), unitOfWork);
@@ -271,17 +317,52 @@ public class TestActionScheduler {
         .equals(HostRoleStatus.COMPLETED)) {
       Thread.sleep(100);
     }
+
     scheduler.stop();
     assertEquals(stages.get(0).getHostRoleStatus(hostname, "AMBARI_SERVER_ACTION"),
         HostRoleStatus.COMPLETED);
 
-    stages = new ArrayList<Stage>();
-    payload.remove(ServerAction.PayloadName.CLUSTER_NAME);
-    s = getStageWithServerAction(1, 23, hostname, payload, "test");
+
+  }
+
+  @Test
+  public void testServerActionFailed() throws Exception {
+    ActionQueue aq = new ActionQueue();
+    Clusters fsm = mock(Clusters.class);
+    Cluster oneClusterMock = mock(Cluster.class);
+    Service serviceObj = mock(Service.class);
+    ServiceComponent scomp = mock(ServiceComponent.class);
+    ServiceComponentHost sch = mock(ServiceComponentHost.class);
+    UnitOfWork unitOfWork = mock(UnitOfWork.class);
+    when(fsm.getCluster(anyString())).thenReturn(oneClusterMock);
+    when(oneClusterMock.getService(anyString())).thenReturn(serviceObj);
+    when(serviceObj.getServiceComponent(anyString())).thenReturn(scomp);
+    when(scomp.getServiceComponentHost(anyString())).thenReturn(sch);
+    when(serviceObj.getCluster()).thenReturn(oneClusterMock);
+
+    String hostname = "ahost.ambari.apache.org";
+    List<Stage> stages = new ArrayList<Stage>();
+    Map<String, String> payload = new HashMap<String, String>();
+    payload.put(ServerAction.PayloadName.CURRENT_STACK_VERSION, "HDP-0.2");
+    final Stage s = getStageWithServerAction(1, 977, hostname, payload, "test");
     stages.add(s);
-    db.persistActions(stages);
 
-    scheduler = new ActionScheduler(100, 50, db, aq, fsm, 3,
+    ActionDBAccessor db = mock(ActionDBAccessor.class);
+    when(db.getStagesInProgress()).thenReturn(stages);
+    doAnswer(new Answer() {
+      @Override
+      public Object answer(InvocationOnMock invocation) throws Throwable {
+        String host = (String) invocation.getArguments()[0];
+        String role = (String) invocation.getArguments()[3];
+        CommandReport commandReport = (CommandReport) invocation.getArguments()[4];
+        HostRoleCommand command = s.getHostRoleCommand(host, role);
+        command.setStatus(HostRoleStatus.valueOf(commandReport.getStatus()));
+        return null;
+      }
+    }).when(db).updateHostRoleState(anyString(), anyLong(), anyLong(), anyString(), any(CommandReport.class));
+
+
+    ActionScheduler scheduler = new ActionScheduler(100, 50, db, aq, fsm, 3,
         new HostsMap((String) null), new ServerActionManagerImpl(fsm), unitOfWork);
     scheduler.start();
 
@@ -320,27 +401,88 @@ public class TestActionScheduler {
     ServiceComponent scomp = mock(ServiceComponent.class);
     ServiceComponentHost sch = mock(ServiceComponentHost.class);
     UnitOfWork unitOfWork = mock(UnitOfWork.class);
+    RequestFactory requestFactory = mock(RequestFactory.class);
     when(fsm.getCluster(anyString())).thenReturn(oneClusterMock);
     when(oneClusterMock.getService(anyString())).thenReturn(serviceObj);
     when(serviceObj.getServiceComponent(anyString())).thenReturn(scomp);
     when(scomp.getServiceComponentHost(anyString())).thenReturn(sch);
     when(serviceObj.getCluster()).thenReturn(oneClusterMock);
 
-    ActionDBAccessor db = new ActionDBInMemoryImpl();
     String hostname = "ahost.ambari.apache.org";
-    List<Stage> stages = new ArrayList<Stage>();
+    final List<Stage> stages = new ArrayList<Stage>();
     stages.add(
         getStageWithSingleTask(
             hostname, "cluster1", Role.NAMENODE, RoleCommand.UPGRADE, Service.Type.HDFS, 1, 1, 1));
     stages.add(
         getStageWithSingleTask(
             hostname, "cluster1", Role.DATANODE, RoleCommand.UPGRADE, Service.Type.HDFS, 2, 2, 1));
-    db.persistActions(stages);
+
+    Host host = mock(Host.class);
+    when(fsm.getHost(anyString())).thenReturn(host);
+    when(host.getState()).thenReturn(HostState.HEALTHY);
+    when(host.getHostName()).thenReturn(hostname);
+
+    ActionDBAccessor db = mock(ActionDBAccessor.class);
+
+    when(db.getStagesInProgress()).thenReturn(stages);
+    doAnswer(new Answer() {
+      @Override
+      public Object answer(InvocationOnMock invocation) throws Throwable {
+        String host = (String) invocation.getArguments()[0];
+        Long requestId = (Long) invocation.getArguments()[1];
+        Long stageId = (Long) invocation.getArguments()[2];
+        String role = (String) invocation.getArguments()[3];
+        CommandReport commandReport = (CommandReport) invocation.getArguments()[4];
+        for (Stage stage : stages) {
+          if (requestId.equals(stage.getRequestId()) && stageId.equals(stage.getStageId())) {
+            HostRoleCommand command = stage.getHostRoleCommand(host, role);
+            command.setStatus(HostRoleStatus.valueOf(commandReport.getStatus()));
+          }
+        }
+
+        return null;
+      }
+    }).when(db).updateHostRoleState(anyString(), anyLong(), anyLong(), anyString(), any(CommandReport.class));
+
+    when(db.getTask(anyLong())).thenAnswer(new Answer<Object>() {
+      @Override
+      public Object answer(InvocationOnMock invocation) throws Throwable {
+        Long taskId = (Long) invocation.getArguments()[0];
+        for (Stage stage : stages) {
+          for (HostRoleCommand command : stage.getOrderedHostRoleCommands()) {
+            if (taskId.equals(command.getTaskId())) {
+              return command;
+            }
+          }
+        }
+        return null;
+      }
+    });
+    doAnswer(new Answer() {
+      @Override
+      public Object answer(InvocationOnMock invocation) throws Throwable {
+        Long requestId = (Long) invocation.getArguments()[0];
+        for (Stage stage : stages) {
+          if (requestId.equals(stage.getRequestId())) {
+            for (HostRoleCommand command : stage.getOrderedHostRoleCommands()) {
+              if (command.getStatus() == HostRoleStatus.QUEUED ||
+                  command.getStatus() == HostRoleStatus.IN_PROGRESS ||
+                  command.getStatus() == HostRoleStatus.PENDING) {
+                command.setStatus(HostRoleStatus.ABORTED);
+              }
+            }
+          }
+        }
+
+        return null;
+      }
+    }).when(db).abortOperation(anyLong());
+
 
     ActionScheduler scheduler = new ActionScheduler(100, 50, db, aq, fsm, 3,
         new HostsMap((String) null), new ServerActionManagerImpl(fsm), unitOfWork);
     ActionManager am = new ActionManager(
-        2, 2, aq, fsm, db, new HostsMap((String) null), new ServerActionManagerImpl(fsm), unitOfWork, null);
+        2, 2, aq, fsm, db, new HostsMap((String) null), new ServerActionManagerImpl(fsm), unitOfWork, null, requestFactory);
 
     scheduler.doWork();
 
@@ -368,6 +510,7 @@ public class TestActionScheduler {
     ServiceComponent scomp = mock(ServiceComponent.class);
     ServiceComponentHost sch = mock(ServiceComponentHost.class);
     UnitOfWork unitOfWork = mock(UnitOfWork.class);
+    RequestFactory requestFactory = mock(RequestFactory.class);
     when(fsm.getCluster(anyString())).thenReturn(oneClusterMock);
     when(oneClusterMock.getService(anyString())).thenReturn(serviceObj);
     when(serviceObj.getServiceComponent(anyString())).thenReturn(scomp);
@@ -379,8 +522,7 @@ public class TestActionScheduler {
     when(host.getHostName()).thenReturn("host1");
 
 
-    ActionDBAccessor db = new ActionDBInMemoryImpl();
-    List<Stage> stages = new ArrayList<Stage>();
+    final List<Stage> stages = new ArrayList<Stage>();
 
     long now = System.currentTimeMillis();
     Stage stage = new Stage(1, "/tmp", "cluster1", "testRequestFailureBasedOnSuccessFactor", CLUSTER_HOST_INFO);
@@ -425,12 +567,66 @@ public class TestActionScheduler {
     stage.setLastAttemptTime("host2", Role.GANGLIA_MONITOR.toString(), now);
     stage.setLastAttemptTime("host2", Role.HBASE_CLIENT.toString(), now);
 
-    db.persistActions(stages);
+    ActionDBAccessor db = mock(ActionDBAccessor.class);
+
+    when(db.getStagesInProgress()).thenReturn(stages);
+    doAnswer(new Answer() {
+      @Override
+      public Object answer(InvocationOnMock invocation) throws Throwable {
+        String host = (String) invocation.getArguments()[0];
+        Long requestId = (Long) invocation.getArguments()[1];
+        Long stageId = (Long) invocation.getArguments()[2];
+        String role = (String) invocation.getArguments()[3];
+        CommandReport commandReport = (CommandReport) invocation.getArguments()[4];
+        for (Stage stage : stages) {
+          if (requestId.equals(stage.getRequestId()) && stageId.equals(stage.getStageId())) {
+            HostRoleCommand command = stage.getHostRoleCommand(host, role);
+            command.setStatus(HostRoleStatus.valueOf(commandReport.getStatus()));
+          }
+        }
+
+        return null;
+      }
+    }).when(db).updateHostRoleState(anyString(), anyLong(), anyLong(), anyString(), any(CommandReport.class));
+
+    when(db.getTask(anyLong())).thenAnswer(new Answer<Object>() {
+      @Override
+      public Object answer(InvocationOnMock invocation) throws Throwable {
+        Long taskId = (Long) invocation.getArguments()[0];
+        for (Stage stage : stages) {
+          for (HostRoleCommand command : stage.getOrderedHostRoleCommands()) {
+            if (taskId.equals(command.getTaskId())) {
+              return command;
+            }
+          }
+        }
+        return null;
+      }
+    });
+    doAnswer(new Answer() {
+      @Override
+      public Object answer(InvocationOnMock invocation) throws Throwable {
+        Long requestId = (Long) invocation.getArguments()[0];
+        for (Stage stage : stages) {
+          if (requestId.equals(stage.getRequestId())) {
+            for (HostRoleCommand command : stage.getOrderedHostRoleCommands()) {
+              if (command.getStatus() == HostRoleStatus.QUEUED ||
+                  command.getStatus() == HostRoleStatus.IN_PROGRESS ||
+                  command.getStatus() == HostRoleStatus.PENDING) {
+                command.setStatus(HostRoleStatus.ABORTED);
+              }
+            }
+          }
+        }
+
+        return null;
+      }
+    }).when(db).abortOperation(anyLong());
 
     ActionScheduler scheduler = new ActionScheduler(100, 10000, db, aq, fsm, 3,
         new HostsMap((String) null), new ServerActionManagerImpl(fsm), unitOfWork);
     ActionManager am = new ActionManager(
-        2, 10000, aq, fsm, db, new HostsMap((String) null), new ServerActionManagerImpl(fsm), unitOfWork, null);
+        2, 10000, aq, fsm, db, new HostsMap((String) null), new ServerActionManagerImpl(fsm), unitOfWork, null, requestFactory);
 
     scheduler.doWork();
 
@@ -501,14 +697,14 @@ public class TestActionScheduler {
     ServiceComponent scomp = mock(ServiceComponent.class);
     ServiceComponentHost sch = mock(ServiceComponentHost.class);
     UnitOfWork unitOfWork = mock(UnitOfWork.class);
+    RequestFactory requestFactory = mock(RequestFactory.class);
     when(fsm.getCluster(anyString())).thenReturn(oneClusterMock);
     when(oneClusterMock.getService(anyString())).thenReturn(serviceObj);
     when(serviceObj.getServiceComponent(anyString())).thenReturn(scomp);
     when(scomp.getServiceComponentHost(anyString())).thenReturn(sch);
     when(serviceObj.getCluster()).thenReturn(oneClusterMock);
 
-    ActionDBAccessor db = new ActionDBInMemoryImpl();
-    List<Stage> stages = new ArrayList<Stage>();
+    final List<Stage> stages = new ArrayList<Stage>();
 
     long now = System.currentTimeMillis();
     Stage stage = new Stage(1, "/tmp", "cluster1", "testRequestFailureBasedOnSuccessFactor", CLUSTER_HOST_INFO);
@@ -539,12 +735,67 @@ public class TestActionScheduler {
     stages.add(
         getStageWithSingleTask(
             "host1", "cluster1", Role.HDFS_CLIENT, RoleCommand.UPGRADE, Service.Type.HDFS, 4, 2, 1));
-    db.persistActions(stages);
+
+    ActionDBAccessor db = mock(ActionDBAccessor.class);
+
+    when(db.getStagesInProgress()).thenReturn(stages);
+    doAnswer(new Answer() {
+      @Override
+      public Object answer(InvocationOnMock invocation) throws Throwable {
+        String host = (String) invocation.getArguments()[0];
+        Long requestId = (Long) invocation.getArguments()[1];
+        Long stageId = (Long) invocation.getArguments()[2];
+        String role = (String) invocation.getArguments()[3];
+        CommandReport commandReport = (CommandReport) invocation.getArguments()[4];
+        for (Stage stage : stages) {
+          if (requestId.equals(stage.getRequestId()) && stageId.equals(stage.getStageId())) {
+            HostRoleCommand command = stage.getHostRoleCommand(host, role);
+            command.setStatus(HostRoleStatus.valueOf(commandReport.getStatus()));
+          }
+        }
+
+        return null;
+      }
+    }).when(db).updateHostRoleState(anyString(), anyLong(), anyLong(), anyString(), any(CommandReport.class));
+
+    when(db.getTask(anyLong())).thenAnswer(new Answer<Object>() {
+      @Override
+      public Object answer(InvocationOnMock invocation) throws Throwable {
+        Long taskId = (Long) invocation.getArguments()[0];
+        for (Stage stage : stages) {
+          for (HostRoleCommand command : stage.getOrderedHostRoleCommands()) {
+            if (taskId.equals(command.getTaskId())) {
+              return command;
+            }
+          }
+        }
+        return null;
+      }
+    });
+    doAnswer(new Answer() {
+      @Override
+      public Object answer(InvocationOnMock invocation) throws Throwable {
+        Long requestId = (Long) invocation.getArguments()[0];
+        for (Stage stage : stages) {
+          if (requestId.equals(stage.getRequestId())) {
+            for (HostRoleCommand command : stage.getOrderedHostRoleCommands()) {
+              if (command.getStatus() == HostRoleStatus.QUEUED ||
+                  command.getStatus() == HostRoleStatus.IN_PROGRESS ||
+                  command.getStatus() == HostRoleStatus.PENDING) {
+                command.setStatus(HostRoleStatus.ABORTED);
+              }
+            }
+          }
+        }
+
+        return null;
+      }
+    }).when(db).abortOperation(anyLong());
 
     ActionScheduler scheduler = new ActionScheduler(100, 50, db, aq, fsm, 3,
         new HostsMap((String) null), new ServerActionManagerImpl(fsm), unitOfWork);
     ActionManager am = new ActionManager(
-        2, 2, aq, fsm, db, new HostsMap((String) null), new ServerActionManagerImpl(fsm), unitOfWork, null);
+        2, 2, aq, fsm, db, new HostsMap((String) null), new ServerActionManagerImpl(fsm), unitOfWork, null, requestFactory);
 
     scheduler.doWork();
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/test/java/org/apache/ambari/server/agent/AgentResourceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/agent/AgentResourceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/agent/AgentResourceTest.java
index a832c8a..37766c6 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/agent/AgentResourceTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/agent/AgentResourceTest.java
@@ -31,6 +31,7 @@ import com.google.inject.persist.jpa.JpaPersistModule;
 
 import junit.framework.Assert;
 
+import org.apache.ambari.server.actionmanager.ActionDBAccessor;
 import org.apache.ambari.server.actionmanager.ActionManager;
 import org.apache.ambari.server.actionmanager.HostRoleCommandFactory;
 import org.apache.ambari.server.actionmanager.StageFactory;
@@ -76,6 +77,7 @@ public class AgentResourceTest extends JerseyTest {
   ActionManager actionManager;
   Injector injector;
   AmbariMetaInfo ambariMetaInfo;
+  ActionDBAccessor actionDBAccessor;
 
   public AgentResourceTest() {
     super(new WebAppDescriptor.Builder(PACKAGE_NAME).servletClass(ServletContainer.class)
@@ -254,6 +256,8 @@ public class AgentResourceTest extends JerseyTest {
       bind(Clusters.class).to(ClustersImpl.class);
       actionManager = mock(ActionManager.class);
       ambariMetaInfo = mock(AmbariMetaInfo.class);
+      actionDBAccessor = mock(ActionDBAccessor.class);
+      bind(ActionDBAccessor.class).toInstance(actionDBAccessor);
       bind(ActionManager.class).toInstance(actionManager);
       bind(AgentCommand.class).to(ExecutionCommand.class);
       bind(HeartBeatHandler.class).toInstance(handler);

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/test/java/org/apache/ambari/server/agent/TestHeartbeatHandler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/agent/TestHeartbeatHandler.java b/ambari-server/src/test/java/org/apache/ambari/server/agent/TestHeartbeatHandler.java
index 049c566..4e716dc 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/agent/TestHeartbeatHandler.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/agent/TestHeartbeatHandler.java
@@ -58,12 +58,7 @@ import junit.framework.Assert;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.Role;
 import org.apache.ambari.server.RoleCommand;
-import org.apache.ambari.server.actionmanager.ActionDBAccessor;
-import org.apache.ambari.server.actionmanager.ActionDBAccessorImpl;
-import org.apache.ambari.server.actionmanager.ActionDBInMemoryImpl;
-import org.apache.ambari.server.actionmanager.ActionManager;
-import org.apache.ambari.server.actionmanager.HostRoleStatus;
-import org.apache.ambari.server.actionmanager.Stage;
+import org.apache.ambari.server.actionmanager.*;
 import org.apache.ambari.server.agent.HostStatus.Status;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.configuration.Configuration;
@@ -106,8 +101,12 @@ public class TestHeartbeatHandler {
   AmbariMetaInfo metaInfo;
   @Inject
   Configuration config;
+  @Inject
+  ActionDBAccessor actionDBAccessor;
+
   private UnitOfWork unitOfWork;
 
+
   @Before
   public void setup() throws Exception {
     injector = Guice.createInjector(new InMemoryDefaultTestModule());
@@ -414,7 +413,7 @@ public class TestHeartbeatHandler {
     clusters.addCluster(DummyCluster);
     ActionDBAccessor db = injector.getInstance(ActionDBAccessorImpl.class);
     ActionManager am = new ActionManager(5000, 1200000, new ActionQueue(), clusters, db,
-        new HostsMap((String) null), null, unitOfWork, null);
+        new HostsMap((String) null), null, unitOfWork, null, injector.getInstance(RequestFactory.class));
     populateActionDB(db, DummyHostname1);
     Stage stage = db.getAllStages(requestId).get(0);
     Assert.assertEquals(stageId, stage.getStageId());
@@ -458,7 +457,8 @@ public class TestHeartbeatHandler {
             DummyHostname1, System.currentTimeMillis()), DummyCluster, HBASE);
     List<Stage> stages = new ArrayList<Stage>();
     stages.add(s);
-    db.persistActions(stages);
+    Request request = new Request(stages, clusters);
+    db.persistActions(request);
   }
 
   @Test
@@ -1511,7 +1511,7 @@ public class TestHeartbeatHandler {
 
   private ActionManager getMockActionManager() {
     return new ActionManager(0, 0, null, null,
-              new ActionDBInMemoryImpl(), new HostsMap((String) null), null, unitOfWork, null);
+              actionDBAccessor, new HostsMap((String) null), null, unitOfWork, null, injector.getInstance(RequestFactory.class));
   }
 
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
index 552a669..d6e59ee 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
@@ -36,13 +36,7 @@ import org.apache.ambari.server.Role;
 import org.apache.ambari.server.RoleCommand;
 import org.apache.ambari.server.ServiceNotFoundException;
 import org.apache.ambari.server.StackAccessException;
-import org.apache.ambari.server.actionmanager.ActionDBAccessor;
-import org.apache.ambari.server.actionmanager.ActionType;
-import org.apache.ambari.server.actionmanager.ExecutionCommandWrapper;
-import org.apache.ambari.server.actionmanager.HostRoleCommand;
-import org.apache.ambari.server.actionmanager.HostRoleStatus;
-import org.apache.ambari.server.actionmanager.Stage;
-import org.apache.ambari.server.actionmanager.TargetHostType;
+import org.apache.ambari.server.actionmanager.*;
 import org.apache.ambari.server.agent.ExecutionCommand;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.configuration.Configuration;
@@ -7096,22 +7090,27 @@ public class AmbariManagementControllerTest {
             new ServiceComponentHostStartEvent(Role.HBASE_CLIENT.toString(),
                     hostName1, System.currentTimeMillis()), clusterName, "HBASE");
 
+    Request request = new Request(stages, clusters);
+    actionDB.persistActions(request);
 
+    stages.clear();
     stages.add(new Stage(requestId2, "/a4", clusterName, context, CLUSTER_HOST_INFO));
-    stages.get(3).setStageId(4);
-    stages.get(3).addHostRoleExecutionCommand(hostName1, Role.HBASE_CLIENT,
+    stages.get(0).setStageId(4);
+    stages.get(0).addHostRoleExecutionCommand(hostName1, Role.HBASE_CLIENT,
             RoleCommand.START,
             new ServiceComponentHostStartEvent(Role.HBASE_CLIENT.toString(),
                     hostName1, System.currentTimeMillis()), clusterName, "HBASE");
 
     stages.add(new Stage(requestId2, "/a5", clusterName, context, CLUSTER_HOST_INFO));
-    stages.get(4).setStageId(5);
-    stages.get(4).addHostRoleExecutionCommand(hostName1, Role.HBASE_CLIENT,
+    stages.get(1).setStageId(5);
+    stages.get(1).addHostRoleExecutionCommand(hostName1, Role.HBASE_CLIENT,
             RoleCommand.START,
             new ServiceComponentHostStartEvent(Role.HBASE_CLIENT.toString(),
                     hostName1, System.currentTimeMillis()), clusterName, "HBASE");
 
-    actionDB.persistActions(stages);
+    request = new Request(stages, clusters);
+    actionDB.persistActions(request);
+
 
     Set<TaskStatusRequest> taskStatusRequests;
     Set<TaskStatusResponse> taskStatusResponses;

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestResourceProviderTest.java
index 016ba59..6df5de5 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestResourceProviderTest.java
@@ -38,15 +38,7 @@ import org.easymock.Capture;
 import org.junit.Assert;
 import org.junit.Test;
 
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 import static org.easymock.EasyMock.capture;
 import static org.easymock.EasyMock.createMock;
@@ -107,24 +99,26 @@ public class RequestResourceProviderTest {
     ActionManager actionManager = createNiceMock(ActionManager.class);
     HostRoleCommand hostRoleCommand = createNiceMock(HostRoleCommand.class);
 
+
     List<HostRoleCommand> hostRoleCommands = new LinkedList<HostRoleCommand>();
     hostRoleCommands.add(hostRoleCommand);
 
-    Capture<Collection<Long>> requestIdsCapture = new Capture<Collection<Long>>();
-    Capture<List<Long>> requestIdListCapture = new Capture<List<Long>>();
+    org.apache.ambari.server.actionmanager.Request requestMock =
+        createNiceMock(org.apache.ambari.server.actionmanager.Request.class);
+    expect(requestMock.getCommands()).andReturn(hostRoleCommands).anyTimes();
+    expect(requestMock.getRequestContext()).andReturn("this is a context").anyTimes();
+    expect(requestMock.getRequestId()).andReturn(100L).anyTimes();
 
-    Map<Long, String> requestContexts = new HashMap<Long, String>();
-    requestContexts.put(100L, "this is a context");
+    Capture<Collection<Long>> requestIdsCapture = new Capture<Collection<Long>>();
 
     // set expectations
     expect(managementController.getActionManager()).andReturn(actionManager);
-    expect(actionManager.getAllTasksByRequestIds(capture(requestIdsCapture))).andReturn(hostRoleCommands);
-    expect(actionManager.getRequestContext(capture(requestIdListCapture))).andReturn(requestContexts);
+    expect(actionManager.getRequests(capture(requestIdsCapture))).andReturn(Collections.singletonList(requestMock)).anyTimes();
     expect(hostRoleCommand.getRequestId()).andReturn(100L).anyTimes();
     expect(hostRoleCommand.getStatus()).andReturn(HostRoleStatus.IN_PROGRESS);
 
     // replay
-    replay(managementController, actionManager, hostRoleCommand);
+    replay(managementController, actionManager, hostRoleCommand, requestMock);
 
     ResourceProvider provider = AbstractControllerResourceProvider.getResourceProvider(
         type,
@@ -165,24 +159,26 @@ public class RequestResourceProviderTest {
     List<HostRoleCommand> hostRoleCommands = new LinkedList<HostRoleCommand>();
     hostRoleCommands.add(hostRoleCommand);
 
-    Capture<Collection<Long>> requestIdsCapture = new Capture<Collection<Long>>();
-    Capture<List<Long>> requestIdListCapture = new Capture<List<Long>>();
+    org.apache.ambari.server.actionmanager.Request requestMock =
+        createNiceMock(org.apache.ambari.server.actionmanager.Request.class);
+    expect(requestMock.getCommands()).andReturn(hostRoleCommands).anyTimes();
+    expect(requestMock.getRequestContext()).andReturn("this is a context").anyTimes();
+    expect(requestMock.getClusterName()).andReturn("c1").anyTimes();
+    expect(requestMock.getRequestId()).andReturn(100L).anyTimes();
 
-    Map<Long, String> requestContexts = new HashMap<Long, String>();
-    requestContexts.put(100L, "this is a context");
+    Capture<Collection<Long>> requestIdsCapture = new Capture<Collection<Long>>();
 
     // set expectations
     expect(managementController.getActionManager()).andReturn(actionManager).anyTimes();
     expect(managementController.getClusters()).andReturn(clusters).anyTimes();
     expect(clusters.getCluster("c1")).andReturn(cluster).anyTimes();
     expect(clusters.getCluster("bad-cluster")).andThrow(new AmbariException("bad cluster!")).anyTimes();
-    expect(actionManager.getAllTasksByRequestIds(capture(requestIdsCapture))).andReturn(hostRoleCommands);
-    expect(actionManager.getRequestContext(capture(requestIdListCapture))).andReturn(requestContexts);
+    expect(actionManager.getRequests(capture(requestIdsCapture))).andReturn(Collections.singletonList(requestMock));
     expect(hostRoleCommand.getRequestId()).andReturn(100L).anyTimes();
     expect(hostRoleCommand.getStatus()).andReturn(HostRoleStatus.IN_PROGRESS);
 
     // replay
-    replay(managementController, actionManager, hostRoleCommand, clusters, cluster);
+    replay(managementController, actionManager, hostRoleCommand, clusters, cluster, requestMock);
 
     ResourceProvider provider = AbstractControllerResourceProvider.getResourceProvider(
         type,
@@ -234,22 +230,28 @@ public class RequestResourceProviderTest {
     List<HostRoleCommand> hostRoleCommands = new LinkedList<HostRoleCommand>();
     hostRoleCommands.add(hostRoleCommand);
 
-    Capture<Collection<Long>> requestIdsCapture = new Capture<Collection<Long>>();
-    Capture<List<Long>> requestIdListCapture = new Capture<List<Long>>();
+    org.apache.ambari.server.actionmanager.Request requestMock =
+        createNiceMock(org.apache.ambari.server.actionmanager.Request.class);
+    expect(requestMock.getCommands()).andReturn(hostRoleCommands).anyTimes();
+    expect(requestMock.getRequestContext()).andReturn("this is a context").anyTimes();
+    expect(requestMock.getRequestId()).andReturn(100L).anyTimes();
+
+    org.apache.ambari.server.actionmanager.Request requestMock1 =
+        createNiceMock(org.apache.ambari.server.actionmanager.Request.class);
+    expect(requestMock1.getCommands()).andReturn(hostRoleCommands).anyTimes();
+    expect(requestMock1.getRequestContext()).andReturn("this is a context").anyTimes();
+    expect(requestMock1.getRequestId()).andReturn(101L).anyTimes();
 
-    Map<Long, String> requestContexts = new HashMap<Long, String>();
-    requestContexts.put(100L, "this is a context");
+    Capture<Collection<Long>> requestIdsCapture = new Capture<Collection<Long>>();
 
     // set expectations
     expect(managementController.getActionManager()).andReturn(actionManager).anyTimes();
-    expect(actionManager.getAllTasksByRequestIds(capture(requestIdsCapture))).andReturn(hostRoleCommands).anyTimes();
-    expect(actionManager.getRequestContext(capture(requestIdListCapture))).andReturn(requestContexts).anyTimes();
-    expect(hostRoleCommand.getRequestId()).andReturn(100L);
-    expect(hostRoleCommand.getRequestId()).andReturn(101L);
+    expect(actionManager.getRequests(capture(requestIdsCapture))).
+        andReturn(Arrays.asList(requestMock, requestMock1)).anyTimes();
     expect(hostRoleCommand.getStatus()).andReturn(HostRoleStatus.IN_PROGRESS).anyTimes();
 
     // replay
-    replay(managementController, actionManager, hostRoleCommand);
+    replay(managementController, actionManager, hostRoleCommand, requestMock, requestMock1);
 
     ResourceProvider provider = AbstractControllerResourceProvider.getResourceProvider(
         type,
@@ -296,21 +298,24 @@ public class RequestResourceProviderTest {
     hostRoleCommands1.add(hostRoleCommand2);
     hostRoleCommands1.add(hostRoleCommand3);
 
-    Capture<Collection<Long>> requestIdsCapture = new Capture<Collection<Long>>();
-    Capture<List<Long>> requestIdListCapture = new Capture<List<Long>>();
+    org.apache.ambari.server.actionmanager.Request requestMock0 =
+        createNiceMock(org.apache.ambari.server.actionmanager.Request.class);
+    expect(requestMock0.getCommands()).andReturn(hostRoleCommands0).anyTimes();
+    expect(requestMock0.getRequestContext()).andReturn("this is a context").anyTimes();
+    expect(requestMock0.getRequestId()).andReturn(100L).anyTimes();
 
-    Map<Long, String> requestContexts0 = new HashMap<Long, String>();
-    requestContexts0.put(100L, "this is a context");
+    org.apache.ambari.server.actionmanager.Request requestMock1 =
+        createNiceMock(org.apache.ambari.server.actionmanager.Request.class);
+    expect(requestMock1.getCommands()).andReturn(hostRoleCommands1).anyTimes();
+    expect(requestMock1.getRequestContext()).andReturn("this is a context").anyTimes();
+    expect(requestMock1.getRequestId()).andReturn(101L).anyTimes();
 
-    Map<Long, String> requestContexts1 = new HashMap<Long, String>();
-    requestContexts1.put(101L, "this is a context");
+    Capture<Collection<Long>> requestIdsCapture = new Capture<Collection<Long>>();
 
     // set expectations
     expect(managementController.getActionManager()).andReturn(actionManager).anyTimes();
-    expect(actionManager.getAllTasksByRequestIds(capture(requestIdsCapture))).andReturn(hostRoleCommands0);
-    expect(actionManager.getAllTasksByRequestIds(capture(requestIdsCapture))).andReturn(hostRoleCommands1);
-    expect(actionManager.getRequestContext(capture(requestIdListCapture))).andReturn(requestContexts0);
-    expect(actionManager.getRequestContext(capture(requestIdListCapture))).andReturn(requestContexts1);
+    expect(actionManager.getRequests(capture(requestIdsCapture))).andReturn(Arrays.asList(requestMock0));
+    expect(actionManager.getRequests(capture(requestIdsCapture))).andReturn(Arrays.asList(requestMock1));
     expect(hostRoleCommand0.getRequestId()).andReturn(100L).anyTimes();
     expect(hostRoleCommand1.getRequestId()).andReturn(100L).anyTimes();
     expect(hostRoleCommand2.getRequestId()).andReturn(101L).anyTimes();
@@ -321,7 +326,8 @@ public class RequestResourceProviderTest {
     expect(hostRoleCommand3.getStatus()).andReturn(HostRoleStatus.COMPLETED).anyTimes();
 
     // replay
-    replay(managementController, actionManager, hostRoleCommand0, hostRoleCommand1, hostRoleCommand2, hostRoleCommand3);
+    replay(managementController, actionManager, hostRoleCommand0, hostRoleCommand1, hostRoleCommand2, hostRoleCommand3,
+        requestMock0, requestMock1);
 
     ResourceProvider provider = AbstractControllerResourceProvider.getResourceProvider(
         type,
@@ -378,21 +384,24 @@ public class RequestResourceProviderTest {
     hostRoleCommands1.add(hostRoleCommand2);
     hostRoleCommands1.add(hostRoleCommand3);
 
-    Capture<Collection<Long>> requestIdsCapture = new Capture<Collection<Long>>();
-    Capture<List<Long>> requestIdListCapture = new Capture<List<Long>>();
+    org.apache.ambari.server.actionmanager.Request requestMock0 =
+        createNiceMock(org.apache.ambari.server.actionmanager.Request.class);
+    expect(requestMock0.getCommands()).andReturn(hostRoleCommands0).anyTimes();
+    expect(requestMock0.getRequestContext()).andReturn("this is a context").anyTimes();
+    expect(requestMock0.getRequestId()).andReturn(100L).anyTimes();
 
-    Map<Long, String> requestContexts0 = new HashMap<Long, String>();
-    requestContexts0.put(100L, "this is a context");
+    org.apache.ambari.server.actionmanager.Request requestMock1 =
+        createNiceMock(org.apache.ambari.server.actionmanager.Request.class);
+    expect(requestMock1.getCommands()).andReturn(hostRoleCommands1).anyTimes();
+    expect(requestMock1.getRequestContext()).andReturn("this is a context").anyTimes();
+    expect(requestMock1.getRequestId()).andReturn(101L).anyTimes();
 
-    Map<Long, String> requestContexts1 = new HashMap<Long, String>();
-    requestContexts1.put(101L, "this is a context");
+    Capture<Collection<Long>> requestIdsCapture = new Capture<Collection<Long>>();
 
     // set expectations
     expect(managementController.getActionManager()).andReturn(actionManager).anyTimes();
-    expect(actionManager.getAllTasksByRequestIds(capture(requestIdsCapture))).andReturn(hostRoleCommands0);
-    expect(actionManager.getAllTasksByRequestIds(capture(requestIdsCapture))).andReturn(hostRoleCommands1);
-    expect(actionManager.getRequestContext(capture(requestIdListCapture))).andReturn(requestContexts0);
-    expect(actionManager.getRequestContext(capture(requestIdListCapture))).andReturn(requestContexts1);
+    expect(actionManager.getRequests(capture(requestIdsCapture))).andReturn(Arrays.asList(requestMock0));
+    expect(actionManager.getRequests(capture(requestIdsCapture))).andReturn(Arrays.asList(requestMock1));
     expect(hostRoleCommand0.getRequestId()).andReturn(100L).anyTimes();
     expect(hostRoleCommand1.getRequestId()).andReturn(100L).anyTimes();
     expect(hostRoleCommand2.getRequestId()).andReturn(101L).anyTimes();
@@ -403,7 +412,8 @@ public class RequestResourceProviderTest {
     expect(hostRoleCommand3.getStatus()).andReturn(HostRoleStatus.QUEUED).anyTimes();
 
     // replay
-    replay(managementController, actionManager, hostRoleCommand0, hostRoleCommand1, hostRoleCommand2, hostRoleCommand3);
+    replay(managementController, actionManager, hostRoleCommand0, hostRoleCommand1, hostRoleCommand2, hostRoleCommand3,
+        requestMock0, requestMock1);
 
     ResourceProvider provider = AbstractControllerResourceProvider.getResourceProvider(
         type,
@@ -469,21 +479,24 @@ public class RequestResourceProviderTest {
     hostRoleCommands1.add(hostRoleCommand2);
     hostRoleCommands1.add(hostRoleCommand3);
 
-    Capture<Collection<Long>> requestIdsCapture = new Capture<Collection<Long>>();
-    Capture<List<Long>> requestIdListCapture = new Capture<List<Long>>();
+    org.apache.ambari.server.actionmanager.Request requestMock0 =
+        createNiceMock(org.apache.ambari.server.actionmanager.Request.class);
+    expect(requestMock0.getCommands()).andReturn(hostRoleCommands0).anyTimes();
+    expect(requestMock0.getRequestContext()).andReturn("this is a context").anyTimes();
+    expect(requestMock0.getRequestId()).andReturn(100L).anyTimes();
 
-    Map<Long, String> requestContexts0 = new HashMap<Long, String>();
-    requestContexts0.put(100L, "this is a context");
+    org.apache.ambari.server.actionmanager.Request requestMock1 =
+        createNiceMock(org.apache.ambari.server.actionmanager.Request.class);
+    expect(requestMock1.getCommands()).andReturn(hostRoleCommands1).anyTimes();
+    expect(requestMock1.getRequestContext()).andReturn("this is a context").anyTimes();
+    expect(requestMock1.getRequestId()).andReturn(101L).anyTimes();
 
-    Map<Long, String> requestContexts1 = new HashMap<Long, String>();
-    requestContexts1.put(101L, "this is a context");
+    Capture<Collection<Long>> requestIdsCapture = new Capture<Collection<Long>>();
 
     // set expectations
     expect(managementController.getActionManager()).andReturn(actionManager).anyTimes();
-    expect(actionManager.getAllTasksByRequestIds(capture(requestIdsCapture))).andReturn(hostRoleCommands0);
-    expect(actionManager.getAllTasksByRequestIds(capture(requestIdsCapture))).andReturn(hostRoleCommands1);
-    expect(actionManager.getRequestContext(capture(requestIdListCapture))).andReturn(requestContexts0);
-    expect(actionManager.getRequestContext(capture(requestIdListCapture))).andReturn(requestContexts1);
+    expect(actionManager.getRequests(capture(requestIdsCapture))).andReturn(Arrays.asList(requestMock0));
+    expect(actionManager.getRequests(capture(requestIdsCapture))).andReturn(Arrays.asList(requestMock1));
     expect(hostRoleCommand0.getRequestId()).andReturn(100L).anyTimes();
     expect(hostRoleCommand1.getRequestId()).andReturn(100L).anyTimes();
     expect(hostRoleCommand2.getRequestId()).andReturn(101L).anyTimes();
@@ -494,7 +507,8 @@ public class RequestResourceProviderTest {
     expect(hostRoleCommand3.getStatus()).andReturn(HostRoleStatus.TIMEDOUT).anyTimes();
 
     // replay
-    replay(managementController, actionManager, hostRoleCommand0, hostRoleCommand1, hostRoleCommand2, hostRoleCommand3);
+    replay(managementController, actionManager, hostRoleCommand0, hostRoleCommand1, hostRoleCommand2, hostRoleCommand3,
+        requestMock0, requestMock1);
 
     ResourceProvider provider = AbstractControllerResourceProvider.getResourceProvider(
         type,

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/test/java/org/apache/ambari/server/orm/OrmTestHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/OrmTestHelper.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/OrmTestHelper.java
index 99ab8ee..59b14c1 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/orm/OrmTestHelper.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/OrmTestHelper.java
@@ -149,10 +149,18 @@ public class OrmTestHelper {
     StageDAO stageDAO = injector.getInstance(StageDAO.class);
     HostRoleCommandDAO hostRoleCommandDAO = injector.getInstance(HostRoleCommandDAO.class);
     HostDAO hostDAO = injector.getInstance(HostDAO.class);
+    RequestDAO requestDAO = injector.getInstance(RequestDAO.class);
+    RequestEntity requestEntity = new RequestEntity();
+    requestEntity.setRequestId(1L);
+    requestEntity.setCluster(clusterDAO.findByName("test_cluster1"));
+
     StageEntity stageEntity = new StageEntity();
+    stageEntity.setRequest(requestEntity);
     stageEntity.setCluster(clusterDAO.findByName("test_cluster1"));
-    stageEntity.setRequestId(0L);
-    stageEntity.setStageId(0L);
+    stageEntity.setRequestId(1L);
+    stageEntity.setStageId(1L);
+
+    requestEntity.setStages(Collections.singletonList(stageEntity));
 
     HostRoleCommandEntity commandEntity = new HostRoleCommandEntity();
     HostRoleCommandEntity commandEntity2 = new HostRoleCommandEntity();
@@ -184,6 +192,7 @@ public class OrmTestHelper {
     stageEntity.getHostRoleCommands().add(commandEntity2);
     stageEntity.getHostRoleCommands().add(commandEntity3);
 
+    requestDAO.create(requestEntity);
     stageDAO.create(stageEntity);
     hostRoleCommandDAO.create(commandEntity3);
     hostRoleCommandDAO.create(commandEntity);

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/test/java/org/apache/ambari/server/orm/TestOrmImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/TestOrmImpl.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/TestOrmImpl.java
index 96daeea..aa79883 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/orm/TestOrmImpl.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/TestOrmImpl.java
@@ -23,6 +23,7 @@ import com.google.inject.Injector;
 import com.google.inject.persist.PersistService;
 import org.apache.ambari.server.Role;
 import org.apache.ambari.server.actionmanager.HostRoleStatus;
+import org.apache.ambari.server.actionmanager.Stage;
 import org.apache.ambari.server.orm.dao.*;
 import org.apache.ambari.server.orm.entities.*;
 import org.junit.*;
@@ -31,6 +32,7 @@ import org.slf4j.LoggerFactory;
 
 import javax.persistence.EntityManager;
 import javax.persistence.RollbackException;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
@@ -163,7 +165,7 @@ public class TestOrmImpl extends Assert {
 
     List<HostRoleCommandEntity> list =
         hostRoleCommandDAO.findSortedCommandsByStageAndHost(
-            stageDAO.findByActionId("0-0"), hostDAO.findByName("test_host1"));
+            stageDAO.findByActionId("1-1"), hostDAO.findByName("test_host1"));
     log.info("command '{}' - taskId '{}' ", list.get(0).getRoleCommand(),
         list.get(0).getTaskId());
     log.info("command '{}' - taskId '{}'", list.get(1).getRoleCommand(),
@@ -176,7 +178,7 @@ public class TestOrmImpl extends Assert {
     injector.getInstance(OrmTestHelper.class).createStageCommands();
     HostDAO hostDAO = injector.getInstance(HostDAO.class);
     StageDAO stageDAO = injector.getInstance(StageDAO.class);
-    StageEntity stageEntity = stageDAO.findByActionId("0-0");
+    StageEntity stageEntity = stageDAO.findByActionId("1-1");
     log.info("StageEntity {} {}" + stageEntity.getRequestId() + " "
         + stageEntity.getStageId());
     List<HostEntity> hosts = hostDAO.findByStage(stageEntity);
@@ -188,10 +190,10 @@ public class TestOrmImpl extends Assert {
     injector.getInstance(OrmTestHelper.class).createStageCommands();
     HostRoleCommandDAO hostRoleCommandDAO = injector.getInstance(HostRoleCommandDAO.class);
     int result = hostRoleCommandDAO.updateStatusByRequestId(
-        0L, HostRoleStatus.ABORTED, Arrays.asList(HostRoleStatus.QUEUED,
+        1L, HostRoleStatus.ABORTED, Arrays.asList(HostRoleStatus.QUEUED,
         HostRoleStatus.IN_PROGRESS, HostRoleStatus.PENDING));
     //result always 1 in batch mode
-    List<HostRoleCommandEntity> commandEntities = hostRoleCommandDAO.findByRequest(0L);
+    List<HostRoleCommandEntity> commandEntities = hostRoleCommandDAO.findByRequest(1L);
     int count = 0;
     for (HostRoleCommandEntity commandEntity : commandEntities) {
       if (commandEntity.getStatus() == HostRoleStatus.ABORTED) {
@@ -205,7 +207,7 @@ public class TestOrmImpl extends Assert {
   public void testFindStageByHostRole() {
     injector.getInstance(OrmTestHelper.class).createStageCommands();
     HostRoleCommandDAO hostRoleCommandDAO = injector.getInstance(HostRoleCommandDAO.class);
-    List<HostRoleCommandEntity> list = hostRoleCommandDAO.findByHostRole("test_host1", 0L, 0L, Role.DATANODE.toString());
+    List<HostRoleCommandEntity> list = hostRoleCommandDAO.findByHostRole("test_host1", 1L, 1L, Role.DATANODE.toString());
     assertEquals(1, list.size());
   }
 
@@ -214,17 +216,28 @@ public class TestOrmImpl extends Assert {
     injector.getInstance(OrmTestHelper.class).createStageCommands();
     ClusterDAO clusterDAO = injector.getInstance(ClusterDAO.class);
     StageDAO stageDAO = injector.getInstance(StageDAO.class);
+    RequestDAO requestDAO = injector.getInstance(RequestDAO.class);
+
+    RequestEntity requestEntity = requestDAO.findByPK(1L);
+    List<StageEntity> stageEntities = new ArrayList<StageEntity>();
+
     StageEntity stageEntity = new StageEntity();
     stageEntity.setCluster(clusterDAO.findByName("test_cluster1"));
-    stageEntity.setRequestId(0L);
-    stageEntity.setStageId(1L);
+    stageEntity.setRequest(requestEntity);
+    stageEntity.setStageId(2L);
     stageDAO.create(stageEntity);
     StageEntity stageEntity2 = new StageEntity();
     stageEntity2.setCluster(clusterDAO.findByName("test_cluster1"));
-    stageEntity2.setRequestId(0L);
-    stageEntity2.setStageId(2L);
+    stageEntity2.setRequest(requestEntity);
+    stageEntity2.setRequestId(1L);
+    stageEntity2.setStageId(3L);
     stageDAO.create(stageEntity2);
-    assertEquals(0L, stageDAO.getLastRequestId());
+
+    stageEntities.add(stageEntity);
+    stageEntities.add(stageEntity2);
+    requestEntity.setStages(stageEntities);
+    requestDAO.merge(requestEntity);
+    assertEquals(1L, stageDAO.getLastRequestId());
   }
 
   @Test

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/test/java/org/apache/ambari/server/scheduler/ExecutionScheduleManagerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/scheduler/ExecutionScheduleManagerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/scheduler/ExecutionScheduleManagerTest.java
index 39d223d..1000bf9 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/scheduler/ExecutionScheduleManagerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/scheduler/ExecutionScheduleManagerTest.java
@@ -17,6 +17,7 @@
  */
 package org.apache.ambari.server.scheduler;
 
+import com.google.gson.Gson;
 import com.google.inject.Binder;
 import com.google.inject.Guice;
 import com.google.inject.Inject;
@@ -26,19 +27,18 @@ import com.google.inject.persist.PersistService;
 import com.google.inject.persist.Transactional;
 import com.google.inject.util.Modules;
 import junit.framework.Assert;
+import org.apache.ambari.server.actionmanager.HostRoleCommand;
+import org.apache.ambari.server.actionmanager.HostRoleStatus;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.orm.GuiceJpaInitializer;
 import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
+import org.apache.ambari.server.security.authorization.internal.InternalTokenStorage;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.StackId;
-import org.apache.ambari.server.state.scheduler.Batch;
-import org.apache.ambari.server.state.scheduler.BatchRequest;
-import org.apache.ambari.server.state.scheduler.BatchSettings;
-import org.apache.ambari.server.state.scheduler.RequestExecution;
-import org.apache.ambari.server.state.scheduler.RequestExecutionFactory;
-import org.apache.ambari.server.state.scheduler.Schedule;
+import org.apache.ambari.server.state.scheduler.*;
+import org.easymock.Capture;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -55,12 +55,11 @@ import org.quartz.impl.matchers.GroupMatcher;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Properties;
+import java.util.*;
 
+import static org.easymock.EasyMock.*;
 import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
 
 public class ExecutionScheduleManagerTest {
@@ -311,4 +310,151 @@ public class ExecutionScheduleManagerTest {
       waitCount++;
     }
   }
+
+  @Test
+  public void testExecuteBatchRequest() throws Exception {
+    Clusters clustersMock = createMock(Clusters.class);
+    Cluster clusterMock = createMock(Cluster.class);
+    RequestExecution requestExecutionMock = createMock(RequestExecution.class);
+    Configuration configurationMock = createNiceMock(Configuration.class);
+    ExecutionScheduler executionSchedulerMock = createMock(ExecutionScheduler.class);
+    InternalTokenStorage tokenStorageMock = createMock(InternalTokenStorage.class);
+    Gson gson = new Gson();
+    BatchRequest batchRequestMock = createMock(BatchRequest.class);
+
+    long executionId = 11L;
+    long batchId = 1L;
+    long requestId = 5L;
+    String clusterName = "mycluster";
+    String uri = "clusters";
+    String type = "post";
+    String body = "body";
+    Map<Long, RequestExecution> executionMap = new HashMap<Long, RequestExecution>();
+    executionMap.put(executionId, requestExecutionMock);
+
+    BatchRequestResponse batchRequestResponse = new BatchRequestResponse();
+    batchRequestResponse.setStatus(HostRoleStatus.IN_PROGRESS.toString());
+    batchRequestResponse.setRequestId(requestId);
+    batchRequestResponse.setReturnCode(202);
+
+    ExecutionScheduleManager scheduleManager = createMockBuilder(ExecutionScheduleManager.class).
+      withConstructor(configurationMock, executionSchedulerMock, tokenStorageMock, clustersMock, gson).
+      addMockedMethods("performApiRequest", "updateBatchRequest").createNiceMock();
+
+    //interesting easymock behavior, workaround to not to expect method called in constructor
+    expectLastCall().anyTimes();
+
+    expect(clustersMock.getCluster(clusterName)).andReturn(clusterMock).anyTimes();
+    expect(clusterMock.getAllRequestExecutions()).andReturn(executionMap).anyTimes();
+
+
+    expect(requestExecutionMock.getBatchRequest(eq(batchId))).andReturn(batchRequestMock).once();
+    expect(requestExecutionMock.getRequestBody(eq(batchId))).andReturn(body).once();
+
+    expect(batchRequestMock.getUri()).andReturn(uri).once();
+    expect(batchRequestMock.getType()).andReturn(type).once();
+
+    expect(scheduleManager.performApiRequest(eq(uri), eq(body), eq(type))).andReturn(batchRequestResponse).once();
+
+    scheduleManager.updateBatchRequest(eq(executionId), eq(batchId), eq(clusterName), eq(batchRequestResponse), eq(false));
+    expectLastCall().once();
+
+
+    replay(clusterMock, clustersMock, configurationMock, requestExecutionMock, executionSchedulerMock,
+      tokenStorageMock, batchRequestMock, scheduleManager);
+
+    scheduleManager.executeBatchRequest(executionId, batchId, clusterName);
+
+    verify(clusterMock, clustersMock, configurationMock, requestExecutionMock, executionSchedulerMock,
+      tokenStorageMock, batchRequestMock, scheduleManager);
+
+  }
+
+  @Test
+  public void testUpdateBatchRequest() throws Exception {
+    Clusters clustersMock = createMock(Clusters.class);
+    Cluster clusterMock = createMock(Cluster.class);
+    RequestExecution requestExecutionMock = createMock(RequestExecution.class);
+    Configuration configurationMock = createNiceMock(Configuration.class);
+    ExecutionScheduler executionSchedulerMock = createMock(ExecutionScheduler.class);
+    InternalTokenStorage tokenStorageMock = createMock(InternalTokenStorage.class);
+    Gson gson = new Gson();
+    BatchRequest batchRequestMock = createMock(BatchRequest.class);
+
+    long executionId = 11L;
+    long batchId = 1L;
+    long requestId = 5L;
+    String clusterName = "mycluster";
+
+    Map<Long, RequestExecution> executionMap = new HashMap<Long, RequestExecution>();
+    executionMap.put(executionId, requestExecutionMock);
+
+    BatchRequestResponse batchRequestResponse = new BatchRequestResponse();
+    batchRequestResponse.setStatus(HostRoleStatus.IN_PROGRESS.toString());
+    batchRequestResponse.setRequestId(requestId);
+    batchRequestResponse.setReturnCode(202);
+
+    ExecutionScheduleManager scheduleManager = createMockBuilder(ExecutionScheduleManager.class).
+      withConstructor(configurationMock, executionSchedulerMock, tokenStorageMock, clustersMock, gson).
+      addMockedMethods("performApiRequest").createNiceMock();
+
+    //interesting easymock behavior, workaround to not to expect method called in constructor
+    expectLastCall().anyTimes();
+
+    expect(clustersMock.getCluster(clusterName)).andReturn(clusterMock).anyTimes();
+    expect(clusterMock.getAllRequestExecutions()).andReturn(executionMap).anyTimes();
+
+    requestExecutionMock.updateBatchRequest(eq(batchId), eq(batchRequestResponse), eq(true));
+    expectLastCall().once();
+
+
+    replay(clusterMock, clustersMock, configurationMock, requestExecutionMock, executionSchedulerMock,
+      tokenStorageMock, batchRequestMock, scheduleManager);
+
+    scheduleManager.updateBatchRequest(executionId, batchId, clusterName, batchRequestResponse, true);
+
+    verify(clusterMock, clustersMock, configurationMock, requestExecutionMock, executionSchedulerMock,
+      tokenStorageMock, batchRequestMock, scheduleManager);
+
+  }
+
+  @Test
+  public void testGetBatchRequestResponse() throws Exception {
+    Clusters clustersMock = createMock(Clusters.class);
+    Cluster clusterMock = createMock(Cluster.class);
+    Configuration configurationMock = createNiceMock(Configuration.class);
+    ExecutionScheduler executionSchedulerMock = createMock(ExecutionScheduler.class);
+    InternalTokenStorage tokenStorageMock = createMock(InternalTokenStorage.class);
+    Gson gson = new Gson();
+
+    long requestId = 5L;
+    String clusterName = "mycluster";
+    String apiUri = "api/v1/clusters/mycluster/requests/5";
+    Capture<String> uriCapture= new Capture<String>();
+
+    BatchRequestResponse batchRequestResponse = new BatchRequestResponse();
+    batchRequestResponse.setStatus(HostRoleStatus.IN_PROGRESS.toString());
+    batchRequestResponse.setRequestId(requestId);
+    batchRequestResponse.setReturnCode(202);
+
+    ExecutionScheduleManager scheduleManager = createMockBuilder(ExecutionScheduleManager.class).
+      withConstructor(configurationMock, executionSchedulerMock, tokenStorageMock, clustersMock, gson).
+      addMockedMethods("performApiGetRequest").createNiceMock();
+
+    //interesting easymock behavior, workaround to not to expect method called in constructor
+    expectLastCall().anyTimes();
+
+
+    expect(scheduleManager.performApiGetRequest(capture(uriCapture), eq(true))).andReturn(batchRequestResponse).once();
+
+    replay(clusterMock, clustersMock, configurationMock, executionSchedulerMock,
+      tokenStorageMock, scheduleManager);
+
+    scheduleManager.getBatchRequestResponse(requestId, clusterName);
+
+    verify(clusterMock, clustersMock, configurationMock, executionSchedulerMock,
+      tokenStorageMock, scheduleManager);
+
+    assertEquals(apiUri, uriCapture.getValue());
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/test/java/org/apache/ambari/server/state/scheduler/BatchRequestJobTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/scheduler/BatchRequestJobTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/scheduler/BatchRequestJobTest.java
new file mode 100644
index 0000000..8768645
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/scheduler/BatchRequestJobTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.ambari.server.state.scheduler;
+
+import org.apache.ambari.server.actionmanager.HostRoleStatus;
+import org.apache.ambari.server.scheduler.ExecutionScheduleManager;
+import org.easymock.Capture;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.easymock.EasyMock.*;
+
+public class BatchRequestJobTest {
+
+
+  @Test
+  public void testDoWork() throws Exception {
+    ExecutionScheduleManager scheduleManagerMock = createMock(ExecutionScheduleManager.class);
+    BatchRequestJob batchRequestJob = new BatchRequestJob(scheduleManagerMock, 100L);
+    String clusterName = "mycluster";
+    Long requestId = 11L;
+
+    Map<String, Object> properties = new HashMap<String, Object>();
+    properties.put(BatchRequestJob.BATCH_REQUEST_EXECUTION_ID_KEY, 1L);
+    properties.put(BatchRequestJob.BATCH_REQUEST_BATCH_ID_KEY, 1L);
+    properties.put(BatchRequestJob.BATCH_REQUEST_CLUSTER_NAME_KEY, clusterName);
+
+
+    BatchRequestResponse pendingResponse = new BatchRequestResponse();
+    pendingResponse.setStatus(HostRoleStatus.PENDING.toString());
+    BatchRequestResponse inProgressResponse = new BatchRequestResponse();
+    inProgressResponse.setStatus(HostRoleStatus.IN_PROGRESS.toString());
+    BatchRequestResponse completedResponse = new BatchRequestResponse();
+    completedResponse.setStatus(HostRoleStatus.COMPLETED.toString());
+
+    Capture<Long> executionIdCapture = new Capture<Long>();
+    Capture<Long> batchIdCapture = new Capture<Long>();
+    Capture<String> clusterNameCapture = new Capture<String>();
+
+
+    expect(scheduleManagerMock.executeBatchRequest(captureLong(executionIdCapture), captureLong(batchIdCapture),
+      capture(clusterNameCapture))).andReturn(requestId);
+
+    expect(scheduleManagerMock.getBatchRequestResponse(requestId, clusterName)).
+      andReturn(pendingResponse).times(2);
+    expect(scheduleManagerMock.getBatchRequestResponse(requestId, clusterName)).
+      andReturn(inProgressResponse).times(4);
+    expect(scheduleManagerMock.getBatchRequestResponse(requestId, clusterName)).
+      andReturn(completedResponse).atLeastOnce();
+
+
+    replay(scheduleManagerMock);
+
+    batchRequestJob.doWork(properties);
+
+    verify(scheduleManagerMock);
+
+
+  }
+}


[2/3] AMBARI-4267. Enable BatchRequest(s) to transform to API calls to the server. (mpapirkovskyy)

Posted by mp...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/scheduler/ExecutionScheduleManager.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/scheduler/ExecutionScheduleManager.java b/ambari-server/src/main/java/org/apache/ambari/server/scheduler/ExecutionScheduleManager.java
index 9813cee..a2d0996 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/scheduler/ExecutionScheduleManager.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/scheduler/ExecutionScheduleManager.java
@@ -18,14 +18,20 @@
 
 package org.apache.ambari.server.scheduler;
 
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
 import com.google.inject.Inject;
-import com.google.inject.Injector;
 import com.google.inject.Singleton;
+import com.sun.jersey.api.client.*;
+import com.sun.jersey.api.client.filter.ClientFilter;
+import com.sun.jersey.api.client.filter.CsrfProtectionFilter;
 import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.actionmanager.HostRoleStatus;
 import org.apache.ambari.server.configuration.Configuration;
-import org.apache.ambari.server.orm.dao.RequestScheduleBatchRequestDAO;
-import org.apache.ambari.server.orm.entities.RequestScheduleBatchRequestEntity;
-import org.apache.ambari.server.orm.entities.RequestScheduleBatchRequestEntityPK;
+import org.apache.ambari.server.security.authorization.internal.InternalTokenClientFilter;
+import org.apache.ambari.server.security.authorization.internal.InternalTokenStorage;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.scheduler.Batch;
 import org.apache.ambari.server.state.scheduler.BatchRequest;
 import org.apache.ambari.server.state.scheduler.BatchRequestJob;
@@ -33,6 +39,7 @@ import org.apache.ambari.server.state.scheduler.BatchRequestResponse;
 import org.apache.ambari.server.state.scheduler.RequestExecution;
 import org.apache.ambari.server.state.scheduler.Schedule;
 import org.apache.ambari.server.utils.DateUtils;
+import org.apache.commons.lang.text.StrBuilder;
 import org.quartz.CronExpression;
 import org.quartz.JobDetail;
 import org.quartz.JobExecutionContext;
@@ -43,10 +50,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.text.ParseException;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.ListIterator;
+import java.util.*;
 
 import static org.quartz.CronScheduleBuilder.cronSchedule;
 import static org.quartz.JobBuilder.newJob;
@@ -60,21 +64,59 @@ import static org.quartz.TriggerBuilder.newTrigger;
 public class ExecutionScheduleManager {
   private static final Logger LOG = LoggerFactory.getLogger
     (ExecutionScheduleManager.class);
-  @Inject
-  private ExecutionScheduler executionScheduler;
-  @Inject
-  private Configuration configuration;
-  @Inject
-  private RequestScheduleBatchRequestDAO batchRequestDAO;
+
+  private final InternalTokenStorage tokenStorage;
+  private final Gson gson;
+  private final Clusters clusters;
+  ExecutionScheduler executionScheduler;
+  Configuration configuration;
 
   private volatile boolean schedulerAvailable = false;
   protected static final String BATCH_REQUEST_JOB_PREFIX = "BatchRequestJob";
   protected static final String REQUEST_EXECUTION_TRIGGER_PREFIX =
     "RequestExecution";
+  protected static final String DEFAULT_API_PATH = "api/v1";
+
+  protected Client ambariClient;
+  protected WebResource ambariWebResource;
 
   @Inject
-  public ExecutionScheduleManager(Injector injector) {
-    injector.injectMembers(this);
+  public ExecutionScheduleManager(Configuration configuration,
+                                  ExecutionScheduler executionScheduler,
+                                  InternalTokenStorage tokenStorage,
+                                  Clusters clusters,
+                                  Gson gson) {
+    this.configuration = configuration;
+    this.executionScheduler = executionScheduler;
+    this.tokenStorage = tokenStorage;
+    this.clusters = clusters;
+    this.gson = gson;
+
+    buildApiClient();
+  }
+
+  protected void buildApiClient() {
+    if (configuration.getApiSSLAuthentication()) {
+      //TODO build SSL client
+
+    } else {
+      Client client = Client.create();
+
+      this.ambariClient = client;
+
+      String pattern = "http://localhost:%s/";
+      String url = String.format(pattern, configuration.getClientApiPort());
+
+      this.ambariWebResource = client.resource(url);
+
+    }
+
+    //Install auth filters
+    ClientFilter csrfFilter = new CsrfProtectionFilter("RequestSchedule");
+    ClientFilter tokenFilter = new InternalTokenClientFilter(tokenStorage);
+    ambariClient.addFilter(csrfFilter);
+    ambariClient.addFilter(tokenFilter);
+
   }
 
   /**
@@ -197,8 +239,11 @@ public class ExecutionScheduleManager {
           .endAt(endDate)
           .build();
 
+
+
       try {
         executionScheduler.scheduleJob(trigger);
+        LOG.debug("Scheduled trigger next fire time: " + trigger.getNextFireTime());
       } catch (SchedulerException e) {
         LOG.error("Unable to schedule request execution.", e);
         throw new AmbariException(e.getMessage());
@@ -216,6 +261,7 @@ public class ExecutionScheduleManager {
 
       try {
         executionScheduler.scheduleJob(trigger);
+        LOG.debug("Scheduled trigger next fire time: " + trigger.getNextFireTime());
       } catch (SchedulerException e) {
         LOG.error("Unable to schedule request execution.", e);
         throw new AmbariException(e.getMessage());
@@ -252,6 +298,8 @@ public class ExecutionScheduleManager {
               requestExecution.getId())
             .usingJobData(BatchRequestJob.BATCH_REQUEST_BATCH_ID_KEY,
               batchRequest.getOrderId())
+            .usingJobData(BatchRequestJob.BATCH_REQUEST_CLUSTER_NAME_KEY,
+              requestExecution.getClusterName())
             .storeDurably()
             .build();
 
@@ -369,30 +417,31 @@ public class ExecutionScheduleManager {
    * @return request id
    * @throws AmbariException
    */
-  public synchronized Long executeBatchRequest(Long executionId,
-                                               Long batchId) throws AmbariException {
+  public Long executeBatchRequest(Long executionId,
+                                  Long batchId,
+                                  String clusterName) throws AmbariException {
 
     String type = null;
     String uri = null;
     String body = null;
 
     try {
-      RequestScheduleBatchRequestEntityPK batchRequestEntityPK = new
-        RequestScheduleBatchRequestEntityPK();
-      batchRequestEntityPK.setScheduleId(executionId);
-      batchRequestEntityPK.setBatchId(batchId);
-      RequestScheduleBatchRequestEntity batchRequestEntity =
-        batchRequestDAO.findByPk(batchRequestEntityPK);
+      RequestExecution requestExecution = clusters.getCluster(clusterName).getAllRequestExecutions().get(executionId);
+      BatchRequest batchRequest = requestExecution.getBatchRequest(batchId);
+      type = batchRequest.getType();
+      uri = batchRequest.getUri();
 
-      type = batchRequestEntity.getRequestType();
-      uri = batchRequestEntity.getRequestUri();
-      body = batchRequestEntity.getRequestBodyAsString();
+      body = requestExecution.getRequestBody(batchId);
 
-    } catch (Exception e) {
+      BatchRequestResponse batchRequestResponse = performApiRequest(uri, body, type);
+
+      updateBatchRequest(executionId, batchId, clusterName, batchRequestResponse, false);
 
+      return batchRequestResponse.getRequestId();
+    } catch (Exception e) {
+      throw new AmbariException("Exception occurred while performing request", e);
     }
 
-    return -1L;
   }
 
   /**
@@ -400,10 +449,118 @@ public class ExecutionScheduleManager {
    * @return
    * @throws AmbariException
    */
-  public BatchRequestResponse getBatchRequestResponse(Long requestId)
+  public BatchRequestResponse getBatchRequestResponse(Long requestId, String clusterName)
     throws AmbariException {
 
+    StrBuilder sb = new StrBuilder();
+    sb.append(DEFAULT_API_PATH).append("/clusters/").append(clusterName).append("/requests/").append(requestId);
+
+    return performApiGetRequest(sb.toString(), true);
+
+  }
+
+  private BatchRequestResponse convertToBatchRequestResponse(ClientResponse clientResponse) {
     BatchRequestResponse batchRequestResponse = new BatchRequestResponse();
+    int retCode = clientResponse.getStatus();
+
+    batchRequestResponse.setReturnCode(retCode);
+
+    String responseString = clientResponse.getEntity(String.class);
+    LOG.debug("Processing API response: status={}, body={}", retCode, responseString);
+    Map httpResponseMap;
+    try {
+      httpResponseMap = gson.fromJson(responseString, Map.class);
+      LOG.debug("Processing responce as JSON");
+    } catch (JsonSyntaxException e) {
+      LOG.debug("Response is not valid JSON object. Recording as is");
+      httpResponseMap = new HashMap();
+      httpResponseMap.put("message", responseString);
+    }
+
+
+    if (retCode < 300) {
+      if (httpResponseMap == null) {
+        //Empty response on successful scenario
+        batchRequestResponse.setStatus(HostRoleStatus.COMPLETED.toString());
+        return batchRequestResponse;
+      }
+
+      Map requestMap = null;
+      Object requestMapObject = httpResponseMap.get("Requests");
+      if (requestMapObject instanceof Map) {
+        requestMap = (Map) requestMapObject;
+      }
+
+      if (requestMap != null) {
+        batchRequestResponse.setRequestId(((Double) requestMap.get("id")).longValue());
+        //TODO fix different names for field
+        String status = null;
+        if (requestMap.get("request_status") != null) {
+          status = requestMap.get("request_status").toString();
+        }
+        if (requestMap.get("status") != null) {
+          status = requestMap.get("status").toString();
+        }
+        batchRequestResponse.setStatus(status);
+      }
+
+    } else {
+      //unsuccessful response
+      batchRequestResponse.setReturnMessage((String) httpResponseMap.get("message"));
+      batchRequestResponse.setStatus(HostRoleStatus.FAILED.toString());
+    }
+
     return batchRequestResponse;
   }
+
+  public void updateBatchRequest(long executionId, long batchId, String clusterName,
+                                 BatchRequestResponse batchRequestResponse,
+                                 boolean statusOnly)
+      throws AmbariException{
+
+    Cluster cluster = clusters.getCluster(clusterName);
+    RequestExecution requestExecution = cluster.getAllRequestExecutions().get(executionId);
+
+    requestExecution.updateBatchRequest(batchId, batchRequestResponse, statusOnly);
+
+  }
+
+  protected BatchRequestResponse performUriRequest(String url, String body, String method) {
+    ClientResponse response;
+    try {
+      response = ambariClient.resource(url).entity(body).method(method, ClientResponse.class);
+    } catch (UniformInterfaceException e) {
+      response = e.getResponse();
+    }
+    //Don't read response entity for logging purposes, it can be read only once from http stream
+
+    return convertToBatchRequestResponse(response);
+  }
+
+  protected BatchRequestResponse performApiGetRequest(String relativeUri, boolean queryAllFields) {
+    WebResource webResource = ambariWebResource.path(relativeUri);
+    if (queryAllFields) {
+      webResource = webResource.queryParam("fields", "*");
+    }
+    ClientResponse response;
+    try {
+      response = webResource.get(ClientResponse.class);
+    } catch (UniformInterfaceException e) {
+      response = e.getResponse();
+    }
+    return convertToBatchRequestResponse(response);
+  }
+
+  protected BatchRequestResponse performApiRequest(String relativeUri, String body, String method) {
+    ClientResponse response;
+    try {
+      response = ambariWebResource.path(relativeUri).method(method, ClientResponse.class, body);
+    } catch (UniformInterfaceException e) {
+      response = e.getResponse();
+    }
+
+    return convertToBatchRequestResponse(response);
+  }
+
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/scheduler/ExecutionSchedulerImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/scheduler/ExecutionSchedulerImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/scheduler/ExecutionSchedulerImpl.java
index 2b938bc..353aaf0 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/scheduler/ExecutionSchedulerImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/scheduler/ExecutionSchedulerImpl.java
@@ -22,6 +22,7 @@ import com.google.inject.Injector;
 import com.google.inject.Singleton;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.state.scheduler.GuiceJobFactory;
 import org.apache.ambari.server.state.scheduler.RequestExecution;
 import org.apache.ambari.server.state.scheduler.Schedule;
 import org.quartz.Job;
@@ -40,6 +41,9 @@ import java.util.Properties;
 public class ExecutionSchedulerImpl implements ExecutionScheduler {
   @Inject
   private Configuration configuration;
+  @Inject
+  GuiceJobFactory guiceJobFactory;
+
   private static final Logger LOG = LoggerFactory.getLogger(ExecutionSchedulerImpl.class);
   protected static final String DEFAULT_SCHEDULER_NAME = "ExecutionScheduler";
   protected Scheduler scheduler;
@@ -71,6 +75,7 @@ public class ExecutionSchedulerImpl implements ExecutionScheduler {
     }
     try {
       scheduler = sf.getScheduler();
+      scheduler.setJobFactory(guiceJobFactory);
       isInitialized = true;
     } catch (SchedulerException e) {
       LOG.warn("Failed to create Request Execution scheduler !");

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/internal/AmbariInternalAuthenticationProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/internal/AmbariInternalAuthenticationProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/internal/AmbariInternalAuthenticationProvider.java
new file mode 100644
index 0000000..243c843
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/internal/AmbariInternalAuthenticationProvider.java
@@ -0,0 +1,52 @@
+/*
+ * 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.ambari.server.security.authorization.internal;
+
+import com.google.inject.Inject;
+import org.springframework.security.authentication.AuthenticationProvider;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+
+public class AmbariInternalAuthenticationProvider implements AuthenticationProvider {
+
+  private final InternalTokenStorage internalTokenStorage;
+
+  @Inject
+  public AmbariInternalAuthenticationProvider(InternalTokenStorage internalTokenStorage) {
+    this.internalTokenStorage = internalTokenStorage;
+  }
+
+  @Override
+  public Authentication authenticate(Authentication authentication) throws AuthenticationException {
+    InternalAuthenticationToken token = (InternalAuthenticationToken) authentication;
+    if (internalTokenStorage.isValidInternalToken(token.getCredentials())) {
+      token.setAuthenticated(true);
+    } else {
+      String message = "Bad credentials";
+      throw new BadCredentialsException(message);
+    }
+    return token;
+  }
+
+  @Override
+  public boolean supports(Class<?> authentication) {
+    return InternalAuthenticationToken.class.isAssignableFrom(authentication);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/internal/InternalAuthenticationToken.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/internal/InternalAuthenticationToken.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/internal/InternalAuthenticationToken.java
new file mode 100644
index 0000000..5d865ea
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/internal/InternalAuthenticationToken.java
@@ -0,0 +1,78 @@
+/*
+ * 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.ambari.server.security.authorization.internal;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.User;
+
+import java.util.Collection;
+import java.util.Collections;
+
+public class InternalAuthenticationToken implements Authentication {
+
+  private static final String INTERNAL_NAME = "internal";
+  private static final Collection<? extends GrantedAuthority> AUTHORITIES =
+      Collections.singleton(new SimpleGrantedAuthority("ADMIN"));
+  private static final User INTERNAL_USER = new User(INTERNAL_NAME, "empty", AUTHORITIES);
+
+  private String token;
+  private boolean authenticated = false;
+
+
+  public InternalAuthenticationToken(String tokenString) {
+    this.token = tokenString;
+  }
+
+  @Override
+  public Collection<? extends GrantedAuthority> getAuthorities() {
+    return AUTHORITIES;
+  }
+
+  @Override
+  public String getCredentials() {
+    return token;
+  }
+
+  @Override
+  public Object getDetails() {
+    return null;
+  }
+
+  @Override
+  public Object getPrincipal() {
+    return INTERNAL_USER;
+  }
+
+  @Override
+  public boolean isAuthenticated() {
+    return authenticated;
+  }
+
+  @Override
+  public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
+    this.authenticated = isAuthenticated;
+  }
+
+  @Override
+  public String getName() {
+    return INTERNAL_NAME;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/internal/InternalTokenAuthenticationFilter.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/internal/InternalTokenAuthenticationFilter.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/internal/InternalTokenAuthenticationFilter.java
new file mode 100644
index 0000000..c05de28
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/internal/InternalTokenAuthenticationFilter.java
@@ -0,0 +1,60 @@
+/*
+ * 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.ambari.server.security.authorization.internal;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+public class InternalTokenAuthenticationFilter implements Filter {
+  public static final String INTERNAL_TOKEN_HEADER = "X-Internal-Token";
+
+  @Override
+  public void init(FilterConfig filterConfig) throws ServletException {
+
+  }
+
+  @Override
+  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+    HttpServletRequest httpRequest = (HttpServletRequest) request;
+    HttpServletResponse httpResponse = (HttpServletResponse) response;
+
+    SecurityContext context = SecurityContextHolder.getContext();
+
+    if (context.getAuthentication() == null || !context.getAuthentication().isAuthenticated()) {
+      String token = httpRequest.getHeader(INTERNAL_TOKEN_HEADER);
+      if (token != null) {
+        context.setAuthentication(new InternalAuthenticationToken(token));
+      }
+    }
+
+    chain.doFilter(request, response);
+  }
+
+  @Override
+  public void destroy() {
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/internal/InternalTokenClientFilter.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/internal/InternalTokenClientFilter.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/internal/InternalTokenClientFilter.java
new file mode 100644
index 0000000..c1ba9e1
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/internal/InternalTokenClientFilter.java
@@ -0,0 +1,41 @@
+/*
+ * 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.ambari.server.security.authorization.internal;
+
+import com.google.inject.Inject;
+import com.sun.jersey.api.client.ClientHandlerException;
+import com.sun.jersey.api.client.ClientRequest;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.filter.ClientFilter;
+
+public class InternalTokenClientFilter extends ClientFilter {
+  public static final String INTERNAL_TOKEN_HEADER = "X-Internal-Token";
+  private final InternalTokenStorage tokenStorage;
+
+  @Inject
+  public InternalTokenClientFilter(InternalTokenStorage tokenStorage) {
+    this.tokenStorage = tokenStorage;
+  }
+
+  @Override
+  public ClientResponse handle(ClientRequest cr) throws ClientHandlerException {
+    cr.getHeaders().add(INTERNAL_TOKEN_HEADER, tokenStorage.getInternalToken());
+    return getNext().handle(cr);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/internal/InternalTokenStorage.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/internal/InternalTokenStorage.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/internal/InternalTokenStorage.java
new file mode 100644
index 0000000..92d7fa9
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/internal/InternalTokenStorage.java
@@ -0,0 +1,52 @@
+/*
+ * 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.ambari.server.security.authorization.internal;
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+@Singleton
+/**
+ * Generates single token for internal authentication
+ */
+public class InternalTokenStorage {
+  private final SecureRandom random;
+  private final String token;
+
+  @Inject
+  public InternalTokenStorage(SecureRandom secureRandom) {
+    this.random = secureRandom;
+    token = createNewToken();
+  }
+
+  public String getInternalToken() {
+    return token;
+  }
+
+  public boolean isValidInternalToken(String token) {
+    return this.token.equals(token);
+  }
+
+  public String createNewToken() {
+    return new BigInteger(130, random).toString(32);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/BatchRequestJob.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/BatchRequestJob.java b/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/BatchRequestJob.java
index 7405706..9fbb571 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/BatchRequestJob.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/BatchRequestJob.java
@@ -17,29 +17,44 @@
  */
 package org.apache.ambari.server.state.scheduler;
 
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
 import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.actionmanager.HostRoleStatus;
 import org.apache.ambari.server.scheduler.AbstractLinearExecutionJob;
 import org.apache.ambari.server.scheduler.ExecutionScheduleManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.Map;
 
 public class BatchRequestJob extends AbstractLinearExecutionJob {
+  private static final Logger LOG = LoggerFactory.getLogger(BatchRequestJob.class);
+
   public static final String BATCH_REQUEST_EXECUTION_ID_KEY =
     "BatchRequestJob.ExecutionId";
   public static final String BATCH_REQUEST_BATCH_ID_KEY =
     "BatchRequestJob.BatchId";
+  public static final String BATCH_REQUEST_CLUSTER_NAME_KEY =
+      "BatchRequestJob.ClusterName";
+
+  private final long statusCheckInterval;
 
-  public BatchRequestJob(ExecutionScheduleManager executionScheduleManager) {
+  @Inject
+  public BatchRequestJob(ExecutionScheduleManager executionScheduleManager,
+                         @Named("statusCheckInterval") long statusCheckInterval) {
     super(executionScheduleManager);
+    this.statusCheckInterval = statusCheckInterval;
   }
 
   @Override
   protected void doWork(Map<String, Object> properties) throws AmbariException {
 
-    String executionId = properties.get(BATCH_REQUEST_EXECUTION_ID_KEY) != null ?
-      (String) properties.get(BATCH_REQUEST_EXECUTION_ID_KEY) : null;
-    String batchId = properties.get(BATCH_REQUEST_BATCH_ID_KEY) != null ?
-      (String) properties.get(BATCH_REQUEST_BATCH_ID_KEY) : null;
+    Long executionId = properties.get(BATCH_REQUEST_EXECUTION_ID_KEY) != null ?
+      (Long) properties.get(BATCH_REQUEST_EXECUTION_ID_KEY) : null;
+    Long batchId = properties.get(BATCH_REQUEST_BATCH_ID_KEY) != null ?
+      (Long) properties.get(BATCH_REQUEST_BATCH_ID_KEY) : null;
+    String clusterName = (String) properties.get(BATCH_REQUEST_CLUSTER_NAME_KEY);
 
 
     if (executionId == null || batchId == null) {
@@ -49,13 +64,26 @@ public class BatchRequestJob extends AbstractLinearExecutionJob {
     }
 
     Long requestId = executionScheduleManager.executeBatchRequest
-      (Long.parseLong(executionId), Long.parseLong(batchId));
+      (executionId, batchId, clusterName);
 
     if (requestId != null) {
-      // Wait on request completion
+      HostRoleStatus status;
+      do {
+        BatchRequestResponse batchRequestResponse =
+            executionScheduleManager.getBatchRequestResponse(requestId, clusterName);
+
+        status = HostRoleStatus.valueOf(batchRequestResponse.getStatus());
+
+        executionScheduleManager.updateBatchRequest(executionId, batchId, clusterName, batchRequestResponse, true);
 
-      BatchRequestResponse batchRequestResponse =
-        executionScheduleManager.getBatchRequestResponse(requestId);
+        try {
+          Thread.sleep(statusCheckInterval);
+        } catch (InterruptedException e) {
+          String message = "Job Thread interrupted";
+          LOG.error(message, e);
+          throw new AmbariException(message, e);
+        }
+      } while (!status.isCompletedState());
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/BatchRequestResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/BatchRequestResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/BatchRequestResponse.java
index 2710ffa..59a45fd 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/BatchRequestResponse.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/BatchRequestResponse.java
@@ -23,4 +23,42 @@ package org.apache.ambari.server.state.scheduler;
  * tolerance calculations
  */
 public class BatchRequestResponse {
+
+  private Long requestId;
+  private String status;
+  private int returnCode;
+  private String returnMessage;
+
+
+  public Long getRequestId() {
+    return requestId;
+  }
+
+  public void setRequestId(Long requestId) {
+    this.requestId = requestId;
+  }
+
+  public String getStatus() {
+    return status;
+  }
+
+  public void setStatus(String status) {
+    this.status = status;
+  }
+
+  public int getReturnCode() {
+    return returnCode;
+  }
+
+  public void setReturnCode(int returnCode) {
+    this.returnCode = returnCode;
+  }
+
+  public String getReturnMessage() {
+    return returnMessage;
+  }
+
+  public void setReturnMessage(String returnMessage) {
+    this.returnMessage = returnMessage;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/GuiceJobFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/GuiceJobFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/GuiceJobFactory.java
new file mode 100644
index 0000000..5756853
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/GuiceJobFactory.java
@@ -0,0 +1,42 @@
+/*
+ * 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.ambari.server.state.scheduler;
+
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import org.quartz.Job;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+import org.quartz.spi.JobFactory;
+import org.quartz.spi.TriggerFiredBundle;
+
+public class GuiceJobFactory implements JobFactory {
+
+  private final Injector injector;
+
+  @Inject
+  public GuiceJobFactory(Injector injector) {
+    this.injector = injector;
+  }
+
+  @Override
+  public Job newJob(TriggerFiredBundle bundle, Scheduler scheduler) throws SchedulerException {
+    return injector.getInstance(bundle.getJobDetail().getJobClass());
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/RequestExecution.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/RequestExecution.java b/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/RequestExecution.java
index bbeece3..44e8ece 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/RequestExecution.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/RequestExecution.java
@@ -151,6 +151,19 @@ public interface RequestExecution {
   public String getRequestBody(Long batchId);
 
   /**
+   * Get batch request with specified order id
+   */
+  BatchRequest getBatchRequest(long batchId);
+
+  /**
+   * Updates batch request data
+   * @param batchId order id of batch request
+   * @param batchRequestResponse
+   * @param statusOnly true if only status should be updated
+   */
+  void updateBatchRequest(long batchId, BatchRequestResponse batchRequestResponse, boolean statusOnly);
+
+  /**
    * Status of the Request execution
    */
   public enum Status {

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/RequestExecutionImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/RequestExecutionImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/RequestExecutionImpl.java
index 8c89392..a1e7d53 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/RequestExecutionImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/RequestExecutionImpl.java
@@ -30,6 +30,7 @@ import org.apache.ambari.server.orm.dao.RequestScheduleBatchRequestDAO;
 import org.apache.ambari.server.orm.dao.RequestScheduleDAO;
 import org.apache.ambari.server.orm.entities.ClusterEntity;
 import org.apache.ambari.server.orm.entities.RequestScheduleBatchRequestEntity;
+import org.apache.ambari.server.orm.entities.RequestScheduleBatchRequestEntityPK;
 import org.apache.ambari.server.orm.entities.RequestScheduleEntity;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
@@ -412,4 +413,47 @@ public class RequestExecutionImpl implements RequestExecution {
     return body;
   }
 
+  @Override
+  public BatchRequest getBatchRequest(long batchId) {
+    for (BatchRequest batchRequest : batch.getBatchRequests()) {
+      if (batchId == batchRequest.getOrderId()) {
+        return batchRequest;
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public void updateBatchRequest(long batchId, BatchRequestResponse batchRequestResponse, boolean statusOnly) {
+    long executionId = requestScheduleEntity.getScheduleId();
+
+    RequestScheduleBatchRequestEntityPK batchRequestEntityPK = new
+        RequestScheduleBatchRequestEntityPK();
+    batchRequestEntityPK.setScheduleId(executionId);
+    batchRequestEntityPK.setBatchId(batchId);
+    RequestScheduleBatchRequestEntity batchRequestEntity =
+        batchRequestDAO.findByPk(batchRequestEntityPK);
+
+    batchRequestEntity.setRequestStatus(batchRequestResponse.getStatus());
+
+    if (!statusOnly) {
+      batchRequestEntity.setReturnCode(batchRequestResponse.getReturnCode());
+      batchRequestEntity.setRequestId(batchRequestResponse.getRequestId());
+      batchRequestEntity.setReturnMessage(batchRequestResponse.getReturnMessage());
+    }
+
+    batchRequestDAO.merge(batchRequestEntity);
+
+    BatchRequest batchRequest = getBatchRequest(batchId);
+
+    batchRequest.setStatus(batchRequestResponse.getStatus());
+
+    if (!statusOnly) {
+      batchRequest.setReturnCode(batchRequestResponse.getReturnCode());
+      batchRequest.setResponseMsg(batchRequestResponse.getReturnMessage());
+    }
+
+    setLastExecutionStatus(batchRequestResponse.getStatus());
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
index aea886a..ba6f1d4 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -41,7 +41,8 @@ CREATE TABLE users (user_id INTEGER, create_time TIMESTAMP DEFAULT NOW(), ldap_u
 CREATE TABLE execution_command (task_id BIGINT NOT NULL, command LONGBLOB, PRIMARY KEY (task_id));
 CREATE TABLE host_role_command (task_id BIGINT NOT NULL, attempt_count SMALLINT NOT NULL, event LONGTEXT NOT NULL, exitcode INTEGER NOT NULL, host_name VARCHAR(255) NOT NULL, last_attempt_time BIGINT NOT NULL, request_id BIGINT NOT NULL, role VARCHAR(255), role_command VARCHAR(255), stage_id BIGINT NOT NULL, start_time BIGINT NOT NULL, end_time BIGINT, status VARCHAR(255), std_error LONGBLOB, std_out LONGBLOB, structured_out LONGBLOB, PRIMARY KEY (task_id));
 CREATE TABLE role_success_criteria (role VARCHAR(255) NOT NULL, request_id BIGINT NOT NULL, stage_id BIGINT NOT NULL, success_factor DOUBLE NOT NULL, PRIMARY KEY (role, request_id, stage_id));
-CREATE TABLE stage (stage_id BIGINT NOT NULL, request_id BIGINT NOT NULL, cluster_id BIGINT NOT NULL, log_info VARCHAR(255) NOT NULL, request_context VARCHAR(255), cluster_host_info LONGBLOB NOT NULL, PRIMARY KEY (stage_id, request_id));
+CREATE TABLE stage (stage_id BIGINT NOT NULL, request_id BIGINT NOT NULL, cluster_id BIGINT, log_info VARCHAR(255) NOT NULL, request_context VARCHAR(255), cluster_host_info LONGBLOB, PRIMARY KEY (stage_id, request_id));
+CREATE TABLE request (request_id BIGINT NOT NULL, cluster_id BIGINT, command_name VARCHAR(255), create_time BIGINT NOT NULL, end_time BIGINT NOT NULL, inputs LONGTEXT, request_context VARCHAR(255), request_type VARCHAR(255), start_time BIGINT NOT NULL, status VARCHAR(255), target_component VARCHAR(255), target_hosts LONGTEXT, target_service VARCHAR(255), PRIMARY KEY (request_id));
 CREATE TABLE key_value_store (`key` VARCHAR(255), `value` LONGTEXT, PRIMARY KEY (`key`));
 CREATE TABLE clusterconfigmapping (type_name VARCHAR(255) NOT NULL, create_timestamp BIGINT NOT NULL, cluster_id BIGINT NOT NULL, selected INTEGER NOT NULL DEFAULT 0, version_tag VARCHAR(255) NOT NULL, user_name VARCHAR(255) NOT NULL DEFAULT '_db', PRIMARY KEY (type_name, create_timestamp, cluster_id));
 CREATE TABLE hostconfigmapping (create_timestamp BIGINT NOT NULL, host_name VARCHAR(255) NOT NULL, cluster_id BIGINT NOT NULL, type_name VARCHAR(255) NOT NULL, selected INTEGER NOT NULL DEFAULT 0, service_name VARCHAR(255), version_tag VARCHAR(255) NOT NULL, user_name VARCHAR(255) NOT NULL DEFAULT '_db', PRIMARY KEY (create_timestamp, host_name, cluster_id, type_name));
@@ -53,7 +54,7 @@ CREATE TABLE confgroupclusterconfigmapping (config_group_id BIGINT NOT NULL, clu
 CREATE TABLE configgroup (group_id BIGINT, cluster_id BIGINT NOT NULL, group_name VARCHAR(255) NOT NULL, tag VARCHAR(1024) NOT NULL, description VARCHAR(1024), create_timestamp BIGINT NOT NULL, PRIMARY KEY(group_id));
 CREATE TABLE configgrouphostmapping (config_group_id BIGINT NOT NULL, host_name VARCHAR(255) NOT NULL, PRIMARY KEY(config_group_id, host_name));
 CREATE TABLE requestschedule (schedule_id bigint, cluster_id BIGINT NOT NULL, description varchar(255), status varchar(255), batch_separation_seconds smallint, batch_toleration_limit smallint, create_user varchar(255), create_timestamp bigint, update_user varchar(255), update_timestamp bigint, minutes varchar(10), hours varchar(10), days_of_month varchar(10), month varchar(10), day_of_week varchar(10), yearToSchedule varchar(10), startTime varchar(50), endTime varchar(50), last_execution_status varchar(255), PRIMARY KEY(schedule_id));
-CREATE TABLE requestschedulebatchrequest (schedule_id bigint, batch_id bigint, request_id bigint, request_type varchar(255), request_uri varchar(1024), request_body LONGBLOB, request_status varchar(255), return_code smallint, return_message varchar(255), PRIMARY KEY(schedule_id, batch_id));
+CREATE TABLE requestschedulebatchrequest (schedule_id bigint, batch_id bigint, request_id bigint, request_type varchar(255), request_uri varchar(1024), request_body LONGBLOB, request_status varchar(255), return_code smallint, return_message varchar(2000), PRIMARY KEY(schedule_id, batch_id));
 CREATE TABLE action (action_name VARCHAR(255) NOT NULL, action_type VARCHAR(32) NOT NULL, inputs VARCHAR(1000), target_service VARCHAR(255), target_component VARCHAR(255), default_timeout SMALLINT NOT NULL, description VARCHAR(1000), target_type VARCHAR(32), PRIMARY KEY (action_name));
 
 ALTER TABLE users ADD CONSTRAINT UNQ_users_0 UNIQUE (user_name, ldap_user);
@@ -72,6 +73,8 @@ ALTER TABLE host_role_command ADD CONSTRAINT FK_host_role_command_stage_id FOREI
 ALTER TABLE host_role_command ADD CONSTRAINT FK_host_role_command_host_name FOREIGN KEY (host_name) REFERENCES hosts (host_name);
 ALTER TABLE role_success_criteria ADD CONSTRAINT FK_role_success_criteria_stage_id FOREIGN KEY (stage_id, request_id) REFERENCES stage (stage_id, request_id);
 ALTER TABLE stage ADD CONSTRAINT FK_stage_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
+ALTER TABLE stage ADD CONSTRAINT FK_stage_request_id FOREIGN KEY (request_id) REFERENCES request (request_id);
+ALTER TABLE request ADD CONSTRAINT FK_request_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
 ALTER TABLE clusterconfigmapping ADD CONSTRAINT FK_clusterconfigmapping_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
 ALTER TABLE hostconfigmapping ADD CONSTRAINT FK_hostconfigmapping_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
 ALTER TABLE hostconfigmapping ADD CONSTRAINT FK_hostconfigmapping_host_name FOREIGN KEY (host_name) REFERENCES hosts (host_name);

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
index 9246c4a..4dcd37f 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -32,6 +32,7 @@ CREATE TABLE execution_command (task_id NUMBER(19) NOT NULL, command BLOB NULL,
 CREATE TABLE host_role_command (task_id NUMBER(19) NOT NULL, attempt_count NUMBER(5) NOT NULL, event CLOB NULL, exitcode NUMBER(10) NOT NULL, host_name VARCHAR2(255) NOT NULL, last_attempt_time NUMBER(19) NOT NULL, request_id NUMBER(19) NOT NULL, role VARCHAR2(255) NULL, role_command VARCHAR2(255) NULL, stage_id NUMBER(19) NOT NULL, start_time NUMBER(19) NOT NULL, end_time NUMBER(19), status VARCHAR2(255) NULL, std_error BLOB NULL, std_out BLOB NULL, structured_out BLOB NULL, PRIMARY KEY (task_id));
 CREATE TABLE role_success_criteria (role VARCHAR2(255) NOT NULL, request_id NUMBER(19) NOT NULL, stage_id NUMBER(19) NOT NULL, success_factor NUMBER(19,4) NOT NULL, PRIMARY KEY (role, request_id, stage_id));
 CREATE TABLE stage (stage_id NUMBER(19) NOT NULL, request_id NUMBER(19) NOT NULL, cluster_id NUMBER(19) NULL, log_info VARCHAR2(255) NULL, request_context VARCHAR2(255) NULL, cluster_host_info BLOB NOT NULL, PRIMARY KEY (stage_id, request_id));
+CREATE TABLE request (request_id NUMBER(19) NOT NULL, cluster_id NUMBER(19), command_name VARCHAR(255), create_time NUMBER(19) NOT NULL, end_time NUMBER(19) NOT NULL, inputs CLOB, request_context VARCHAR(255), request_type VARCHAR(255), start_time NUMBER(19) NOT NULL, status VARCHAR(255), target_component VARCHAR(255), target_hosts CLOB, target_service VARCHAR(255), PRIMARY KEY (request_id));
 CREATE TABLE key_value_store ("key" VARCHAR2(255) NOT NULL, "value" CLOB NULL, PRIMARY KEY ("key"));
 CREATE TABLE clusterconfigmapping (type_name VARCHAR2(255) NOT NULL, create_timestamp NUMBER(19) NOT NULL, cluster_id NUMBER(19) NOT NULL, selected NUMBER(10) NOT NULL, version_tag VARCHAR2(255) NOT NULL, user_name VARCHAR(255) DEFAULT '_db', PRIMARY KEY (type_name, create_timestamp, cluster_id));
 CREATE TABLE hostconfigmapping (create_timestamp NUMBER(19) NOT NULL, host_name VARCHAR2(255) NOT NULL, cluster_id NUMBER(19) NOT NULL, type_name VARCHAR2(255) NOT NULL, selected NUMBER(10) NOT NULL, service_name VARCHAR2(255) NULL, version_tag VARCHAR2(255) NOT NULL, user_name VARCHAR(255) DEFAULT '_db', PRIMARY KEY (create_timestamp, host_name, cluster_id, type_name));
@@ -44,7 +45,7 @@ CREATE TABLE confgroupclusterconfigmapping (config_group_id NUMBER(19) NOT NULL,
 CREATE TABLE configgrouphostmapping (config_group_id NUMBER(19) NOT NULL, host_name VARCHAR2(255) NOT NULL, PRIMARY KEY(config_group_id, host_name));
 CREATE TABLE action (action_name VARCHAR2(255) NOT NULL, action_type VARCHAR2(255) NOT NULL, inputs VARCHAR2(1024), target_service VARCHAR2(255), target_component VARCHAR2(255), default_timeout NUMBER(10) NOT NULL, description VARCHAR2(1024), target_type VARCHAR2(255), PRIMARY KEY (action_name));
 CREATE TABLE ambari.requestschedule (schedule_id NUMBER(19), cluster_id NUMBER(19) NOT NULL, description VARCHAR2(255), status VARCHAR2(255), batch_separation_seconds smallint, batch_toleration_limit smallint, create_user VARCHAR2(255), create_timestamp NUMBER(19), update_user VARCHAR2(255), update_timestamp NUMBER(19), minutes VARCHAR2(10), hours VARCHAR2(10), days_of_month VARCHAR2(10), month VARCHAR2(10), day_of_week VARCHAR2(10), yearToSchedule VARCHAR2(10), startTime VARCHAR2(50), endTime VARCHAR2(50), last_execution_status VARCHAR2(255), PRIMARY KEY(schedule_id));
-CREATE TABLE ambari.requestschedulebatchrequest (schedule_id NUMBER(19), batch_id NUMBER(19), request_id NUMBER(19), request_type VARCHAR2(255), request_uri VARCHAR2(1024), request_body BLOB, request_status VARCHAR2(255), return_code smallint, return_message VARCHAR2(255), PRIMARY KEY(schedule_id, batch_id));
+CREATE TABLE ambari.requestschedulebatchrequest (schedule_id NUMBER(19), batch_id NUMBER(19), request_id NUMBER(19), request_type VARCHAR2(255), request_uri VARCHAR2(1024), request_body BLOB, request_status VARCHAR2(255), return_code smallint, return_message VARCHAR2(2000), PRIMARY KEY(schedule_id, batch_id));
 
 ALTER TABLE users ADD CONSTRAINT UNQ_users_0 UNIQUE (user_name, ldap_user);
 ALTER TABLE clusterconfig ADD CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
@@ -62,6 +63,8 @@ ALTER TABLE host_role_command ADD CONSTRAINT FK_host_role_command_stage_id FOREI
 ALTER TABLE host_role_command ADD CONSTRAINT FK_host_role_command_host_name FOREIGN KEY (host_name) REFERENCES hosts (host_name);
 ALTER TABLE role_success_criteria ADD CONSTRAINT role_success_criteria_stage_id FOREIGN KEY (stage_id, request_id) REFERENCES stage (stage_id, request_id);
 ALTER TABLE stage ADD CONSTRAINT FK_stage_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
+ALTER TABLE stage ADD CONSTRAINT FK_stage_request_id FOREIGN KEY (request_id) REFERENCES request (request_id);
+ALTER TABLE request ADD CONSTRAINT FK_request_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
 ALTER TABLE clusterconfigmapping ADD CONSTRAINT clusterconfigmappingcluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
 ALTER TABLE ClusterHostMapping ADD CONSTRAINT ClusterHostMapping_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
 ALTER TABLE ClusterHostMapping ADD CONSTRAINT ClusterHostMapping_host_name FOREIGN KEY (host_name) REFERENCES hosts (host_name);

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
index fdb6eb5..2bdb174 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -79,6 +79,9 @@ GRANT ALL PRIVILEGES ON TABLE ambari.role_success_criteria TO :username;
 CREATE TABLE ambari.stage (stage_id BIGINT NOT NULL, request_id BIGINT NOT NULL, cluster_id BIGINT NOT NULL, log_info VARCHAR(255) NOT NULL, request_context VARCHAR(255), cluster_host_info BYTEA NOT NULL, PRIMARY KEY (stage_id, request_id));
 GRANT ALL PRIVILEGES ON TABLE ambari.stage TO :username;
 
+CREATE TABLE ambari.request (request_id BIGINT NOT NULL, cluster_id BIGINT, command_name VARCHAR(255), create_time BIGINT NOT NULL, end_time BIGINT NOT NULL, inputs VARCHAR(32000), request_context VARCHAR(255), request_type VARCHAR(255), start_time BIGINT NOT NULL, status VARCHAR(255), target_component VARCHAR(255), target_hosts TEXT, target_service VARCHAR(255), PRIMARY KEY (request_id));
+GRANT ALL PRIVILEGES ON TABLE ambari.request TO :username;
+
 CREATE TABLE ambari.ClusterHostMapping (cluster_id BIGINT NOT NULL, host_name VARCHAR(255) NOT NULL, PRIMARY KEY (cluster_id, host_name));
 GRANT ALL PRIVILEGES ON TABLE ambari.ClusterHostMapping TO :username;
 
@@ -113,7 +116,7 @@ GRANT ALL PRIVILEGES ON TABLE ambari.action TO :username;
 CREATE TABLE ambari.requestschedule (schedule_id bigint, cluster_id bigint NOT NULL, description varchar(255), status varchar(255), batch_separation_seconds smallint, batch_toleration_limit smallint, create_user varchar(255), create_timestamp bigint, update_user varchar(255), update_timestamp bigint, minutes varchar(10), hours varchar(10), days_of_month varchar(10), month varchar(10), day_of_week varchar(10), yearToSchedule varchar(10), startTime varchar(50), endTime varchar(50), last_execution_status varchar(255), PRIMARY KEY(schedule_id));
 GRANT ALL PRIVILEGES ON TABLE ambari.requestschedule TO :username;
 
-CREATE TABLE ambari.requestschedulebatchrequest (schedule_id bigint, batch_id bigint, request_id bigint, request_type varchar(255), request_uri varchar(1024), request_body BYTEA, request_status varchar(255), return_code smallint, return_message varchar(255), PRIMARY KEY(schedule_id, batch_id));
+CREATE TABLE ambari.requestschedulebatchrequest (schedule_id bigint, batch_id bigint, request_id bigint, request_type varchar(255), request_uri varchar(1024), request_body BYTEA, request_status varchar(255), return_code smallint, return_message varchar(20000), PRIMARY KEY(schedule_id, batch_id));
 GRANT ALL PRIVILEGES ON TABLE ambari.requestschedulebatchrequest TO :username;
 
 --------altering tables by creating foreign keys----------
@@ -133,6 +136,8 @@ ALTER TABLE ambari.host_role_command ADD CONSTRAINT FK_host_role_command_stage_i
 ALTER TABLE ambari.host_role_command ADD CONSTRAINT FK_host_role_command_host_name FOREIGN KEY (host_name) REFERENCES ambari.hosts (host_name);
 ALTER TABLE ambari.role_success_criteria ADD CONSTRAINT FK_role_success_criteria_stage_id FOREIGN KEY (stage_id, request_id) REFERENCES ambari.stage (stage_id, request_id);
 ALTER TABLE ambari.stage ADD CONSTRAINT FK_stage_cluster_id FOREIGN KEY (cluster_id) REFERENCES ambari.clusters (cluster_id);
+ALTER TABLE ambari.stage ADD CONSTRAINT FK_stage_request_id FOREIGN KEY (request_id) REFERENCES ambari.request (request_id);
+ALTER TABLE ambari.request ADD CONSTRAINT FK_request_cluster_id FOREIGN KEY (cluster_id) REFERENCES ambari.clusters (cluster_id);
 ALTER TABLE ambari.ClusterHostMapping ADD CONSTRAINT FK_ClusterHostMapping_host_name FOREIGN KEY (host_name) REFERENCES ambari.hosts (host_name);
 ALTER TABLE ambari.ClusterHostMapping ADD CONSTRAINT FK_ClusterHostMapping_cluster_id FOREIGN KEY (cluster_id) REFERENCES ambari.clusters (cluster_id);
 ALTER TABLE ambari.user_roles ADD CONSTRAINT FK_user_roles_user_id FOREIGN KEY (user_id) REFERENCES ambari.users (user_id);
@@ -176,7 +181,7 @@ COMMIT;
 
 -- Quartz tables
 
-CREATE TABLE qrtz_job_details
+CREATE TABLE ambari.qrtz_job_details
   (
     SCHED_NAME VARCHAR(120) NOT NULL,
     JOB_NAME  VARCHAR(200) NOT NULL,
@@ -190,8 +195,9 @@ CREATE TABLE qrtz_job_details
     JOB_DATA BYTEA NULL,
     PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
 );
+GRANT ALL PRIVILEGES ON TABLE ambari.qrtz_job_details TO :username;
 
-CREATE TABLE qrtz_triggers
+CREATE TABLE ambari.qrtz_triggers
   (
     SCHED_NAME VARCHAR(120) NOT NULL,
     TRIGGER_NAME VARCHAR(200) NOT NULL,
@@ -211,10 +217,11 @@ CREATE TABLE qrtz_triggers
     JOB_DATA BYTEA NULL,
     PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
     FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
-	REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)
+	REFERENCES ambari.QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)
 );
+GRANT ALL PRIVILEGES ON TABLE ambari.qrtz_triggers TO :username;
 
-CREATE TABLE qrtz_simple_triggers
+CREATE TABLE ambari.qrtz_simple_triggers
   (
     SCHED_NAME VARCHAR(120) NOT NULL,
     TRIGGER_NAME VARCHAR(200) NOT NULL,
@@ -224,10 +231,11 @@ CREATE TABLE qrtz_simple_triggers
     TIMES_TRIGGERED BIGINT NOT NULL,
     PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
     FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
-	REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+	REFERENCES ambari.QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
 );
+GRANT ALL PRIVILEGES ON TABLE ambari.qrtz_simple_triggers TO :username;
 
-CREATE TABLE qrtz_cron_triggers
+CREATE TABLE ambari.qrtz_cron_triggers
   (
     SCHED_NAME VARCHAR(120) NOT NULL,
     TRIGGER_NAME VARCHAR(200) NOT NULL,
@@ -236,10 +244,11 @@ CREATE TABLE qrtz_cron_triggers
     TIME_ZONE_ID VARCHAR(80),
     PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
     FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
-	REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+	REFERENCES ambari.QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
 );
+GRANT ALL PRIVILEGES ON TABLE ambari.qrtz_cron_triggers TO :username;
 
-CREATE TABLE qrtz_simprop_triggers
+CREATE TABLE ambari.qrtz_simprop_triggers
   (
     SCHED_NAME VARCHAR(120) NOT NULL,
     TRIGGER_NAME VARCHAR(200) NOT NULL,
@@ -257,10 +266,11 @@ CREATE TABLE qrtz_simprop_triggers
     BOOL_PROP_2 BOOL NULL,
     PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
     FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
-    REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+    REFERENCES ambari.QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
 );
+GRANT ALL PRIVILEGES ON TABLE ambari.qrtz_simprop_triggers TO :username;
 
-CREATE TABLE qrtz_blob_triggers
+CREATE TABLE ambari.qrtz_blob_triggers
   (
     SCHED_NAME VARCHAR(120) NOT NULL,
     TRIGGER_NAME VARCHAR(200) NOT NULL,
@@ -268,26 +278,29 @@ CREATE TABLE qrtz_blob_triggers
     BLOB_DATA BYTEA NULL,
     PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
     FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
-        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+        REFERENCES ambari.QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
 );
+GRANT ALL PRIVILEGES ON TABLE ambari.qrtz_blob_triggers TO :username;
 
-CREATE TABLE qrtz_calendars
+CREATE TABLE ambari.qrtz_calendars
   (
     SCHED_NAME VARCHAR(120) NOT NULL,
     CALENDAR_NAME  VARCHAR(200) NOT NULL,
     CALENDAR BYTEA NOT NULL,
     PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
 );
+GRANT ALL PRIVILEGES ON TABLE ambari.qrtz_calendars TO :username;
 
 
-CREATE TABLE qrtz_paused_trigger_grps
+CREATE TABLE ambari.qrtz_paused_trigger_grps
   (
     SCHED_NAME VARCHAR(120) NOT NULL,
     TRIGGER_GROUP  VARCHAR(200) NOT NULL,
     PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
 );
+GRANT ALL PRIVILEGES ON TABLE ambari.qrtz_paused_trigger_grps TO :username;
 
-CREATE TABLE qrtz_fired_triggers
+CREATE TABLE ambari.qrtz_fired_triggers
   (
     SCHED_NAME VARCHAR(120) NOT NULL,
     ENTRY_ID VARCHAR(95) NOT NULL,
@@ -304,8 +317,9 @@ CREATE TABLE qrtz_fired_triggers
     REQUESTS_RECOVERY BOOL NULL,
     PRIMARY KEY (SCHED_NAME,ENTRY_ID)
 );
+GRANT ALL PRIVILEGES ON TABLE ambari.qrtz_fired_triggers TO :username;
 
-CREATE TABLE qrtz_scheduler_state
+CREATE TABLE ambari.qrtz_scheduler_state
   (
     SCHED_NAME VARCHAR(120) NOT NULL,
     INSTANCE_NAME VARCHAR(200) NOT NULL,
@@ -313,36 +327,38 @@ CREATE TABLE qrtz_scheduler_state
     CHECKIN_INTERVAL BIGINT NOT NULL,
     PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
 );
+GRANT ALL PRIVILEGES ON TABLE ambari.qrtz_scheduler_state TO :username;
 
-CREATE TABLE qrtz_locks
+CREATE TABLE ambari.qrtz_locks
   (
     SCHED_NAME VARCHAR(120) NOT NULL,
     LOCK_NAME  VARCHAR(40) NOT NULL,
     PRIMARY KEY (SCHED_NAME,LOCK_NAME)
 );
-
-create index idx_qrtz_j_req_recovery on qrtz_job_details(SCHED_NAME,REQUESTS_RECOVERY);
-create index idx_qrtz_j_grp on qrtz_job_details(SCHED_NAME,JOB_GROUP);
-
-create index idx_qrtz_t_j on qrtz_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP);
-create index idx_qrtz_t_jg on qrtz_triggers(SCHED_NAME,JOB_GROUP);
-create index idx_qrtz_t_c on qrtz_triggers(SCHED_NAME,CALENDAR_NAME);
-create index idx_qrtz_t_g on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP);
-create index idx_qrtz_t_state on qrtz_triggers(SCHED_NAME,TRIGGER_STATE);
-create index idx_qrtz_t_n_state on qrtz_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
-create index idx_qrtz_t_n_g_state on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
-create index idx_qrtz_t_next_fire_time on qrtz_triggers(SCHED_NAME,NEXT_FIRE_TIME);
-create index idx_qrtz_t_nft_st on qrtz_triggers(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
-create index idx_qrtz_t_nft_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
-create index idx_qrtz_t_nft_st_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
-create index idx_qrtz_t_nft_st_misfire_grp on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
-
-create index idx_qrtz_ft_trig_inst_name on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME);
-create index idx_qrtz_ft_inst_job_req_rcvry on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
-create index idx_qrtz_ft_j_g on qrtz_fired_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP);
-create index idx_qrtz_ft_jg on qrtz_fired_triggers(SCHED_NAME,JOB_GROUP);
-create index idx_qrtz_ft_t_g on qrtz_fired_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
-create index idx_qrtz_ft_tg on qrtz_fired_triggers(SCHED_NAME,TRIGGER_GROUP);
+GRANT ALL PRIVILEGES ON TABLE ambari.qrtz_locks TO :username;
+
+create index idx_qrtz_j_req_recovery on ambari.qrtz_job_details(SCHED_NAME,REQUESTS_RECOVERY);
+create index idx_qrtz_j_grp on ambari.qrtz_job_details(SCHED_NAME,JOB_GROUP);
+
+create index idx_qrtz_t_j on ambari.qrtz_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP);
+create index idx_qrtz_t_jg on ambari.qrtz_triggers(SCHED_NAME,JOB_GROUP);
+create index idx_qrtz_t_c on ambari.qrtz_triggers(SCHED_NAME,CALENDAR_NAME);
+create index idx_qrtz_t_g on ambari.qrtz_triggers(SCHED_NAME,TRIGGER_GROUP);
+create index idx_qrtz_t_state on ambari.qrtz_triggers(SCHED_NAME,TRIGGER_STATE);
+create index idx_qrtz_t_n_state on ambari.qrtz_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
+create index idx_qrtz_t_n_g_state on ambari.qrtz_triggers(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
+create index idx_qrtz_t_next_fire_time on ambari.qrtz_triggers(SCHED_NAME,NEXT_FIRE_TIME);
+create index idx_qrtz_t_nft_st on ambari.qrtz_triggers(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
+create index idx_qrtz_t_nft_misfire on ambari.qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
+create index idx_qrtz_t_nft_st_misfire on ambari.qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
+create index idx_qrtz_t_nft_st_misfire_grp on ambari.qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
+
+create index idx_qrtz_ft_trig_inst_name on ambari.qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME);
+create index idx_qrtz_ft_inst_job_req_rcvry on ambari.qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
+create index idx_qrtz_ft_j_g on ambari.qrtz_fired_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP);
+create index idx_qrtz_ft_jg on ambari.qrtz_fired_triggers(SCHED_NAME,JOB_GROUP);
+create index idx_qrtz_ft_t_g on ambari.qrtz_fired_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
+create index idx_qrtz_ft_tg on ambari.qrtz_fired_triggers(SCHED_NAME,TRIGGER_GROUP);
 
 commit;
 
@@ -438,4 +454,4 @@ CREATE TABLE clusterEvent (
   error     TEXT, data TEXT,
   host      TEXT, rack TEXT
 );
-GRANT ALL PRIVILEGES ON TABLE clusterEvent TO "mapred";
\ No newline at end of file
+GRANT ALL PRIVILEGES ON TABLE clusterEvent TO "mapred";

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/resources/Ambari-DDL-Postgres-REMOTE-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-REMOTE-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-REMOTE-CREATE.sql
index 4ecc697..7c77d61 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-REMOTE-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-REMOTE-CREATE.sql
@@ -36,6 +36,7 @@ CREATE TABLE ambari.execution_command (command bytea, task_id BIGINT NOT NULL, P
 CREATE TABLE ambari.host_role_command (task_id BIGINT NOT NULL, attempt_count SMALLINT NOT NULL, event VARCHAR(32000) NOT NULL, exitcode INTEGER NOT NULL, host_name VARCHAR(255) NOT NULL, last_attempt_time BIGINT NOT NULL, request_id BIGINT NOT NULL, role VARCHAR(255), stage_id BIGINT NOT NULL, start_time BIGINT NOT NULL, end_time BIGINT, status VARCHAR(255), std_error BYTEA, std_out BYTEA, structured_out BYTEA, role_command VARCHAR(255), PRIMARY KEY (task_id));
 CREATE TABLE ambari.role_success_criteria (role VARCHAR(255) NOT NULL, request_id BIGINT NOT NULL, stage_id BIGINT NOT NULL, success_factor FLOAT NOT NULL, PRIMARY KEY (role, request_id, stage_id));
 CREATE TABLE ambari.stage (stage_id BIGINT NOT NULL, request_id BIGINT NOT NULL, cluster_id BIGINT NOT NULL, log_info VARCHAR(255) NOT NULL, request_context VARCHAR(255), PRIMARY KEY (stage_id, request_id));
+CREATE TABLE ambari.request (request_id BIGINT NOT NULL, cluster_id BIGINT, command_name VARCHAR(255), create_time BIGINT NOT NULL, end_time BIGINT NOT NULL, inputs VARCHAR(32000), request_context VARCHAR(255), request_type VARCHAR(255), start_time BIGINT NOT NULL, status VARCHAR(255), target_component VARCHAR(255), target_hosts TEXT, target_service VARCHAR(255), PRIMARY KEY (request_id));
 CREATE TABLE ambari.ClusterHostMapping (cluster_id BIGINT NOT NULL, host_name VARCHAR(255) NOT NULL, PRIMARY KEY (cluster_id, host_name));
 CREATE TABLE ambari.user_roles (role_name VARCHAR(255) NOT NULL, user_id INTEGER NOT NULL, PRIMARY KEY (role_name, user_id));
 CREATE TABLE ambari.key_value_store ("key" VARCHAR(255), "value" VARCHAR, PRIMARY KEY("key"));
@@ -46,7 +47,7 @@ CREATE TABLE ambari.configgroup (group_id BIGINT, cluster_id BIGINT NOT NULL, gr
 CREATE TABLE ambari.confgroupclusterconfigmapping (config_group_id BIGINT NOT NULL, cluster_id BIGINT NOT NULL, config_type VARCHAR(255) NOT NULL, version_tag VARCHAR(255) NOT NULL, user_name VARCHAR(255) DEFAULT '_db', create_timestamp BIGINT NOT NULL, PRIMARY KEY(config_group_id, cluster_id, config_type));
 CREATE TABLE ambari.configgrouphostmapping (config_group_id BIGINT NOT NULL, host_name VARCHAR(255) NOT NULL, PRIMARY KEY(config_group_id, host_name));
 CREATE TABLE ambari.requestschedule (schedule_id bigint, cluster_id BIGINT NOT NULL, status varchar(255), batch_separation_seconds smallint, batch_toleration_limit smallint, create_user varchar(255), create_timestamp bigint, update_user varchar(255), update_timestamp bigint, minutes varchar(10), hours varchar(10), days_of_month varchar(10), month varchar(10), day_of_week varchar(10), yearToSchedule varchar(10), startTime varchar(50), endTime varchar(50), last_execution_status varchar(255), PRIMARY KEY(schedule_id));
-CREATE TABLE ambari.requestschedulebatchrequest (schedule_id bigint, batch_id bigint, request_id bigint, request_type varchar(255), request_uri varchar(1024), request_body BYTEA, request_status varchar(255), return_code smallint, return_message varchar(255), PRIMARY KEY(schedule_id, batch_id));
+CREATE TABLE ambari.requestschedulebatchrequest (schedule_id bigint, batch_id bigint, request_id bigint, request_type varchar(255), request_uri varchar(1024), request_body BYTEA, request_status varchar(255), return_code smallint, return_message varchar(2000), PRIMARY KEY(schedule_id, batch_id));
 
 ALTER TABLE ambari.clusterconfig ADD CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY (cluster_id) REFERENCES ambari.clusters (cluster_id);
 ALTER TABLE ambari.clusterservices ADD CONSTRAINT FK_clusterservices_cluster_id FOREIGN KEY (cluster_id) REFERENCES ambari.clusters (cluster_id);
@@ -64,6 +65,8 @@ ALTER TABLE ambari.host_role_command ADD CONSTRAINT FK_host_role_command_stage_i
 ALTER TABLE ambari.host_role_command ADD CONSTRAINT FK_host_role_command_host_name FOREIGN KEY (host_name) REFERENCES ambari.hosts (host_name);
 ALTER TABLE ambari.role_success_criteria ADD CONSTRAINT FK_role_success_criteria_stage_id FOREIGN KEY (stage_id, request_id) REFERENCES ambari.stage (stage_id, request_id);
 ALTER TABLE ambari.stage ADD CONSTRAINT FK_stage_cluster_id FOREIGN KEY (cluster_id) REFERENCES ambari.clusters (cluster_id);
+ALTER TABLE ambari.stage ADD CONSTRAINT FK_stage_request_id FOREIGN KEY (request_id) REFERENCES request (request_id);
+ALTER TABLE ambari.request ADD CONSTRAINT FK_request_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
 ALTER TABLE ambari.ClusterHostMapping ADD CONSTRAINT FK_ClusterHostMapping_host_name FOREIGN KEY (host_name) REFERENCES ambari.hosts (host_name);
 ALTER TABLE ambari.ClusterHostMapping ADD CONSTRAINT FK_ClusterHostMapping_cluster_id FOREIGN KEY (cluster_id) REFERENCES ambari.clusters (cluster_id);
 ALTER TABLE ambari.user_roles ADD CONSTRAINT FK_user_roles_user_id FOREIGN KEY (user_id) REFERENCES ambari.users (user_id);
@@ -348,4 +351,4 @@ CREATE TABLE clusterEvent (
   service TEXT, status TEXT,
   error TEXT, data TEXT ,
   host TEXT, rack TEXT
-);
\ No newline at end of file
+);

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/resources/META-INF/persistence.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/META-INF/persistence.xml b/ambari-server/src/main/resources/META-INF/persistence.xml
index 6c8a5d6..3b07bd7 100644
--- a/ambari-server/src/main/resources/META-INF/persistence.xml
+++ b/ambari-server/src/main/resources/META-INF/persistence.xml
@@ -30,6 +30,7 @@
     <class>org.apache.ambari.server.orm.entities.HostRoleCommandEntity</class>
     <class>org.apache.ambari.server.orm.entities.RoleSuccessCriteriaEntity</class>
     <class>org.apache.ambari.server.orm.entities.StageEntity</class>
+    <class>org.apache.ambari.server.orm.entities.RequestEntity</class>
     <class>org.apache.ambari.server.orm.entities.KeyValueEntity</class>
     <class>org.apache.ambari.server.orm.entities.ClusterConfigMappingEntity</class>
     <class>org.apache.ambari.server.orm.entities.HostConfigMappingEntity</class>
@@ -47,6 +48,8 @@
       <property name="eclipselink.cache.size.default" value="10000" />
       <property name="eclipselink.jdbc.batch-writing" value="JDBC"/>
       <property name="eclipselink.weaving" value="static" />
+      <!--<property name="eclipselink.id-validation" value="NULL" />-->
+
     </properties>
   </persistence-unit>
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/resources/properties.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/properties.json b/ambari-server/src/main/resources/properties.json
index 9c9529f..52c0a20 100644
--- a/ambari-server/src/main/resources/properties.json
+++ b/ambari-server/src/main/resources/properties.json
@@ -96,6 +96,14 @@
         "Requests/cluster_name",
         "Requests/request_status",
         "Requests/request_context",
+        "Requests/type",
+        "Requests/inputs",
+        "Requests/target_service",
+        "Requests/target_component",
+        "Requests/target_hosts",
+        "Requests/create_time",
+        "Requests/start_time",
+        "Requests/end_time",
         "Requests/task_count",
         "Requests/failed_task_count",
         "Requests/aborted_task_count",

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/resources/webapp/WEB-INF/spring-security.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/webapp/WEB-INF/spring-security.xml b/ambari-server/src/main/resources/webapp/WEB-INF/spring-security.xml
index 6a722d5..bb232b7 100644
--- a/ambari-server/src/main/resources/webapp/WEB-INF/spring-security.xml
+++ b/ambari-server/src/main/resources/webapp/WEB-INF/spring-security.xml
@@ -27,6 +27,7 @@
     <http-basic entry-point-ref="ambariEntryPoint"/>
     <intercept-url pattern="/**" access="isAuthenticated()" method="GET"/>
     <intercept-url pattern="/**" access="hasRole('ADMIN')"/>
+    <custom-filter ref="internalTokenAuthenticationFilter" after="BASIC_AUTH_FILTER"/>
   </http>
 
   <!--<ldap-server id="ldapServer" root="dc=ambari,dc=apache,dc=org"/>-->
@@ -39,8 +40,10 @@
 
     <authentication-provider ref="ambariLdapAuthenticationProvider"/>
 
+    <authentication-provider ref="ambariInternalAuthenticationProvider"/>
+
   </authentication-manager>
 
   <beans:bean id="ambariEntryPoint" class="org.apache.ambari.server.security.AmbariEntryPoint">
   </beans:bean>
-</beans:beans>
\ No newline at end of file
+</beans:beans>

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapperTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapperTest.java b/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapperTest.java
index 62e3c88..183c126 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapperTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapperTest.java
@@ -160,7 +160,8 @@ public class ExecutionCommandWrapperTest {
             hostName, System.currentTimeMillis()), clusterName, "HDFS");
     List<Stage> stages = new ArrayList<Stage>();
     stages.add(s);
-    db.persistActions(stages);
+    Request request = new Request(stages, clusters);
+    db.persistActions(request);
   }
   
   @Test

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionDBAccessorImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionDBAccessorImpl.java b/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionDBAccessorImpl.java
index d8042ae..6f8c884 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionDBAccessorImpl.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionDBAccessorImpl.java
@@ -83,7 +83,7 @@ public class TestActionDBAccessorImpl {
     cdb = injector.getInstance(CustomActionDBAccessor.class);
 
     am = new ActionManager(5000, 1200000, new ActionQueue(), clusters, db,
-        new HostsMap((String) null), null, injector.getInstance(UnitOfWork.class), cdb);
+        new HostsMap((String) null), null, injector.getInstance(UnitOfWork.class), cdb, injector.getInstance(RequestFactory.class));
   }
 
   @After
@@ -121,9 +121,13 @@ public class TestActionDBAccessorImpl {
   @Test
   public void testGetStagesInProgress() {
     String hostname = "host1";
-    populateActionDB(db, hostname, requestId, stageId);
-    populateActionDB(db, hostname, requestId, stageId+1);
-    List<Stage> stages = db.getStagesInProgress();
+    List<Stage> stages = new ArrayList<Stage>();
+    stages.add(createStubStage(hostname, requestId, stageId));
+    stages.add(createStubStage(hostname, requestId, stageId + 1));
+    Request request = new Request(stages, clusters);
+    db.persistActions(request);
+
+    List<Stage> stages2 = db.getStagesInProgress();
     assertEquals(2, stages.size());
   }
   
@@ -314,7 +318,8 @@ public class TestActionDBAccessorImpl {
     String hostName = cmd.getHostName();
     cmd.setStatus(HostRoleStatus.COMPLETED);
 
-    db.persistActions(stages);
+    Request request = new Request(stages, clusters);
+    db.persistActions(request);
     db.abortOperation(requestId);
 
     List<HostRoleCommand> commands = db.getRequestTasks(requestId);
@@ -329,6 +334,14 @@ public class TestActionDBAccessorImpl {
 
   private void populateActionDB(ActionDBAccessor db, String hostname,
       long requestId, long stageId) {
+    Stage s = createStubStage(hostname, requestId, stageId);
+    List<Stage> stages = new ArrayList<Stage>();
+    stages.add(s);
+    Request request = new Request(stages, clusters);
+    db.persistActions(request);
+  }
+
+  private Stage createStubStage(String hostname, long requestId, long stageId) {
     Stage s = new Stage(requestId, "/a/b", "cluster1", "action db accessor test", "clusterHostInfo");
     s.setStageId(stageId);
     s.addHostRoleExecutionCommand(hostname, Role.HBASE_MASTER,
@@ -341,9 +354,7 @@ public class TestActionDBAccessorImpl {
         RoleCommand.START,
         new ServiceComponentHostStartEvent(Role.HBASE_REGIONSERVER
             .toString(), hostname, System.currentTimeMillis()), "cluster1", "HBASE");
-    List<Stage> stages = new ArrayList<Stage>();
-    stages.add(s);
-    db.persistActions(stages);
+    return s;
   }
 
   private void populateActionDBWithCustomAction(ActionDBAccessor db, String hostname,
@@ -356,8 +367,9 @@ public class TestActionDBAccessorImpl {
             hostname, System.currentTimeMillis()), "cluster1", "HBASE");
     List<Stage> stages = new ArrayList<Stage>();
     stages.add(s);
-    ExecuteActionRequest request = new ExecuteActionRequest("cluster1", null, actionName, "HBASE",
+    ExecuteActionRequest executeActionRequest = new ExecuteActionRequest("cluster1", null, actionName, "HBASE",
         "HBASE_MASTER", null, null);
-    db.persistActions(stages);
+    Request request = new Request(stages, clusters);
+    db.persistActions(request);
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionManager.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionManager.java b/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionManager.java
index 20d6792..a266cc6 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionManager.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionManager.java
@@ -84,7 +84,7 @@ public class TestActionManager {
   public void testActionResponse() {
     ActionDBAccessor db = injector.getInstance(ActionDBAccessorImpl.class);
     ActionManager am = new ActionManager(5000, 1200000, new ActionQueue(),
-        clusters, db, new HostsMap((String) null), null, unitOfWork, null);
+        clusters, db, new HostsMap((String) null), null, unitOfWork, null, injector.getInstance(RequestFactory.class));
     populateActionDB(db, hostname);
     Stage stage = db.getAllStages(requestId).get(0);
     Assert.assertEquals(stageId, stage.getStageId());
@@ -124,7 +124,7 @@ public class TestActionManager {
   public void testLargeLogs() {
     ActionDBAccessor db = injector.getInstance(ActionDBAccessorImpl.class);
     ActionManager am = new ActionManager(5000, 1200000, new ActionQueue(),
-        clusters, db, new HostsMap((String) null), null, unitOfWork, null);
+        clusters, db, new HostsMap((String) null), null, unitOfWork, null, injector.getInstance(RequestFactory.class));
     populateActionDB(db, hostname);
     Stage stage = db.getAllStages(requestId).get(0);
     Assert.assertEquals(stageId, stage.getStageId());
@@ -171,7 +171,8 @@ public class TestActionManager {
             hostname, System.currentTimeMillis()), "cluster1", "HBASE");
     List<Stage> stages = new ArrayList<Stage>();
     stages.add(s);
-    db.persistActions(stages);
+    Request request = new Request(stages, clusters);
+    db.persistActions(request);
   }
 
   // Test failing ... tracked by Jira BUG-4966
@@ -212,7 +213,7 @@ public class TestActionManager {
 
     replay(queue, db, clusters);
 
-    ActionManager manager = new ActionManager(0, 0, queue, clusters, db, null, null, unitOfWork, null);
+    ActionManager manager = new ActionManager(0, 0, queue, clusters, db, null, null, unitOfWork, null, injector.getInstance(RequestFactory.class));
     assertSame(listStages, manager.getActions(requestId));
 
     verify(queue, db, clusters);


[3/3] git commit: AMBARI-4267. Enable BatchRequest(s) to transform to API calls to the server. (mpapirkovskyy)

Posted by mp...@apache.org.
AMBARI-4267. Enable BatchRequest(s) to transform to API calls to the server. (mpapirkovskyy)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/c8697655
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/c8697655
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/c8697655

Branch: refs/heads/trunk
Commit: c86976551f4dd1a437bed6e728ae39bbc2040736
Parents: 46d86dc
Author: Myroslav Papirkovskyy <mp...@hortonworks.com>
Authored: Mon Jan 13 23:44:11 2014 +0200
Committer: Myroslav Papirkovskyy <mp...@hortonworks.com>
Committed: Mon Jan 13 23:44:11 2014 +0200

----------------------------------------------------------------------
 .../server/actionmanager/ActionDBAccessor.java  |  21 +-
 .../actionmanager/ActionDBAccessorImpl.java     | 155 ++++++----
 .../actionmanager/ActionDBInMemoryImpl.java     | 232 --------------
 .../server/actionmanager/ActionManager.java     |  28 +-
 .../ambari/server/actionmanager/Request.java    | 293 ++++++++++++++++++
 .../server/actionmanager/RequestFactory.java    |  38 +++
 .../server/actionmanager/RequestType.java       |  25 ++
 .../ambari/server/actionmanager/Stage.java      |  42 +--
 .../server/actionmanager/StageFactory.java      |   2 -
 .../AmbariManagementControllerImpl.java         |  25 +-
 .../ambari/server/controller/AmbariServer.java  |  52 +++-
 .../server/controller/ControllerModule.java     |  19 +-
 .../internal/RequestResourceProvider.java       | 101 ++++--
 .../server/orm/dao/HostRoleCommandDAO.java      |  11 +
 .../ambari/server/orm/dao/RequestDAO.java       |  68 ++++
 .../server/orm/entities/ClusterEntity.java      |  11 +
 .../server/orm/entities/RequestEntity.java      | 224 ++++++++++++++
 .../RequestScheduleBatchRequestEntity.java      |   8 +-
 .../ambari/server/orm/entities/StageEntity.java |  33 +-
 .../scheduler/AbstractLinearExecutionJob.java   |   2 +
 .../scheduler/ExecutionScheduleManager.java     | 217 +++++++++++--
 .../scheduler/ExecutionSchedulerImpl.java       |   5 +
 .../AmbariInternalAuthenticationProvider.java   |  52 ++++
 .../internal/InternalAuthenticationToken.java   |  78 +++++
 .../InternalTokenAuthenticationFilter.java      |  60 ++++
 .../internal/InternalTokenClientFilter.java     |  41 +++
 .../internal/InternalTokenStorage.java          |  52 ++++
 .../server/state/scheduler/BatchRequestJob.java |  46 ++-
 .../state/scheduler/BatchRequestResponse.java   |  38 +++
 .../server/state/scheduler/GuiceJobFactory.java |  42 +++
 .../state/scheduler/RequestExecution.java       |  13 +
 .../state/scheduler/RequestExecutionImpl.java   |  44 +++
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |   7 +-
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |   5 +-
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |  98 +++---
 .../Ambari-DDL-Postgres-REMOTE-CREATE.sql       |   7 +-
 .../src/main/resources/META-INF/persistence.xml |   3 +
 .../src/main/resources/properties.json          |   8 +
 .../webapp/WEB-INF/spring-security.xml          |   5 +-
 .../ExecutionCommandWrapperTest.java            |   3 +-
 .../actionmanager/TestActionDBAccessorImpl.java |  32 +-
 .../server/actionmanager/TestActionManager.java |   9 +-
 .../actionmanager/TestActionScheduler.java      | 307 +++++++++++++++++--
 .../ambari/server/agent/AgentResourceTest.java  |   4 +
 .../server/agent/TestHeartbeatHandler.java      |  18 +-
 .../AmbariManagementControllerTest.java         |  23 +-
 .../internal/RequestResourceProviderTest.java   | 144 +++++----
 .../apache/ambari/server/orm/OrmTestHelper.java |  13 +-
 .../apache/ambari/server/orm/TestOrmImpl.java   |  33 +-
 .../scheduler/ExecutionScheduleManagerTest.java | 166 +++++++++-
 .../state/scheduler/BatchRequestJobTest.java    |  78 +++++
 51 files changed, 2405 insertions(+), 636 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessor.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessor.java b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessor.java
index 11605bb..ac36bc6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessor.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessor.java
@@ -17,6 +17,8 @@
  */
 package org.apache.ambari.server.actionmanager;
 
+import com.google.inject.persist.Transactional;
+import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.agent.CommandReport;
 import org.apache.ambari.server.controller.ExecuteActionRequest;
 
@@ -55,10 +57,16 @@ public interface ActionDBAccessor {
 
   /**
    * Persists all tasks for a given request
-   *
-   * @param stages  Stages belonging to the request
+   * @param request request object
    */
-  public void persistActions(List<Stage> stages);
+  @Transactional
+  void persistActions(Request request);
+
+  @Transactional
+  void startRequest(long requestId);
+
+  @Transactional
+  void endRequest(long requestId);
 
   /**
    * For the given host, update all the tasks based on the command report
@@ -114,7 +122,7 @@ public interface ActionDBAccessor {
   /**
    * Get all requests
    */
-  public List<Long> getRequests();
+  public List<Long> getRequestIds();
 
   /**
    * Gets the host role command corresponding to the task id
@@ -135,4 +143,9 @@ public interface ActionDBAccessor {
    * Gets the request context associated with the request id
    */
   public String getRequestContext(long requestId);
+
+  /**
+   * Gets request objects by ids
+   */
+  List<Request> getRequests(Collection<Long> requestIds);
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessorImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessorImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessorImpl.java
index 3fcf4f4..a75848c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessorImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessorImpl.java
@@ -27,63 +27,50 @@ import com.google.inject.persist.Transactional;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.agent.CommandReport;
 import org.apache.ambari.server.controller.ExecuteActionRequest;
-import org.apache.ambari.server.orm.dao.ActionDefinitionDAO;
-import org.apache.ambari.server.orm.dao.ClusterDAO;
-import org.apache.ambari.server.orm.dao.ExecutionCommandDAO;
-import org.apache.ambari.server.orm.dao.HostDAO;
-import org.apache.ambari.server.orm.dao.HostRoleCommandDAO;
-import org.apache.ambari.server.orm.dao.RoleSuccessCriteriaDAO;
-import org.apache.ambari.server.orm.dao.StageDAO;
-import org.apache.ambari.server.orm.entities.ClusterEntity;
-import org.apache.ambari.server.orm.entities.ExecutionCommandEntity;
-import org.apache.ambari.server.orm.entities.HostEntity;
-import org.apache.ambari.server.orm.entities.HostRoleCommandEntity;
-import org.apache.ambari.server.orm.entities.RoleSuccessCriteriaEntity;
-import org.apache.ambari.server.orm.entities.StageEntity;
+import org.apache.ambari.server.orm.dao.*;
+import org.apache.ambari.server.orm.entities.*;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 import java.util.concurrent.TimeUnit;
 
 @Singleton
 public class ActionDBAccessorImpl implements ActionDBAccessor {
   private static final Logger LOG = LoggerFactory.getLogger(ActionDBAccessorImpl.class);
-  private final long requestId;
+  private long requestId;
   @Inject
-  private ClusterDAO clusterDAO;
+  ClusterDAO clusterDAO;
   @Inject
-  private HostDAO hostDAO;
+  HostDAO hostDAO;
   @Inject
-  private StageDAO stageDAO;
+  RequestDAO requestDAO;
   @Inject
-  private HostRoleCommandDAO hostRoleCommandDAO;
+  StageDAO stageDAO;
   @Inject
-  private ExecutionCommandDAO executionCommandDAO;
+  HostRoleCommandDAO hostRoleCommandDAO;
   @Inject
-  private RoleSuccessCriteriaDAO roleSuccessCriteriaDAO;
+  ExecutionCommandDAO executionCommandDAO;
   @Inject
-  private StageFactory stageFactory;
+  RoleSuccessCriteriaDAO roleSuccessCriteriaDAO;
   @Inject
-  private HostRoleCommandFactory hostRoleCommandFactory;
+  StageFactory stageFactory;
   @Inject
-  private Clusters clusters;
+  RequestFactory requestFactory;
+  @Inject
+  HostRoleCommandFactory hostRoleCommandFactory;
+  @Inject
+  Clusters clusters;
+
+
+
   private Cache<Long, HostRoleCommand> hostRoleCommandCache;
   private long cacheLimit; //may be exceeded to store tasks from one request
 
   @Inject
-  public ActionDBAccessorImpl(Injector injector, @Named("executionCommandCacheSize") long cacheLimit) {
-    injector.injectMembers(this);
-    requestId = stageDAO.getLastRequestId();
+  public ActionDBAccessorImpl(@Named("executionCommandCacheSize") long cacheLimit) {
 
     this.cacheLimit = cacheLimit;
     hostRoleCommandCache = CacheBuilder.newBuilder().
@@ -92,12 +79,18 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
 
   }
 
+  @Inject
+  void init() {
+    requestId = stageDAO.getLastRequestId();
+  }
+
   /* (non-Javadoc)
    * @see org.apache.ambari.server.actionmanager.ActionDBAccessor#getStage(java.lang.String)
    */
   @Override
   public Stage getStage(String actionId) {
-    return stageFactory.createExisting(actionId);
+    StageEntity stageEntity = stageDAO.findByActionId(actionId);
+    return stageFactory.createExisting(stageEntity);
   }
 
   /* (non-Javadoc)
@@ -116,8 +109,17 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
    * @see org.apache.ambari.server.actionmanager.ActionDBAccessor#abortOperation(long)
    */
   @Override
+  @Transactional
   public void abortOperation(long requestId) {
     long now = System.currentTimeMillis();
+
+    //mark request as ended
+    RequestEntity requestEntity = requestDAO.findByPK(requestId);
+    if (requestEntity != null && requestEntity.getEndTime() == -1L) {
+      requestEntity.setEndTime(now);
+      requestDAO.merge(requestEntity);
+    }
+
     List<HostRoleCommandEntity> commands =
         hostRoleCommandDAO.findByRequest(requestId);
     for (HostRoleCommandEntity command : commands) {
@@ -168,32 +170,36 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
     return stages;
   }
 
-  /* (non-Javadoc)
-   * @see org.apache.ambari.server.actionmanager.ActionDBAccessor#persistActions(java.util.List)
-   */
   @Override
   @Transactional
-  public void persistActions(List<Stage> stages) {
-    if (LOG.isDebugEnabled()) {
-      LOG.debug("Adding stages to DB, stageCount=" + stages.size());
+  public void persistActions(Request request) {
+
+    RequestEntity requestEntity = request.constructNewPersistenceEntity();
+
+    ClusterEntity clusterEntity = clusterDAO.findById(request.getClusterId());
+    if (clusterEntity == null) {
+      throw new RuntimeException(String.format("Cluster with id=%s not found", request.getClusterId()));
     }
+    requestEntity.setCluster(clusterEntity);
+    requestDAO.create(requestEntity);
 
-    for (Stage stage : stages) {
-      StageEntity stageEntity = stage.constructNewPersistenceEntity();
-      Cluster cluster;
-      try {
-        cluster = clusters.getCluster(stage.getClusterName());
-      } catch (AmbariException e) {
-        throw new RuntimeException(e);
-      }
-      ClusterEntity clusterEntity = clusterDAO.findById(cluster.getClusterId());
+    //TODO wire request to cluster
+    List<StageEntity> stageEntities = new ArrayList<StageEntity>(request.getStages().size());
 
+    for (Stage stage : request.getStages()) {
+      StageEntity stageEntity = stage.constructNewPersistenceEntity();
+      stageEntities.add(stageEntity);
       stageEntity.setCluster(clusterEntity);
+      //TODO refactor to reduce merges
+      stageEntity.setRequest(requestEntity);
       stageDAO.create(stageEntity);
 
-      for (HostRoleCommand hostRoleCommand : stage.getOrderedHostRoleCommands()) {
-        HostRoleCommandEntity hostRoleCommandEntity = hostRoleCommand.constructNewPersistenceEntity();
+      List<HostRoleCommand> orderedHostRoleCommands = stage.getOrderedHostRoleCommands();
+      List<HostRoleCommandEntity> hostRoleCommandEntities = new ArrayList<HostRoleCommandEntity>();
 
+      for (HostRoleCommand hostRoleCommand : orderedHostRoleCommands) {
+        HostRoleCommandEntity hostRoleCommandEntity = hostRoleCommand.constructNewPersistenceEntity();
+        hostRoleCommandEntities.add(hostRoleCommandEntity);
         hostRoleCommandEntity.setStage(stageEntity);
 
         HostEntity hostEntity = hostDAO.findByName(hostRoleCommandEntity.getHostName());
@@ -221,7 +227,32 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
       for (RoleSuccessCriteriaEntity roleSuccessCriteriaEntity : stageEntity.getRoleSuccessCriterias()) {
         roleSuccessCriteriaDAO.create(roleSuccessCriteriaEntity);
       }
+
+      stageDAO.create(stageEntity);
     }
+    requestEntity.setStages(stageEntities);
+    requestDAO.merge(requestEntity);
+//    requestDAO.create(requestEntity);
+  }
+
+  @Override
+  @Transactional
+  public void startRequest(long requestId) {
+    RequestEntity requestEntity = requestDAO.findByPK(requestId);
+    if (requestEntity != null && requestEntity.getStartTime() == -1L) {
+      requestEntity.setStartTime(System.currentTimeMillis());
+    }
+    requestDAO.merge(requestEntity);
+  }
+
+  @Override
+  @Transactional
+  public void endRequest(long requestId) {
+    RequestEntity requestEntity = requestDAO.findByPK(requestId);
+    if (requestEntity != null && requestEntity.getEndTime() == -1L) {
+      requestEntity.setEndTime(System.currentTimeMillis());
+    }
+    requestDAO.merge(requestEntity);
   }
 
   @Override
@@ -349,7 +380,12 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
         }
       }
     }
-
+    Collections.sort(commands, new Comparator<HostRoleCommand>() {
+      @Override
+      public int compare(HostRoleCommand o1, HostRoleCommand o2) {
+        return (int) (o1.getTaskId()-o2.getTaskId());
+      }
+    });
     return commands;
   }
 
@@ -363,7 +399,7 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
   }
 
   @Override
-  public List<Long> getRequests() {
+  public List<Long> getRequestIds() {
     return hostRoleCommandDAO.getRequests();
   }
 
@@ -406,4 +442,15 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
   public String getRequestContext(long requestId) {
     return stageDAO.findRequestContext(requestId);
   }
+
+  @Override
+  @Transactional
+  public List<Request> getRequests(Collection<Long> requestIds){
+    List<RequestEntity> requestEntities = requestDAO.findByPks(requestIds);
+    List<Request> requests = new ArrayList<Request>(requestEntities.size());
+    for (RequestEntity requestEntity : requestEntities) {
+      requests.add(requestFactory.createExisting(requestEntity));
+    }
+    return requests;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBInMemoryImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBInMemoryImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBInMemoryImpl.java
deleted file mode 100644
index 8c36366..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBInMemoryImpl.java
+++ /dev/null
@@ -1,232 +0,0 @@
-/**
- * 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.ambari.server.actionmanager;
-
-import com.google.inject.Singleton;
-import org.apache.ambari.server.agent.CommandReport;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-@Singleton
-public class ActionDBInMemoryImpl implements ActionDBAccessor {
-
-  private static Logger LOG = LoggerFactory.getLogger(ActionDBInMemoryImpl.class);
-  // for a persisted DB, this will be initialized in the ctor
-  // with the highest persisted requestId value in the DB
-  private final long lastRequestId = 0;
-  List<Stage> stageList = new ArrayList<Stage>();
-
-  @Override
-  public synchronized Stage getStage(String actionId) {
-    for (Stage s : stageList) {
-      if (s.getActionId().equals(actionId)) {
-        return s;
-      }
-    }
-    return null;
-  }
-
-  @Override
-  public synchronized List<Stage> getAllStages(long requestId) {
-    List<Stage> l = new ArrayList<Stage>();
-    for (Stage s : stageList) {
-      if (s.getRequestId() == requestId) {
-        l.add(s);
-      }
-    }
-    return l;
-  }
-
-  @Override
-  public synchronized void abortOperation(long requestId) {
-    for (Stage s : stageList) {
-      if (s.getRequestId() == requestId) {
-        for (String host : s.getHostRoleCommands().keySet()) {
-          Map<String, HostRoleCommand> roleCommands = s.getHostRoleCommands().get(host);
-          for (String role : roleCommands.keySet()) {
-            HostRoleCommand cmd = roleCommands.get(role);
-            HostRoleStatus status = s.getHostRoleStatus(host, cmd.getRole()
-                .toString());
-            if (status.equals(HostRoleStatus.IN_PROGRESS)
-                || status.equals(HostRoleStatus.QUEUED)
-                || status.equals(HostRoleStatus.PENDING)) {
-              s.setHostRoleStatus(host, cmd.getRole().toString(),
-                  HostRoleStatus.ABORTED);
-            }
-          }
-        }
-      }
-    }
-  }
-
-  @Override
-  public synchronized void timeoutHostRole(String host, long requestId,
-                                           long stageId, String role) {
-    for (Stage s : stageList) {
-      s.setHostRoleStatus(host, role.toString(), HostRoleStatus.TIMEDOUT);
-    }
-  }
-
-  @Override
-  public synchronized List<Stage> getStagesInProgress() {
-    List<Stage> l = new ArrayList<Stage>();
-    for (Stage s : stageList) {
-      if (s.isStageInProgress()) {
-        l.add(s);
-      }
-    }
-    return l;
-  }
-
-  @Override
-  public synchronized void persistActions(List<Stage> stages) {
-    for (Stage s : stages) {
-      stageList.add(s);
-    }
-  }
-
-  @Override
-  public synchronized void updateHostRoleState(String hostname, long requestId,
-                                               long stageId, String role, CommandReport report) {
-    LOG.info("DEBUG stages to iterate: " + stageList.size());
-    if (null == report.getStatus()
-        || null == report.getStdOut()
-        || null == report.getStdErr()) {
-      throw new RuntimeException("Badly formed command report.");
-    }
-    for (Stage s : stageList) {
-      if (s.getRequestId() == requestId && s.getStageId() == stageId) {
-        s.setHostRoleStatus(hostname, role,
-            HostRoleStatus.valueOf(report.getStatus()));
-        s.setExitCode(hostname, role, report.getExitCode());
-        s.setStderr(hostname, role, report.getStdErr());
-        s.setStdout(hostname, role, report.getStdOut());
-      }
-    }
-  }
-
-  @Override
-  public void abortHostRole(String host, long requestId, long stageId, String role) {
-    CommandReport report = new CommandReport();
-    report.setExitCode(999);
-    report.setStdErr("Host Role in invalid state");
-    report.setStdOut("");
-    report.setStatus("ABORTED");
-    updateHostRoleState(host, requestId, stageId, role, report);
-  }
-
-  @Override
-  public synchronized long getLastPersistedRequestIdWhenInitialized() {
-    return lastRequestId;
-  }
-
-  @Override
-  public void hostRoleScheduled(Stage s, String hostname, String roleStr) {
-    //Nothing needed for in-memory implementation
-  }
-
-  @Override
-  public List<HostRoleCommand> getRequestTasks(long requestId) {
-    return null;
-  }
-
-  @Override
-  public List<HostRoleCommand> getAllTasksByRequestIds(Collection<Long> requestIds) {
-    //TODO not implemented
-    return null;
-  }
-
-  @Override
-  public List<HostRoleCommand> getTasksByRequestAndTaskIds(Collection<Long> requestIds, Collection<Long> taskIds) {
-    //TODO not implemented
-    return null;
-  }
-
-  @Override
-  public Collection<HostRoleCommand> getTasks(Collection<Long> taskIds) {
-    return null;
-  }
-
-  @Override
-  public List<Stage> getStagesByHostRoleStatus(Set<HostRoleStatus> statuses) {
-    List<Stage> l = new ArrayList<Stage>();
-    for (Stage s : stageList) {
-      if (s.doesStageHaveHostRoleStatus(statuses)) {
-        l.add(s);
-      }
-    }
-    return l;
-  }
-
-  @Override
-  public synchronized List<Long> getRequests() {
-    Set<Long> requestIds = new HashSet<Long>();
-    for (Stage s : stageList) {
-      requestIds.add(s.getRequestId());
-    }
-    List<Long> ids = new ArrayList<Long>();
-    ids.addAll(requestIds);
-    return ids;
-  }
-
-  public HostRoleCommand getTask(long taskId) {
-    for (Stage s : stageList) {
-      for (String host : s.getHostRoleCommands().keySet()) {
-        Map<String, HostRoleCommand> map = s.getHostRoleCommands().get(host);
-        for (HostRoleCommand hostRoleCommand : map.values()) {
-          if (hostRoleCommand.getTaskId() == taskId) {
-            return hostRoleCommand;
-          }
-        }
-      }
-    }
-    return null;
-  }
-
-  @Override
-  public List<Long> getRequestsByStatus(RequestStatus status) {
-    // TODO
-    throw new RuntimeException("Functionality not implemented");
-  }
-
-  @Override
-  public Map<Long, String> getRequestContext(List<Long> requestIds) {
-    Map<Long, String> result = new HashMap<Long, String>();
-    for (Long requestId : requestIds) {
-      List<Stage> stages = getAllStages(requestId);
-      result.put(requestId, stages != null && !stages.isEmpty() ? stages.get
-          (0).getRequestContext() : "");
-    }
-    return result;
-  }
-
-  @Override
-  public String getRequestContext(long requestId) {
-    List<Stage> stages = getAllStages(requestId);
-    return stages != null && !stages.isEmpty() ? stages.get(0)
-        .getRequestContext() : "";
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionManager.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionManager.java b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionManager.java
index aa553c4..af25149 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionManager.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionManager.java
@@ -50,12 +50,15 @@ public class ActionManager {
   private final ActionQueue actionQueue;
   private final AtomicLong requestCounter;
   private final CustomActionDBAccessor cdb;
+  private final RequestFactory requestFactory;
+
 
   @Inject
   public ActionManager(@Named("schedulerSleeptime") long schedulerSleepTime,
                        @Named("actionTimeout") long actionTimeout,
                        ActionQueue aq, Clusters fsm, ActionDBAccessor db, HostsMap hostsMap,
-                       ServerActionManager serverActionManager, UnitOfWork unitOfWork, CustomActionDBAccessor cdb) {
+                       ServerActionManager serverActionManager, UnitOfWork unitOfWork, CustomActionDBAccessor cdb,
+                       RequestFactory requestFactory) {
     this.actionQueue = aq;
     this.db = db;
     scheduler = new ActionScheduler(schedulerSleepTime, actionTimeout, db,
@@ -63,6 +66,7 @@ public class ActionManager {
     requestCounter = new AtomicLong(
         db.getLastPersistedRequestIdWhenInitialized());
     this.cdb = cdb;
+    this.requestFactory = requestFactory;
   }
 
   public void start() {
@@ -74,23 +78,27 @@ public class ActionManager {
     scheduler.stop();
   }
 
-  public void sendActions(List<Stage> stages, ExecuteActionRequest request) {
+  public void sendActions(List<Stage> stages, ExecuteActionRequest actionRequest) throws AmbariException {
+    Request request = requestFactory.createNewFromStages(stages, actionRequest);
+    sendActions(request, actionRequest);
+  }
 
+  public void sendActions(Request request, ExecuteActionRequest executeActionRequest) {
     if (LOG.isDebugEnabled()) {
-      for (Stage s : stages) {
-        LOG.debug("Persisting stage into db: " + s.toString());
-      }
+      LOG.debug(String.format("Persisting Request into DB: %s", request));
 
-      if (request != null) {
+      if (executeActionRequest != null) {
         LOG.debug("In response to request: " + request.toString());
       }
     }
-    db.persistActions(stages);
-
-    // Now scheduler should process actions
+    db.persistActions(request);
     scheduler.awake();
   }
 
+  public List<Request> getRequests(Collection<Long> requestIds) {
+    return db.getRequests(requestIds);
+  }
+
   public List<Stage> getRequestStatus(long requestId) {
     return db.getAllStages(requestId);
   }
@@ -179,7 +187,7 @@ public class ActionManager {
    * @return
    */
   public List<Long> getRequests() {
-    return db.getRequests();
+    return db.getRequestIds();
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Request.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Request.java b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Request.java
new file mode 100644
index 0000000..35f6864
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Request.java
@@ -0,0 +1,293 @@
+/*
+ * 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.ambari.server.actionmanager;
+
+import com.google.gson.Gson;
+import com.google.inject.assistedinject.Assisted;
+import com.google.inject.assistedinject.AssistedInject;
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.controller.ExecuteActionRequest;
+import org.apache.ambari.server.orm.entities.RequestEntity;
+import org.apache.ambari.server.orm.entities.StageEntity;
+import org.apache.ambari.server.state.Clusters;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class Request {
+  private static final Logger LOG = LoggerFactory.getLogger(Request.class);
+
+  private final long requestId;
+  private final long clusterId;
+  private final String clusterName;
+  private String commandName;
+  private String requestContext;
+  private long createTime;
+  private long startTime;
+  private long endTime;
+  private String inputs;
+  private String targetService;
+  private String targetComponent;
+  private String targetHosts;
+  private RequestType requestType;
+
+  private Collection<Stage> stages = new ArrayList<Stage>();
+
+  @AssistedInject
+  /**
+   * Construct new entity
+   */
+  public Request(@Assisted long requestId, @Assisted("clusterId") Long clusterId, Clusters clusters) {
+    this.requestId = requestId;
+    this.clusterId = clusterId;
+    this.createTime = System.currentTimeMillis();
+    this.startTime = -1;
+    this.endTime = -1;
+    try {
+      this.clusterName = clusters.getClusterById(clusterId).getClusterName();
+    } catch (AmbariException e) {
+      String message = String.format("Cluster with id=%s not found", clusterId);
+      LOG.error(message);
+      throw new RuntimeException(message);
+    }
+  }
+
+  @AssistedInject
+  /**
+   * Construct new entity from stages provided
+   */
+  //TODO remove when not needed
+  public Request(@Assisted Collection<Stage> stages, Clusters clusters){
+    if (stages != null && !stages.isEmpty()) {
+      this.stages.addAll(stages);
+      Stage stage = stages.iterator().next();
+      this.requestId = stage.getRequestId();
+      this.clusterName = stage.getClusterName();
+      try {
+        this.clusterId = clusters.getCluster(clusterName).getClusterId();
+      } catch (AmbariException e) {
+        String message = String.format("Cluster %s not found", clusterName);
+        LOG.error(message);
+        throw new RuntimeException(message);
+      }
+      this.requestContext = stages.iterator().next().getRequestContext();
+      this.createTime = System.currentTimeMillis();
+      this.startTime = -1;
+      this.endTime = -1;
+      this.requestType = RequestType.INTERNAL_REQUEST;
+    } else {
+      String message = "Attempted to construct request from empty stage collection";
+      LOG.error(message);
+      throw new RuntimeException(message);
+    }
+  }
+
+  @AssistedInject
+  /**
+   * Construct new entity from stages provided
+   */
+  //TODO remove when not needed
+  public Request(@Assisted Collection<Stage> stages, @Assisted ExecuteActionRequest actionRequest,
+                 Clusters clusters, Gson gson) throws AmbariException {
+    this(stages, clusters);
+    if (actionRequest != null) {
+      this.targetService = actionRequest.getServiceName();
+      this.targetComponent = actionRequest.getComponentName();
+      this.targetHosts = gson.toJson(actionRequest.getHosts());
+      this.inputs = gson.toJson(actionRequest.getParameters());
+      this.requestType = actionRequest.isCommand() ? RequestType.COMMAND : RequestType.ACTION;
+      this.commandName = actionRequest.isCommand() ? actionRequest.getCommandName() : actionRequest.getActionName();
+    }
+  }
+
+  @AssistedInject
+  /**
+   * Load existing request from database
+   */
+  public Request(@Assisted RequestEntity entity, StageFactory stageFactory){
+    if (entity == null) {
+      throw new RuntimeException("Request entity cannot be null.");
+    }
+
+    this.requestId = entity.getRequestId();
+    this.clusterId = entity.getCluster().getClusterId();
+    this.clusterName = entity.getCluster().getClusterName();
+    this.createTime = entity.getCreateTime();
+    this.startTime = entity.getStartTime();
+    this.endTime = entity.getEndTime();
+    this.requestContext = entity.getRequestContext();
+    this.inputs = entity.getInputs();
+    this.targetService = entity.getTargetService();
+    this.targetComponent = entity.getTargetComponent();
+    this.targetHosts = entity.getTargetHosts();
+    this.requestType = entity.getRequestType();
+    this.commandName = entity.getCommandName();
+
+    for (StageEntity stageEntity : entity.getStages()) {
+      Stage stage = stageFactory.createExisting(stageEntity);
+      stages.add(stage);
+    }
+  }
+
+  public Collection<Stage> getStages() {
+    return stages;
+  }
+
+  public void setStages(Collection<Stage> stages) {
+    this.stages = stages;
+  }
+
+  public long getRequestId() {
+    return requestId;
+  }
+
+  public synchronized RequestEntity constructNewPersistenceEntity() {
+    RequestEntity requestEntity = new RequestEntity();
+
+    requestEntity.setRequestId(requestId);
+    requestEntity.setClusterId(clusterId);
+    requestEntity.setCreateTime(createTime);
+    requestEntity.setStartTime(startTime);
+    requestEntity.setEndTime(endTime);
+    requestEntity.setRequestContext(requestContext);
+    requestEntity.setInputs(inputs);
+    requestEntity.setTargetService(targetService);
+    requestEntity.setTargetComponent(targetComponent);
+    requestEntity.setTargetHosts(targetHosts);
+    requestEntity.setRequestType(requestType);
+    //TODO set all fields
+
+    return requestEntity;
+  }
+
+
+  public Long getClusterId() {
+    return clusterId;
+  }
+
+  public String getClusterName() {
+    return clusterName;
+  }
+
+  public String getRequestContext() {
+    return requestContext;
+  }
+
+  public void setRequestContext(String requestContext) {
+    this.requestContext = requestContext;
+  }
+
+  public long getCreateTime() {
+    return createTime;
+  }
+
+  public long getStartTime() {
+    return startTime;
+  }
+
+  public void setStartTime(long startTime) {
+    this.startTime = startTime;
+  }
+
+  public long getEndTime() {
+    return endTime;
+  }
+
+  public void setEndTime(long endTime) {
+    this.endTime = endTime;
+  }
+
+  public String getInputs() {
+    return inputs;
+  }
+
+  public void setInputs(String inputs) {
+    this.inputs = inputs;
+  }
+
+  public String getTargetService() {
+    return targetService;
+  }
+
+  public void setTargetService(String targetService) {
+    this.targetService = targetService;
+  }
+
+  public String getTargetComponent() {
+    return targetComponent;
+  }
+
+  public void setTargetComponent(String targetComponent) {
+    this.targetComponent = targetComponent;
+  }
+
+  public String getTargetHosts() {
+    return targetHosts;
+  }
+
+  public void setTargetHosts(String targetHosts) {
+    this.targetHosts = targetHosts;
+  }
+
+  public RequestType getRequestType() {
+    return requestType;
+  }
+
+  public void setRequestType(RequestType requestType) {
+    this.requestType = requestType;
+  }
+
+  public String getCommandName() {
+    return commandName;
+  }
+
+  public void setCommandName(String commandName) {
+    this.commandName = commandName;
+  }
+
+  public List<HostRoleCommand> getCommands() {
+    List<HostRoleCommand> commands = new ArrayList<HostRoleCommand>();
+    for (Stage stage : stages) {
+      commands.addAll(stage.getOrderedHostRoleCommands());
+    }
+    return commands;
+  }
+
+  @Override
+  public String toString() {
+    return "Request{" +
+        "requestId=" + requestId +
+        ", clusterId=" + clusterId +
+        ", clusterName='" + clusterName + '\'' +
+        ", requestContext='" + requestContext + '\'' +
+        ", createTime=" + createTime +
+        ", startTime=" + startTime +
+        ", endTime=" + endTime +
+        ", inputs='" + inputs + '\'' +
+        ", targetService='" + targetService + '\'' +
+        ", targetComponent='" + targetComponent + '\'' +
+        ", targetHosts='" + targetHosts + '\'' +
+        ", requestType=" + requestType +
+        ", stages=" + stages +
+        '}';
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/RequestFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/RequestFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/RequestFactory.java
new file mode 100644
index 0000000..3313582
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/RequestFactory.java
@@ -0,0 +1,38 @@
+/*
+ * 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.ambari.server.actionmanager;
+
+import com.google.inject.assistedinject.Assisted;
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.controller.ExecuteActionRequest;
+import org.apache.ambari.server.orm.entities.RequestEntity;
+
+import java.util.Collection;
+
+public interface RequestFactory {
+
+  Request createNew(long requestId, @Assisted("clusterId") Long clusterName) throws AmbariException;
+
+  Request createNewFromStages(Collection<Stage> stages);
+
+  Request createNewFromStages(Collection<Stage> stages, ExecuteActionRequest actionRequest);
+
+  Request createExisting(RequestEntity entity);
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/RequestType.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/RequestType.java b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/RequestType.java
new file mode 100644
index 0000000..90b2c6a
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/RequestType.java
@@ -0,0 +1,25 @@
+/*
+ * 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.ambari.server.actionmanager;
+
+public enum RequestType {
+  ACTION,
+  COMMAND,
+  INTERNAL_REQUEST
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Stage.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Stage.java b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Stage.java
index 264e5d7..3a9cc5c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Stage.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Stage.java
@@ -17,12 +17,7 @@
  */
 package org.apache.ambari.server.actionmanager;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
+import java.util.*;
 
 import org.apache.ambari.server.Role;
 import org.apache.ambari.server.RoleCommand;
@@ -83,20 +78,8 @@ public class Stage {
     this.clusterHostInfo = clusterHostInfo;
   }
 
-  /**
-   * Creates Stage existing in database
-   * @param actionId "requestId-stageId" string
-   */
-  @AssistedInject
-  public Stage(@Assisted String actionId, Injector injector) {
-    this(injector.getInstance(StageDAO.class).findByActionId(actionId), injector);
-  }
-
   @AssistedInject
-  public Stage(@Assisted StageEntity stageEntity, Injector injector) {
-    HostRoleCommandDAO hostRoleCommandDAO = injector.getInstance(HostRoleCommandDAO.class);
-    HostDAO hostDAO = injector.getInstance(HostDAO.class);
-    HostRoleCommandFactory hostRoleCommandFactory = injector.getInstance(HostRoleCommandFactory.class);
+  public Stage(@Assisted StageEntity stageEntity, HostRoleCommandDAO hostRoleCommandDAO, ActionDBAccessor dbAccessor) {
 
     requestId = stageEntity.getRequestId();
     stageId = stageEntity.getStageId();
@@ -106,19 +89,18 @@ public class Stage {
     clusterHostInfo = stageEntity.getClusterHostInfo();
 
 
-    Map<String, List<HostRoleCommandEntity>> hostCommands = hostRoleCommandDAO.findSortedCommandsByStage(stageEntity);
+    List<Long> taskIds = hostRoleCommandDAO.findTaskIdsByStage(requestId, stageId);
+    Collection<HostRoleCommand> commands = dbAccessor.getTasks(taskIds);
 
-    for (Map.Entry<String, List<HostRoleCommandEntity>> entry : hostCommands.entrySet()) {
-      String hostname = entry.getKey();
-      commandsToSend.put(hostname, new ArrayList<ExecutionCommandWrapper>());
-      hostRoleCommands.put(hostname, new TreeMap<String, HostRoleCommand>());
-      for (HostRoleCommandEntity hostRoleCommandEntity : entry.getValue()) {
-        HostRoleCommand hostRoleCommand = hostRoleCommandFactory.createExisting(hostRoleCommandEntity);
-
-
-        hostRoleCommands.get(hostname).put(hostRoleCommand.getRole().toString(), hostRoleCommand);
-        commandsToSend.get(hostname).add(hostRoleCommand.getExecutionCommandWrapper());
+    for (HostRoleCommand command : commands) {
+      String hostname = command.getHostName();
+      if (!hostRoleCommands.containsKey(hostname)) {
+        commandsToSend.put(hostname, new ArrayList<ExecutionCommandWrapper>());
+        hostRoleCommands.put(hostname, new TreeMap<String, HostRoleCommand>());
       }
+
+      hostRoleCommands.get(hostname).put(command.getRole().toString(), command);
+      commandsToSend.get(hostname).add(command.getExecutionCommandWrapper());
     }
 
     for (RoleSuccessCriteriaEntity successCriteriaEntity : stageEntity.getRoleSuccessCriterias()) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/StageFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/StageFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/StageFactory.java
index 3086072..c0e2e6e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/StageFactory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/StageFactory.java
@@ -26,7 +26,5 @@ public interface StageFactory {
   Stage createNew(long requestId, @Assisted("logDir") String logDir, @Assisted("clusterName") String clusterName,
                    @Assisted("requestContext") String requestContext, @Assisted("clusterHostInfo") String clusterHostInfo);
 
-  Stage createExisting(String actionId);
-
   Stage createExisting(StageEntity stageEntity);
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
index ca14f14..afff8e4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
@@ -45,10 +45,7 @@ import org.apache.ambari.server.ServiceComponentHostNotFoundException;
 import org.apache.ambari.server.ServiceComponentNotFoundException;
 import org.apache.ambari.server.ServiceNotFoundException;
 import org.apache.ambari.server.StackAccessException;
-import org.apache.ambari.server.actionmanager.ActionManager;
-import org.apache.ambari.server.actionmanager.HostRoleCommand;
-import org.apache.ambari.server.actionmanager.Stage;
-import org.apache.ambari.server.actionmanager.StageFactory;
+import org.apache.ambari.server.actionmanager.*;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.internal.URLStreamProvider;
@@ -117,6 +114,8 @@ public class AmbariManagementControllerImpl implements
   @Inject
   private StageFactory stageFactory;
   @Inject
+  private RequestFactory requestFactory;
+  @Inject
   private ActionMetadata actionMetadata;
   @Inject
   private AmbariMetaInfo ambariMetaInfo;
@@ -1279,15 +1278,19 @@ public class AmbariManagementControllerImpl implements
     return null;
   }
 
-  private void persistStages(List<Stage> stages) {
-    if(stages != null && stages.size() > 0) {
+  private void persistStages(List<Stage> stages) throws AmbariException {
+    if (stages != null && !stages.isEmpty()) {
+      persistRequest(requestFactory.createNewFromStages(stages));
+    }
+  }
+
+  //TODO use when request created externally
+  private void persistRequest(Request request) {
+    if (request != null && request.getStages()!= null && !request.getStages().isEmpty()) {
       if (LOG.isDebugEnabled()) {
-        LOG.debug("Triggering Action Manager"
-            + ", clusterName=" + stages.get(0).getClusterName()
-            + ", requestId=" + stages.get(0).getRequestId()
-            + ", stagesCount=" + stages.size());
+        LOG.debug(String.format("Triggering Action Manager, request=%s", request));
       }
-      actionManager.sendActions(stages, null);
+      actionManager.sendActions(request, null);
     }
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
index 7ca3ea1..8cefa74 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
@@ -25,6 +25,7 @@ import java.util.Map;
 
 import javax.crypto.BadPaddingException;
 
+import com.google.inject.name.Named;
 import org.apache.ambari.eventdb.webservice.WorkflowJsonService;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.actionmanager.ActionManager;
@@ -41,21 +42,23 @@ import org.apache.ambari.server.bootstrap.BootStrapImpl;
 import org.apache.ambari.server.configuration.ComponentSSLConfiguration;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.internal.AbstractControllerResourceProvider;
-import org.apache.ambari.server.controller.internal.ClusterControllerImpl;
 import org.apache.ambari.server.controller.internal.StackDefinedPropertyProvider;
 import org.apache.ambari.server.controller.nagios.NagiosPropertyProvider;
 import org.apache.ambari.server.orm.GuiceJpaInitializer;
 import org.apache.ambari.server.orm.PersistenceType;
 import org.apache.ambari.server.orm.dao.MetainfoDAO;
+import org.apache.ambari.server.orm.entities.MetainfoEntity;
 import org.apache.ambari.server.resources.ResourceManager;
 import org.apache.ambari.server.resources.api.rest.GetResource;
 import org.apache.ambari.server.scheduler.ExecutionScheduleManager;
-import org.apache.ambari.server.scheduler.ExecutionScheduler;
 import org.apache.ambari.server.security.CertificateManager;
 import org.apache.ambari.server.security.SecurityFilter;
 import org.apache.ambari.server.security.authorization.AmbariLdapAuthenticationProvider;
 import org.apache.ambari.server.security.authorization.AmbariLocalUserDetailsService;
 import org.apache.ambari.server.security.authorization.Users;
+import org.apache.ambari.server.security.authorization.internal.AmbariInternalAuthenticationProvider;
+import org.apache.ambari.server.security.authorization.internal.InternalTokenAuthenticationFilter;
+import org.apache.ambari.server.security.authorization.internal.InternalTokenStorage;
 import org.apache.ambari.server.security.unsecured.rest.CertificateDownload;
 import org.apache.ambari.server.security.unsecured.rest.CertificateSign;
 import org.apache.ambari.server.state.Clusters;
@@ -110,6 +113,9 @@ public class AmbariServer {
   AmbariMetaInfo ambariMetaInfo;
   @Inject
   MetainfoDAO metainfoDAO;
+  @Inject
+  @Named("dbInitNeeded")
+  boolean dbInitNeeded;
 
   public String getServerOsType() {
     return configs.getServerOsType();
@@ -127,7 +133,7 @@ public class AmbariServer {
     LOG.info("********* Meta Info initialized **********");
 
     performStaticInjection();
-    addInMemoryUsers();
+    initDB();
     server = new Server();
     serverForAgent = new Server();
 
@@ -147,6 +153,11 @@ public class AmbariServer {
           injector.getInstance(AmbariLocalUserDetailsService.class));
       factory.registerSingleton("ambariLdapAuthenticationProvider",
           injector.getInstance(AmbariLdapAuthenticationProvider.class));
+      factory.registerSingleton("internalTokenAuthenticationFilter",
+          injector.getInstance(InternalTokenAuthenticationFilter.class));
+      factory.registerSingleton("ambariInternalAuthenticationProvider",
+          injector.getInstance(AmbariInternalAuthenticationProvider.class));
+
       //Spring Security xml config depends on this Bean
 
       String[] contextLocations = {SPRING_CONTEXT_LOCATION};
@@ -393,9 +404,9 @@ public class AmbariServer {
    * Creates default users and roles if in-memory database is used
    */
   @Transactional
-  protected void addInMemoryUsers() {
-    if (configs.getPersistenceType() == PersistenceType.IN_MEMORY) {
-      LOG.info("In-memory database is used - creating default users");
+  protected void initDB() {
+    if (configs.getPersistenceType() == PersistenceType.IN_MEMORY || dbInitNeeded) {
+      LOG.info("Database init needed - creating default data");
       Users users = injector.getInstance(Users.class);
 
       users.createDefaultRoles();
@@ -403,24 +414,37 @@ public class AmbariServer {
       users.createUser("user", "user");
       try {
         users.promoteToAdmin(users.getLocalUser("admin"));
-      } catch (AmbariException e) {
-        throw new RuntimeException(e);
+      } catch (AmbariException ignored) {
       }
+
+      MetainfoEntity schemaVersion = new MetainfoEntity();
+      schemaVersion.setMetainfoName(Configuration.SERVER_VERSION_KEY);
+      schemaVersion.setMetainfoValue(ambariMetaInfo.getServerVersion());
+
+      metainfoDAO.create(schemaVersion);
     }
   }
 
   protected void checkDBVersion() throws AmbariException {
     LOG.info("Checking DB store version");
-    String schemaVersion = metainfoDAO.findByKey(Configuration.SERVER_VERSION_KEY).getMetainfoValue();
-    String serverVersion = ambariMetaInfo.getServerVersion();
-    if (! schemaVersion.equals(serverVersion)) {
+    MetainfoEntity schemaVersionEntity = metainfoDAO.findByKey(Configuration.SERVER_VERSION_KEY);
+    String schemaVersion = null;
+    String serverVersion = null;
+
+    if (schemaVersionEntity != null) {
+      schemaVersion = schemaVersionEntity.getMetainfoValue();
+      serverVersion = ambariMetaInfo.getServerVersion();
+    }
+
+    if (schemaVersionEntity==null || !schemaVersion.equals(serverVersion)) {
       String error = "Current database store version is not compatible with " +
-              "current server version"
-              + ", serverVersion=" + serverVersion
-              + ", schemaVersion=" + schemaVersion;
+          "current server version"
+          + ", serverVersion=" + serverVersion
+          + ", schemaVersion=" + schemaVersion;
       LOG.warn(error);
       throw new AmbariException(error);
     }
+
     LOG.info("DB store version is compatible");
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
index 135650f..b3776e7 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
@@ -18,18 +18,12 @@
 
 package org.apache.ambari.server.controller;
 
+import java.security.SecureRandom;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Properties;
 
-import org.apache.ambari.server.actionmanager.ActionDBAccessor;
-import org.apache.ambari.server.actionmanager.ActionDBAccessorImpl;
-import org.apache.ambari.server.actionmanager.CustomActionDBAccessor;
-import org.apache.ambari.server.actionmanager.CustomActionDBAccessorImpl;
-import org.apache.ambari.server.actionmanager.ExecutionCommandWrapper;
-import org.apache.ambari.server.actionmanager.HostRoleCommandFactory;
-import org.apache.ambari.server.actionmanager.HostRoleCommandFactoryImpl;
-import org.apache.ambari.server.actionmanager.StageFactory;
+import org.apache.ambari.server.actionmanager.*;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.internal.ComponentResourceProvider;
 import org.apache.ambari.server.controller.internal.HostComponentResourceProvider;
@@ -84,6 +78,7 @@ public class ControllerModule extends AbstractModule {
 
   private final Configuration configuration;
   private final HostsMap hostsMap;
+  private boolean dbInitNeeded;
 
   public ControllerModule() throws Exception {
     configuration = new Configuration();
@@ -106,12 +101,16 @@ public class ControllerModule extends AbstractModule {
     install(buildJpaPersistModule());
 
     bind(Gson.class).in(Scopes.SINGLETON);
+    bind(SecureRandom.class).in(Scopes.SINGLETON);
+
     bind(Clusters.class).to(ClustersImpl.class);
     bind(AmbariCustomCommandExecutionHelper.class).to(AmbariCustomCommandExecutionHelperImpl.class);
     bind(ActionDBAccessor.class).to(ActionDBAccessorImpl.class);
     bind(CustomActionDBAccessor.class).to(CustomActionDBAccessorImpl.class);
     bindConstant().annotatedWith(Names.named("schedulerSleeptime")).to(10000L);
     bindConstant().annotatedWith(Names.named("actionTimeout")).to(600000L);
+    bindConstant().annotatedWith(Names.named("dbInitNeeded")).to(dbInitNeeded);
+    bindConstant().annotatedWith(Names.named("statusCheckInterval")).to(5000L);
 
     //ExecutionCommands cache size
 
@@ -167,9 +166,11 @@ public class ControllerModule extends AbstractModule {
     switch (configuration.getJPATableGenerationStrategy()) {
       case CREATE:
         properties.setProperty("eclipselink.ddl-generation", "create-tables");
+        dbInitNeeded = true;
         break;
       case DROP_AND_CREATE:
         properties.setProperty("eclipselink.ddl-generation", "drop-and-create-tables");
+        dbInitNeeded = true;
         break;
       default:
         break;
@@ -213,6 +214,8 @@ public class ControllerModule extends AbstractModule {
     install(new FactoryModuleBuilder().implement(RequestExecution.class,
       RequestExecutionImpl.class).build(RequestExecutionFactory.class));
     install(new FactoryModuleBuilder().build(StageFactory.class));
+    install(new FactoryModuleBuilder().build(RequestFactory.class));
+
     bind(HostRoleCommandFactory.class).to(HostRoleCommandFactoryImpl.class);
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestResourceProvider.java
index d9f840c..fef258b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestResourceProvider.java
@@ -56,6 +56,14 @@ class RequestResourceProvider extends AbstractControllerResourceProvider {
   protected static final String REQUEST_ID_PROPERTY_ID = "Requests/id";
   protected static final String REQUEST_STATUS_PROPERTY_ID = "Requests/request_status";
   protected static final String REQUEST_CONTEXT_ID = "Requests/request_context";
+  protected static final String REQUEST_TYPE_ID = "Requests/type";
+  protected static final String REQUEST_INPUTS_ID = "Requests/inputs";
+  protected static final String REQUEST_TARGET_SERVICE_ID = "Requests/target_service";
+  protected static final String REQUEST_TARGET_COMPONENT_ID = "Requests/target_component";
+  protected static final String REQUEST_TARGET_HOSTS_ID = "Requests/target_hosts";
+  protected static final String REQUEST_CREATE_TIME_ID = "Requests/create_time";
+  protected static final String REQUEST_START_TIME_ID = "Requests/start_time";
+  protected static final String REQUEST_END_TIME_ID = "Requests/end_time";
   protected static final String REQUEST_TASK_CNT_ID = "Requests/task_count";
   protected static final String REQUEST_FAILED_TASK_CNT_ID = "Requests/failed_task_count";
   protected static final String REQUEST_ABORTED_TASK_CNT_ID = "Requests/aborted_task_count";
@@ -254,33 +262,88 @@ class RequestResourceProvider extends AbstractControllerResourceProvider {
                                                    List<Long> requestIds,
                                                    Set<String> requestedPropertyIds) {
 
-    List<HostRoleCommand> hostRoleCommands = actionManager.getAllTasksByRequestIds(requestIds);
-    Map<Long, String> requestContexts = actionManager.getRequestContext(requestIds);
+    List<org.apache.ambari.server.actionmanager.Request> requests = actionManager.getRequests(requestIds);
+
     Map<Long, Resource> resourceMap = new HashMap<Long, Resource>();
 
-    // group by request id
-    Map<Long, Set<HostRoleCommand>> commandMap = new HashMap<Long, Set<HostRoleCommand>>();
+    for (org.apache.ambari.server.actionmanager.Request request : requests) {
+      resourceMap.put(request.getRequestId(), getRequestResource(request, requestedPropertyIds));
+    }
+
+    return resourceMap.values();
+  }
+
+  private Resource getRequestResource(org.apache.ambari.server.actionmanager.Request request,
+                                      Set<String> requestedPropertyIds) {
+    Resource resource = new ResourceImpl(Resource.Type.Request);
+
+    setResourceProperty(resource, REQUEST_CLUSTER_NAME_PROPERTY_ID, request.getClusterName(), requestedPropertyIds);
+    setResourceProperty(resource, REQUEST_ID_PROPERTY_ID, request.getRequestId(), requestedPropertyIds);
+    setResourceProperty(resource, REQUEST_CONTEXT_ID, request.getRequestContext(), requestedPropertyIds);
+    setResourceProperty(resource, REQUEST_TYPE_ID, request.getRequestType(), requestedPropertyIds);
+    setResourceProperty(resource, REQUEST_INPUTS_ID, request.getInputs(), requestedPropertyIds);
+    setResourceProperty(resource, REQUEST_TARGET_SERVICE_ID, request.getTargetService(), requestedPropertyIds);
+    setResourceProperty(resource, REQUEST_TARGET_COMPONENT_ID, request.getTargetComponent(), requestedPropertyIds);
+    setResourceProperty(resource, REQUEST_TARGET_HOSTS_ID, request.getTargetHosts(), requestedPropertyIds);
+    setResourceProperty(resource, REQUEST_CREATE_TIME_ID, request.getCreateTime(), requestedPropertyIds);
+    setResourceProperty(resource, REQUEST_START_TIME_ID, request.getStartTime(), requestedPropertyIds);
+    setResourceProperty(resource, REQUEST_END_TIME_ID, request.getEndTime(), requestedPropertyIds);
+
+    List<HostRoleCommand> commands = request.getCommands();
+
+    int taskCount = commands.size();
+    int completedTaskCount = 0;
+    int queuedTaskCount = 0;
+    int pendingTaskCount = 0;
+    int failedTaskCount = 0;
+    int abortedTaskCount = 0;
+    int timedOutTaskCount = 0;
 
-    for (HostRoleCommand hostRoleCommand : hostRoleCommands) {
-      Long requestId = hostRoleCommand.getRequestId();
-      Set<HostRoleCommand> commands = commandMap.get(requestId);
+    for (HostRoleCommand hostRoleCommand : commands) {
+      HostRoleStatus status = hostRoleCommand.getStatus();
+      if (status.isCompletedState()) {
+        completedTaskCount++;
 
-      if (commands == null) {
-        commands = new HashSet<HostRoleCommand>();
-        commandMap.put(requestId, commands);
+        switch (status) {
+          case ABORTED:
+            abortedTaskCount++;
+            break;
+          case FAILED:
+            failedTaskCount++;
+            break;
+          case TIMEDOUT:
+            timedOutTaskCount++;
+            break;
+        }
+      } else if (status.equals(HostRoleStatus.QUEUED)) {
+        queuedTaskCount++;
+      } else if (status.equals(HostRoleStatus.PENDING)) {
+        pendingTaskCount++;
       }
-      commands.add(hostRoleCommand);
     }
 
-    for (Map.Entry<Long, Set<HostRoleCommand>> entry : commandMap.entrySet()) {
-      Long requestId = entry.getKey();
-      Set<HostRoleCommand> commands = entry.getValue();
-      String context = requestContexts.get(requestId);
+    int inProgressTaskCount = taskCount - completedTaskCount - queuedTaskCount - pendingTaskCount;
 
-      resourceMap.put(requestId,
-          getRequestResource(clusterName, requestId, context, commands, requestedPropertyIds));
-    }
-    return resourceMap.values();
+    // determine request status
+    HostRoleStatus requestStatus = failedTaskCount > 0 ? HostRoleStatus.FAILED :
+        abortedTaskCount > 0 ? HostRoleStatus.ABORTED :
+            timedOutTaskCount > 0 ? HostRoleStatus.TIMEDOUT :
+                inProgressTaskCount > 0 ? HostRoleStatus.IN_PROGRESS :
+                    completedTaskCount == taskCount ? HostRoleStatus.COMPLETED :
+                        HostRoleStatus.PENDING;
+    double progressPercent =
+        ((queuedTaskCount * 0.09 + inProgressTaskCount * 0.35 + completedTaskCount) / (double) taskCount) * 100.0;
+
+    setResourceProperty(resource, REQUEST_STATUS_PROPERTY_ID, requestStatus.toString(), requestedPropertyIds);
+    setResourceProperty(resource, REQUEST_TASK_CNT_ID, taskCount, requestedPropertyIds);
+    setResourceProperty(resource, REQUEST_FAILED_TASK_CNT_ID, failedTaskCount, requestedPropertyIds);
+    setResourceProperty(resource, REQUEST_ABORTED_TASK_CNT_ID, abortedTaskCount, requestedPropertyIds);
+    setResourceProperty(resource, REQUEST_TIMED_OUT_TASK_CNT_ID, timedOutTaskCount, requestedPropertyIds);
+    setResourceProperty(resource, REQUEST_QUEUED_TASK_CNT_ID, queuedTaskCount, requestedPropertyIds);
+    setResourceProperty(resource, REQUEST_COMPLETED_TASK_CNT_ID, completedTaskCount, requestedPropertyIds);
+    setResourceProperty(resource, REQUEST_PROGRESS_PERCENT_ID, progressPercent, requestedPropertyIds);
+
+    return resource;
   }
 
   // Get a request resource from the given set of host role commands.

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAO.java
index 5678887..e68b974 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAO.java
@@ -129,6 +129,17 @@ public class HostRoleCommandDAO {
   }
 
   @Transactional
+  public List<Long> findTaskIdsByStage(long requestId, long stageId) {
+    TypedQuery<Long> query = entityManagerProvider.get().createQuery("SELECT hostRoleCommand.taskId " +
+        "FROM HostRoleCommandEntity hostRoleCommand " +
+        "WHERE hostRoleCommand.stage.requestId=?1 " +
+        "AND hostRoleCommand.stage.stageId=?2 "+
+        "ORDER BY hostRoleCommand.taskId", Long.class);
+
+    return daoUtils.selectList(query, requestId, stageId);
+  }
+
+  @Transactional
   public List<HostRoleCommandEntity> findByHostRole(String hostName, long requestId, long stageId, String role) {
     TypedQuery<HostRoleCommandEntity> query = entityManagerProvider.get().createQuery("SELECT command " +
         "FROM HostRoleCommandEntity command " +

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/RequestDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/RequestDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/RequestDAO.java
new file mode 100644
index 0000000..483550f
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/RequestDAO.java
@@ -0,0 +1,68 @@
+/*
+ * 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.ambari.server.orm.dao;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.persist.Transactional;
+import org.apache.ambari.server.orm.entities.RequestEntity;
+
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+import java.util.Collection;
+import java.util.List;
+
+public class RequestDAO {
+  @Inject
+  Provider<EntityManager> entityManagerProvider;
+  @Inject
+  DaoUtils daoUtils;
+
+  @Transactional
+  public RequestEntity findByPK(Long requestId) {
+    return entityManagerProvider.get().find(RequestEntity.class, requestId);
+  }
+
+  @Transactional
+  public List<RequestEntity> findByPks(Collection<Long> requestIds) {
+    TypedQuery<RequestEntity> query = entityManagerProvider.get().createQuery("SELECT request FROM RequestEntity request " +
+        "WHERE request.requestId IN ?1", RequestEntity.class);
+    return daoUtils.selectList(query, requestIds);
+  }
+
+  @Transactional
+  public void create(RequestEntity requestEntity) {
+    entityManagerProvider.get().persist(requestEntity);
+  }
+
+  @Transactional
+  public RequestEntity merge(RequestEntity requestEntity) {
+    return entityManagerProvider.get().merge(requestEntity);
+  }
+
+  @Transactional
+  public void remove(RequestEntity requestEntity) {
+    entityManagerProvider.get().remove(merge(requestEntity));
+  }
+
+  @Transactional
+  public void removeByPK(Long requestId) {
+    remove(findByPK(requestId));
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java
index 55f7ee7..b9e18cf 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java
@@ -76,6 +76,9 @@ public class ClusterEntity {
   @OneToMany(mappedBy = "cluster", cascade = {CascadeType.REMOVE, CascadeType.REFRESH})
   private Collection<StageEntity> stages;
 
+  @OneToMany(mappedBy = "cluster", cascade = {CascadeType.REMOVE, CascadeType.REFRESH})
+  private Collection<RequestEntity> requests;
+
   @OneToMany(mappedBy = "clusterEntity", cascade = CascadeType.ALL)
   private Collection<ClusterConfigEntity> configEntities;
 
@@ -219,4 +222,12 @@ public class ClusterEntity {
   public void setRequestScheduleEntities(Collection<RequestScheduleEntity> requestScheduleEntities) {
     this.requestScheduleEntities = requestScheduleEntities;
   }
+
+  public Collection<RequestEntity> getRequests() {
+    return requests;
+  }
+
+  public void setRequests(Collection<RequestEntity> requests) {
+    this.requests = requests;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RequestEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RequestEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RequestEntity.java
new file mode 100644
index 0000000..c8d7fb7
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RequestEntity.java
@@ -0,0 +1,224 @@
+/*
+ * 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.ambari.server.orm.entities;
+
+import org.apache.ambari.server.actionmanager.RequestType;
+
+import javax.persistence.*;
+import java.util.Collection;
+
+@Table(name = "request")
+@Entity
+public class RequestEntity {
+
+  @Column(name = "request_id")
+  @Id
+  private Long requestId;
+
+  @Column(name = "cluster_id", updatable = false, insertable = false)
+  @Basic
+  private Long clusterId;
+
+  @Column(name = "request_context")
+  @Basic
+  private String requestContext;
+
+  @Column(name = "command_name")
+  @Basic
+  private String commandName;
+
+  @Column(name = "inputs", length = 32000)
+  @Basic
+  private String inputs;
+
+  @Column(name = "target_service")
+  @Basic
+  private String targetService;
+
+  @Column(name = "target_component")
+  @Basic
+  private String targetComponent;
+
+  @Column(name = "target_hosts")
+  @Lob
+  private String targetHosts;
+
+  @Column(name = "request_type")
+  @Enumerated(value = EnumType.STRING)
+  private RequestType requestType;
+
+  @Column(name = "status")
+  private String status;
+
+  @Basic
+  @Column(name = "create_time", nullable = false)
+  private Long createTime = System.currentTimeMillis();
+
+  @Basic
+  @Column(name = "start_time", nullable = false)
+  private Long startTime = -1L;
+
+  @Basic
+  @Column(name = "end_time", nullable = false)
+  private Long endTime = -1L;
+
+  @OneToMany(mappedBy = "request")
+  private Collection<StageEntity> stages;
+
+  @ManyToOne(cascade = {CascadeType.MERGE})
+  @JoinColumn(name = "cluster_id", referencedColumnName = "cluster_id")
+  private ClusterEntity cluster;
+
+  public Long getRequestId() {
+    return requestId;
+  }
+
+  public void setRequestId(Long id) {
+    this.requestId = id;
+  }
+
+  public String getRequestContext() {
+    return requestContext;
+  }
+
+  public void setRequestContext(String request_context) {
+    this.requestContext = request_context;
+  }
+
+  public Collection<StageEntity> getStages() {
+    return stages;
+  }
+
+  public void setStages(Collection<StageEntity> stages) {
+    this.stages = stages;
+  }
+
+  public ClusterEntity getCluster() {
+    return cluster;
+  }
+
+  public void setCluster(ClusterEntity cluster) {
+    this.cluster = cluster;
+  }
+
+  public Long getCreateTime() {
+    return createTime;
+  }
+
+  public void setCreateTime(Long createTime) {
+    this.createTime = createTime;
+  }
+
+  public Long getStartTime() {
+    return startTime;
+  }
+
+  public void setStartTime(Long startTime) {
+    this.startTime = startTime;
+  }
+
+  public Long getEndTime() {
+    return endTime;
+  }
+
+  public void setEndTime(Long endTime) {
+    this.endTime = endTime;
+  }
+
+  public String getInputs() {
+    return inputs;
+  }
+
+  public void setInputs(String inputs) {
+    this.inputs = inputs;
+  }
+
+  public String getTargetService() {
+    return targetService;
+  }
+
+  public void setTargetService(String targetService) {
+    this.targetService = targetService;
+  }
+
+  public String getTargetComponent() {
+    return targetComponent;
+  }
+
+  public void setTargetComponent(String targetComponent) {
+    this.targetComponent = targetComponent;
+  }
+
+  public String getTargetHosts() {
+    return targetHosts;
+  }
+
+  public void setTargetHosts(String targetHosts) {
+    this.targetHosts = targetHosts;
+  }
+
+  public RequestType getRequestType() {
+    return requestType;
+  }
+
+  public void setRequestType(RequestType requestType) {
+    this.requestType = requestType;
+  }
+
+  public Long getClusterId() {
+    return clusterId;
+  }
+
+  public void setClusterId(Long clusterId) {
+    this.clusterId = clusterId;
+  }
+
+  public String getCommandName() {
+    return commandName;
+  }
+
+  public void setCommandName(String commandName) {
+    this.commandName = commandName;
+  }
+
+  public String getStatus() {
+    return status;
+  }
+
+  public void setStatus(String status) {
+    this.status = status;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    RequestEntity that = (RequestEntity) o;
+
+    if (requestId != null ? !requestId.equals(that.requestId) : that.requestId != null) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    return requestId != null ? requestId.hashCode() : 0;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RequestScheduleBatchRequestEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RequestScheduleBatchRequestEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RequestScheduleBatchRequestEntity.java
index 79ee689..0775df6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RequestScheduleBatchRequestEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RequestScheduleBatchRequestEntity.java
@@ -50,10 +50,10 @@ public class RequestScheduleBatchRequestEntity {
   @Column(name = "request_id")
   private Long requestId;
 
-  @Column(name = "request_type")
+  @Column(name = "request_type", length = 255)
   private String requestType;
 
-  @Column(name = "request_uri")
+  @Column(name = "request_uri", length = 1024)
   private String requestUri;
 
   @Lob
@@ -61,13 +61,13 @@ public class RequestScheduleBatchRequestEntity {
   @Column(name = "request_body")
   private byte[] requestBody;
 
-  @Column(name = "request_status")
+  @Column(name = "request_status", length = 255)
   private String requestStatus;
 
   @Column(name = "return_code")
   private Integer returnCode;
 
-  @Column(name = "return_message")
+  @Column(name = "return_message", length = 2000)
   private String returnMessage;
 
   @ManyToOne

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/StageEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/StageEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/StageEntity.java
index c042dd0..2a353b4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/StageEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/StageEntity.java
@@ -32,7 +32,7 @@ public class StageEntity {
   @Basic
   private Long clusterId;
 
-  @Column(name = "request_id")
+  @Column(name = "request_id", insertable = false, updatable = false, nullable = false)
   @Id
   private Long requestId;
 
@@ -51,21 +51,16 @@ public class StageEntity {
   @Column(name = "cluster_host_info")
   @Basic
   private byte[] clusterHostInfo;
-  
-
-  public String getClusterHostInfo() {
-    return clusterHostInfo == null ? new String() : new String(clusterHostInfo);
-  }
-
-  public void setClusterHostInfo(String clusterHostInfo) {
-    this.clusterHostInfo = clusterHostInfo.getBytes();
-  }
 
+  @ManyToOne
+  @JoinColumn(name = "request_id", referencedColumnName = "request_id", nullable = false)
+  private RequestEntity request;
+  
   @ManyToOne(cascade = {CascadeType.MERGE})
   @JoinColumn(name = "cluster_id", referencedColumnName = "cluster_id")
   private ClusterEntity cluster;
 
-  @OneToMany(mappedBy = "stage", cascade = CascadeType.REMOVE)
+  @OneToMany(mappedBy = "stage", cascade = CascadeType.REMOVE, fetch = FetchType.LAZY)
   private Collection<HostRoleCommandEntity> hostRoleCommands;
 
   @OneToMany(mappedBy = "stage", cascade = CascadeType.REMOVE)
@@ -107,6 +102,14 @@ public class StageEntity {
     return defaultString(requestContext);
   }
 
+  public String getClusterHostInfo() {
+    return clusterHostInfo == null ? new String() : new String(clusterHostInfo);
+  }
+
+  public void setClusterHostInfo(String clusterHostInfo) {
+    this.clusterHostInfo = clusterHostInfo.getBytes();
+  }
+
   public void setRequestContext(String requestContext) {
     if (requestContext != null) {
       this.requestContext = requestContext;
@@ -163,4 +166,12 @@ public class StageEntity {
   public void setRoleSuccessCriterias(Collection<RoleSuccessCriteriaEntity> roleSuccessCriterias) {
     this.roleSuccessCriterias = roleSuccessCriterias;
   }
+
+  public RequestEntity getRequest() {
+    return request;
+  }
+
+  public void setRequest(RequestEntity request) {
+    this.request = request;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/c8697655/ambari-server/src/main/java/org/apache/ambari/server/scheduler/AbstractLinearExecutionJob.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/scheduler/AbstractLinearExecutionJob.java b/ambari-server/src/main/java/org/apache/ambari/server/scheduler/AbstractLinearExecutionJob.java
index 72fb601..a68910a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/scheduler/AbstractLinearExecutionJob.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/scheduler/AbstractLinearExecutionJob.java
@@ -85,6 +85,8 @@ public abstract class AbstractLinearExecutionJob implements ExecutionJob {
       throw new JobExecutionException(e);
     }
 
+    LOG.debug("Finished linear job: " + jobKey);
+
     JobDataMap jobDataMap = context.getMergedJobDataMap();
     String nextJobName = jobDataMap.getString(NEXT_EXECUTION_JOB_NAME_KEY);
     String nextJobGroup = jobDataMap.getString(NEXT_EXECUTION_JOB_GROUP_KEY);