You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by sp...@apache.org on 2014/12/04 17:23:03 UTC

ambari git commit: AMBARI-7121: CapScheduler service endpoint for operator

Repository: ambari
Updated Branches:
  refs/heads/trunk a1b32f08e -> 403cb0c7e


AMBARI-7121: CapScheduler service endpoint for operator

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

Branch: refs/heads/trunk
Commit: 403cb0c7e1f609670c1fec7b91826ee55d523664
Parents: a1b32f0
Author: sposetti <co...@yahoo.com>
Authored: Thu Dec 4 11:22:50 2014 -0500
Committer: sposetti <co...@yahoo.com>
Committed: Thu Dec 4 11:22:50 2014 -0500

----------------------------------------------------------------------
 contrib/views/capacity-scheduler/pom.xml        |   2 +-
 contrib/views/capacity-scheduler/readme.md      |  68 ++++++++++
 .../capacityscheduler/ConfigurationService.java | 131 +++++++++++++++++--
 .../src/main/resources/ui/app/adapters.js       | 113 +---------------
 .../src/main/resources/ui/app/router.js         |   8 +-
 .../src/main/resources/view.xml                 |  14 +-
 6 files changed, 196 insertions(+), 140 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/403cb0c7/contrib/views/capacity-scheduler/pom.xml
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/pom.xml b/contrib/views/capacity-scheduler/pom.xml
index bf851c8..6245a3f 100644
--- a/contrib/views/capacity-scheduler/pom.xml
+++ b/contrib/views/capacity-scheduler/pom.xml
@@ -19,7 +19,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>org.apache.ambari.view</groupId>
     <artifactId>capacity-scheduler</artifactId>
-    <version>0.0.1-SNAPSHOT</version>
+    <version>0.2.0-SNAPSHOT</version>
     <name>Capacity Scheduler</name>
 
     <parent>

http://git-wip-us.apache.org/repos/asf/ambari/blob/403cb0c7/contrib/views/capacity-scheduler/readme.md
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/readme.md b/contrib/views/capacity-scheduler/readme.md
new file mode 100644
index 0000000..6428d21
--- /dev/null
+++ b/contrib/views/capacity-scheduler/readme.md
@@ -0,0 +1,68 @@
+<!---
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at [http://www.apache.org/licenses/LICENSE-2.0](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.
+-->
+
+Capacity Scheduler View
+============
+
+Description
+-----
+This View provides a UI to manage queues for the YARN Capacity Scheduler.
+
+Requirements
+-----
+
+- Ambari 1.7.0
+- YARN
+
+Build
+-----
+
+The view can be built as a maven project.
+
+    mvn clean install
+
+The build will produce the view archive.
+
+    target/capacity-scheduler-0.2.0-SNAPSHOT.jar
+
+Place the view archive on the Ambari Server and restart to deploy.    
+
+    cp capacity-scheduler-0.2.0-SNAPSHOT /var/lib/ambari-server/resources/views/
+    ambari-server restart
+
+Deploying the View
+-----
+
+Use the [Ambari Vagrant](https://cwiki.apache.org/confluence/display/AMBARI/Quick+Start+Guide) setup to create a cluster:
+
+Deploy the Capacity Scheduler view into Ambari.
+
+    cp capacity-scheduler-0.2.0-SNAPSHOT /var/lib/ambari-server/resources/views/
+    ambari-server restart
+
+From the Ambari Administration interface, create a view instance.
+
+|Property|Value|
+|---|---|
+| Details: Instance Name | CS_1 |
+| Details: Display Name | Queue Manager |
+| Details: Description | Browse and manage YARN Capacity Scheduler queues |
+| Properties: ambari.server.url | http://c6401.ambari.apache.org:8080/api/v1/clusters/MyCluster |
+| Properties: ambari.server.username | admin |
+| Properties: ambari.server.password | password |
+
+Login to Ambari and browse to the view instance.
+
+    http://c6401.ambari.apache.org:8080/#/main/views/CAPACITY-SCHEDULER/0.2.0/CS_1

http://git-wip-us.apache.org/repos/asf/ambari/blob/403cb0c7/contrib/views/capacity-scheduler/src/main/java/org/apache/ambari/view/capacityscheduler/ConfigurationService.java
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/java/org/apache/ambari/view/capacityscheduler/ConfigurationService.java b/contrib/views/capacity-scheduler/src/main/java/org/apache/ambari/view/capacityscheduler/ConfigurationService.java
index 550991a..556491e 100644
--- a/contrib/views/capacity-scheduler/src/main/java/org/apache/ambari/view/capacityscheduler/ConfigurationService.java
+++ b/contrib/views/capacity-scheduler/src/main/java/org/apache/ambari/view/capacityscheduler/ConfigurationService.java
@@ -32,6 +32,8 @@ import javax.ws.rs.*;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import java.util.HashMap;
+import java.net.URL;
+import java.net.MalformedURLException;
 
 /**
  * Help service
@@ -41,6 +43,7 @@ public class ConfigurationService {
   private static final Logger LOG = LoggerFactory.getLogger(ConfigurationService.class);
   private final Proxy proxy;
   private final String baseUrl;
+  private final String serverUrl;
 
   private ViewContext context;
   private final String refreshRMRequestData =
@@ -77,8 +80,9 @@ public class ConfigurationService {
       "}\n";
 
   /**
-   * Constructor
-   * @param context View Context instance
+   * Constructor.
+   
+   * @param context     the ViewContext instance (may not be <code>null</code>)
    */
   public ConfigurationService(ViewContext context) {
     this.context = context;
@@ -89,10 +93,23 @@ public class ConfigurationService {
     proxy.setPassword(context.getProperties().get("ambari.server.password"));
 
     HashMap<String, String> customHeaders = new HashMap<String, String>();
-    customHeaders.put("X-Requested-By", "capacity-scheduler-app");
+    customHeaders.put("X-Requested-By", "view-capacity-scheduler");
     proxy.setCustomHeaders(customHeaders);
 
     baseUrl = context.getProperties().get("ambari.server.url");
+    
+    URL url = null;
+    try {
+        url = new URL(baseUrl);
+    } catch (MalformedURLException e) {
+        // !!! I know, I know
+        e.printStackTrace();
+    }
+
+    // !!! and yes, I know
+    String file = url.getFile();
+    serverUrl = baseUrl.substring(0, baseUrl.length() - file.length());
+
   }
 
   // ================================================================================
@@ -103,8 +120,16 @@ public class ConfigurationService {
   private final String configurationUrl = "%%s/configurations?type=capacity-scheduler&tag=%s";
   private final String rmHostUrl = "%s/services/YARN/components/RESOURCEMANAGER?fields=host_components/host_name";
 
+  // ================================================================================
+  // Privilege Reading
+  // ================================================================================
+
+  private final String clusterOperatorPrivilegeUrl = "%s?privileges/PrivilegeInfo/permission_name=CLUSTER.OPERATE&privileges/PrivilegeInfo/principal_name=%s";
+  private final String ambariAdminPrivilegeUrl = "%s/api/v1/users/%s?Users/admin=true";
+
   /**
-   * Get capacity scheduler configuration
+   * Gets capacity scheduler configuration.
+   *
    * @return scheduler configuration
    */
   @GET
@@ -112,7 +137,8 @@ public class ConfigurationService {
   public Response readConfiguration() {
     Response response = null;
     try {
-      validateConfig();
+      validateViewConfiguration();
+      
       String versionTag = getVersionTag();
       JSONObject configurations = getConfigurationFromAmbari(versionTag);
       response = Response.ok(configurations).build();
@@ -125,7 +151,59 @@ public class ConfigurationService {
     return response;
   }
 
-  private void validateConfig() {
+  /**
+   * Gets the privilege for this user.
+   *
+   * @return scheduler configuration
+   */
+  @GET
+  @Produces(MediaType.APPLICATION_JSON)
+  @Path("/privilege")
+  public Response getPrivilege() {
+    Response response = null;
+    
+    try {
+      boolean   operator = isOperator();
+            
+      response = Response.ok(operator).build();
+    } catch (WebApplicationException ex) {
+      throw ex;
+    } catch (Exception ex) {
+      throw new ServiceFormattedException(ex.getMessage(), ex);
+    }
+
+    return response;
+  }
+
+  /**
+   * Checks if the user is an operator.
+   *
+   * @return    if <code>true</code>, the user is an operator; otherwise <code>false</code>
+   */
+  private   boolean isOperator() {
+      validateViewConfiguration();
+            
+      // first check if the user is an CLUSTER.OPERATOR
+      String url = String.format(clusterOperatorPrivilegeUrl, baseUrl, context.getUsername()); 
+      JSONObject json = proxy.request(url).get().asJSON();
+      
+      if (json == null || json.size() <= 0) {
+        // user is not a CLUSTER.OPERATOR but might be an AMBARI.ADMIN
+        url = String.format(ambariAdminPrivilegeUrl, serverUrl, context.getUsername()); 
+        json = proxy.request(url).get().asJSON();
+        if (json == null || json.size() <= 0)
+            return false;
+      }
+      
+    return  true;
+  }
+  
+  /**
+   * Validates the view configuration properties.
+   *
+   * @throws MisconfigurationFormattedException if one of the required view configuration properties are not set
+   */
+  private void validateViewConfiguration() {
     String hostname = context.getProperties().get("ambari.server.url");
     if (hostname == null)
       throw new MisconfigurationFormattedException("ambari.server.url");
@@ -145,6 +223,11 @@ public class ConfigurationService {
     return proxy.request(url).get().asJSON();
   }
 
+  /**
+   * Gets the capacity scheduler version tag.
+   *
+   * @return    the capacity scheduler version tag
+   */
   private String getVersionTag() {
     JSONObject json = getDesiredConfigs();
     JSONObject clusters = (JSONObject) json.get("Clusters");
@@ -153,12 +236,22 @@ public class ConfigurationService {
     return (String) scheduler.get("tag");
   }
 
+  /**
+   * Gets the cluster name.
+   *
+   * @return    the cluster name
+   */
   private String getClusterName() {
     JSONObject json = getDesiredConfigs();
     JSONObject clusters = (JSONObject) json.get("Clusters");
     return (String) clusters.get("cluster_name");
   }
 
+  /**
+   * Gets the desired config.
+   *
+   * @return  the desired config JSON object
+   */
   private JSONObject getDesiredConfigs() {
     String url = String.format(versionTagUrl, baseUrl);
     return proxy.request(url).get().asJSON();
@@ -167,16 +260,22 @@ public class ConfigurationService {
   // ================================================================================
   // Configuration Writing
   // ================================================================================
+  
   /**
-   * Set capacity scheduler configuration
-   * @return http response
+   * Sets capacity scheduler configuration.
+   *
+   * @return the http response
    */
   @PUT
   @Consumes(MediaType.APPLICATION_JSON)
   @Produces(MediaType.APPLICATION_JSON)
   public Response writeConfiguration(JSONObject request) {
     try {
-      validateConfig();
+      validateViewConfiguration();
+
+      if (isOperator() == false) {
+        return Response.status(401).build();
+      }
 
       proxy.request(baseUrl).
             setData(makeConfigUpdateData(request)).
@@ -192,7 +291,8 @@ public class ConfigurationService {
   }
 
   /**
-   * Set capacity scheduler configuration and refresh RM
+   * Sets capacity scheduler configuration and refresh ResourceManager.
+   *
    * @return http response
    */
   @PUT
@@ -202,6 +302,10 @@ public class ConfigurationService {
   public Response writeAndRefreshConfiguration(JSONObject request) {
     try {
 
+      if (isOperator() == false) {
+        return Response.status(401).build();
+      }
+      
       writeConfiguration(request);
 
       String rmHost = getRMHost();
@@ -219,7 +323,8 @@ public class ConfigurationService {
   }
 
   /**
-   * Set capacity scheduler configuration and restart RM
+   * Sets capacity scheduler configuration and restart ResourceManager.
+   *
    * @return http response
    */
   @PUT
@@ -229,6 +334,10 @@ public class ConfigurationService {
   public Response writeAndRestartConfiguration(JSONObject request) {
     try {
 
+      if (isOperator() == false) {
+        return Response.status(401).build();
+      }
+
       writeConfiguration(request);
 
       String rmHost = getRMHost();

http://git-wip-us.apache.org/repos/asf/ambari/blob/403cb0c7/contrib/views/capacity-scheduler/src/main/resources/ui/app/adapters.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/adapters.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/adapters.js
index 50d31f6..ca2cdee 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/adapters.js
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/adapters.js
@@ -108,35 +108,6 @@ App.QueueAdapter = DS.Adapter.extend({
 
   },
      
-  /**
-   * Finds the cluster name.
-   *
-   */
-  findClusterName: function() {
-    var uri = _getClusterNameUri();
-        
-    return this.ajax(uri).then(function(data) {
-      var clusterName = data.ViewInstanceInfo.properties.clusterName;
-      console.log("found cluster name: "+clusterName);
-      App.Adapter.clusterName = clusterName;
-      return clusterName;
-    });
-  },
-
-  /**
-   * Finds the capacity scheduler tag.
-   */
-  findTag: function(clusterName) {
-    var uri = _getTagVersionUri(clusterName);
-    
-    return this.ajax(uri).then(function(data) {
-      var tag = data.Clusters.desired_configs["capacity-scheduler"].tag;
-      console.log("found tag version: "+tag);
-      App.Adapter.tag = tag;
-      return  tag;
-    })
-  },
-  
   ajax: function(url, type, hash) {
     var adapter = this;
 
@@ -167,7 +138,7 @@ App.QueueAdapter = DS.Adapter.extend({
       hash.data = JSON.stringify(hash.data);
     }
     hash.beforeSend = function (xhr) {
-      xhr.setRequestHeader('X-Requested-By', 'ambari');
+      xhr.setRequestHeader('X-Requested-By', 'view-capacity-scheduler');
     };
     return hash;
   },
@@ -419,9 +390,6 @@ function _recurseQueues(parentQueue, queueName, depth, props, queues, store) {
  * @return  cluster name URI
  */
 function _getCapacitySchedulerUri() {
-  if (App.testMode)
-    return  "/data/scheduler-configuration.json"
-
   var parts = window.location.pathname.match(/\/[^\/]*/g);
   var view = parts[1];
   var version = '/versions' + parts[2];
@@ -432,82 +400,3 @@ function _getCapacitySchedulerUri() {
   }
   return '/api/v1/views' + view + version + '/instances' + instance+'/resources/scheduler/configuration';
 }
-
-/**
- * Gets the cluster name URI based on test mode
- *
- * @return  cluster name URI
- */
-function _getClusterNameUri() {
-  if (App.testMode)
-    return  "/data/view-instance.json"
-
-  var parts = window.location.pathname.match(/\/[^\/]*/g);
-  var view = parts[1];
-  var version = '/versions' + parts[2];
-  var instance = parts[3];
-  if (parts.length == 4) { // version is not present
-    instance = parts[2];
-    version = '';
-  }
-  return '/api/v1/views' + view + version + '/instances' + instance;
-}
-
-/**
- * Gets the capacity scheduler URI based on test mode.
- *
- * @param   clusterName     the cluster name
- * @param   tagVersion      the tag version
- * @return  the capacity scheduler URI
- */
-function _getCapacitySchedulerUri_old(clusterName, tagVersion) {
-  console.log("_getCapacitySchedulerUri.clusterName = "+clusterName);
-  console.log("_getCapacitySchedulerUri.tagVersion = "+tagVersion);
-  if (App.testMode)
-    return  "/data/capacity-scheduler.json"
-    
-  return "/api/v1/clusters/" + clusterName + "/configurations?type=capacity-scheduler&tag="+tagVersion;
-}
-
-/**
- * Gets the tag version URI based on test mode.
- *
- * @param   clusterName     the cluster name
- * @return  the capacity scheduler tag URI
- */
-function _getTagVersionUri(clusterName) {
-  if (App.testMode)
-    return  "/data/cs-tag.json"
-    
-  return "/api/v1/clusters/" + clusterName + "?fields=Clusters/desired_configs/capacity-scheduler";
-}
-
-/**
- * Setup claster name and version tag for adapter
- */
-
-/*App.deferReadiness();
-
-(function () {
-
-  var clusterNameUri = _getClusterNameUri();
-    
-  return Em.$.ajax({url: clusterNameUri, dataType: "json"}).then(function(data) {
-    var clusterName = data.ViewInstanceInfo.properties.clusterName;
-    console.log("found cluster name: "+clusterName);
-
-    App.QueueAdapter.reopen({clusterName:clusterName});
-
-    var tagVersionUri = _getTagVersionUri(clusterName);
-  
-    return Em.$.ajax({url: tagVersionUri, dataType: "json"}).then(function(data) {
-      var tag = data.Clusters.desired_configs["capacity-scheduler"].tag;
-      console.log("found tag version: "+tag);
-
-      App.QueueAdapter.reopen({tag:tag});
-
-      App.advanceReadiness();
-
-    });
-  });
-})();*/

http://git-wip-us.apache.org/repos/asf/ambari/blob/403cb0c7/contrib/views/capacity-scheduler/src/main/resources/ui/app/router.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/router.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/router.js
index ea21d90..ceb4f86 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/router.js
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/router.js
@@ -77,13 +77,7 @@ App.QueueRoute = Ember.Route.extend({
   },
   
   actions: {
-    refreshQueue: function() {
-    var x = "{ \"RequestInfo\" : { \"command\" : \"REFRESHQUEUES\", \"context\" : \"Refresh YARN Capacity Scheduler\",\"parameters/forceRefreshConfigTags\":\"capacity-scheduler\" }, "
-    x = x + "\"Requests/resource_filters\":[{\"service_name\":\"YARN\",\"component_name\":\"RESOURCEMANAGER\",\"hosts\":\"c6403.ambari.apache.org\"}]}";
-    
-      App.Adapter.ajaxPost("/api/v1/clusters/MyCluster/requests", x);
-    },
-    willTransition:function (tr) {
+    willTransition: function (tr) {
       if (this.get('controller.isRenaming')) {
         tr.abort();
       };

http://git-wip-us.apache.org/repos/asf/ambari/blob/403cb0c7/contrib/views/capacity-scheduler/src/main/resources/view.xml
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/view.xml b/contrib/views/capacity-scheduler/src/main/resources/view.xml
index 4bd33d5..6206ccc 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/view.xml
+++ b/contrib/views/capacity-scheduler/src/main/resources/view.xml
@@ -17,25 +17,25 @@
 <view>
     <name>CAPACITY-SCHEDULER</name>
     <label>Capacity Scheduler</label>
-    <version>0.1.0</version>
+    <version>0.2.0</version>
 
     <parameter>
         <name>ambari.server.url</name>
-        <description>Ambari Server REST API cluster URL (for example: http://ambari.server:8080/api/v1/clusters/c1)</description>
+        <description>Ambari REST API Cluster URL (for example: http://ambari.server:8080/api/v1/clusters/c1)</description>
         <required>true</required>
     </parameter>
 
     <parameter>
         <name>ambari.server.username</name>
-        <description>Ambari administrator username (for example: admin)</description>
+        <description>Ambari Cluster Operator username (for example: admin)</description>
         <required>true</required>
     </parameter>
 
     <parameter>
         <name>ambari.server.password</name>
-        <description>Ambari administrator password (for example: admin)</description>
+        <description>Ambari Cluster Operator password (for example: password)</description>
         <required>true</required>
-        <!-- <hidden>true</hidden> -->
+        <masked>true</masked>
     </parameter>
 
     <resource>
@@ -43,8 +43,4 @@
       <service-class>org.apache.ambari.view.capacityscheduler.CapacitySchedulerService</service-class>
     </resource>
 
-    <instance>
-        <name>Scheduler</name>
-    </instance>
-
 </view>