incubator-ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From omal...@apache.org
Subject svn commit: r1174242 [6/9] - in /incubator/ambari/trunk: ./ agent/ agent/bin/ agent/conf/ agent/src/ agent/src/main/ agent/src/main/python/ agent/src/main/python/ambari_agent/ agent/src/main/python/ambari_torrent/ agent/src/main/python/ambari_torrent/h...
Date Thu, 22 Sep 2011 16:14:02 GMT
Added: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/rest/resources/ClusterResource.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/rest/resources/ClusterResource.java?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/rest/resources/ClusterResource.java (added)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/rest/resources/ClusterResource.java Thu Sep 22 16:13:55 2011
@@ -0,0 +1,174 @@
+package org.apache.ambari.controller.rest.resources;
+
+
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+
+
+import org.apache.ambari.common.rest.entities.Cluster;
+import org.apache.ambari.common.rest.entities.Clusters;
+import org.apache.ambari.common.rest.entities.Node;
+import org.apache.ambari.common.rest.entities.ClusterState;
+
+/** ClusterResource represents a Hadoop Cluster in a data center.
+ *  
+ */
+@Path(value = "/clusters/{clusterName}")
+public class ClusterResource {
+	
+	/** Get the definition of specified Hadoop cluster.
+	 * 
+	 *  <p>
+	 *  REST:<br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;URL Path                                    : /clusters/{clusterName}<br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Method                                 : GET <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Request Header	                        : <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Content-type        = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accept              = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Response Header                        : <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Content-type        = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accept              = application/json <br>
+	 *  <p> 
+	 *  
+	 *  @param	clusterName		Name of the cluster; Each cluster is identified w/ unique name
+	 *  @return					Returns the Cluster definition
+	 *  @throws	Exception  		Throws exception (TBD)
+	 */
+	@GET
+	@Produces({"application/json", "application/xml"})
+	public Cluster getCluster(@PathParam("clusterName") String clusterName) throws Exception {
+		//return Clusters.getInstance().getCluster(clusterName);
+		return null;
+	}
+    
+    /** Update cluster definition.
+     *  <p>
+     *  Update cluster definition allows updating any sub-elements of cluster definition. Only sub-elements to be 
+     *  updated can be specified with new values while others can be "null".
+     *  <p>
+	 *  REST:<br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;URL Path                                    : /clusters/{clusterName}<br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Method                                 : PUT <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Request Header	                        : <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Content-type        = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accept              = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Response Header                        : <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Content-type        = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accept              = application/json <br>
+	 *  <p> 
+     * 
+     * @param	clusterName		Name of the cluster; Each cluster is identified w/ unique name
+     * @param	cluster			Cluster definition with specific sub-elements to be updated
+     * @return					Returns updated cluster definition
+     * @throws	Exception		throws Exception (TBD)
+     */	
+    @PUT
+	@Consumes({"application/json", "application/xml"})
+	public Cluster updateClusterDefinition(@PathParam("clusterName") String clusterName, Cluster cluster) throws Exception {
+        //    	if (cluster.getName() == null || cluster.getName().equals("") || !cluster.getName().equals(clusterName)) {
+	//		throw new Exception("Cluster name in URI ["+clusterName+"] does not match with one specified in update request elelemt");
+      //		}
+    	//Clusters.getInstance().updateCluster(clusterName, cluster);
+    	return null;
+    }
+     
+    /** Delete the the cluster.
+     *  <p>
+     * 	Delete operation will lead the cluster to "ATTIC" state and then the cluster definition is purged from
+     *  the controller repository. In "ATTIC" state all the cluster services would be stopped and nodes are 
+     *  released. All the data on the cluster will be lost.
+     *  <p>
+	 *  REST:<br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;URL Path                                    : /clusters/{clusterName}/action/terminate<br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Method                                 : DELETE <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Request Header	                        : <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Content-type        = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accept              = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Response Header                        : <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Content-type        = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accept              = application/json <br>
+	 *  <p> 
+	 *  
+     * 	@param	clusterName		Name of the cluster; Each cluster is identified w/ unique name
+     * 	@throws	Exception		throws Exception (TBD)
+     */
+    @DELETE
+	@Consumes({"application/json", "application/xml"})
+	public void deleteCluster( @PathParam("clusterName") String clusterName) throws Exception {
+		//Clusters.getInstance().changeClusterGoalState (clusterName, Clusters.GOAL_STATE_ATTIC, new Date());
+	}
+    
+    /** Get the cluster state.
+     * 	<p>
+     * 	This provides the run time state of the cluster. Representative cluster state is based on the state of various services running on the cluster. <br>
+     * 	Representative cluster states: <br>
+     *  	"ACTIVE" 	: Hadoop stack is deployed on cluster nodes and required cluster services are running <br>
+     *  	"INACTIVE	: No cluster services are running. Hadoop stack may or may not be deployed on the cluster nodes <br>
+     *  	"ATTIC"		: Only cluster definition is available. No nodes are reserved for the cluster in this state.  <br>
+     *  
+     *  <p>
+	 *  REST:<br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;URL Path                                    : /clusters/{clusterName}/clusterstate<br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Method                                 : GET <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Request Header	                        : <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Content-type        = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accept              = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Response Header                        : <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Content-type        = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accept              = application/json <br>
+	 *  <p> 
+	 *  
+     * 	@param	clusterName		Name of the cluster; Each cluster is identified w/ unique name
+     * 	@return					Returns cluster state object.
+     * 	@throws	Exception		throws Exception (TBD)	
+     */
+    @Path(value = "/state")
+    @GET
+	@Produces({"application/json", "application/xml"})
+	public ClusterState getClusterState(@PathParam("clusterName") String clusterName) throws Exception {
+		//return Clusters.getInstance().getCluster(clusterName).getCurrentState();
+    	return null;
+	}
+    
+    /** Get list of nodes associated with the cluster.
+     *  <p>
+     *	The "alive" is a boolean variable that specify the type of nodes to return based on their state i.e. live or dead. Live nodes are the ones that are consistently heart beating with the controller. 
+     *  If both live and dead nodes are need to be returned then specify the alive parameter as null.  
+     *	<p>
+	 *  REST:<br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;URL Path                                    : /clusters/{clusterName}/nodes<br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Method                                 : GET <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Request Header	                        : <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Content-type        = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accept              = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Response Header                        : <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Content-type        = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accept              = application/json <br>
+	 *  <p> 
+	 *  
+     * 	@param	clusterName		Name of the cluster; Each cluster is identified w/ unique name
+     * 	@param	roleName		Optionally specify the role name to get the nodes associated with the service role
+     * 	@param	alive			Boolean value to specify, if nodes to be returned are alive or dead or both (if alive is set to null) 
+     * 	@return					List of nodes
+     * 	@throws	Exception		throws Exception
+     */
+    @Path(value = "/nodes")
+    @GET
+    @Produces({"application/json", "application/xml"})
+    public List<Node> getNodes (@PathParam("clusterName") String clusterName,
+    								@DefaultValue("") @QueryParam("roleName") String roleName,
+    								@DefaultValue("true") @QueryParam("alive") Boolean alive) throws Exception {
+    	//return NodesType.getInstance().getNodes (clusterName, roleName, allocated, alive);
+    	return null;
+	}
+}

Added: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/rest/resources/ClustersResource.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/rest/resources/ClustersResource.java?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/rest/resources/ClustersResource.java (added)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/rest/resources/ClustersResource.java Thu Sep 22 16:13:55 2011
@@ -0,0 +1,127 @@
+/**
+ * 
+ */
+package org.apache.ambari.controller.rest.resources;
+
+import java.util.List;
+
+import org.apache.ambari.common.rest.entities.Clusters;
+import org.apache.ambari.common.rest.entities.ClusterDefinition;
+
+import com.sun.jersey.spi.resource.Singleton;
+import javax.ws.rs.GET;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+
+
+/**
+ * Clusters Resource represents the collection of Hadoop clusters in a data center
+ */
+@Singleton
+@Path(value = "/clusters")
+public class ClustersResource {
+	
+    public ClustersResource() throws Exception {	
+        ClusterDefinition cluster123 = new ClusterDefinition();
+        ClusterDefinition cluster124 = new ClusterDefinition();
+        cluster123.setName("blue.dev.Cluster123");
+       //cluster123.setBlueprintURI("http://localhost:123/blueprint");
+       // cluster123.setDescription("test cluster");
+       // cluster124.setName("blue.research.Cluster124");
+       //cluster124.setBlueprintURI("http://localhost:124/blueprint");
+       // cluster124.setDescription("production cluster");
+       // Clusters.getInstance().addCluster(cluster123, Clusters.GOAL_STATE_ATTIC);
+       // Clusters.getInstance().addCluster(cluster124, Clusters.GOAL_STATE_ATTIC);
+    }  
+    
+    /** Get the list of clusters.
+     *  <p>
+     *  State: <br>
+     *  &nbsp;&nbsp;&nbsp;&nbsp;"ALL"		: All the clusters (irrespective of their state), 
+     *  &nbsp;&nbsp;&nbsp;&nbsp;"ACTIVE"	: All the active state clusters
+     *  &nbsp;&nbsp;&nbsp;&nbsp;"INACTIVE"	: All the inactive state clusters
+     *  &nbsp;&nbsp;&nbsp;&nbsp;"ATTIC"		: All the retired i.e. ATTIC state clusters
+     *  
+     *  <p>
+	 *  REST:<br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;URL Path                                    : /clusters<br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Method                                 : GET <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Request Header	                        : <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Content-type        = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accept              = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Response Header                        : <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Content-type        = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accept              = application/json <br>
+	 *  <p> 
+	 *  
+     *  @param	state			The state of the cluster
+     *  @param	search   		Optional search expression to return list of matching clusters
+     *  @return					Returns the list of clusters based on specified state and optional search criteria.
+     *  @throws	Exception		throws Exception (TBD)
+     */
+    @GET
+    @Produces({"application/json", "application/xml"})
+    public List<ClusterDefinition> getClusterList (
+    						 @DefaultValue("ALL") @QueryParam("state") String state,
+    		                 @DefaultValue("") @QueryParam("search") String search) throws Exception {
+    	List<ClusterDefinition> searchResults = null;
+    	if (!search.equals("")) {
+    		/*
+    		 * TODO: Implement search 
+    		searchResults = new ArrayList<Cluster>();
+    		for (Cluster cls : Clusters.getInstance().getClusterList(state)) {
+    			if (cls.getName().matches("^.*"+search+".*$")) {
+    				searchResults.add(cls);
+    			}
+    		}
+    		*/
+    	} else {
+    		//searchResults = Clusters.getInstance().getClusterList(state);
+    	}
+    
+    	if (searchResults.isEmpty()) {
+    		throw new WebApplicationException(Response.Status.NOT_FOUND);
+    	}
+    	
+    	return searchResults;
+    }
+    
+    /** Add new cluster definition.
+	 *  <p>
+	 *  Cluster goal state can be either "ACTIVE" or "INACTIVE". In the "INACTIVE" state, nodes specified in the 
+	 *  cluster definition will be reserved for the cluster. Although the actual deployment and starting of services 
+	 *  would begin when cluster definition is updated to be "ACTIVE"
+     *  <p>   
+     *  For cluster to be in active state cluster definition needs to be complete & valid 
+     *  e.g. number of nodes associated are sufficient for each role, specified blueprint for cluster configuration
+     *  should exist etc. 
+     *  
+     *  <p>
+	 *  REST:<br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;URL Path                                    : /clusters/<br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Method                                 : POST <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Request Header	                        : <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Content-type        = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accept              = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Response Header                        : <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Content-type        = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accept              = application/json <br>
+	 *  <p> 
+     *  
+     *   @param		cluster			Definition of the cluster to be created 
+     *   @return					Returns the cluster definition 
+     *   @throws	Exception		Throws exception (TBD)
+     */
+    @POST
+	@Consumes({"application/json", "application/xml"})
+	public ClusterDefinition addCluster(ClusterDefinition cluster) throws Exception {
+		Clusters.getInstance().addCluster(cluster);
+		return null;
+	}
+}

Added: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/rest/resources/ControllerResource.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/rest/resources/ControllerResource.java?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/rest/resources/ControllerResource.java (added)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/rest/resources/ControllerResource.java Thu Sep 22 16:13:55 2011
@@ -0,0 +1,159 @@
+package org.apache.ambari.controller.rest.resources;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+
+import org.apache.ambari.common.rest.entities.agent.Action;
+import org.apache.ambari.common.rest.entities.agent.ActionResult;
+import org.apache.ambari.common.rest.entities.agent.Command;
+import org.apache.ambari.common.rest.entities.agent.CommandResult;
+import org.apache.ambari.common.rest.entities.agent.ControllerResponse;
+import org.apache.ambari.common.rest.entities.agent.HardwareProfile;
+import org.apache.ambari.common.rest.entities.agent.HeartBeat;
+import org.apache.ambari.common.rest.entities.agent.ServerStatus;
+import org.apache.ambari.common.rest.entities.agent.ServersStatus;
+
+/** Controller Resource represents Ambari controller.
+ *	It provides API for Ambari agents to get the cluster configuration changes
+ *	as well as report the node attributes and state of services running the on the 
+ *	cluster nodes
+ */
+@Path(value = "/controller")
+public class ControllerResource {
+	
+	/** Update state of the node (Internal API to be used by Ambari agent).
+	 *  <p>
+	 *	This API is invoked by Ambari agent running on a cluster to update the 
+	 *	the state of various services running on the nodes. This API also registers 
+	 *	the node w/ controller (if not already done).
+	 *  <p>
+	 *  REST:<br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;URL Path                                    : /controller/agent/{hostname}<br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Method                                 : PUT <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Request Header	                        : <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Content-type        = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accept              = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Response Header                        : <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Content-type        = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accept              = application/json <br>
+	 *  <p> 
+	 * 
+	 * @response.representation.200.doc This API is invoked by Ambari agent running
+	 *  on a cluster to update the state of various services running on the node.
+	 * @response.representation.200.mediaType application/json
+	 * @response.representation.500.doc Error in accepting heartbeat message
+	 * @param message Heartbeat message
+	 * @throws Exception	throws Exception
+	 */
+  @Path(value = "/agent/{hostname}")
+  @POST
+  @Consumes(MediaType.APPLICATION_JSON)
+  public ControllerResponse heartbeat(HeartBeat message) {
+    ControllerResponse response = new ControllerResponse();
+  	return response;
+	}
+
+  /**
+   * @response.representation.200.doc Print an example of the Ambari heartbeat message
+   * @response.representation.200.mediaType application/json
+   * @param stackId
+   * @return Heartbeat message
+   */
+  @Path("agent/heartbeat/sample")
+  @GET
+  @Produces(MediaType.APPLICATION_JSON)
+  public HeartBeat getHeartBeat(@DefaultValue("stack-123") @QueryParam("stackId") String stackId) {
+    try {
+      InetAddress addr = InetAddress.getLocalHost();
+      List<ActionResult> actionResults = new ArrayList<ActionResult>();      
+
+      List<CommandResult> commandResults = new ArrayList<CommandResult>();
+      commandResults.add(new CommandResult("id", 0, "stdout", "stderr"));
+      List<CommandResult> cleanUpResults = new ArrayList<CommandResult>();
+      cleanUpResults.add(new CommandResult("id", 0, "stdout", "stderr"));
+      ActionResult actionResult = new ActionResult();
+      actionResult.setCommandResults(commandResults);
+      actionResult.setCleanUpResults(cleanUpResults);
+
+      ActionResult actionResult2 = new ActionResult();
+      actionResult2.setCommandResults(commandResults);
+      actionResult2.setCleanUpResults(cleanUpResults);
+
+      actionResults.add(actionResult);
+      actionResults.add(actionResult2);
+
+      ServersStatus serversStatus = new ServersStatus();
+      serversStatus.add("hadoop.datanode", ServerStatus.State.STARTED);
+
+      HardwareProfile hp = new HardwareProfile();
+      hp.setCoreCount(8);
+      hp.setCpuFlags("fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx lm constant_tsc pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 lahf_lm");
+      hp.setCpuSpeed(2003);
+      hp.setDiskCount(4);
+      hp.setNetSpeed(1000);
+      hp.setRamSize(16442752);
+      
+      HeartBeat hb = new HeartBeat();
+      hb.setClusterId("cluster-123");
+      hb.setTimestamp(System.currentTimeMillis());
+      hb.setHostname(addr.getHostName());
+      hb.setStackId(stackId);
+      hb.setActionResults(actionResults);
+      hb.setHardwareProfile(hp);
+      return hb;
+    } catch (UnknownHostException e) {
+      throw new WebApplicationException(e);
+    }
+  }
+  
+  /**
+   * @response.representation.200.doc Print an example of Controller Response to Agent
+   * @response.representation.200.mediaType application/json
+   * @return
+   */
+  @Path("response/sample")
+  @GET
+  @Produces("application/json")
+  public ControllerResponse getControllerResponse() {
+    ControllerResponse controllerResponse = new ControllerResponse();
+        
+    List<Command> commands = new ArrayList<Command>();
+    String[] cmd = { "ls", "-l" };
+    commands.add(new Command("cmd-001", "root", cmd));
+    commands.add(new Command("cmd-002", "root", cmd));
+    commands.add(new Command("cmd-003", "root", cmd));
+
+    List<Command> cleanUps = new ArrayList<Command>();
+    String[] cleanUpCmd = { "ls", "-t" };
+    cleanUps.add(new Command("clean-01", "hdfs", cleanUpCmd));
+    cleanUps.add(new Command("clean-02", "hdfs", cleanUpCmd));
+    
+    Action action = new Action();
+    action.setId("action-001");
+    action.setCommands(commands);
+    action.setCleanUpCommands(cleanUps);
+
+    Action action2 = new Action();
+    action2.setId("action-002");
+    action2.setCommands(commands);
+    action2.setCleanUpCommands(cleanUps);
+    
+    List<Action> actions = new ArrayList<Action>();
+    actions.add(action);
+    actions.add(action2);
+    controllerResponse.setActions(actions);
+    return controllerResponse;
+  }
+}

Added: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/rest/resources/NodesResource.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/rest/resources/NodesResource.java?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/rest/resources/NodesResource.java (added)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/rest/resources/NodesResource.java Thu Sep 22 16:13:55 2011
@@ -0,0 +1,79 @@
+package org.apache.ambari.controller.rest.resources;
+
+import java.util.List;
+
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+
+import org.apache.ambari.common.rest.entities.Node;
+
+import com.sun.jersey.spi.resource.Singleton;
+
+/** Nodes Resource represents collection of cluster nodes.
+ */
+@Singleton
+@Path(value = "/nodes")
+public class NodesResource {
+	    
+	/** Get list of nodes
+     *  <p>
+     *	The "allocated and "alive" are the boolean variables that specify the type of nodes to return based on their state i.e. if they are already allocated to any cluster and live or dead. 
+     *  Live nodes are the ones that are consistently heart beating with the controller. If both "allocated" and "alive" are set to NULL then all the nodes are returned.  
+     *	<p>
+	 *  REST:<br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;URL Path                                    : /clusters/{clusterName}/nodes<br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Method                                 : GET <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Request Header	                        : <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Content-type        = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accept              = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Response Header                        : <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Content-type        = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accept              = application/json <br>
+	 *  <p> 
+	 *  
+     *  @param	allocated		Boolean value to specify, if nodes to be returned are allocated/reserved for some cluster (specify null to return both allocated and unallocated nodes)
+     * 	@param	alive			Boolean value to specify, if nodes to be returned are alive or dead or both (specify null to return both live and dead nodes) 
+     * 	@return					List of nodes
+     * 	@throws	Exception		throws Exception
+     */
+    @Path(value = "/nodes")
+    @GET
+    @Produces({"application/json", "application/xml"})
+    public List<Node> getNodes (@DefaultValue("false") @QueryParam("allocated") Boolean allocated,
+    							@DefaultValue("false") @QueryParam("alive") Boolean alive) throws Exception {
+    	//return NodesType.getInstance().getNodes (clusterName, roleName, allocated, alive);
+    	return null;
+	}
+
+    /*
+     * Get specified Node information
+     */
+    /** Get the node information that includes, service states, node attributes etc.
+     * 
+     *  <p>
+	 *  REST:<br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;URL Path                                    : /nodes/{hostname}<br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Method                                 : GET <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Request Header	                        : <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Content-type        = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accept              = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Response Header                        : <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Content-type        = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accept              = application/json <br>
+	 *  <p> 
+	 *  
+     * @param hostname		Fully qualified hostname
+     * @return				Returns the node information
+     * @throws Exception	throws Exception
+     */
+    @Path(value = "/{hostname}")
+    @GET
+    @Produces({"application/json", "application/xml"})
+    public Node getNode (@PathParam("hostname") String hostname) throws Exception {
+    	return null;
+    }
+}

Added: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/rest/resources/StacksResource.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/rest/resources/StacksResource.java?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/rest/resources/StacksResource.java (added)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/rest/resources/StacksResource.java Thu Sep 22 16:13:55 2011
@@ -0,0 +1,118 @@
+package org.apache.ambari.controller.rest.resources;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.xml.bind.annotation.XmlElement;
+
+import org.apache.ambari.common.rest.entities.Blueprint;
+import org.apache.ambari.common.rest.entities.Cluster;
+import org.apache.ambari.common.rest.entities.Clusters;
+import org.apache.ambari.common.rest.entities.Stack;
+import org.apache.ambari.common.rest.entities.Stacks;
+import com.sun.jersey.spi.resource.Singleton;
+
+/** Stacks resource represents a collection of Hadoop Stacks
+ */
+@Singleton
+@Path(value = "/stacks")
+public class StacksResource {
+	   
+	Stacks stacks = Stacks.getInstance();
+	
+    public StacksResource() throws Exception {	
+        Stack stack123 = new Stack();
+        stacks.addStack(stack123);
+    }  
+    
+    /** Import a new Hadoop Stack description
+     * 
+     *  <p>
+	 *  REST:<br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;URL Path                                    : /stacks/<br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Method                                 : POST <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Request Header	                        : <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Content-type        = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accept              = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Response Header                        : <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Content-type        = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accept              = application/json <br>
+	 *  <p> 
+     * 
+     * @param	url Location of the new stack definition
+     * @throws 	Exception		throws Exception
+     */
+    @Path(value = "/stacks/")
+    @PUT
+    @Consumes({"application/json", "application/xml"})
+    public synchronized void importStackDescription(String url) throws Exception {
+    }
+    
+    /** Get the list of stacks installed with Ambari controller.
+     * 
+     *  <p>
+	 *  REST:<br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;URL Path                                    : /stacks/{stackName}<br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Method                                 : POST <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Request Header	                        : <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Content-type        = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accept              = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Response Header                        : <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Content-type        = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accept              = application/json <br>
+	 *  <p> 
+     * 
+     * @param searchToken	Optionally specify the search token to return the stacks where stack name includes the search token 
+     * @return				Returns list of stack definitions
+     * @throws Exception	throws Exception
+     */
+    /*@GET
+    public List<Stack> getStackList (@DefaultValue("") @QueryParam("search") String searchToken) throws Exception {
+    	List<Stack> searchResults = Stacks.getInstance().getStackList();
+    	if (!searchToken.equals("")) {
+    		searchResults = new ArrayList<Stack>();
+    		for (Stack cls : Stacks.getInstance().getStackList()) {
+    			if (cls.getName().matches("^.*"+searchToken+".*$")) {
+    				searchResults.add(cls);
+    			}
+    		}
+    	}
+    
+    	if (searchResults.isEmpty()) {
+    		throw new Exception ("No matching stacks found!");
+    	}
+    	return null;
+    }*/
+
+    /** Get the default blueprint for a particular stack
+     * 
+     *  <p>
+	 *  REST:<br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;URL Path                                    : /stacks/{stackName}<br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Method                                 : GET <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Request Header	                        : <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Content-type        = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accept              = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;HTTP Response Header                        : <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Content-type        = application/json <br>
+	 *  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accept              = application/json <br>
+	 *  <p> 
+     * 
+     * @param stackName  The name of the stack to get the default blueprint
+     * @return	The default blueprint for that stack
+     * @throws Exception	throws Exception
+     */
+    @GET
+    public Blueprint getDefaultBlueprint(@PathParam("stackName") String stackName) throws Exception {
+      return null;
+    }
+}

Added: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/Cluster.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/Cluster.java?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/Cluster.java (added)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/Cluster.java Thu Sep 22 16:13:55 2011
@@ -0,0 +1,14 @@
+package org.apache.ambari.resource.statemachine;
+
+import java.util.List;
+import java.util.Map;
+
+public interface Cluster extends LifeCycle {
+  public String getClusterName();
+  public List<Service> getServices();
+  public ClusterState getClusterState();
+  public Map<String, String> getServiceStates();
+  
+  public void addServices(List<Service> services);
+  public void terminate();
+}

Added: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ClusterEvent.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ClusterEvent.java?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ClusterEvent.java (added)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ClusterEvent.java Thu Sep 22 16:13:55 2011
@@ -0,0 +1,25 @@
+package org.apache.ambari.resource.statemachine;
+
+import org.apache.ambari.event.AbstractEvent;
+
+public class ClusterEvent extends AbstractEvent<ClusterEventType> {
+  private Cluster cluster;
+  private Service service;
+  public ClusterEvent(ClusterEventType type, Cluster cluster) {
+    super(type);
+    this.cluster = cluster;
+  }
+  //Need this to create an event that has details about the service
+  //that moved into a different state
+  public ClusterEvent(ClusterEventType type, Cluster cluster, Service service) {
+    super(type);
+    this.cluster = cluster;
+    this.service = service;
+  }
+  public Cluster getCluster() {
+    return cluster;
+  }
+  public Service getServiceCausingTransition() {
+    return service;
+  }
+}

Added: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ClusterEventType.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ClusterEventType.java?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ClusterEventType.java (added)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ClusterEventType.java Thu Sep 22 16:13:55 2011
@@ -0,0 +1,29 @@
+package org.apache.ambari.resource.statemachine;
+
+public enum ClusterEventType {
+  
+  //Producer:Client, Cluster
+  S_START,
+
+  //Producer:Client, Cluster
+  S_STOP,
+
+  //Producer: Service
+  S_START_SUCCESS,
+  
+  //Producer: Service
+  S_START_FAILURE,
+  
+  //Producer: Service
+  S_STOP_SUCCESS,
+  
+  //Producer: Service
+  S_STOP_FAILURE,
+  
+  //Producer: Client
+  S_RELEASE_NODES,
+  
+  //Producer: Client
+  S_ADD_NODES
+  
+}
\ No newline at end of file

Added: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ClusterImpl.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ClusterImpl.java?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ClusterImpl.java (added)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ClusterImpl.java Thu Sep 22 16:13:55 2011
@@ -0,0 +1,198 @@
+package org.apache.ambari.resource.statemachine;
+
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
+
+import org.apache.ambari.common.state.MultipleArcTransition;
+import org.apache.ambari.common.state.SingleArcTransition;
+import org.apache.ambari.common.state.StateMachine;
+import org.apache.ambari.common.state.StateMachineFactory;
+import org.apache.ambari.event.EventHandler;
+
+public class ClusterImpl implements Cluster, EventHandler<ClusterEvent> {
+
+  /* The state machine for the cluster looks like:
+   * INACTIVE --S_START--> STARTING --S_START_SUCCESS from all services--> ACTIVE
+   *                                --S_START_FAILURE from any service--> FAIL
+   * ACTIVE --S_STOP--> STOPPING --S_STOP_SUCCESS from all services--> INACTIVE
+   *                             --S_STOP_FAILURE from any service--> UNCLEAN_STOP
+   * FAIL --S_STOP--> STOPPING --S_STOP_SUCCESS--> INACTIVE
+   *                           --S_STOP_FAILURE--> UNCLEAN_STOP
+   * INACTIVE --S_RELEASE_NODES--> ATTIC
+   * ATTIC --S_ADD_NODES--> INACTIVE
+   */
+
+  private static final StateMachineFactory
+  <ClusterImpl,ClusterState,ClusterEventType,ClusterEvent>
+  stateMachineFactory = 
+  new StateMachineFactory
+  <ClusterImpl,ClusterState,ClusterEventType,ClusterEvent>(ClusterState.INACTIVE)
+  .addTransition(ClusterState.INACTIVE, ClusterState.STARTING, 
+      ClusterEventType.S_START, new StartClusterTransition())
+  .addTransition(ClusterState.STARTING, EnumSet.of(ClusterState.ACTIVE, 
+      ClusterState.STARTING), ClusterEventType.S_START_SUCCESS, 
+      new ServiceStartedTransition())
+  .addTransition(ClusterState.STARTING, ClusterState.FAIL, 
+      ClusterEventType.S_START_FAILURE)
+  .addTransition(ClusterState.ACTIVE, ClusterState.STOPPING, 
+      ClusterEventType.S_STOP)
+  .addTransition(ClusterState.STOPPING, ClusterState.INACTIVE, 
+      ClusterEventType.S_STOP_SUCCESS)
+  .addTransition(ClusterState.STOPPING, ClusterState.UNCLEAN_STOP, 
+      ClusterEventType.S_STOP_FAILURE)
+  .addTransition(ClusterState.FAIL, ClusterState.STOPPING, 
+      ClusterEventType.S_STOP)
+  .addTransition(ClusterState.STOPPING, ClusterState.INACTIVE, 
+      ClusterEventType.S_STOP_SUCCESS)
+  .addTransition(ClusterState.STOPPING, ClusterState.UNCLEAN_STOP, 
+      ClusterEventType.S_STOP_FAILURE)
+  .addTransition(ClusterState.INACTIVE, ClusterState.ATTIC, 
+      ClusterEventType.S_RELEASE_NODES)
+  .addTransition(ClusterState.ATTIC, ClusterState.INACTIVE, 
+      ClusterEventType.S_ADD_NODES)
+  .installTopology();
+  
+  private List<Service> services;
+  private Map<String, Set<String>> roleToNodes;
+  private StateMachine<ClusterState, ClusterEventType, ClusterEvent> 
+          stateMachine;
+  private String clusterName;
+  private int numServicesStarted;
+  private int totalEnabledServices;
+  private Lock readLock;
+  private Lock writeLock;
+  private short roleCount; 
+    
+  public ClusterImpl(String name) {
+    this.clusterName = name;
+    ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
+    this.readLock = readWriteLock.readLock();
+    this.writeLock = readWriteLock.writeLock();
+    this.stateMachine = stateMachineFactory.make(this);
+  }
+
+  @Override
+  public String getClusterName() {
+    return clusterName;
+  }
+
+  @Override
+  public ClusterState getClusterState() {
+    return stateMachine.getCurrentState();
+  }
+  
+  @Override
+  public void handle(ClusterEvent event) {
+    getStateMachine().doTransition(event.getType(), event);
+  }
+
+  @Override
+  public List<Service> getServices() {
+    return services;
+  }
+  
+  public StateMachine getStateMachine() {
+    return stateMachine;
+  }
+  
+  @Override  
+  public void addServices(List<Service> services) {
+    this.services.addAll(services);
+  }
+  
+  public Service getNextService() {
+    if (++roleCount <= services.size()) {
+      return services.get(roleCount - 1);
+    }
+    return null;
+  }
+  
+  private void incrStartedServiceCount() {
+    try {
+      writeLock.lock();
+      numServicesStarted++;
+    } finally {
+      writeLock.unlock();
+    }
+  }
+  
+  private int getStartedServiceCount() {
+    try {
+      readLock.lock();
+      return numServicesStarted;
+    } finally {
+      readLock.unlock();
+    }
+  }
+  
+  private int getTotalServiceCount() {
+    return totalEnabledServices;
+  }
+  
+  static class StartClusterTransition implements 
+  SingleArcTransition<ClusterImpl, ClusterEvent>  {
+
+    @Override
+    public void transition(ClusterImpl operand, ClusterEvent event) {
+      Service service = operand.getNextService();
+      if (service != null) {
+              //start the first service (plugin)
+        StateMachineInvoker.getAMBARIEventHandler().handle(
+            new ServiceEvent(ServiceEventType.S_START, service));
+      }
+    }
+    
+  }
+  
+  static class ServiceStartedTransition implements 
+  MultipleArcTransition<ClusterImpl, ClusterEvent, ClusterState>  {
+    @Override
+    public ClusterState transition(ClusterImpl operand, ClusterEvent event) {
+      //check whether all services started, and if not remain in the STARTING
+      //state, else move to the ACTIVE state
+      if (operand.getStartedServiceCount() == operand.getTotalServiceCount()) {
+        return ClusterState.ACTIVE;
+      }
+      operand.incrStartedServiceCount();
+      //TODO: start the next service (plugin)
+      return ClusterState.STARTING;
+    }
+    
+  }
+
+  @Override
+  public Map<String, String> getServiceStates() {
+    Map<String, String> serviceStateMap = new HashMap<String,String>();
+    for (Service s : services) {
+      serviceStateMap.put(s.getServiceName(), s.getServiceState().toString());
+    }
+    return serviceStateMap;
+  }
+
+  @Override
+  public void activate() {
+    StateMachineInvoker.getAMBARIEventHandler().handle(
+        new ClusterEvent(ClusterEventType.S_START, this));
+  }
+
+  @Override
+  public void deactivate() {
+    StateMachineInvoker.getAMBARIEventHandler().handle(
+        new ClusterEvent(ClusterEventType.S_STOP, this));
+  }
+
+  @Override
+  public void terminate() {
+    StateMachineInvoker.getAMBARIEventHandler().handle(
+        new ClusterEvent(ClusterEventType.S_RELEASE_NODES, this));    
+  }
+
+}

Added: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ClusterState.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ClusterState.java?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ClusterState.java (added)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ClusterState.java Thu Sep 22 16:13:55 2011
@@ -0,0 +1,5 @@
+package org.apache.ambari.resource.statemachine;
+
+public enum ClusterState {
+  INACTIVE, STARTING, ACTIVE, FAIL, ATTIC, STOPPING, UNCLEAN_STOP
+}
\ No newline at end of file

Added: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/LifeCycle.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/LifeCycle.java?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/LifeCycle.java (added)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/LifeCycle.java Thu Sep 22 16:13:55 2011
@@ -0,0 +1,11 @@
+package org.apache.ambari.resource.statemachine;
+
+/**
+ * All participants have two states -
+ * ACTIVE, INACTIVE
+ * 
+ */
+public interface LifeCycle {
+  public void activate();
+  public void deactivate();
+}

Added: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/Role.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/Role.java?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/Role.java (added)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/Role.java Thu Sep 22 16:13:55 2011
@@ -0,0 +1,11 @@
+package org.apache.ambari.resource.statemachine;
+
+public interface Role extends LifeCycle {
+  
+  public RoleState getRoleState();
+  
+  public String getRoleName();
+  
+  public Service getAssociatedService();
+  
+}

Added: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/RoleEvent.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/RoleEvent.java?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/RoleEvent.java (added)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/RoleEvent.java Thu Sep 22 16:13:55 2011
@@ -0,0 +1,17 @@
+package org.apache.ambari.resource.statemachine;
+
+import org.apache.ambari.event.AbstractEvent;
+
+
+public class RoleEvent extends AbstractEvent<RoleEventType> {
+  Role role;
+  public RoleEvent(RoleEventType eventType, Role role) {
+    super (eventType);
+    this.role = role;
+  }
+  
+  public Role getRole() {
+    return role;
+  }
+
+}

Added: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/RoleEventType.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/RoleEventType.java?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/RoleEventType.java (added)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/RoleEventType.java Thu Sep 22 16:13:55 2011
@@ -0,0 +1,23 @@
+package org.apache.ambari.resource.statemachine;
+
+public enum RoleEventType {
+  
+  //Producer:Client, Cluster
+  S_START,
+
+  //Producer:Client, Cluster
+  S_STOP,
+
+  //Producer: Service
+  S_START_SUCCESS,
+  
+  //Producer: Service
+  S_START_FAILURE,
+  
+  //Producer: Service
+  S_STOP_SUCCESS,
+  
+  //Producer: Service
+  S_STOP_FAILURE,
+  
+}

Added: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/RoleImpl.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/RoleImpl.java?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/RoleImpl.java (added)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/RoleImpl.java Thu Sep 22 16:13:55 2011
@@ -0,0 +1,100 @@
+package org.apache.ambari.resource.statemachine;
+
+import java.util.List;
+import java.util.Set;
+
+import org.apache.ambari.common.state.SingleArcTransition;
+import org.apache.ambari.common.state.StateMachine;
+import org.apache.ambari.common.state.StateMachineFactory;
+import org.apache.ambari.event.EventHandler;
+
+public class RoleImpl implements Role, EventHandler<RoleEvent> {
+
+  private RoleState myState;
+  private String roleName;
+  private List<String> hosts;
+  private Service service;
+  
+  /* The state machine for the service looks like:
+   * INACTIVE --S_START--> STARTING --S_START_SUCCESS--> ACTIVE
+   *                                --S_START_FAILURE--> FAIL
+   * ACTIVE --S_STOP--> STOPPING --S_STOP_SUCCESS--> INACTIVE
+   *                             --S_STOP_FAILURE--> UNCLEAN_STOP
+   * FAIL --S_STOP--> STOPPING --S_STOP_SUCCESS--> INACTIVE
+   *                           --S_STOP_FAILURE--> UNCLEAN_STOP
+   */
+  
+  private static final StateMachineFactory 
+  <RoleImpl, RoleState, RoleEventType, RoleEvent> stateMachineFactory 
+         = new StateMachineFactory<RoleImpl, RoleState, RoleEventType, 
+         RoleEvent>(RoleState.INACTIVE)
+         .addTransition(RoleState.INACTIVE, RoleState.STARTING, RoleEventType.S_START)
+         .addTransition(RoleState.STARTING, RoleState.ACTIVE, RoleEventType.S_START_SUCCESS, new SuccessStartTransition())
+         .addTransition(RoleState.STARTING, RoleState.FAIL, RoleEventType.S_START_FAILURE)
+         .addTransition(RoleState.ACTIVE, RoleState.STOPPING, RoleEventType.S_STOP)
+         .addTransition(RoleState.STOPPING, RoleState.INACTIVE, RoleEventType.S_STOP_SUCCESS)
+         .addTransition(RoleState.STOPPING, RoleState.UNCLEAN_STOP, RoleEventType.S_STOP_FAILURE)
+         .addTransition(RoleState.FAIL, RoleState.STOPPING, RoleEventType.S_STOP)
+         .addTransition(RoleState.STOPPING, RoleState.INACTIVE, RoleEventType.S_STOP_SUCCESS)
+         .addTransition(RoleState.STOPPING, RoleState.UNCLEAN_STOP, RoleEventType.S_STOP_FAILURE)
+         .installTopology();
+  
+  private final StateMachine<RoleState, RoleEventType, RoleEvent>
+      stateMachine;
+  
+  public RoleImpl(Service service, String roleName, Set<String> hosts) {
+    this.roleName = roleName;
+    this.service = service;
+    this.myState = RoleState.INACTIVE;
+    stateMachine = stateMachineFactory.make(this);
+  }
+  
+  public StateMachine getStateMachine() {
+    return stateMachine;
+  }
+  
+  @Override
+  public RoleState getRoleState() {
+    return stateMachine.getCurrentState();
+  }
+
+  @Override
+  public String getRoleName() {
+    return roleName;
+  }
+
+  @Override
+  public void handle(RoleEvent event) {
+    getStateMachine().doTransition(event.getType(), event);
+  }
+
+  @Override
+  public Service getAssociatedService() {
+    return service;
+  }
+  
+  public void addHosts(List<String> hosts) {
+    this.hosts.addAll(hosts);
+  }
+  
+  static class SuccessStartTransition implements 
+  SingleArcTransition<RoleImpl, RoleEvent>  {
+
+    @Override
+    public void transition(RoleImpl operand, RoleEvent event) {
+      ServiceImpl service = (ServiceImpl)operand.getAssociatedService();
+      StateMachineInvoker.getAMBARIEventHandler().handle(
+       new ServiceEvent(ServiceEventType.S_ROLE_STARTED, service, operand));
+    }
+  }
+
+  @Override
+  public void activate() {
+    //load the plugin and get the commands for starting the role
+  }
+
+  @Override
+  public void deactivate() {
+    //load the plugin and get the commands for stopping the role
+  }  
+}

Added: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/RoleState.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/RoleState.java?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/RoleState.java (added)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/RoleState.java Thu Sep 22 16:13:55 2011
@@ -0,0 +1,5 @@
+package org.apache.ambari.resource.statemachine;
+
+public enum RoleState {
+  INACTIVE, STARTING, ACTIVE, FAIL, STOPPING, UNCLEAN_STOP
+}
\ No newline at end of file

Added: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/Service.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/Service.java?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/Service.java (added)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/Service.java Thu Sep 22 16:13:55 2011
@@ -0,0 +1,10 @@
+package org.apache.ambari.resource.statemachine;
+
+public interface Service extends LifeCycle {
+  
+  public ServiceState getServiceState();
+  
+  public String getServiceName();
+  
+  public Cluster getAssociatedCluster();
+}

Added: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceEvent.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceEvent.java?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceEvent.java (added)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceEvent.java Thu Sep 22 16:13:55 2011
@@ -0,0 +1,29 @@
+package org.apache.ambari.resource.statemachine;
+
+import org.apache.ambari.event.AbstractEvent;
+
+
+public class ServiceEvent extends AbstractEvent<ServiceEventType> {
+  private Service service;
+  private Role role;
+  
+  public ServiceEvent(ServiceEventType eventType, Service service) {
+    super (eventType);
+    this.service = service;
+  }
+  
+  public ServiceEvent(ServiceEventType eventType, Service service, Role role) {
+    super (eventType);
+    this.service = service;
+    this.role = role;
+  }
+  
+  public Service getService() {
+    return service;
+  }
+  
+  public Role getRole() {
+    return role;
+  }
+
+}

Added: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceEventType.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceEventType.java?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceEventType.java (added)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceEventType.java Thu Sep 22 16:13:55 2011
@@ -0,0 +1,25 @@
+package org.apache.ambari.resource.statemachine;
+
+public enum ServiceEventType {
+  
+  //Producer:Client, Cluster
+  S_START,
+
+  //Producer:Client, Cluster
+  S_STOP,
+
+  //Producer: Service
+  S_START_SUCCESS,
+  
+  //Producer: Service
+  S_START_FAILURE,
+  
+  //Producer: Service
+  S_STOP_SUCCESS,
+  
+  //Producer: Service
+  S_STOP_FAILURE,
+  
+  //Producer: Role
+  S_ROLE_STARTED
+}

Added: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceImpl.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceImpl.java?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceImpl.java (added)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceImpl.java Thu Sep 22 16:13:55 2011
@@ -0,0 +1,137 @@
+package org.apache.ambari.resource.statemachine;
+
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.common.state.MultipleArcTransition;
+import org.apache.ambari.common.state.SingleArcTransition;
+import org.apache.ambari.common.state.StateMachine;
+import org.apache.ambari.common.state.StateMachineFactory;
+import org.apache.ambari.event.EventHandler;
+
+public class ServiceImpl implements Service, EventHandler<ServiceEvent> {
+
+  private ServiceState myState;
+  private Cluster cluster;
+  
+  /* The state machine for the service looks like:
+   * INACTIVE --S_START--> STARTING --S_START_SUCCESS--> ACTIVE
+   *                                --S_START_FAILURE--> FAIL
+   * ACTIVE --S_STOP--> STOPPING --S_STOP_SUCCESS--> INACTIVE
+   *                             --S_STOP_FAILURE--> UNCLEAN_STOP
+   * FAIL --S_STOP--> STOPPING --S_STOP_SUCCESS--> INACTIVE
+   *                           --S_STOP_FAILURE--> UNCLEAN_STOP
+   */
+  
+  private static final StateMachineFactory 
+  <ServiceImpl, ServiceState, ServiceEventType, ServiceEvent> stateMachineFactory 
+         = new StateMachineFactory<ServiceImpl, ServiceState, ServiceEventType, 
+         ServiceEvent>(ServiceState.INACTIVE)
+         .addTransition(ServiceState.INACTIVE, ServiceState.STARTING, ServiceEventType.S_START, new StartServiceTransition())
+         .addTransition(ServiceState.STARTING, EnumSet.of(ServiceState.ACTIVE, ServiceState.STARTING), ServiceEventType.S_ROLE_STARTED,
+             new RoleStartedTransition())
+         .addTransition(ServiceState.STARTING, ServiceState.FAIL, ServiceEventType.S_START_FAILURE)
+         .addTransition(ServiceState.ACTIVE, ServiceState.STOPPING, ServiceEventType.S_STOP)
+         .addTransition(ServiceState.STOPPING, ServiceState.INACTIVE, ServiceEventType.S_STOP_SUCCESS)
+         .addTransition(ServiceState.STOPPING, ServiceState.UNCLEAN_STOP, ServiceEventType.S_STOP_FAILURE)
+         .addTransition(ServiceState.FAIL, ServiceState.STOPPING, ServiceEventType.S_STOP)
+         .addTransition(ServiceState.STOPPING, ServiceState.INACTIVE, ServiceEventType.S_STOP_SUCCESS)
+         .addTransition(ServiceState.STOPPING, ServiceState.UNCLEAN_STOP, ServiceEventType.S_STOP_FAILURE)
+         .installTopology();
+  
+  private final StateMachine<ServiceState, ServiceEventType, ServiceEvent>
+      stateMachine;
+  private final List<Role> serviceRoles = new ArrayList<Role>();
+  private final String serviceName;
+  private short roleCount;
+  
+  public ServiceImpl(Cluster cluster, String serviceName) {
+    this.cluster = cluster;
+    this.serviceName = serviceName;
+    this.myState = ServiceState.INACTIVE;
+    stateMachine = stateMachineFactory.make(this);
+    //load plugin and get the roles and create them
+  }
+    
+  public StateMachine getStateMachine() {
+    return stateMachine;
+  }
+  
+  @Override
+  public ServiceState getServiceState() {
+    return stateMachine.getCurrentState();
+  }
+
+  @Override
+  public void handle(ServiceEvent event) {
+    getStateMachine().doTransition(event.getType(), event);
+  }
+
+  @Override
+  public Cluster getAssociatedCluster() {
+    return cluster;
+  }
+  
+  @Override
+  public String getServiceName() {
+    return serviceName;
+  }
+  
+  public void addRoles(List<Role> roles) {
+    this.serviceRoles.addAll(roles);
+  }
+  
+  public Role getNextRole() {
+    if (++roleCount <= serviceRoles.size()) {
+      return serviceRoles.get(roleCount - 1);  
+    }
+    return null;
+  }
+
+  static class StartServiceTransition implements 
+  SingleArcTransition<ServiceImpl, ServiceEvent>  {
+
+    @Override
+    public void transition(ServiceImpl operand, ServiceEvent event) {
+      Role firstRole = operand.getNextRole();
+      if (firstRole != null) {
+        StateMachineInvoker.getAMBARIEventHandler().handle(
+                            new RoleEvent(RoleEventType.S_START, firstRole));
+      }
+    }
+    
+  }
+  
+  static class RoleStartedTransition 
+  implements MultipleArcTransition<ServiceImpl, ServiceEvent, ServiceState>  {
+
+    @Override
+    public ServiceState transition(ServiceImpl operand, ServiceEvent event) {
+      //check whether all roles started, and if not remain in the STARTING
+      //state, else move to the ACTIVE state
+      Role role = operand.getNextRole();
+      if (role != null) {
+        StateMachineInvoker.getAMBARIEventHandler().handle(new RoleEvent(
+            RoleEventType.S_START, role));
+        return ServiceState.STARTING;
+      } else {
+        return ServiceState.ACTIVE;
+      }
+    }
+  }
+
+  @Override
+  public void activate() {
+    StateMachineInvoker.getAMBARIEventHandler().handle(
+              new ServiceEvent(ServiceEventType.S_START, this));
+  }
+
+  @Override
+  public void deactivate() {
+    StateMachineInvoker.getAMBARIEventHandler().handle(
+              new ServiceEvent(ServiceEventType.S_STOP, this));
+  }
+}

Added: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceState.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceState.java?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceState.java (added)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/ServiceState.java Thu Sep 22 16:13:55 2011
@@ -0,0 +1,5 @@
+package org.apache.ambari.resource.statemachine;
+
+public enum ServiceState {
+  INACTIVE, STARTING, ACTIVE, FAIL, STOPPING, UNCLEAN_STOP
+}
\ No newline at end of file

Added: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/StateMachineInvoker.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/StateMachineInvoker.java?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/StateMachineInvoker.java (added)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/resource/statemachine/StateMachineInvoker.java Thu Sep 22 16:13:55 2011
@@ -0,0 +1,61 @@
+package org.apache.ambari.resource.statemachine;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.ambari.event.AsyncDispatcher;
+import org.apache.ambari.event.Dispatcher;
+import org.apache.ambari.event.EventHandler;
+
+public class StateMachineInvoker {
+  
+  private static Dispatcher dispatcher;
+  
+  static {
+    dispatcher = new AsyncDispatcher();
+    dispatcher.register(ClusterEventType.class, new ClusterEventDispatcher());
+    dispatcher.register(ServiceEventType.class, new ServiceEventDispatcher());
+  }
+
+  public Dispatcher getAMBARIDispatcher() {
+    return dispatcher;
+  }
+
+  public static EventHandler getAMBARIEventHandler() {
+    return dispatcher.getEventHandler();
+  }
+
+  public static class ClusterEventDispatcher 
+  implements EventHandler<ClusterEvent> {
+    @Override
+    public void handle(ClusterEvent event) {
+      ((EventHandler<ClusterEvent>)event.getCluster()).handle(event);
+    }
+  }
+  
+  public static class ServiceEventDispatcher 
+  implements EventHandler<ServiceEvent> {
+    @Override
+    public void handle(ServiceEvent event) {
+      ((EventHandler<ServiceEvent>)event.getService()).handle(event);
+    }
+  }
+  
+  public static Cluster createClusterImpl(String clusterName) {
+    return new ClusterImpl(clusterName);
+  }
+  
+  public static Service addServiceInCluster(Cluster cluster, String serviceName) {
+    Service service = new ServiceImpl(cluster, serviceName);
+    return addServiceInCluster(cluster, service);
+  }
+  
+  public static Service addServiceInCluster(Cluster cluster, Service service) {
+    List<Service> serviceList = new ArrayList<Service>();
+    serviceList.add(service);
+    cluster.addServices(serviceList);
+    return service;
+  }
+    
+}

Added: incubator/ambari/trunk/controller/src/main/resources/WEB-INF/jetty.xml
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/resources/WEB-INF/jetty.xml?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/resources/WEB-INF/jetty.xml (added)
+++ incubator/ambari/trunk/controller/src/main/resources/WEB-INF/jetty.xml Thu Sep 22 16:13:55 2011
@@ -0,0 +1,191 @@
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
+
+<!-- =============================================================== -->
+<!-- Configure the Jetty Server                                      -->
+<!--                                                                 -->
+<!-- Documentation of this file format can be found at:              -->
+<!-- http://docs.codehaus.org/display/JETTY/jetty.xml                -->
+<!--                                                                 -->
+<!-- =============================================================== -->
+
+
+<Configure id="Server" class="org.mortbay.jetty.Server">
+
+    <!-- =========================================================== -->
+    <!-- Server Thread Pool                                          -->
+    <!-- =========================================================== -->
+    <Set name="ThreadPool">
+
+      <New class="org.mortbay.thread.QueuedThreadPool">
+        <Set name="minThreads">10</Set>
+        <Set name="maxThreads">200</Set>
+        <Set name="lowThreads">20</Set>
+        <Set name="SpawnOrShrinkAt">2</Set>
+      </New>
+
+      <!-- Optional Java 5 bounded threadpool with job queue 
+      <New class="org.mortbay.thread.concurrent.ThreadPool">
+        <Set name="corePoolSize">50</Set>
+        <Set name="maximumPoolSize">50</Set>
+      </New>
+      -->
+    </Set>
+
+
+
+    <!-- =========================================================== -->
+    <!-- Set connectors                                              -->
+    <!-- =========================================================== -->
+    <!-- One of each type!                                           -->
+    <!-- =========================================================== -->
+
+    <!-- Use this connector for many frequently idle connections
+         and for threadless continuations.
+    -->    
+    <Call name="addConnector">
+      <Arg>
+          <New class="org.mortbay.jetty.nio.SelectChannelConnector">
+            <Set name="port"><SystemProperty name="jetty.port" default="4088"/></Set>
+            <Set name="maxIdleTime">30000</Set>
+            <Set name="Acceptors">2</Set>
+            <Set name="statsOn">false</Set>
+            <Set name="confidentialPort">8443</Set>
+	    <Set name="lowResourcesConnections">5000</Set>
+	    <Set name="lowResourcesMaxIdleTime">5000</Set>
+          </New>
+      </Arg>
+    </Call>
+
+    <!-- Use this connector if NIO is not available. 
+    <Call name="addConnector">
+      <Arg>
+          <New class="org.mortbay.jetty.bio.SocketConnector">
+            <Set name="port">8081</Set>
+            <Set name="maxIdleTime">50000</Set>
+            <Set name="lowResourceMaxIdleTime">1500</Set>
+          </New>
+      </Arg>
+    </Call>
+    -->
+
+    <!-- =========================================================== -->
+    <!-- Set up global session ID manager                            -->
+    <!-- =========================================================== -->
+    <!--
+    <Set name="sessionIdManager">
+      <New class="org.mortbay.jetty.servlet.HashSessionIdManager">
+        <Set name="workerName">node1</Set>
+      </New>
+    </Set>
+    -->
+
+<!--    <Set name="UserRealms">
+    <Array type="org.mortbay.jetty.security.UserRealm">
+    <Item>
+    <New class="org.mortbay.jetty.security.HashUserRealm">
+    <Set name="name">Auth</Set>
+    <Set name="config"><SystemProperty name="CHUKWA_CONF_DIR" default="."/>/auth.conf</Set>
+    <Set name="refreshInterval">0</Set>
+    </New>
+    </Item>
+    </Array>
+    </Set> -->
+
+    <!-- =========================================================== -->
+    <!-- Set handler Collection Structure                            --> 
+    <!-- =========================================================== -->
+<!--    <Set name="handler">
+      <New id="Handlers" class="org.mortbay.jetty.handler.HandlerCollection">
+        <Set name="handlers">
+         <Array type="org.mortbay.jetty.Handler">
+           <Item>
+             <New id="Contexts" class="org.mortbay.jetty.handler.ContextHandlerCollection"/>
+           </Item>
+           <Item>
+             <New id="DefaultHandler" class="org.mortbay.jetty.handler.DefaultHandler"/>
+           </Item>
+           <Item>
+             <New id="RequestLog" class="org.mortbay.jetty.handler.RequestLogHandler"/>
+           </Item>
+         </Array>
+        </Set>
+      </New>
+    </Set> -->
+    
+    <!-- =========================================================== -->
+    <!-- Configure the context deployer                              -->
+    <!-- A context deployer will deploy contexts described in        -->
+    <!-- configuration files discovered in a directory.              -->
+    <!-- The configuration directory can be scanned for hot          -->
+    <!-- deployments at the configured scanInterval.                 -->
+    <!--                                                             -->
+    <!-- This deployer is configured to deploy contexts configured   -->
+    <!-- in the $JETTY_HOME/contexts directory                       -->
+    <!--                                                             -->
+    <!-- =========================================================== -->
+<!--    <Call name="addLifeCycle">
+      <Arg>
+        <New class="org.mortbay.jetty.deployer.ContextDeployer">
+          <Set name="contexts"><Ref id="Contexts"/></Set>
+          <Set name="configurationDir"><SystemProperty name="HMS_HOME" default="."/>/webapps/sandbox</Set>
+          <Set name="scanInterval">1</Set>
+        </New>
+      </Arg>
+    </Call> -->
+
+    <!-- =========================================================== -->
+    <!-- Configure the webapp deployer.                              -->
+    <!-- A webapp  deployer will deploy standard webapps discovered  -->
+    <!-- in a directory at startup, without the need for additional  -->
+    <!-- configuration files.    It does not support hot deploy or   -->
+    <!-- non standard contexts (see ContextDeployer above).          -->
+    <!--                                                             -->
+    <!-- This deployer is configured to deploy webapps from the      -->
+    <!-- $JETTY_HOME/webapps directory                               -->
+    <!--                                                             -->
+    <!-- Normally only one type of deployer need be used.            -->
+    <!--                                                             -->
+    <!-- =========================================================== -->
+    <Call name="addLifeCycle">
+      <Arg>
+        <New class="org.mortbay.jetty.deployer.WebAppDeployer">
+          <Set name="contexts"><Ref id="Contexts"/></Set>
+          <Set name="webAppDir"><SystemProperty name="HMS_HOME" default="."/>/webapps</Set>
+	  <Set name="parentLoaderPriority">false</Set>
+	  <Set name="extract">false</Set>
+	  <Set name="allowDuplicates">false</Set>
+        </New>
+      </Arg>
+    </Call>
+
+    <!-- =========================================================== -->
+    <!-- Configure Request Log                                       -->
+    <!-- Request logs  may be configured for the entire server here, -->
+    <!-- or they can be configured for a specific web app in a       -->
+    <!-- contexts configuration (see $(jetty.home)/contexts/test.xml -->
+    <!-- for an example).                                            -->
+    <!-- =========================================================== -->
+<!--    <Ref id="RequestLog">
+      <Set name="requestLog">
+        <New id="RequestLogImpl" class="org.mortbay.jetty.NCSARequestLog">
+          <Set name="filename"><SystemProperty name="HMS_LOG_DIR" default="./logs"/>/yyyy_mm_dd.request.log</Set>
+          <Set name="filenameDateFormat">yyyy_MM_dd</Set>
+          <Set name="retainDays">90</Set>
+          <Set name="append">true</Set>
+          <Set name="extended">true</Set>
+          <Set name="logCookies">false</Set>
+          <Set name="LogTimeZone">GMT</Set>
+        </New>
+      </Set>
+    </Ref> -->
+
+    <!-- =========================================================== -->
+    <!-- extra options                                               -->
+    <!-- =========================================================== -->
+    <Set name="stopAtShutdown">true</Set>
+    <Set name="sendServerVersion">true</Set>
+    <Set name="sendDateHeader">true</Set>
+    <Set name="gracefulShutdown">1000</Set>
+
+</Configure>

Added: incubator/ambari/trunk/controller/src/main/resources/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/resources/WEB-INF/web.xml?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/resources/WEB-INF/web.xml (added)
+++ incubator/ambari/trunk/controller/src/main/resources/WEB-INF/web.xml Thu Sep 22 16:13:55 2011
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+   version="2.5"> 
+
+    <description>
+      HMS Controller
+    </description>
+    <display-name>HMS Controller</display-name>
+
+    <servlet>
+      <servlet-name>REST_API</servlet-name>
+      <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer
+      </servlet-class>
+      <init-param>
+	<param-name>com.sun.jersey.config.property.packages</param-name>
+	<param-value>org.apache.hms.controller.rest</param-value>
+      </init-param>
+      <load-on-startup>1</load-on-startup>
+    </servlet>
+    <servlet-mapping>
+      <servlet-name>REST_API</servlet-name>
+      <url-pattern>/v1/*</url-pattern>
+    </servlet-mapping>    
+
+</web-app>

Added: incubator/ambari/trunk/controller/src/main/resources/log4j.properties
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/resources/log4j.properties?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/resources/log4j.properties (added)
+++ incubator/ambari/trunk/controller/src/main/resources/log4j.properties Thu Sep 22 16:13:55 2011
@@ -0,0 +1,28 @@
+# 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.
+
+log4j.rootLogger=INFO, R
+log4j.appender.R=org.apache.log4j.RollingFileAppender
+log4j.appender.R.File=${HMS_LOG_DIR}/hms-controller.log
+log4j.appender.R.MaxFileSize=10MB
+log4j.appender.R.MaxBackupIndex=10
+log4j.appender.R.layout=org.apache.log4j.PatternLayout
+log4j.appender.R.layout.ConversionPattern=%d{ISO8601} %p %t %c{1} - %m%n
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.follow=true
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %p %t %c{1} - %m%n
+

Added: incubator/ambari/trunk/controller/src/main/webapps/configure-cluster.html
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/webapps/configure-cluster.html?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/webapps/configure-cluster.html (added)
+++ incubator/ambari/trunk/controller/src/main/webapps/configure-cluster.html Thu Sep 22 16:13:55 2011
@@ -0,0 +1,105 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<h2>Configure a cluster</h2>
+<form class="form">
+<p>Cluster Name</p>
+<p>
+  <span id="clusterName"></span>
+  <input type="hidden" id="cluster" value="">
+  <span id="cluster_message" class="warn"></span>
+</p>
+<p>Nodes Manifest</p>
+<p>
+  <input type="text" id="nodes" value="http://hadooplab21:4080/v1/nodes/manifest/sample" size="80">
+  <span id="nodes_message" class="warn"></span>
+</p>
+<p>Software Manifest</p>
+<p>
+  <input type="text" id="software" value="http://hadooplab21:4080/v1/software/manifest/sample" size="80">
+  <span id="software_message" class="warn"></span>
+</p>
+<p>Configuration Manifest</p>
+<p>
+  <input type="text" id="config" value="http://hadooplab21:4080/v1/config/manifest/create-hadoop-cluster" size="80">
+  <span id="config_message" class="warn"></span>
+</p>
+<p>
+<button type="submit" id="config" value="Configure" onClick="return configureCluster()">Configure</button>
+<button type="submit" id="cancel" onclick="javascript:window.location='/';">Cancel</button>
+</p>
+</form>
+<script type="text/javascript">
+function configureCluster() {
+  var cluster = $('#cluster').val();
+  var nodes = $('#nodes').val();
+  var config = $('#config').val();
+  var software = $('#software').val();
+  var bailout = false;
+
+  if(cluster=="") {
+    $('#cluster_message').text("Cluster name can not be empty.");
+    bailout = true;
+  }
+
+  if(nodes=="") {
+    $('#nodes_message').text("Nodes manifest URL can not be empty.");
+    bailout = true;
+  }
+
+  if(software=="") {
+    $('#software_message').text("Software manifest URL can not be empty.");
+    bailout = true;
+  }
+
+  if(config=="") {
+    $('#config_message').text("Config manifest URL can not be empty.");
+    bailout = true;
+  }
+
+  if(bailout) {
+    return false;
+  }
+
+  var data = '{"cmd":"upgrade","dry-run":"false","clusterManifest":{"@clusterName":"'+cluster+'","nodes":{"@url":"'+nodes+'"},"software":{"@url":"'+software+'"},"config":{"@url":"'+config+'"}}}';
+    $.ajax({
+      type: 'POST',
+      url: '/v1/controller/upgrade/cluster',
+      contentType: "application/json; charset=utf-8",
+      data: data,
+      success: function(data) {
+        var url = '/?func=status-command&cmd='+data['output'];
+        window.location.href = url;
+      },
+      dataType:'json'
+    });
+}
+
+$(document).ready(function() {
+  $.extend({
+    getUrlVars: function(){
+      var vars = [], hash;
+      var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
+      for(var i = 0; i < hashes.length; i++) {
+        hash = hashes[i].split('=');
+        vars.push(hash[0]);
+        vars[hash[0]] = hash[1];
+      }
+      return vars;
+    },
+    getUrlVar: function(name){
+      return $.getUrlVars()[name];
+    }
+  });
+  var prefix = window.location.protocol+'//'+window.location.hostname+':'+window.location.port;
+  $('#nodes').val(prefix+'/v1/nodes/manifest/sample');
+  $('#software').val(prefix+'/v1/software/manifest/sample');
+  $('#config').val(prefix+'/v1/config/manifest/create-hadoop-cluster');
+  var cluster = $.getUrlVar('cluster');
+  $('#cluster').val(cluster);
+  $('#clusterName').text(cluster);
+
+});
+</script>
+</body>
+</html>

Added: incubator/ambari/trunk/controller/src/main/webapps/create-cluster.html
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/webapps/create-cluster.html?rev=1174242&view=auto
==============================================================================
--- incubator/ambari/trunk/controller/src/main/webapps/create-cluster.html (added)
+++ incubator/ambari/trunk/controller/src/main/webapps/create-cluster.html Thu Sep 22 16:13:55 2011
@@ -0,0 +1,111 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<h2>Create A New Cluster</h2>
+<form class="form">
+<p>Cluster Name</p>
+<p>
+  <input type="text" id="cluster" value="" size="50">
+  <span id="cluster_message" class="warn"></span>
+</p>
+<p>Nodes Manifest</p>
+<p>
+  <input type="text" id="nodes" value="http://localhost:4080/v1/nodes/manifest/sample" class="formInput">
+  <span id="nodes_message" class="warn"></span>
+</p>
+<p>Software Manifest</p>
+<p>
+  <input type="text" id="software" value="http://localhost:4080/v1/software/manifest/sample" class="formInput">
+  <span id="software_message" class="warn"></span>
+</p>
+<p>Configuration Manifest</p>
+<p>
+  <input type="text" id="config" value="http://localhost:4080/v1/config/manifest/create-hadoop-cluster" class="formInput">
+  <span id="config_message" class="warn"></span>
+</p>
+  <p>
+    <button type="submit" id="create" onClick="return createCluster()">Create</button>
+    <button type="submit" id="cancel" onclick="javascript:window.location='/';">Cancel</button>
+  </p>
+</form>
+<script type="text/javascript">
+function createCluster() {
+  var cluster = $('#cluster').val();
+  var nodes = $('#nodes').val();
+  var config = $('#config').val();
+  var software = $('#software').val();
+  var bailout = false;
+
+  if(cluster=="") {
+    $('#cluster_message').text("Cluster name can not be empty.");
+    bailout = true;
+  }
+
+  if(nodes=="") {
+    $('#nodes_message').text("Nodes manifest URL can not be empty.");
+    bailout = true;
+  }
+
+  if(software=="") {
+    $('#software_message').text("Software manifest URL can not be empty.");
+    bailout = true;
+  }
+
+  if(config=="") {
+    $('#config_message').text("Config manifest URL can not be empty.");
+    bailout = true;
+  }
+
+  if(bailout) {
+    return false;
+  }
+
+  var data = '{"cmd":"create","dry-run":"false","clusterManifest":{"@clusterName":"'+cluster+'","nodes":{"@url":"'+nodes+'"},"software":{"@url":"'+software+'"},"config":{"@url":"'+config+'"}}}';
+    $.ajax({
+      type: 'POST',
+      url: '/v1/controller/create/cluster',
+      contentType: "application/json; charset=utf-8",
+      data: data,
+      success: function(data) {
+        var url = '/?func=status-command&cmd='+data['output'];
+        window.location.href = url;
+      },
+      dataType:'json'
+    });
+  return false;
+}
+
+$(document).ready(function() {
+  var prefix = window.location.protocol+'//'+window.location.hostname+':'+window.location.port;
+  $('#nodes').val(prefix+'/v1/nodes/manifest/sample');
+  $.ajax({
+    type: 'GET',
+    url: '/v1/nodes/manifest',
+    dataType:'json',
+    success: function(data) {
+      var nodes = data['nodesManifest'];
+      var list = [];
+      var x = 0;
+      if(nodes.constructor.toString().indexOf('Array') == -1) {
+        list[x++] = nodes['@url'];
+      } else {
+        for(var node in nodes) {
+          list[x++] = nodes[node]['@url'];
+        }
+      }
+      if(list.length>0) {
+        $('#nodes').val(list[0]);
+      }
+      $('#nodes').autocomplete({ source: list });
+    }
+  }); 
+  $('#software').val('http://hrt8n36.cc1.ygridcore.net/hadoop-0.20.204.0.xml');
+  $('#config').val('http://hrt8n36.cc1.ygridcore.net/create-hadoop-0.20.204.0.xml');
+  //$('#software').val(prefix+'/v1/software/manifest/sample');
+  //$('#config').val(prefix+'/v1/config/manifest/create-hadoop-cluster');
+  $("#navigation").load("/nav.html");
+});
+
+</script>
+</body>
+</html>



Mime
View raw message