You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by sr...@apache.org on 2014/05/27 22:38:52 UTC

git commit: AMBARI-5903. Implement POST method on the apps endpoint - to create new apps. (srimanth)

Repository: ambari
Updated Branches:
  refs/heads/trunk 66d8d5bf7 -> c7736445d


AMBARI-5903. Implement POST method on the apps endpoint - to create new apps. (srimanth)


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

Branch: refs/heads/trunk
Commit: c7736445d5feb6a19eb31c7692cfdab4e60e1941
Parents: 66d8d5b
Author: Srimanth Gunturi <sg...@hortonworks.com>
Authored: Tue May 27 13:13:24 2014 -0700
Committer: Srimanth Gunturi <sg...@hortonworks.com>
Committed: Tue May 27 13:13:24 2014 -0700

----------------------------------------------------------------------
 contrib/views/slider/pom.xml                    |  79 +++--
 .../view/slider/SliderAppsViewController.java   |  79 ++---
 .../slider/SliderAppsViewControllerImpl.java    | 316 ++++++++++++++-----
 .../view/slider/rest/SliderAppsResource.java    |  69 ++--
 pom.xml                                         |   3 +
 5 files changed, 384 insertions(+), 162 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/c7736445/contrib/views/slider/pom.xml
----------------------------------------------------------------------
diff --git a/contrib/views/slider/pom.xml b/contrib/views/slider/pom.xml
index 13a4d9d..1bcd294 100644
--- a/contrib/views/slider/pom.xml
+++ b/contrib/views/slider/pom.xml
@@ -111,6 +111,37 @@
 		<!-- Slider Dependencies (to be removed when Slider has Maven repository) -->
 		<!-- ==================================================================== -->
 		<dependency>
+			<groupId>org.apache.curator</groupId>
+			<artifactId>curator-client</artifactId>
+			<version>${curator.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.curator</groupId>
+			<artifactId>curator-framework</artifactId>
+			<version>${curator.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.curator</groupId>
+			<artifactId>curator-x-discovery</artifactId>
+			<version>${curator.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.curator</groupId>
+			<artifactId>curator-x-discovery-server</artifactId>
+			<version>${curator.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.zookeeper</groupId>
+			<artifactId>zookeeper</artifactId>
+			<version>${zookeeper.version}</version>
+			<exclusions>
+				<exclusion>
+					<groupId>org.junit</groupId>
+					<artifactId>junit</artifactId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+		<dependency>
 			<groupId>org.apache.hadoop</groupId>
 			<artifactId>hadoop-common</artifactId>
 			<version>${hadoop.version}</version>
@@ -341,6 +372,8 @@
 		<commons-lang.version>2.6</commons-lang.version>
 		<httpclient.version>4.2.5</httpclient.version>
 		<jcommander.version>1.30</jcommander.version>
+		<curator.version>2.4.1</curator.version>
+		<zookeeper.version>3.4.5</zookeeper.version>
 	</properties>
 
 	<build>
@@ -446,29 +479,29 @@
 			</plugin>
 		</plugins>
 		<resources>
-      <resource>
-        <directory>src/main/resources</directory>
-        <filtering>true</filtering>
-        <includes>
-          <include>slider.properties</include>
-        </includes>
-      </resource>
-      <resource>
-        <directory>src/main/resources/</directory>
-        <filtering>false</filtering>
-        <includes>
-          <include>view.xml</include>
-        </includes>
-      </resource>
-      <resource>
-        <directory>src/main/resources/ui/public</directory>
-        <filtering>false</filtering>
-      </resource>
-      <resource>
-        <targetPath>WEB-INF/lib</targetPath>
-        <filtering>false</filtering>
-        <directory>target/lib</directory>
-      </resource>
+			<resource>
+				<directory>src/main/resources</directory>
+				<filtering>true</filtering>
+				<includes>
+					<include>slider.properties</include>
+				</includes>
+			</resource>
+			<resource>
+				<directory>src/main/resources/</directory>
+				<filtering>false</filtering>
+				<includes>
+					<include>view.xml</include>
+				</includes>
+			</resource>
+			<resource>
+				<directory>src/main/resources/ui/public</directory>
+				<filtering>false</filtering>
+			</resource>
+			<resource>
+				<targetPath>WEB-INF/lib</targetPath>
+				<filtering>false</filtering>
+				<directory>target/lib</directory>
+			</resource>
 		</resources>
 		<pluginManagement>
 			<plugins>

http://git-wip-us.apache.org/repos/asf/ambari/blob/c7736445/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/SliderAppsViewController.java
----------------------------------------------------------------------
diff --git a/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/SliderAppsViewController.java b/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/SliderAppsViewController.java
index da66a3b..83b641e 100644
--- a/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/SliderAppsViewController.java
+++ b/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/SliderAppsViewController.java
@@ -24,52 +24,55 @@ import java.util.Set;
 
 import org.apache.hadoop.yarn.exceptions.YarnException;
 
+import com.google.gson.JsonObject;
 import com.google.inject.ImplementedBy;
 
 @ImplementedBy(SliderAppsViewControllerImpl.class)
 public interface SliderAppsViewController {
 
-	public ViewStatus getViewStatus();
+  public ViewStatus getViewStatus();
 
-	/**
-	 * Provides information about requested Slider App.
-	 * 
-	 * @param applicationId
-	 * @param properties
-	 *          Identifies specific properties to show up. Provide
-	 *          <code>null</code> for default properties.
-	 * @return
-	 * @throws YarnException
-	 * @throws IOException
-	 */
-	public SliderApp getSliderApp(String applicationId, Set<String> properties)
-	    throws YarnException, IOException;
+  /**
+   * Provides information about requested Slider App.
+   * 
+   * @param applicationId
+   * @param properties
+   *          Identifies specific properties to show up. Provide
+   *          <code>null</code> for default properties.
+   * @return
+   * @throws YarnException
+   * @throws IOException
+   */
+  public SliderApp getSliderApp(String applicationId, Set<String> properties)
+      throws YarnException, IOException;
 
-	/**
-	 * Provides list of Slider apps with requested properties populated.
-	 * 
-	 * @param properties
-	 *          Identifies specific properties to show up. Provide
-	 *          <code>null</code> for default properties.
-	 * @return
-	 * @throws YarnException
-	 * @throws IOException
-	 */
-	public List<SliderApp> getSliderApps(Set<String> properties)
-	    throws YarnException, IOException;
+  /**
+   * Provides list of Slider apps with requested properties populated.
+   * 
+   * @param properties
+   *          Identifies specific properties to show up. Provide
+   *          <code>null</code> for default properties.
+   * @return
+   * @throws YarnException
+   * @throws IOException
+   */
+  public List<SliderApp> getSliderApps(Set<String> properties)
+      throws YarnException, IOException;
 
-	/**
-	 * Attempts to delete a Slider app. An unsuccessful attempt will result in
-	 * exception.
-	 * 
-	 * @param applicationId
-	 * @throws YarnException
-	 * @throws IOException
-	 */
-	public void deleteSliderApp(String applicationId) throws YarnException,
-	    IOException;
+  /**
+   * Attempts to delete a Slider app. An unsuccessful attempt will result in
+   * exception.
+   * 
+   * @param applicationId
+   * @throws YarnException
+   * @throws IOException
+   */
+  public void deleteSliderApp(String applicationId) throws YarnException,
+      IOException;
 
-	public SliderAppType getSliderAppType(String appTypeId, Set<String> properties);
+  public SliderAppType getSliderAppType(String appTypeId, Set<String> properties);
 
-	public List<SliderAppType> getSliderAppTypes(Set<String> properties);
+  public List<SliderAppType> getSliderAppTypes(Set<String> properties);
+
+  public String createSliderApp(JsonObject requestJson) throws IOException, YarnException, InterruptedException;
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/c7736445/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/SliderAppsViewControllerImpl.java
----------------------------------------------------------------------
diff --git a/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/SliderAppsViewControllerImpl.java b/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/SliderAppsViewControllerImpl.java
index c67e9ce..1947e1d 100644
--- a/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/SliderAppsViewControllerImpl.java
+++ b/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/SliderAppsViewControllerImpl.java
@@ -18,11 +18,22 @@
 
 package org.apache.ambari.view.slider;
 
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.zip.ZipException;
+
 import org.apache.ambari.view.ViewContext;
 import org.apache.ambari.view.slider.clients.AmbariClient;
 import org.apache.ambari.view.slider.clients.AmbariCluster;
@@ -37,7 +48,9 @@ import org.apache.commons.io.IOUtils;
 import org.apache.commons.io.filefilter.RegexFileFilter;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.hdfs.HdfsConfiguration;
+import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.hadoop.yarn.api.records.ApplicationId;
 import org.apache.hadoop.yarn.api.records.ApplicationReport;
 import org.apache.hadoop.yarn.api.records.YarnApplicationState;
@@ -48,6 +61,7 @@ import org.apache.log4j.Logger;
 import org.apache.slider.api.ClusterDescription;
 import org.apache.slider.client.SliderClient;
 import org.apache.slider.common.SliderKeys;
+import org.apache.slider.common.params.ActionCreateArgs;
 import org.apache.slider.common.tools.SliderFileSystem;
 import org.apache.slider.core.exceptions.UnknownApplicationInstanceException;
 import org.apache.slider.core.main.LauncherExitCodes;
@@ -59,19 +73,13 @@ import org.apache.tools.zip.ZipFile;
 import org.codehaus.jackson.map.ObjectMapper;
 import org.codehaus.jackson.type.TypeReference;
 
-import java.io.File;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.zip.ZipException;
+import com.google.gson.Gson;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
 
 @Singleton
 public class SliderAppsViewControllerImpl implements SliderAppsViewController {
@@ -84,10 +92,16 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
   private AmbariClient ambariClient;
   private List<SliderAppType> appTypes;
 
+  private Integer createAppCounter = -1;
+
   private String getAppsFolderPath() {
     return viewContext
-               .getAmbariProperty(org.apache.ambari.server.configuration.Configuration.RESOURCES_DIR_KEY)
-           + "/apps";
+        .getAmbariProperty(org.apache.ambari.server.configuration.Configuration.RESOURCES_DIR_KEY)
+        + "/apps";
+  }
+
+  private String getAppsCreateFolderPath() {
+    return getAppsFolderPath() + "/create";
   }
 
   @Override
@@ -175,33 +189,45 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
     return null;
   }
 
+  private String getApplicationIdString(ApplicationId appId) {
+    return Long.toString(appId.getClusterTimestamp()) + "_"
+        + Integer.toString(appId.getId());
+  }
+
+  private ApplicationId getApplicationId(String appIdString) {
+    if (appIdString != null) {
+      int index = appIdString.indexOf('_');
+      if (index > -1 && index < appIdString.length() - 1) {
+        ApplicationId appId = ApplicationId.newInstance(
+            Long.parseLong(appIdString.substring(0, index)),
+            Integer.parseInt(appIdString.substring(index + 1)));
+        return appId;
+      }
+    }
+    return null;
+  }
+
   @Override
   public SliderApp getSliderApp(String applicationId, Set<String> properties)
       throws YarnException, IOException {
-    if (applicationId != null) {
-      int index = applicationId.indexOf('_');
-      if (index > -1 && index < applicationId.length() - 1) {
-        ApplicationId appId = ApplicationId.newInstance(
-            Long.parseLong(applicationId.substring(0, index)),
-            Integer.parseInt(applicationId.substring(index + 1)));
-        ClassLoader currentClassLoader = Thread.currentThread()
-            .getContextClassLoader();
-        Thread.currentThread().setContextClassLoader(
-            getClass().getClassLoader());
-        try {
-          SliderClient sliderClient = getSliderClient();
-          ApplicationReport yarnApp = sliderClient.getApplicationReport(appId);
-          return createSliderAppObject(yarnApp, properties, sliderClient);
-        } finally {
-          Thread.currentThread().setContextClassLoader(currentClassLoader);
-        }
+    ApplicationId appId = getApplicationId(applicationId);
+    if (appId != null) {
+      ClassLoader currentClassLoader = Thread.currentThread()
+          .getContextClassLoader();
+      Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+      try {
+        SliderClient sliderClient = getSliderClient();
+        ApplicationReport yarnApp = sliderClient.getApplicationReport(appId);
+        return createSliderAppObject(yarnApp, properties, sliderClient);
+      } finally {
+        Thread.currentThread().setContextClassLoader(currentClassLoader);
       }
     }
     return null;
   }
 
   private SliderApp createSliderAppObject(ApplicationReport yarnApp,
-                                          Set<String> properties, SliderClient sliderClient) {
+      Set<String> properties, SliderClient sliderClient) {
     if (yarnApp == null) {
       return null;
     }
@@ -229,8 +255,7 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
       }
     }
 
-    app.setId(Long.toString(yarnApp.getApplicationId().getClusterTimestamp())
-              + "_" + Integer.toString(yarnApp.getApplicationId().getId()));
+    app.setId(getApplicationIdString(yarnApp.getApplicationId()));
     app.setName(yarnApp.getName());
     app.setUser(yarnApp.getUser());
     app.setDiagnostics(yarnApp.getDiagnostics());
@@ -267,10 +292,11 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
               if (quickLinks != null && quickLinks.containsKey("JMX")) {
                 String jmxUrl = quickLinks.get("JMX");
                 List<SliderAppType> appTypes = getSliderAppTypes(null);
-                if(appTypes != null && appTypes.size() > 0) {
+                if (appTypes != null && appTypes.size() > 0) {
                   // TODO: Get the correct app type based on name and version
                   SliderAppType appType = appTypes.get(0);
-                  app.setJmx(sliderAppClient.getJmx(jmxUrl, viewContext, appType));
+                  app.setJmx(sliderAppClient.getJmx(jmxUrl, viewContext,
+                      appType));
                 }
               }
               Map<String, Map<String, String>> configs = sliderAppClient
@@ -286,10 +312,8 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
                   Map<String, SliderAppComponent> componentTypeMap = new HashMap<String, SliderAppComponent>();
                   for (Entry<String, Object> e : description.status.entrySet()) {
                     @SuppressWarnings("unchecked")
-                    Map<String, Map<String, Map<String, Object>>>
-                        componentsObj =
-                        (Map<String, Map<String, Map<String, Object>>>) e
-                            .getValue();
+                    Map<String, Map<String, Map<String, Object>>> componentsObj = (Map<String, Map<String, Map<String, Object>>>) e
+                        .getValue();
                     boolean isLive = "live".equals(e.getKey());
                     for (Entry<String, Map<String, Map<String, Object>>> componentEntry : componentsObj
                         .entrySet()) {
@@ -303,7 +327,7 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
                         appComponent
                             .setCompletedContainers(new HashMap<String, Map<String, String>>());
                         componentTypeMap.put(componentEntry.getKey(),
-                                             appComponent);
+                            appComponent);
                       }
                       for (Entry<String, Map<String, Object>> containerEntry : componentEntry
                           .getValue().entrySet()) {
@@ -316,19 +340,19 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
                           Object containerPropertyValue = containerValues
                               .get(containerProperty);
                           containerDataMap.put(containerProperty,
-                                               containerPropertyValue.toString());
+                              containerPropertyValue.toString());
                         }
                         if (isLive) {
                           appComponent.getActiveContainers().put(containerId,
-                                                                 containerDataMap);
+                              containerDataMap);
                         } else {
                           appComponent.getCompletedContainers().put(
                               containerId, containerDataMap);
                         }
                       }
                       appComponent.setInstanceCount(appComponent
-                                                        .getActiveContainers().size()
-                                                    + appComponent.getCompletedContainers().size());
+                          .getActiveContainers().size()
+                          + appComponent.getCompletedContainers().size());
                     }
                   }
                   app.setComponents(componentTypeMap);
@@ -336,16 +360,16 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
               } catch (UnknownApplicationInstanceException e) {
                 logger.warn(
                     "Unable to determine app components for "
-                    + yarnApp.getName(), e);
+                        + yarnApp.getName(), e);
               } catch (YarnException e) {
                 logger.warn(
                     "Unable to determine app components for "
-                    + yarnApp.getName(), e);
+                        + yarnApp.getName(), e);
                 throw new RuntimeException(e.getMessage(), e);
               } catch (IOException e) {
                 logger.warn(
                     "Unable to determine app components for "
-                    + yarnApp.getName(), e);
+                        + yarnApp.getName(), e);
                 throw new RuntimeException(e.getMessage(), e);
               }
             }
@@ -357,9 +381,10 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
   }
 
   /**
-   * Creates a new {@link SliderClient} initialized with appropriate configuration. If configuration was not determined,
-   * <code>null</code> is returned.
-   *
+   * Creates a new {@link SliderClient} initialized with appropriate
+   * configuration. If configuration was not determined, <code>null</code> is
+   * returned.
+   * 
    * @return
    */
   protected SliderClient getSliderClient() {
@@ -368,7 +393,7 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
       SliderClient client = new SliderClient() {
         @Override
         public String getUsername() throws IOException {
-          return null;
+          return "yarn";
         }
 
         @Override
@@ -376,7 +401,7 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
           super.serviceInit(conf);
           // Override the default FS client to set the super user.
           FileSystem fs = FileSystem.get(FileSystem.getDefaultUri(getConfig()),
-                                         getConfig(), "yarn");
+              getConfig(), "yarn");
           SliderFileSystem fileSystem = new SliderFileSystem(fs, getConfig());
           Field fsField = SliderClient.class
               .getDeclaredField("sliderFileSystem");
@@ -386,7 +411,7 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
       };
       try {
         sliderClientConfiguration = client.bindArgs(sliderClientConfiguration,
-                                                    new String[]{"usage"});
+            new String[] { "usage" });
       } catch (Exception e) {
         logger.warn("Unable to set SliderClient configs", e);
         throw new RuntimeException(e.getMessage(), e);
@@ -399,15 +424,16 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
   }
 
   /**
-   * Dynamically determines Slider client configuration. If unable to determine, <code>null</code> is returned.
-   *
+   * Dynamically determines Slider client configuration. If unable to determine,
+   * <code>null</code> is returned.
+   * 
    * @return
    */
   private Configuration getSliderClientConfiguration() {
     AmbariCluster ambariCluster = getAmbariCluster();
     if (ambariCluster != null) {
       AmbariService zkService = ambariClient.getService(ambariCluster,
-                                                        "ZOOKEEPER");
+          "ZOOKEEPER");
       if (zkService != null && ambariCluster.getDesiredConfigs() != null
           && ambariCluster.getDesiredConfigs().containsKey("global")
           && ambariCluster.getDesiredConfigs().containsKey("yarn-site")
@@ -442,7 +468,7 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
         yarnConfig.set("yarn.log-aggregation-enable", "true");
         yarnConfig.set("yarn.resourcemanager.address", rmAddress);
         yarnConfig.set("yarn.resourcemanager.scheduler.address",
-                       rmSchedulerAddress);
+            rmSchedulerAddress);
         yarnConfig.set("fs.defaultFS", hdfsPath);
         yarnConfig.set("slider.zookeeper.quorum", zkQuorum.toString());
         return yarnConfig;
@@ -463,7 +489,7 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
       List<ApplicationReport> yarnApps = sliderClient.listSliderInstances(null);
       for (ApplicationReport yarnApp : yarnApps) {
         SliderApp sliderAppObject = createSliderAppObject(yarnApp, properties,
-                                                          sliderClient);
+            sliderClient);
         if (sliderAppObject != null) {
           sliderApps.add(sliderAppObject);
         }
@@ -530,7 +556,7 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
           try {
             ZipFile zipFile = new ZipFile(appZip);
             Metainfo metainfo = new MetainfoParser().parse(zipFile
-                                                               .getInputStream(zipFile.getEntry("metainfo.xml")));
+                .getInputStream(zipFile.getEntry("metainfo.xml")));
             // Create app type object
             if (metainfo.getServices() != null
                 && metainfo.getServices().size() > 0) {
@@ -571,11 +597,11 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
                 // appTypeComponent.setPriority(component.);
                 if (component.getMinInstanceCount() != null) {
                   appTypeComponent.setInstanceCount(Integer.parseInt(component
-                                                                         .getMinInstanceCount()));
+                      .getMinInstanceCount()));
                 }
                 if (component.getMaxInstanceCount() != null) {
                   appTypeComponent.setMaxInstanceCount(Integer
-                                                           .parseInt(component.getMaxInstanceCount()));
+                      .parseInt(component.getMaxInstanceCount()));
                 }
                 if (resourcesJson != null) {
                   JsonElement componentJson = resourcesJson.getAsJsonObject()
@@ -583,10 +609,10 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
                       .get(component.getName());
                   if (componentJson != null
                       && componentJson.getAsJsonObject().has(
-                      "yarn.role.priority")) {
+                          "yarn.role.priority")) {
                     appTypeComponent.setPriority(Integer.parseInt(componentJson
-                                                                      .getAsJsonObject().get("yarn.role.priority")
-                                                                      .getAsString()));
+                        .getAsJsonObject().get("yarn.role.priority")
+                        .getAsString()));
                   }
                 }
                 appTypeComponent.setCategory(component.getCategory());
@@ -594,7 +620,8 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
               }
 
               appType.setJmxMetrics(readMetrics(zipFile, "jmx_metrics.json"));
-              appType.setGangliaMetrics(readMetrics(zipFile, "ganglia_metrics.json"));
+              appType.setGangliaMetrics(readMetrics(zipFile,
+                  "ganglia_metrics.json"));
 
               appType.setTypeComponents(appTypeComponentList);
               appTypes.add(appType);
@@ -610,21 +637,152 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
     return appTypes;
   }
 
-  Map<String, Map<String, Map<String, Metric>>> readMetrics(ZipFile zipFile, String fileName) {
+  Map<String, Map<String, Map<String, Metric>>> readMetrics(ZipFile zipFile,
+      String fileName) {
     Map<String, Map<String, Map<String, Metric>>> metrics = null;
     try {
-      InputStream inputStream =
-          zipFile.getInputStream(zipFile.getEntry("jmx_metrics.json"));
+      InputStream inputStream = zipFile.getInputStream(zipFile
+          .getEntry("jmx_metrics.json"));
       ObjectMapper mapper = new ObjectMapper();
 
-      metrics =
-          mapper.readValue(inputStream,
-                           new TypeReference<Map<String, Map<String, Map<String, Metric>>>>() {
-                           });
+      metrics = mapper.readValue(inputStream,
+          new TypeReference<Map<String, Map<String, Map<String, Metric>>>>() {
+          });
     } catch (IOException e) {
       logger.info("Error reading metrics. " + e.getMessage());
     }
 
     return metrics;
   }
+
+  @Override
+  public String createSliderApp(JsonObject json) throws IOException,
+      YarnException, InterruptedException {
+    if (json.has("name") && json.has("typeConfigs")
+        && json.has("typeComponents")) {
+      final String appName = json.get("name").getAsString();
+      JsonObject configs = json.get("typeConfigs").getAsJsonObject();
+      JsonArray componentsArray = json.get("typeComponents").getAsJsonArray();
+      String appsCreateFolderPath = getAppsCreateFolderPath();
+      File appsCreateFolder = new File(appsCreateFolderPath);
+      if (!appsCreateFolder.exists())
+        appsCreateFolder.mkdirs();
+      int appCount;
+      synchronized (createAppCounter) {
+        if (createAppCounter < 0) {
+          // Not initialized
+          createAppCounter = 0;
+          String[] apps = appsCreateFolder.list();
+          for (String app : apps) {
+            try {
+              int count = Integer.parseInt(app);
+              if (count > createAppCounter)
+                createAppCounter = count;
+            } catch (NumberFormatException e) {
+            }
+          }
+        }
+        appCount = ++createAppCounter;
+      }
+      File appCreateFolder = new File(appsCreateFolder,
+          Integer.toString(appCount));
+      appCreateFolder.mkdirs();
+      File appConfigJsonFile = new File(appCreateFolder, "appConfig.json");
+      File resourcesJsonFile = new File(appCreateFolder, "resources.json");
+      saveAppConfigs(configs, componentsArray, appConfigJsonFile);
+      saveAppResources(componentsArray, resourcesJsonFile);
+
+      AmbariClusterInfo clusterInfo = ambariClient.getClusterInfo();
+      AmbariCluster cluster = ambariClient.getCluster(clusterInfo);
+      Map<String, String> coreSiteConfigs = ambariClient.getConfiguration(
+          clusterInfo, "core-site", cluster.getDesiredConfigs()
+              .get("core-site"));
+      String hdfsLocation = coreSiteConfigs.get("fs.defaultFS");
+      final ActionCreateArgs createArgs = new ActionCreateArgs();
+      createArgs.template = appConfigJsonFile;
+      createArgs.resources = resourcesJsonFile;
+      createArgs.image = new Path(hdfsLocation
+          + "/slider/agent/slider-agent.tar.gz");
+
+      ClassLoader currentClassLoader = Thread.currentThread()
+          .getContextClassLoader();
+      Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+      try {
+        ApplicationId applicationId = UserGroupInformation.getBestUGI(null,
+            "yarn").doAs(new PrivilegedExceptionAction<ApplicationId>() {
+          public ApplicationId run() throws IOException, YarnException {
+            SliderClient sliderClient = getSliderClient();
+            sliderClient.actionCreate(appName, createArgs);
+            return sliderClient.applicationId;
+          }
+        });
+        if (applicationId != null)
+          return getApplicationIdString(applicationId);
+      } finally {
+        Thread.currentThread().setContextClassLoader(currentClassLoader);
+      }
+    }
+    return null;
+  }
+
+  private void saveAppResources(JsonArray componentsArray,
+      File resourcesJsonFile) throws IOException {
+    JsonObject resourcesObj = new JsonObject();
+    resourcesObj.addProperty("schema",
+        "http://example.org/specification/v2.0.0");
+    resourcesObj.add("metadata", new JsonObject());
+    resourcesObj.add("global", new JsonObject());
+    JsonObject componentsObj = new JsonObject();
+    if (componentsArray != null) {
+      for (int i = 0; i < componentsArray.size(); i++) {
+        JsonObject inputComponent = componentsArray.get(i).getAsJsonObject();
+        if (inputComponent.has("id")) {
+          JsonObject componentValue = new JsonObject();
+          componentValue.addProperty("yarn.role.priority",
+              inputComponent.get("priority").getAsString());
+          componentValue.addProperty("yarn.component.instances", inputComponent
+              .get("instanceCount").getAsString());
+          componentsObj.add(inputComponent.get("id").getAsString(),
+              componentValue);
+        }
+      }
+    }
+    resourcesObj.add("components", componentsObj);
+    String jsonString = new Gson().toJson(resourcesObj);
+    FileOutputStream fos = null;
+    try {
+      fos = new FileOutputStream(resourcesJsonFile);
+      IOUtils.write(jsonString, fos);
+    } finally {
+      if (fos != null)
+        fos.close();
+    }
+  }
+
+  private void saveAppConfigs(JsonObject configs, JsonArray componentsArray,
+      File appConfigJsonFile) throws IOException {
+    JsonObject appConfigs = new JsonObject();
+    appConfigs.addProperty("schema", "http://example.org/specification/v2.0.0");
+    appConfigs.add("metadata", new JsonObject());
+    appConfigs.add("global", configs);
+    JsonObject componentsObj = new JsonObject();
+    if (componentsArray != null) {
+      for (int i = 0; i < componentsArray.size(); i++) {
+        JsonObject inputComponent = componentsArray.get(i).getAsJsonObject();
+        if (inputComponent.has("id"))
+          componentsObj.add(inputComponent.get("id").getAsString(),
+              new JsonObject());
+      }
+    }
+    appConfigs.add("components", componentsObj);
+    String jsonString = new Gson().toJson(appConfigs);
+    FileOutputStream fos = null;
+    try {
+      fos = new FileOutputStream(appConfigJsonFile);
+      IOUtils.write(jsonString, fos);
+    } finally {
+      if (fos != null)
+        fos.close();
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/c7736445/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/rest/SliderAppsResource.java
----------------------------------------------------------------------
diff --git a/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/rest/SliderAppsResource.java b/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/rest/SliderAppsResource.java
index a221610..30b9f3b 100644
--- a/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/rest/SliderAppsResource.java
+++ b/contrib/views/slider/src/main/java/org/apache/ambari/view/slider/rest/SliderAppsResource.java
@@ -19,9 +19,13 @@
 package org.apache.ambari.view.slider.rest;
 
 import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
 
+import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
+import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
@@ -34,35 +38,56 @@ import javax.ws.rs.core.UriInfo;
 import org.apache.ambari.view.ViewResourceHandler;
 import org.apache.ambari.view.slider.SliderAppsViewController;
 import org.apache.hadoop.yarn.exceptions.YarnException;
+import org.apache.log4j.Logger;
 
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParser;
 import com.google.inject.Inject;
 
 public class SliderAppsResource {
 
-	@Inject
-	ViewResourceHandler resourceHandler;
-	@Inject
-	SliderAppsViewController sliderAppsViewController;
+  private static final Logger logger = Logger
+      .getLogger(SliderAppsResource.class);
+  @Inject
+  ViewResourceHandler resourceHandler;
+  @Inject
+  SliderAppsViewController sliderAppsViewController;
 
-	@GET
-	@Produces({ MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON })
-	public Response getApps(@Context HttpHeaders headers, @Context UriInfo uri) {
-		return resourceHandler.handleRequest(headers, uri, null);
-	}
+  @GET
+  @Produces({ MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON })
+  public Response getApps(@Context HttpHeaders headers, @Context UriInfo uri) {
+    return resourceHandler.handleRequest(headers, uri, null);
+  }
 
-	@GET
-	@Path("{appId}")
-	@Produces({ MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON })
-	public Response getApp(@Context HttpHeaders headers, @Context UriInfo uri,
-	    @PathParam("appId") String appId) {
-		return resourceHandler.handleRequest(headers, uri, appId);
-	}
+  @GET
+  @Path("{appId}")
+  @Produces({ MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON })
+  public Response getApp(@Context HttpHeaders headers, @Context UriInfo uri,
+      @PathParam("appId") String appId) {
+    return resourceHandler.handleRequest(headers, uri, appId);
+  }
 
-	@DELETE
-	@Path("{appId}")
-	public void deleteApp(@Context HttpHeaders headers, @Context UriInfo uri,
-	    @PathParam("appId") String appId) throws YarnException, IOException {
-		sliderAppsViewController.deleteSliderApp(appId);
-	}
+  @DELETE
+  @Path("{appId}")
+  public void deleteApp(@Context HttpHeaders headers, @Context UriInfo uri,
+      @PathParam("appId") String appId) throws YarnException, IOException {
+    sliderAppsViewController.deleteSliderApp(appId);
+  }
 
+  @POST
+  @Consumes({ MediaType.TEXT_PLAIN })
+  public Response createApp(@Context UriInfo uri, String jsonString)
+      throws IOException, YarnException, InterruptedException,
+      URISyntaxException {
+    if (jsonString != null) {
+      JsonElement requestContent = new JsonParser().parse(jsonString);
+      String sliderApp = sliderAppsViewController
+          .createSliderApp(requestContent.getAsJsonObject());
+      if (sliderApp != null)
+        return Response.created(
+            new URI(uri.getAbsolutePath() + "/" + sliderApp)).build();
+    }
+    logger.warn("No request content sent to create app");
+    return Response.status(Response.Status.BAD_REQUEST).build();
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/c7736445/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 214e0b3..2d47548 100644
--- a/pom.xml
+++ b/pom.xml
@@ -213,6 +213,9 @@
             <exclude>contrib/views/slider/src/main/resources/ui/app/assets/javascripts/modernizr-2.6.2.min.js</exclude>
             <exclude>contrib/addons/package/deb/nagios_addon_deb_control</exclude>
             <exclude>contrib/addons/src/addOns/nagios/conf.d/hdp_mon_nagios_addons.conf</exclude>
+            <exclude>contrib/views/*/.classpath</exclude>
+            <exclude>contrib/views/*/.project</exclude>
+            <exclude>contrib/views/*/.settings/**</exclude>
           </excludes>
         </configuration>
         <executions>