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>