ソースを参照

AMBARI-7625. Slider View: Reduce view parameter count and provide /status API (srimanth)

Srimanth Gunturi 11 年 前
コミット
8cc65e396f

+ 9 - 16
contrib/views/slider/src/main/java/org/apache/ambari/view/slider/SliderAppsViewController.java

@@ -31,25 +31,18 @@ import com.google.inject.ImplementedBy;
 @ImplementedBy(SliderAppsViewControllerImpl.class)
 public interface SliderAppsViewController {
 
-  public static final String PROPERTY_HDFS_ADDRESS = "hdfs.url";
-  public static final String PROPERTY_YARN_RM_ADDRESS = "yarn.rm.url";
-  public static final String PROPERTY_YARN_RM_WEBAPP_ADDRESS = "yarn.rm.webapp.url";
-  public static final String PROPERTY_YARN_RM_SCHEDULER_ADDRESS = "yarn.rm.scheduler.url";
-  public static final String PROPERTY_ZK_QUOROM = "zookeeper.quorum";
-  // Ganglia
+  public static final String PARAM_AMBARI_CLUSTER_API = "ambari.server.url";
+  public static final String PARAM_AMBARI_USERNAME = "ambari.server.username";
+  public static final String PARAM_AMBARI_PASSWORD = "ambari.server.password";
+  public static final String PARAM_SLIDER_USER = "slider.user";
+  public static final String PARAM_VIEW_PRINCIPAL = "view.kerberos.principal";
+  public static final String PARAM_VIEW_PRINCIPAL_KEYTAB= "view.kerberos.principal.keytab";
+
+  public static final String PROPERTY_SLIDER_ZK_QUORUM = "slider.zookeeper.quorum";
   public static final String PROPERTY_GANGLIA_SERVER_HOSTNAME = "ganglia.server.hostname";
   public static final String PROPERTY_GANGLIA_CUSTOM_CLUSTERS = "ganglia.additional.clusters";
-  // Security
-  public static final String PROPERTY_SLIDER_USER = "slider.user";
+  public static final String PROPERTY_YARN_RM_WEBAPP_URL = "yarn.rm.webapp.url";
   public static final String PROPERTY_SLIDER_SECURITY_ENABLED = "slider.security.enabled";
-  public static final String PROPERTY_YARN_RM_PRINCIPAL = "yarn.rm.kerberos.principal";
-  public static final String PROPERTY_HDFS_NN_PRINCIPAL = "dfs.namenode.kerberos.principal";
-  public static final String PROPERTY_VIEW_PRINCIPAL = "view.kerberos.principal";
-  public static final String PROPERTY_VIEW_PRINCIPAL_KEYTAB= "view.kerberos.principal.keytab";
-  // HA
-  public static final String PROPERTY_YARN_RM_HA_HOSTS = "yarm.rm.ha.hosts";
-  public static final String PROPERTY_YARN_RM_STORE_CLASS = "yarn.rm.store.class";
-  public static final String PROPERTY_YARN_RM_HA_AUTO_FAILOVER_ZKPATH = "yarn.rm.ha.automatic-failover.zk-base-path";
 
   public ViewStatus getViewStatus();
 

+ 189 - 81
contrib/views/slider/src/main/java/org/apache/ambari/view/slider/SliderAppsViewControllerImpl.java

@@ -36,6 +36,12 @@ import java.util.Set;
 import java.util.zip.ZipException;
 
 import org.apache.ambari.view.ViewContext;
+import org.apache.ambari.view.slider.clients.AmbariCluster;
+import org.apache.ambari.view.slider.clients.AmbariClusterInfo;
+import org.apache.ambari.view.slider.clients.AmbariHostComponent;
+import org.apache.ambari.view.slider.clients.AmbariService;
+import org.apache.ambari.view.slider.clients.AmbariServiceInfo;
+import org.apache.ambari.view.slider.rest.client.AmbariHttpClient;
 import org.apache.ambari.view.slider.rest.client.Metric;
 import org.apache.ambari.view.slider.rest.client.SliderAppMasterClient;
 import org.apache.ambari.view.slider.rest.client.SliderAppMasterClient.SliderAppMasterData;
@@ -85,6 +91,7 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
   @Inject
   private ViewContext viewContext;
   private List<SliderAppType> appTypes;
+  private Map<String, String> hadoopConfigs;
   private Integer createAppCounter = -1;
   @Inject
   private SliderAppsAlerts sliderAlerts;
@@ -101,7 +108,154 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
   @Override
   public ViewStatus getViewStatus() {
     ViewStatus status = new ViewStatus();
+    Map<String, String> newHadoopConfigs = new HashMap<String, String>();
     status.setVersion(SliderAppsConfiguration.INSTANCE.getVersion());
+    String ambariCluster = getViewParameterValue(PARAM_AMBARI_CLUSTER_API);
+    String ambariUsername = getViewParameterValue(PARAM_AMBARI_USERNAME);
+    String ambariPassword = getViewParameterValue(PARAM_AMBARI_PASSWORD);
+    if (ambariCluster != null && ambariUsername != null
+        && ambariPassword != null && ambariCluster.trim().length() > 0
+        && ambariUsername.trim().length() > 0
+        && ambariPassword.trim().length() > 0) {
+      String APIPREFIX = "/api/v1/clusters/";
+      int index = ambariCluster.indexOf(APIPREFIX);
+      if (index > 0) {
+        String ambariUrl = ambariCluster.substring(0, index);
+        String clusterName = ambariCluster
+            .substring(index + APIPREFIX.length());
+        if (clusterName.endsWith("/")) {
+          clusterName = clusterName.substring(0, clusterName.length() - 1);
+        }
+        AmbariHttpClient ambariClient = new AmbariHttpClient(ambariUrl,
+            ambariUsername, ambariPassword);
+        AmbariClusterInfo clusterInfo = ambariClient.getClusterInfo();
+        if (clusterName.equals(clusterInfo.getName())) {
+          AmbariCluster cluster = ambariClient.getCluster(clusterInfo);
+          AmbariServiceInfo hdfsServiceInfo = null;
+          AmbariServiceInfo yarnServiceInfo = null;
+          for (AmbariServiceInfo svc : cluster.getServices()) {
+            if ("HDFS".equals(svc.getId())) {
+              hdfsServiceInfo = svc;
+            } else if ("YARN".equals(svc.getId())) {
+              yarnServiceInfo = svc;
+            }
+          }
+          // HDFS
+          if (hdfsServiceInfo != null) {
+            if (!hdfsServiceInfo.isStarted()) {
+              status.getValidations().add(
+                  new ViewStatus.Validation("HDFS service is not started"));
+            }
+          } else {
+            status.getValidations().add(
+                new ViewStatus.Validation("HDFS service is not installed"));
+          }
+          // YARN
+          if (yarnServiceInfo != null) {
+            if (!yarnServiceInfo.isStarted()) {
+              status.getValidations().add(
+                  new ViewStatus.Validation("YARN service is not started"));
+            }
+          } else {
+            status.getValidations().add(
+                new ViewStatus.Validation("YARN service is not installed"));
+          }
+          // Configs
+          if (cluster.getDesiredConfigs().containsKey("core-site")) {
+            Map<String, String> coreSiteConfigs = ambariClient
+                .getConfiguration(cluster, "core-site", cluster
+                    .getDesiredConfigs().get("core-site"));
+            newHadoopConfigs.putAll(coreSiteConfigs);
+          }
+          if (cluster.getDesiredConfigs().containsKey("cluster-env")) {
+            Map<String, String> clusterEnvConfigs = ambariClient
+                .getConfiguration(cluster, "cluster-env", cluster
+                    .getDesiredConfigs().get("cluster-env"));
+            newHadoopConfigs.put("security_enabled",
+                clusterEnvConfigs.get("security_enabled"));
+          }
+          if (cluster.getDesiredConfigs().containsKey("yarn-site")) {
+            Map<String, String> yarnSiteConfigs = ambariClient
+                .getConfiguration(cluster, "yarn-site", cluster
+                    .getDesiredConfigs().get("yarn-site"));
+            newHadoopConfigs.putAll(yarnSiteConfigs);
+            status.getParameters().put(PROPERTY_YARN_RM_WEBAPP_URL,
+                newHadoopConfigs.get("yarn.resourcemanager.webapp.address"));
+          }
+          if (cluster.getDesiredConfigs().containsKey("zookeeper-env")) {
+            Map<String, String> zkEnvConfigs = ambariClient.getConfiguration(
+                cluster, "zookeeper-env",
+                cluster.getDesiredConfigs().get("zookeeper-env"));
+            StringBuilder zkQuorumBuilder = new StringBuilder();
+            String port = zkEnvConfigs.get("clientPort");
+            AmbariService zkService = ambariClient.getService(cluster,
+                "ZOOKEEPER");
+            if (zkService != null) {
+              List<AmbariHostComponent> hostsList = zkService
+                  .getComponentsToHostComponentsMap().get("ZOOKEEPER_SERVER");
+              int count = 1;
+              for (AmbariHostComponent host : hostsList) {
+                zkQuorumBuilder.append(host.getHostName() + ":" + port);
+                if (count++ < hostsList.size()) {
+                  zkQuorumBuilder.append(",");
+                }
+              }
+              newHadoopConfigs.put(PROPERTY_SLIDER_ZK_QUORUM,
+                  zkQuorumBuilder.toString());
+            } else {
+              status.getValidations().add(
+                  new ViewStatus.Validation(
+                      "ZooKeeper service is not installed"));
+            }
+          } else {
+            status.getValidations()
+                .add(
+                    new ViewStatus.Validation(
+                        "ZooKeeper service is not installed"));
+          }
+          if (cluster.getDesiredConfigs().containsKey("ganglia-env")) {
+            Map<String, String> gangliaConfigs = ambariClient.getConfiguration(
+                cluster, "ganglia-env",
+                cluster.getDesiredConfigs().get("ganglia-env"));
+            String clustersCsv = gangliaConfigs.get("additional_clusters");
+            AmbariService gangliaService = ambariClient.getService(cluster,
+                "GANGLIA");
+            List<AmbariHostComponent> hostsList = gangliaService
+                .getComponentsToHostComponentsMap().get("GANGLIA_SERVER");
+            if (hostsList != null && hostsList.size() > 0) {
+              String gangliaHostName = hostsList
+                  .get(0).getHostName();
+              newHadoopConfigs.put(PROPERTY_GANGLIA_SERVER_HOSTNAME, gangliaHostName);
+              status.getParameters().put(PROPERTY_GANGLIA_SERVER_HOSTNAME, gangliaHostName);
+            }
+            newHadoopConfigs.put(PROPERTY_GANGLIA_CUSTOM_CLUSTERS, clustersCsv);
+            status.getParameters().put(PROPERTY_GANGLIA_CUSTOM_CLUSTERS, clustersCsv);
+          }
+        } else {
+          status.getValidations().add(
+              new ViewStatus.Validation("Ambari cluster with ID ["
+                  + clusterName + "] was not found on Ambari server"));
+        }
+      } else {
+        status
+            .getValidations()
+            .add(
+                new ViewStatus.Validation(
+                    "Ambari server cluster API URL should include cluster name, for example http://ambari.server:8080/api/v1/clusters/c1"));
+      }
+    } else {
+      status.getValidations().add(
+          new ViewStatus.Validation(
+              "View parameters specifying Ambari details required"));
+    }
+    Set<String> removeKeys = new HashSet<String>(viewContext.getInstanceData().keySet());
+    for (Entry<String, String> e : newHadoopConfigs.entrySet()) {
+      viewContext.putInstanceData(e.getKey(), e.getValue());
+      removeKeys.remove(e.getKey());
+    }
+    for (String key : removeKeys) {
+      viewContext.removeInstanceData(key);
+    }
     return status;
   }
 
@@ -128,7 +282,7 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
   }
 
   private String getUserToRunAs() {
-    String user = getViewParameterValue(PROPERTY_SLIDER_USER);
+    String user = getViewParameterValue(PARAM_SLIDER_USER);
     if (user == null || user.trim().length() < 1) {
       return "yarn";
     } else if ("${username}".equals(user)) {
@@ -145,26 +299,25 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
       boolean securityEnabled = Boolean.valueOf(getViewParameterValue(PROPERTY_SLIDER_SECURITY_ENABLED));
       UserGroupInformation sliderUser;
       if (securityEnabled) {
-        String viewPrincipal = getViewParameterValue(PROPERTY_VIEW_PRINCIPAL);
-        String viewPrincipalKeytab = getViewParameterValue(PROPERTY_VIEW_PRINCIPAL_KEYTAB);
+        String viewPrincipal = getViewParameterValue(PARAM_VIEW_PRINCIPAL);
+        String viewPrincipalKeytab = getViewParameterValue(PARAM_VIEW_PRINCIPAL_KEYTAB);
         UserGroupInformation ambariUser = UserGroupInformation.loginUserFromKeytabAndReturnUGI(viewPrincipal, viewPrincipalKeytab);
         sliderUser = UserGroupInformation.createProxyUser(getUserToRunAs(), ambariUser);
       } else {
         sliderUser = UserGroupInformation.getBestUGI(null, getUserToRunAs());
       }
-      try{
-        T value = sliderUser.doAs(
-            new PrivilegedExceptionAction<T>() {
-              @Override
-              public T run() throws Exception {
-                final SliderClient sliderClient = createSliderClient();
-                try{
-                  return runnable.run(sliderClient);
-                }finally{
-                  destroySliderClient(sliderClient);
-                }
-              }
-            });
+      try {
+        T value = sliderUser.doAs(new PrivilegedExceptionAction<T>() {
+          @Override
+          public T run() throws Exception {
+            final SliderClient sliderClient = createSliderClient();
+            try {
+              return runnable.run(sliderClient);
+            } finally {
+              destroySliderClient(sliderClient);
+            }
+          }
+        });
         return value;
       } catch (UndeclaredThrowableException e) {
         Throwable cause = e.getCause();
@@ -178,7 +331,7 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
       Thread.currentThread().setContextClassLoader(currentClassLoader);
     }
   }
-  
+
   @Override
   public SliderApp getSliderApp(final String applicationId, final Set<String> properties)
      throws YarnException, IOException, InterruptedException {
@@ -463,6 +616,13 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
     return value;
   }
 
+  protected Map<String, String> getHadoopConfigs() {
+    if(hadoopConfigs==null) {
+      hadoopConfigs = viewContext.getInstanceData();
+    }
+    return hadoopConfigs;
+  }
+
   /**
    * Dynamically determines Slider client configuration. If unable to determine,
    * <code>null</code> is returned.
@@ -470,79 +630,27 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
    * @return
    */
   private Configuration getSliderClientConfiguration() {
-    String hdfsPath = getViewParameterValue(PROPERTY_HDFS_ADDRESS);
-    String rmAddress = getViewParameterValue(PROPERTY_YARN_RM_ADDRESS);
-    String rmSchedulerAddress = getViewParameterValue(PROPERTY_YARN_RM_SCHEDULER_ADDRESS);
-    String zkQuorum = getViewParameterValue(PROPERTY_ZK_QUOROM);
-    boolean securedCluster = Boolean.valueOf(getViewParameterValue(PROPERTY_SLIDER_SECURITY_ENABLED));
-    String rmHAHosts = getViewParameterValue(PROPERTY_YARN_RM_HA_HOSTS);
-    String rmStoreClass = getViewParameterValue(PROPERTY_YARN_RM_STORE_CLASS);
-    String rmHAAutoFailoverPath = getViewParameterValue(PROPERTY_YARN_RM_HA_AUTO_FAILOVER_ZKPATH);
-
     HdfsConfiguration hdfsConfig = new HdfsConfiguration();
     YarnConfiguration yarnConfig = new YarnConfiguration(hdfsConfig);
 
-    yarnConfig.set("slider.yarn.queue", "default");
-    yarnConfig.set("yarn.log-aggregation-enable", "true");
-    yarnConfig.set("yarn.resourcemanager.address", rmAddress);
-    yarnConfig.set("yarn.resourcemanager.scheduler.address", rmSchedulerAddress);
-    yarnConfig.set("fs.defaultFS", hdfsPath);
-    yarnConfig.set("slider.zookeeper.quorum", zkQuorum.toString());
-    yarnConfig.set("yarn.application.classpath",
-            "/etc/hadoop/conf,/usr/hdp/current/hadoop/*,/usr/hdp/current/hadoop/lib/*,/usr/hdp/current/hadoop-hdfs/*,/usr/hdp/current/hadoop-hdfs/lib/*,/usr/hdp/current/hadoop-yarn/*,/usr/hdp/current/hadoop-yarn/lib/*,/usr/hdp/current/hadoop-mapreduce/*,/usr/hdp/current/hadoop-mapreduce/lib/*");
-
-    if (securedCluster) {
-      String rmPrincipal = getViewParameterValue(PROPERTY_YARN_RM_PRINCIPAL);
-      String nnPrincipal = getViewParameterValue(PROPERTY_HDFS_NN_PRINCIPAL);
-      yarnConfig.set("yarn.resourcemanager.principal", rmPrincipal);
-      yarnConfig.set("dfs.namenode.kerberos.principal", nnPrincipal);
-      yarnConfig.set("hadoop.security.authorization", "true");
-      yarnConfig.set("hadoop.security.authentication", "kerberos");
-      yarnConfig.set("slider.security.enabled", "true");
+    Map<String, String> hadoopConfigs = getHadoopConfigs();
+    for(Entry<String, String> entry: hadoopConfigs.entrySet()) {
+      yarnConfig.set(entry.getKey(), entry.getValue());
     }
-
-    if (rmHAHosts != null && rmHAHosts.trim().length() > 0 && rmStoreClass!=null && rmHAAutoFailoverPath!=null) {
-      yarnConfig.set("yarn.resourcemanager.ha.enabled", "true");
-      yarnConfig.set("yarn.resourcemanager.cluster-id", "yarn-cluster");
-      yarnConfig.set("yarn.resourcemanager.recovery.enabled", "true");
-      yarnConfig.set("yarn.resourcemanager.store.class", rmStoreClass);
-      yarnConfig.set("yarn.resourcemanager.ha.automatic-failover.zk-base-path",
-          rmHAAutoFailoverPath);
-      // ZK
-      int count = 1;
-      String[] zkHostPorts = zkQuorum.split(",");
-      StringBuffer zkHosts = new StringBuffer();
-      for (String zkHostPort : zkHostPorts) {
-        String host = zkHostPort.split(":")[0];
-        zkHosts.append(host);
-        if (count++ < zkHostPorts.length) {
-          zkHosts.append(",");
-        }
-      }
-      yarnConfig.set("yarn.resourcemanager.zk-address", zkHosts.toString());
-      // HA Ids
-      StringBuffer rmIds = new StringBuffer();
-      String[] hosts = rmHAHosts.trim().split(",");
-      count = 1;
-      for (String host : hosts) {
-        String rmId = "rm" + Integer.toString(count++);
-        rmIds.append(rmId);
-        if (count <= hosts.length) {
-          rmIds.append(",");
-        }
-        yarnConfig.set("yarn.resourcemanager.hostname." + rmId, host.trim());
-      }
-      yarnConfig.set("yarn.resourcemanager.ha.rm-ids", rmIds.toString());
+    yarnConfig.set("slider.security.enabled", hadoopConfigs.get("security_enabled"));
+    yarnConfig.set("slider.yarn.queue", "default"); //TODO Remove?
+    if (hadoopConfigs.containsKey(PROPERTY_SLIDER_ZK_QUORUM)) {
+      yarnConfig.set(PROPERTY_SLIDER_ZK_QUORUM, hadoopConfigs.get(PROPERTY_SLIDER_ZK_QUORUM));
     }
     return yarnConfig;
   }
 
   private boolean areViewParametersSet() {
-    String hdfsPath = getViewParameterValue(PROPERTY_HDFS_ADDRESS);
-    String rmAddress = getViewParameterValue(PROPERTY_YARN_RM_ADDRESS);
-    String rmSchedulerAddress = getViewParameterValue(PROPERTY_YARN_RM_SCHEDULER_ADDRESS);
-    String zkQuorum = getViewParameterValue(PROPERTY_ZK_QUOROM);
-    return hdfsPath!=null && rmAddress!=null && rmSchedulerAddress!=null && zkQuorum!=null;
+    Map<String, String> hadoopConfigs = getHadoopConfigs();
+    return hadoopConfigs.containsKey("fs.defaultFS")
+        && hadoopConfigs.containsKey("yarn.resourcemanager.address")
+        && hadoopConfigs.containsKey("yarn.resourcemanager.webapp.address")
+        && hadoopConfigs.containsKey(PROPERTY_SLIDER_ZK_QUORUM);
   }
 
   @Override

+ 40 - 0
contrib/views/slider/src/main/java/org/apache/ambari/view/slider/ViewStatus.java

@@ -18,9 +18,33 @@
 
 package org.apache.ambari.view.slider;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 public class ViewStatus {
+  public static class Validation {
+    public static enum TYPE {
+      ERROR, WARN
+    }
+
+    public String message;
+    public String type;
+
+    public Validation(String message, String type) {
+      this.message = message;
+      this.type = type;
+    }
+    public Validation(String message) {
+      this.message = message;
+      this.type = TYPE.ERROR.name();
+    }
+  }
+
   private String version;
+  private Map<String, String> parameters = new HashMap<String, String>();
+  private List<Validation> validations = new ArrayList<ViewStatus.Validation>();
 
   public String getVersion() {
     return version;
@@ -29,4 +53,20 @@ public class ViewStatus {
   public void setVersion(String version) {
     this.version = version;
   }
+
+  public Map<String, String> getParameters() {
+    return parameters;
+  }
+
+  public void setParameters(Map<String, String> parameters) {
+    this.parameters = parameters;
+  }
+
+  public List<Validation> getValidations() {
+    return validations;
+  }
+
+  public void setValidations(List<Validation> validations) {
+    this.validations = validations;
+  }
 }

+ 65 - 7
contrib/views/slider/src/main/java/org/apache/ambari/view/slider/rest/client/AmbariHttpClient.java

@@ -27,6 +27,7 @@ import java.util.Map;
 import org.apache.ambari.view.slider.clients.AmbariClient;
 import org.apache.ambari.view.slider.clients.AmbariCluster;
 import org.apache.ambari.view.slider.clients.AmbariClusterInfo;
+import org.apache.ambari.view.slider.clients.AmbariHostComponent;
 import org.apache.ambari.view.slider.clients.AmbariHostInfo;
 import org.apache.ambari.view.slider.clients.AmbariService;
 import org.apache.ambari.view.slider.clients.AmbariServiceInfo;
@@ -77,13 +78,14 @@ public class AmbariHttpClient extends BaseHttpClient implements AmbariClient {
 		if (clusterInfo != null) {
 			try {
 				JsonElement jsonElement = doGetJson("/api/v1/clusters/"
-				    + clusterInfo.getName());
+				    + clusterInfo.getName() + "?fields=services/ServiceInfo,hosts,Clusters");
 				if (jsonElement != null) {
 					AmbariCluster cluster = new AmbariCluster();
 					// desired configs
 					Map<String, String> desiredConfigs = new HashMap<String, String>();
-					JsonObject desiredConfigsObj = jsonElement.getAsJsonObject()
-					    .get("Clusters").getAsJsonObject().get("desired_configs")
+					JsonObject jsonObject = jsonElement.getAsJsonObject();
+                    JsonObject clustersJsonObject = jsonObject.get("Clusters").getAsJsonObject();
+                    JsonObject desiredConfigsObj = clustersJsonObject.get("desired_configs")
 					    .getAsJsonObject();
 					for (Map.Entry<String, JsonElement> entry : desiredConfigsObj
 					    .entrySet()) {
@@ -91,11 +93,30 @@ public class AmbariHttpClient extends BaseHttpClient implements AmbariClient {
 						    .getAsJsonObject().get("tag").getAsString());
 					}
 					cluster.setDesiredConfigs(desiredConfigs);
+					cluster.setName(clustersJsonObject.get("cluster_name").getAsString());
+					cluster.setVersion(clustersJsonObject.get("version").getAsString());
 					// services
-					List<AmbariServiceInfo> services = new ArrayList<AmbariServiceInfo>();
+                    List<AmbariServiceInfo> services = new ArrayList<AmbariServiceInfo>();
+                    for (JsonElement svcJson : jsonObject.get("services")
+                        .getAsJsonArray()) {
+                      AmbariServiceInfo si = new AmbariServiceInfo();
+                      si.setId(svcJson.getAsJsonObject().get("ServiceInfo")
+                          .getAsJsonObject().get("service_name").getAsString());
+                      si.setStarted("STARTED".equals(svcJson.getAsJsonObject()
+                          .get("ServiceInfo").getAsJsonObject().get("state")
+                          .getAsString()));
+                      services.add(si);
+                    }
 					cluster.setServices(services);
 					// hosts
 					List<AmbariHostInfo> hosts = new ArrayList<AmbariHostInfo>();
+					for (JsonElement hostJson : jsonObject.get("hosts")
+                        .getAsJsonArray()) {
+                      AmbariHostInfo hi = new AmbariHostInfo();
+                      hi.setHostName(hostJson.getAsJsonObject().get("Hosts")
+                          .getAsJsonObject().get("host_name").getAsString());
+                      hosts.add(hi);
+                    }
 					cluster.setHosts(hosts);
 					return cluster;
 				}
@@ -143,8 +164,45 @@ public class AmbariHttpClient extends BaseHttpClient implements AmbariClient {
 
 	@Override
 	public AmbariService getService(AmbariClusterInfo cluster, String serviceId) {
-		// TODO Auto-generated method stub
-		return null;
-	}
+      if (cluster != null && serviceId != null) {
+        try {
+            JsonElement jsonElement = doGetJson("/api/v1/clusters/"
+                + cluster.getName() + "/services/" + serviceId + "?fields=ServiceInfo,components/host_components/HostRoles");
+            JsonObject jsonObject = jsonElement.getAsJsonObject();
+            if (jsonObject.has("status") && "404".equals(jsonObject.get("status").getAsString())) {
+              return null;
+            }
+            AmbariService svc = new AmbariService();
+            JsonObject serviceInfoJsonObject = jsonObject.get("ServiceInfo").getAsJsonObject();
+            svc.setId(serviceInfoJsonObject.get("service_name").getAsString());
+            svc.setStarted("STARTED".equals(serviceInfoJsonObject.get("state").getAsString()));
+            svc.setMaintenanceMode(!"OFF".equals(serviceInfoJsonObject.get("maintenance_state").getAsString()));
+            Map<String, List<AmbariHostComponent>> componentsToHostComponentsMap = new HashMap<String, List<AmbariHostComponent>>();
+            for(JsonElement ce: jsonObject.get("components").getAsJsonArray()){
+              String componentName = ce.getAsJsonObject().get("ServiceComponentInfo").getAsJsonObject().get("component_name").getAsString();
+              List<AmbariHostComponent> hcList = new ArrayList<AmbariHostComponent>();
+              componentsToHostComponentsMap.put(componentName, hcList);
+              JsonArray hcJsonArray = ce.getAsJsonObject().get("host_components").getAsJsonArray();
+              for(JsonElement hce: hcJsonArray) {
+                AmbariHostComponent hc = new AmbariHostComponent();
+                JsonObject hcJsonObject = hce.getAsJsonObject().get("HostRoles").getAsJsonObject();
+                hc.setHostName(hcJsonObject.get("host_name").getAsString());
+                hc.setStarted("STARTED".equals(hcJsonObject.get("state").getAsString()));
+                hc.setName(hcJsonObject.get("component_name").getAsString());
+                hcList.add(hc);
+              }
+            }
+            svc.setComponentsToHostComponentsMap(componentsToHostComponentsMap);
+            return svc;
+        } catch (HttpException e) {
+            logger.warn("Unable to determine Ambari clusters", e);
+            throw new RuntimeException(e.getMessage(), e);
+        } catch (IOException e) {
+            logger.warn("Unable to determine Ambari clusters", e);
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+    return null;
+}
 
 }

+ 37 - 80
contrib/views/slider/src/main/resources/view.xml

@@ -18,86 +18,43 @@ limitations under the License. Kerberos, LDAP, Custom. Binary/Htt
   <name>SLIDER</name>
   <label>Slider Apps View</label>
   <version>1.0.0</version>
-  <parameter>
-    <name>hdfs.url</name>
-    <description>The URL to access HDFS service via its protocol. Typically this is the fs.defaultFS property in the core-site.xml configuration file. For example: hdfs://hdfs.namenode.host:8020.</description>
-    <required>true</required>
-  </parameter>
-  <parameter>
-    <name>yarn.rm.url</name>
-    <description>The URL to the YARN ResourceManager, used to provide YARN Application data. For example: http://yarn.resourcemanager.host:8050</description>
-    <required>true</required>
-  </parameter>
-  <parameter>
-    <name>yarn.rm.webapp.url</name>
-    <description>The URL to the YARN ResourceManager Web Application, used to provide YARN UI. Typically this is the yarn.resourcemanager.webapp.address config from yarn-site.xml configuration file. For example: http://yarn.resourcemanager.host:8088</description>
-    <required>true</required>
-  </parameter>
-  <parameter>
-    <name>yarn.rm.scheduler.url</name>
-    <description>The URL to the YARN ResourceManager Scheduler, which schedules YARN Applications. For example: http://yarn.resourcemanager.host:8030</description>
-    <required>true</required>
-  </parameter>
-  <parameter>
-    <name>zookeeper.quorum</name>
-    <description>ZooKeeper quorum location. Typically this is a comma separated list of ZooKeeper hostnames and port numbers (clientPort property in the zookeeper-env). For example: zookeeper.host1:2181,zookeeper.host2:2181.</description>
-    <required>true</required>
-  </parameter>
-  <parameter>
-    <name>ganglia.server.hostname</name>
-    <description>Hostname where Ganglia Server is located</description>
-    <required>false</required>
-  </parameter>
-  <parameter>
-    <name>ganglia.additional.clusters</name>
-    <description>Ganglia clusters which can be used by applications created in Slider Apps view. Value is comma separated list of cluster-name and port pairs. Typically this is the additional_clusters in the ganglia-env configuration. For example: Application1:8881,Application2:8882</description>
-    <required>false</required>
-  </parameter>
-  <parameter>
-    <name>slider.user</name>
-    <description>Slider user</description>
-    <required>false</required>
-  </parameter>
-  <parameter>
-    <name>slider.security.enabled</name>
-    <description>Indicates whether cluster has been secured or not.</description>
-    <required>true</required>
-  </parameter>
-  <parameter>
-    <name>yarn.rm.kerberos.principal</name>
-    <description>Kerberos principal used to access YARN ResourceManager. For example: rm/_HOST@EXAMPLE.COM</description>
-    <required>optional</required>
-  </parameter>
-  <parameter>
-    <name>dfs.namenode.kerberos.principal</name>
-    <description>Kerberos principal used to access HDFS NameNode. For example: nn/_HOST@EXAMPLE.COM</description>
-    <required>optional</required>
-  </parameter>
-  <parameter>
-    <name>view.kerberos.principal</name>
-    <description>Kerberos principal associated with this view. For example: ambari/_HOST@EXAMPLE.COM</description>
-    <required>optional</required>
-  </parameter>
-  <parameter>
-    <name>view.kerberos.principal.keytab</name>
-    <description>Path to the Kerberos principal keytab used for view's user. For example: /etc/security/keytabs/ambari.headless.keytab</description>
-    <required>optional</required>
-  </parameter>
-  <parameter>
-    <name>yarm.rm.ha.hosts</name>
-    <description>Hostnames where YARN ResourceManagers are available when High Availability is enabled. Value should be a comma separated list of host names</description>
-    <required>optional</required>
-  </parameter>
-  <parameter>
-    <name>yarn.rm.store.class</name>
-    <description>Name of class used by YARN ResourceManager to persist its state. For example some of the classes are 'org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore', or 'org.apache.hadoop.yarn.server.resourcemanager.recovery.FileSystemRMStateStore'</description>
-    <required>optional</required>
-  </parameter>
-  <parameter>
-    <name>yarn.rm.ha.automatic-failover.zk-base-path</name>
-    <description>The base path in ZooKeeper used for storing leader information. This is used when ZooKeeper based leader election is performed. For example: '/yarn-leader-election'</description>
-    <required>optional</required>
-  </parameter>
+	<parameter>
+		<name>ambari.server.url</name>
+		<description>Ambari Server Cluster REST API 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>
+		<required>true</required>
+	</parameter>
+	<parameter>
+		<name>ambari.server.password</name>
+		<description>Ambari administrator password (for example: admin)
+		</description>
+		<required>true</required>
+	</parameter>
+	<parameter>
+		<name>slider.user</name>
+		<description>Slider user</description>
+		<required>false</required>
+	</parameter>
+	<parameter>
+		<name>view.kerberos.principal</name>
+		<description>Kerberos principal associated with this view. For
+			example: ambari/_HOST@EXAMPLE.COM
+		</description>
+		<required>optional</required>
+	</parameter>
+	<parameter>
+		<name>view.kerberos.principal.keytab</name>
+		<description>Path to the Kerberos principal keytab used for view's
+			user. For example: /etc/security/keytabs/ambari.headless.keytab
+		</description>
+		<required>optional</required>
+	</parameter>
   <resource>
     <name>status</name>
     <service-class>org.apache.ambari.view.slider.rest.ViewStatusResource</service-class>