You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by vg...@apache.org on 2011/09/29 21:16:23 UTC

svn commit: r1177405 - in /incubator/ambari/trunk: ./ client/src/main/java/org/apache/ambari/common/rest/entities/ controller/src/main/java/org/apache/ambari/controller/ controller/src/main/java/org/apache/ambari/controller/rest/resources/

Author: vgogate
Date: Thu Sep 29 19:16:23 2011
New Revision: 1177405

URL: http://svn.apache.org/viewvc?rev=1177405&view=rev
Log:
AMBARI-19

Modified:
    incubator/ambari/trunk/CHANGES.txt
    incubator/ambari/trunk/client/src/main/java/org/apache/ambari/common/rest/entities/Node.java
    incubator/ambari/trunk/client/src/main/java/org/apache/ambari/common/rest/entities/NodeState.java
    incubator/ambari/trunk/client/src/main/java/org/apache/ambari/common/rest/entities/ObjectFactory.java
    incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/Clusters.java
    incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/rest/resources/ClusterResource.java

Modified: incubator/ambari/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/CHANGES.txt?rev=1177405&r1=1177404&r2=1177405&view=diff
==============================================================================
--- incubator/ambari/trunk/CHANGES.txt (original)
+++ incubator/ambari/trunk/CHANGES.txt Thu Sep 29 19:16:23 2011
@@ -2,6 +2,8 @@ Ambari Change log
 
 Release 0.1.0 - unreleased
 
+  AMBARI-19. Fix Cluster resource API nodes reservation logic
+
   AMBARI-16. Implement Stacks resource API
 
   AMBARI-14. Implement Ambari REST API for cluster resource

Modified: incubator/ambari/trunk/client/src/main/java/org/apache/ambari/common/rest/entities/Node.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/client/src/main/java/org/apache/ambari/common/rest/entities/Node.java?rev=1177405&r1=1177404&r2=1177405&view=diff
==============================================================================
--- incubator/ambari/trunk/client/src/main/java/org/apache/ambari/common/rest/entities/Node.java (original)
+++ incubator/ambari/trunk/client/src/main/java/org/apache/ambari/common/rest/entities/Node.java Thu Sep 29 19:16:23 2011
@@ -36,22 +36,20 @@ import javax.xml.datatype.XMLGregorianCa
 @XmlType(name = "NodeType", propOrder = {
     "name",
     "nodeAttributes",
-    "nodeState",
-    "agentDeploymentState"
+    "nodeState"
 })
 public class Node {
     
     @XmlElement(name = "Name", required = true)
     protected String name;
-    @XmlElement(name = "NodeAttributes", required = true)
+    @XmlElement(name = "NodeAttributes")
     protected NodeAttributes nodeAttributes;
     @XmlElement(name = "NodeState", required = true)
     protected NodeState nodeState;
    
-    public Node () {}
-
     public Node (String name) {
       this.name = name;
+      this.nodeState = new NodeState();
     }
 	
     /*

Modified: incubator/ambari/trunk/client/src/main/java/org/apache/ambari/common/rest/entities/NodeState.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/client/src/main/java/org/apache/ambari/common/rest/entities/NodeState.java?rev=1177405&r1=1177404&r2=1177405&view=diff
==============================================================================
--- incubator/ambari/trunk/client/src/main/java/org/apache/ambari/common/rest/entities/NodeState.java (original)
+++ incubator/ambari/trunk/client/src/main/java/org/apache/ambari/common/rest/entities/NodeState.java Thu Sep 29 19:16:23 2011
@@ -38,11 +38,11 @@ import javax.xml.datatype.XMLGregorianCa
 })
 public class NodeState {
 
-        @XmlElement(name = "lastHeartbeatTime", required = true)
+    @XmlElement(name = "lastHeartbeatTime", required = true)
     @XmlSchemaType(name = "dateTime")
     protected XMLGregorianCalendar lastHeartbeatTime;
         
-        /*
+    /*
      * Associating the cluster name would reserve the node for a given cluster
      * 
      */

Modified: incubator/ambari/trunk/client/src/main/java/org/apache/ambari/common/rest/entities/ObjectFactory.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/client/src/main/java/org/apache/ambari/common/rest/entities/ObjectFactory.java?rev=1177405&r1=1177404&r2=1177405&view=diff
==============================================================================
--- incubator/ambari/trunk/client/src/main/java/org/apache/ambari/common/rest/entities/ObjectFactory.java (original)
+++ incubator/ambari/trunk/client/src/main/java/org/apache/ambari/common/rest/entities/ObjectFactory.java Thu Sep 29 19:16:23 2011
@@ -50,13 +50,6 @@ public class ObjectFactory {
     public ObjectFactory() {
     }
 
-    /**
-     * Create an instance of {@link Node }
-     * 
-     */
-    public Node createNodeType() {
-        return new Node();
-    }
 
     /**
      * Create an instance of {@link User }

Modified: incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/Clusters.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/Clusters.java?rev=1177405&r1=1177404&r2=1177405&view=diff
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/Clusters.java (original)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/Clusters.java Thu Sep 29 19:16:23 2011
@@ -56,6 +56,9 @@ public class Clusters {
     private static Clusters ClustersTypeRef=null;
         
     private Clusters() {
+        /*
+         * Cluster definition 
+         */
         ClusterDefinition cluster123 = new ClusterDefinition();
         
         cluster123.setName("blue.dev.Cluster123");
@@ -67,6 +70,46 @@ public class Clusters {
         activeServices.add("mapred");
         cluster123.setActiveServices(activeServices);
         
+        List<String> nodeRangeExpressions = new ArrayList<String>();
+        String nodes1 = "jt-nodex";
+        String nodes2 = "nn-nodex";
+        String nodes3 = "hostname-1x hostname-2x hostname-3x hostname-4x";
+        String nodes4 = "node-2x node-3x node-4x";  
+        nodeRangeExpressions.add(nodes1);
+        nodeRangeExpressions.add(nodes2);
+        nodeRangeExpressions.add(nodes3);
+        nodeRangeExpressions.add(nodes4);    
+        cluster123.setNodeRangeExpressions(nodeRangeExpressions);
+        
+        RoleToNodesMap rnm = new RoleToNodesMap();
+        
+        RoleToNodesMapEntry rnme = new RoleToNodesMapEntry();
+        rnme.setRoleName("jobtracker-role");
+        nodeRangeExpressions = new ArrayList<String>();
+        nodeRangeExpressions.add(nodes1);
+        rnme.setNodeRangeExpressions(nodeRangeExpressions);
+        rnm.getRoleToNodesMapEntry().add(rnme);
+        
+        rnme = new RoleToNodesMapEntry();
+        rnme.setRoleName("namenode-role");
+        nodeRangeExpressions = new ArrayList<String>();
+        nodeRangeExpressions.add(nodes2);
+        rnme.setNodeRangeExpressions(nodeRangeExpressions);
+        rnm.getRoleToNodesMapEntry().add(rnme);
+        
+        rnme = new RoleToNodesMapEntry();
+        rnme.setRoleName("slaves-role");
+        nodeRangeExpressions = new ArrayList<String>();
+        nodeRangeExpressions.add(nodes3);
+        nodeRangeExpressions.add(nodes4);
+        rnme.setNodeRangeExpressions(nodeRangeExpressions);
+        rnm.getRoleToNodesMapEntry().add(rnme);
+        
+        cluster123.setRoleToNodesMap(rnm);
+        
+        /*
+         * Cluster definition 
+         */
         ClusterDefinition cluster124 = new ClusterDefinition();
         cluster124.setName("blue.research.Cluster124");
         cluster124.setBlueprintName("cluster124-blueprint");
@@ -77,6 +120,43 @@ public class Clusters {
         activeServices.add("mapred");
         cluster124.setActiveServices(activeServices);
         
+        nodeRangeExpressions = new ArrayList<String>();
+        nodes1 = "jt-node";
+        nodes2 = "nn-node";
+        nodes3 = "hostname-1 hostname-2 hostname-3 hostname-4";
+        nodes4 = "node-2 node-3 node-4";  
+        nodeRangeExpressions.add(nodes1);
+        nodeRangeExpressions.add(nodes2);
+        nodeRangeExpressions.add(nodes3);
+        nodeRangeExpressions.add(nodes4);    
+        cluster124.setNodeRangeExpressions(nodeRangeExpressions);
+        
+        rnm = new RoleToNodesMap();
+        
+        rnme = new RoleToNodesMapEntry();
+        rnme.setRoleName("jobtracker-role");
+        nodeRangeExpressions = new ArrayList<String>();
+        nodeRangeExpressions.add(nodes1);
+        rnme.setNodeRangeExpressions(nodeRangeExpressions);
+        rnm.getRoleToNodesMapEntry().add(rnme);
+        
+        rnme = new RoleToNodesMapEntry();
+        rnme.setRoleName("namenode-role");
+        nodeRangeExpressions = new ArrayList<String>();
+        nodeRangeExpressions.add(nodes2);
+        rnme.setNodeRangeExpressions(nodeRangeExpressions);
+        rnm.getRoleToNodesMapEntry().add(rnme);
+        
+        rnme = new RoleToNodesMapEntry();
+        rnme.setRoleName("slaves-role");
+        nodeRangeExpressions = new ArrayList<String>();
+        nodeRangeExpressions.add(nodes3);
+        nodeRangeExpressions.add(nodes4);
+        rnme.setNodeRangeExpressions(nodeRangeExpressions);
+        rnm.getRoleToNodesMapEntry().add(rnme);
+        
+        cluster124.setRoleToNodesMap(rnm);
+        
         try {
             addCluster(cluster123);
             addCluster(cluster124);
@@ -116,8 +196,8 @@ public class Clusters {
     	 * TODO: Validate the cluster definition
     	 */
     	if (c.getName() == null ||  c.getName().equals("")) {
-    		Exception e = new Exception("Cluster Name must be specified and must be non-empty string");
-    		throw new WebApplicationException(e, Response.Status.INTERNAL_SERVER_ERROR);
+    		String msg = "Cluster Name must be specified and must be non-empty string";
+    		throw new WebApplicationException((new ExceptionResponse(msg, Response.Status.BAD_REQUEST)).get());
     	}
     	
     	synchronized (operational_clusters) {
@@ -125,8 +205,8 @@ public class Clusters {
     		 * Check if cluster already exists
     		 */
     		if (operational_clusters.containsKey(c.getName())) {
-    			Exception e = new Exception("Cluster ["+c.getName()+"] already exists");
-    			throw new WebApplicationException(e, Response.Status.CONFLICT);
+    			String msg = "Cluster ["+c.getName()+"] already exists";
+    			throw new WebApplicationException((new ExceptionResponse(msg, Response.Status.CONFLICT)).get());
     		}
     		
     		/*
@@ -189,23 +269,41 @@ public class Clusters {
     	String cname = cls.getClusterDefinition().getName();
     	
     	/*
+    	 * Check if all the nodes explicitly specified in the RoleToNodesMap belong the cluster node range specified 
+    	 */
+    	ConcurrentHashMap<String, Node> all_nodes = Nodes.getInstance().getNodes();
+        List<String> cluster_node_range = new ArrayList<String>();
+        cluster_node_range.addAll(getHostnamesFromRangeExpressions(nodeRangeExpressions));
+        
+        List<String> nodes_specified_using_role_association = new ArrayList<String>();
+        for (RoleToNodesMapEntry e : cls.getClusterDefinition().getRoleToNodesMap().getRoleToNodesMapEntry()) {
+            List<String> hosts = getHostnamesFromRangeExpressions(e.getNodeRangeExpressions());
+            nodes_specified_using_role_association.addAll(hosts);
+            // TODO: Remove any duplicate nodes from nodes_specified_using_role_association
+        }
+        
+        nodes_specified_using_role_association.removeAll(cluster_node_range);
+        if (!nodes_specified_using_role_association.isEmpty()) {
+            String msg = "Some nodes explicityly associated with roles using RoleToNodesMap do not belong in the " +
+            		     "golbal node range specified for the cluster : ["+nodes_specified_using_role_association+"]";
+            throw new WebApplicationException((new ExceptionResponse(msg, Response.Status.BAD_REQUEST)).get());
+        }
+        
+    	/*
 		 * Reserve the nodes as specified in the node range expressions
 		 * -- throw exception if any nodes are pre-associated with other cluster
-		 */
-    	ConcurrentHashMap<String, Node> all_nodes = Nodes.getInstance().getNodes();
-    	List<String> specified_node_range = new ArrayList<String>();
-    	specified_node_range.addAll(getHostnamesFromRangeExpressions(nodeRangeExpressions));
-    	List<String> nodes_currently_allocated = new ArrayList<String>();
+		 */	
+    	List<String> nodes_currently_allocated_to_cluster = new ArrayList<String>();
     	for (Node n : Nodes.getInstance().getNodes().values()) {
     		if (n.getNodeState().getClusterName().equals(cls.getClusterDefinition().getName())) {
-    			nodes_currently_allocated.add(n.getName());
+    			nodes_currently_allocated_to_cluster.add(n.getName());
     		}
     	}
     	
-    	List<String> nodes_to_allocate = new ArrayList<String>(specified_node_range);
-    	nodes_to_allocate.removeAll(nodes_currently_allocated);
-    	List<String> nodes_to_deallocate = new ArrayList<String>(nodes_currently_allocated);
-    	nodes_to_deallocate.removeAll(specified_node_range);
+    	List<String> nodes_to_allocate = new ArrayList<String>(cluster_node_range);
+    	nodes_to_allocate.removeAll(nodes_currently_allocated_to_cluster);
+    	List<String> nodes_to_deallocate = new ArrayList<String>(nodes_currently_allocated_to_cluster);
+    	nodes_to_deallocate.removeAll(cluster_node_range);
     	
 		/*
 		 * Check for any nodes that are allocated to other cluster
@@ -229,8 +327,8 @@ public class Clusters {
 			 * TODO: Return invalid request code and return list of preallocated nodes as a part of
 			 *       response element
 			 */
-			Exception e = new Exception("Some of the nodes specified for the cluster roles are allocated to other cluster: ["+preallocatedhosts+"]");
-    		throw new WebApplicationException(e, Response.Status.CONFLICT);
+			String msg = "Some of the nodes specified for the cluster roles are allocated to other cluster: ["+preallocatedhosts+"]";
+    		throw new WebApplicationException((new ExceptionResponse(msg, Response.Status.CONFLICT)).get());
 		}
 		
 		/*
@@ -277,7 +375,6 @@ public class Clusters {
 		/*
 		 * Add list of roles to Node
 		 * If node is not explicitly associated with any role then assign it w/ default role
-		 * TODO: 
 		 */
 		for (RoleToNodesMapEntry e : roleToNodesMap.getRoleToNodesMapEntry()) {
 			List<String> hosts = getHostnamesFromRangeExpressions(e.getNodeRangeExpressions());
@@ -309,23 +406,24 @@ public class Clusters {
     /* 
      * Update cluster definition
      * Always latest version is kept in memory
+     * TODO: Need versions to be preserved in memory w/ link to cluster before update? 
     */
-    public void updateCluster(String clusterName, ClusterDefinition c) throws Exception {
+    public ClusterDefinition updateCluster(String clusterName, ClusterDefinition c) throws Exception {
         
         /*
          * Validate cluster definition
          */
         if (c.getName() == null || c.getName().equals("") || !c.getName().equals(clusterName)) {
-            Exception e = new Exception("Cluster name in resource URI ["+clusterName+"] does not match with one specified in update request element");
-            throw new WebApplicationException(e, Response.Status.BAD_REQUEST);
+            String msg = "Cluster name in resource URI ["+clusterName+"] does not match with one specified in update request element";
+            throw new WebApplicationException((new ExceptionResponse(msg, Response.Status.BAD_REQUEST)).get());
         }
         
         /*
          * Check if cluster already exists
          */
         if (!this.operational_clusters.containsKey(clusterName)) {
-            Exception e = new Exception("Cluster ["+clusterName+"] does not exits");
-            throw new WebApplicationException(e, Response.Status.NOT_FOUND);
+            String msg = "Cluster ["+clusterName+"] does not exits";
+            throw new WebApplicationException((new ExceptionResponse(msg, Response.Status.NOT_FOUND)).get());
         }
         
         Cluster cls = this.operational_clusters.get(clusterName);
@@ -353,7 +451,7 @@ public class Clusters {
              * TODO: Persist the latest cluster definition under new revision
              */
         }
-        return;
+        return cls.getClusterDefinition();
     }
     
     /*
@@ -400,9 +498,8 @@ public class Clusters {
      */
     public ClusterDefinition getClusterDefinition(String clusterName) throws Exception  {
         if (!this.operational_clusters.containsKey(clusterName)) {
-            Exception e = new Exception("Cluster ["+clusterName+"] does not exits");
-            //throw new WebApplicationException(e, Response.Status.NOT_FOUND);
-            throw e;
+            String msg = "Cluster ["+clusterName+"] does not exits";
+            throw new WebApplicationException((new ExceptionResponse(msg, Response.Status.NOT_FOUND)).get());
         }
         return this.operational_clusters.get(clusterName).getClusterDefinition();
     }
@@ -413,8 +510,8 @@ public class Clusters {
     */
     public ClusterState getClusterState(String clusterName) throws WebApplicationException {
         if (!this.operational_clusters.containsKey(clusterName)) {
-            Exception e = new Exception("Cluster ["+clusterName+"] does not exits");
-            throw new WebApplicationException(e, Response.Status.NOT_FOUND);
+            String msg = "Cluster ["+clusterName+"] does not exits";
+            throw new WebApplicationException((new ExceptionResponse(msg, Response.Status.NOT_FOUND)).get());
         }
         return this.operational_clusters.get(clusterName).getClusterState();
     }
@@ -474,7 +571,7 @@ public class Clusters {
 	public String getDefaultRoleName(String clusterName) throws Exception {
 	    Cluster c = Clusters.getInstance().getClusterByName(clusterName);
 	    // TODO: find the default role from the clsuter blueprint 
-		return "slaves";
+		return "slaves-role";
 	}
 	
 	/*

Modified: 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=1177405&r1=1177404&r2=1177405&view=diff
==============================================================================
--- incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/rest/resources/ClusterResource.java (original)
+++ incubator/ambari/trunk/controller/src/main/java/org/apache/ambari/controller/rest/resources/ClusterResource.java Thu Sep 29 19:16:23 2011
@@ -101,10 +101,14 @@ public class ClusterResource {
      */ 
     @PUT
     @Consumes({"application/json", "application/xml"})
-    public ClusterDefinition updateClusterDefinition(@PathParam("clusterName") String clusterName, ClusterDefinition cluster) throws Exception {
-        
-    //Clusters.getInstance().updateCluster(clusterName, cluster);
-    return null;
+    public ClusterDefinition updateClusterDefinition(@PathParam("clusterName") String clusterName, ClusterDefinition cluster) throws Exception {    
+        try {
+            return Clusters.getInstance().updateCluster(clusterName, cluster);
+        }catch (WebApplicationException we) {
+            throw we;
+        }catch (Exception e) {
+            throw new WebApplicationException((new ExceptionResponse(e)).get());
+        }     
     }
      
     /** Delete the the cluster.
@@ -130,7 +134,13 @@ public class ClusterResource {
     @DELETE
     @Consumes({"application/json", "application/xml"})
     public void deleteCluster( @PathParam("clusterName") String clusterName) throws Exception {
-        Clusters.getInstance().deleteCluster(clusterName);
+        try {
+            Clusters.getInstance().deleteCluster(clusterName);
+        }catch (WebApplicationException we) {
+            throw we;
+        }catch (Exception e) {
+            throw new WebApplicationException((new ExceptionResponse(e)).get());
+        }    
     }
     
     /** Get the cluster state.
@@ -159,28 +169,33 @@ public class ClusterResource {
      */
     @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;
-        }
+    @Produces({"application/json", "application/xml"})
+    public ClusterState getClusterState(@PathParam("clusterName") String clusterName) throws Exception {
+        try {
+            return Clusters.getInstance().getClusterState(clusterName);
+        }catch (WebApplicationException we) {
+            throw we;
+        }catch (Exception e) {
+            throw new WebApplicationException((new ExceptionResponse(e)).get());
+        }    
+    }
     
     /** 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> 
-         *  
+     *  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)