|
@@ -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();
|