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/29 01:43:47 UTC

git commit: AMBARI-5918. Implement Slider app api to freeze and thaw an application. (onechiporenko, srimanth)

Repository: ambari
Updated Branches:
  refs/heads/trunk 1064ade01 -> 53e3d8dd0


AMBARI-5918. Implement Slider app api to freeze and thaw an application.  (onechiporenko, srimanth)


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

Branch: refs/heads/trunk
Commit: 53e3d8dd018e694a79982179f9f5fabffd275369
Parents: 1064ade
Author: Srimanth Gunturi <sg...@hortonworks.com>
Authored: Wed May 28 15:18:47 2014 -0700
Committer: Srimanth Gunturi <sg...@hortonworks.com>
Committed: Wed May 28 16:37:59 2014 -0700

----------------------------------------------------------------------
 .../view/slider/SliderAppsViewController.java   |  9 +-
 .../slider/SliderAppsViewControllerImpl.java    | 63 +++++++++++++
 .../view/slider/rest/SliderAppsResource.java    | 37 +++++++-
 .../ui/app/controllers/slider_app_controller.js | 93 +++++++++++++++++++-
 .../src/main/resources/ui/app/helpers/ajax.js   | 32 ++++++-
 .../src/main/resources/ui/app/initialize.js     |  7 ++
 .../src/main/resources/ui/app/routes/main.js    |  6 +-
 7 files changed, 234 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/53e3d8dd/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 83b641e..823fea6 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
@@ -74,5 +74,12 @@ public interface SliderAppsViewController {
 
   public List<SliderAppType> getSliderAppTypes(Set<String> properties);
 
-  public String createSliderApp(JsonObject requestJson) throws IOException, YarnException, InterruptedException;
+  public String createSliderApp(JsonObject requestJson) throws IOException,
+      YarnException, InterruptedException;
+
+  public void freezeApp(String appId) throws YarnException, IOException,
+      InterruptedException;
+
+  public void thawApp(String appId) throws YarnException, IOException,
+      InterruptedException;
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/53e3d8dd/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 679fa3a..4ccc51b 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
@@ -62,6 +62,8 @@ 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.params.ActionFreezeArgs;
+import org.apache.slider.common.params.ActionThawArgs;
 import org.apache.slider.common.tools.SliderFileSystem;
 import org.apache.slider.core.exceptions.UnknownApplicationInstanceException;
 import org.apache.slider.core.main.LauncherExitCodes;
@@ -486,6 +488,10 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
             rmSchedulerAddress);
         yarnConfig.set("fs.defaultFS", hdfsPath);
         yarnConfig.set("slider.zookeeper.quorum", zkQuorum.toString());
+        yarnConfig
+            .set(
+                "yarn.application.classpath",
+                "/etc/hadoop/conf,/usr/lib/hadoop/*,/usr/lib/hadoop/lib/*,/usr/lib/hadoop-hdfs/*,/usr/lib/hadoop-hdfs/lib/*,/usr/lib/hadoop-yarn/*,/usr/lib/hadoop-yarn/lib/*,/usr/lib/hadoop-mapreduce/*,/usr/lib/hadoop-mapreduce/lib/*");
         return yarnConfig;
       }
     }
@@ -802,4 +808,61 @@ public class SliderAppsViewControllerImpl implements SliderAppsViewController {
         fos.close();
     }
   }
+
+  @Override
+  public void freezeApp(String appId) throws YarnException, IOException,
+      InterruptedException {
+    ClassLoader currentClassLoader = Thread.currentThread()
+        .getContextClassLoader();
+    Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+    try {
+      Set<String> properties = new HashSet<String>();
+      properties.add("id");
+      properties.add("name");
+      final SliderApp sliderApp = getSliderApp(appId, properties);
+      if (sliderApp == null)
+        throw new ApplicationNotFoundException(appId);
+
+      ApplicationId applicationId = UserGroupInformation.getBestUGI(null,
+          "yarn").doAs(new PrivilegedExceptionAction<ApplicationId>() {
+        public ApplicationId run() throws IOException, YarnException {
+          SliderClient sliderClient = getSliderClient();
+          ActionFreezeArgs freezeArgs = new ActionFreezeArgs();
+          sliderClient.actionFreeze(sliderApp.getName(), freezeArgs);
+          return sliderClient.applicationId;
+        }
+      });
+      logger.debug("Slider app has been frozen - " + applicationId.toString());
+    } finally {
+      Thread.currentThread().setContextClassLoader(currentClassLoader);
+    }
+  }
+
+  @Override
+  public void thawApp(String appId) throws YarnException, IOException,
+      InterruptedException {
+    ClassLoader currentClassLoader = Thread.currentThread()
+        .getContextClassLoader();
+    Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+    try {
+      Set<String> properties = new HashSet<String>();
+      properties.add("id");
+      properties.add("name");
+      final SliderApp sliderApp = getSliderApp(appId, properties);
+      if (sliderApp == null)
+        throw new ApplicationNotFoundException(appId);
+      ApplicationId applicationId = UserGroupInformation.getBestUGI(null,
+          "yarn").doAs(new PrivilegedExceptionAction<ApplicationId>() {
+        public ApplicationId run() throws IOException, YarnException {
+          SliderClient sliderClient = getSliderClient();
+          ActionThawArgs thawArgs = new ActionThawArgs();
+          sliderClient.actionThaw(sliderApp.getName(), thawArgs);
+          return sliderClient.applicationId;
+        }
+      });
+      logger.debug("Slider app has been thawed - " + applicationId.toString());
+    } finally {
+      Thread.currentThread().setContextClassLoader(currentClassLoader);
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/53e3d8dd/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 30b9f3b..4459db2 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
@@ -26,6 +26,7 @@ import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
@@ -41,6 +42,7 @@ import org.apache.hadoop.yarn.exceptions.YarnException;
 import org.apache.log4j.Logger;
 
 import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
 import com.google.inject.Inject;
 
@@ -74,8 +76,37 @@ public class SliderAppsResource {
     sliderAppsViewController.deleteSliderApp(appId);
   }
 
+  @PUT
+  @Path("{appId}")
+  @Consumes({ MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON })
+  public Response updateApp(@Context UriInfo uri, String jsonString,
+      @PathParam("appId") String appId) throws IOException, YarnException,
+      InterruptedException, URISyntaxException {
+    if (jsonString != null) {
+      JsonElement requestContent = new JsonParser().parse(jsonString);
+      if (requestContent != null && appId != null) {
+        JsonObject requestJson = requestContent.getAsJsonObject();
+        if (requestJson.has("state")) {
+          String newState = requestJson.get("state").getAsString();
+          if ("FROZEN".equals(newState))
+            sliderAppsViewController.freezeApp(appId);
+          else if ("RUNNING".equals(newState))
+            sliderAppsViewController.thawApp(appId);
+        } else if (requestJson.has("components")) {
+        }
+      }
+      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();
+  }
+
   @POST
-  @Consumes({ MediaType.TEXT_PLAIN })
+  @Consumes({ MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON })
   public Response createApp(@Context UriInfo uri, String jsonString)
       throws IOException, YarnException, InterruptedException,
       URISyntaxException {
@@ -84,8 +115,8 @@ public class SliderAppsResource {
       String sliderApp = sliderAppsViewController
           .createSliderApp(requestContent.getAsJsonObject());
       if (sliderApp != null)
-        return Response.created(
-            new URI(uri.getAbsolutePath() + "/" + sliderApp)).build();
+        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/53e3d8dd/contrib/views/slider/src/main/resources/ui/app/controllers/slider_app_controller.js
----------------------------------------------------------------------
diff --git a/contrib/views/slider/src/main/resources/ui/app/controllers/slider_app_controller.js b/contrib/views/slider/src/main/resources/ui/app/controllers/slider_app_controller.js
index 6a383c5..06af9f3 100644
--- a/contrib/views/slider/src/main/resources/ui/app/controllers/slider_app_controller.js
+++ b/contrib/views/slider/src/main/resources/ui/app/controllers/slider_app_controller.js
@@ -83,12 +83,99 @@ App.SliderAppController = Ember.ObjectController.extend({
     this[currentAction]();
   },
 
-  thaw: Ember.K,
-  freeze: Ember.K,
-  flex: Ember.K,
+  /**
+   * Do request to <strong>thaw</strong> current slider's app
+   * @returns {$.ajax}
+   * @method freeze
+   */
+  thaw: function() {
+    var model = this.get('model');
+    return App.ajax.send({
+      name: 'changeAppState',
+      sender: this,
+      data: {
+        id: model.get('id'),
+        data: {
+          id: model.get('id'),
+          name: model.get('name'),
+          state: "RUNNING"
+        }
+      }
+    });
+  },
 
   /**
    * Do request to delete current slider's app
+   * Do request to <strong>freeze</strong> current slider's app
+   * @returns {$.ajax}
+   * @method freeze
+   */
+  freeze: function() {
+    var model = this.get('model');
+    return App.ajax.send({
+      name: 'changeAppState',
+      sender: this,
+      data: {
+        id: model.get('id'),
+        data: {
+          id: model.get('id'),
+          name: model.get('name'),
+          state: "FROZEN"
+        }
+      }
+    });
+  },
+
+  /**
+   * Do request to <strong>flex</strong> current slider's app
+   * @returns {$.ajax}
+   * @method flex
+   */
+  flex: function() {
+    var model = this.get('model');
+    return App.ajax.send({
+      name: 'flexApp',
+      sender: this,
+      data: {
+        id: model.get('id'),
+        data: {
+          id: model.get('id'),
+          name: model.get('name'),
+          components: this.mapComponentsForFlexRequest()
+        }
+      }
+    });
+  },
+
+  /**
+   * Map <code>model.components</code> for Flex request
+   * Output format:
+   * <code>
+   *   {
+   *      COMPONENT_NAME_1: {
+   *        instanceCount: 1
+   *      },
+   *      COMPONENT_NAME_2: {
+   *        instanceCount: 2
+   *      },
+   *      ....
+   *   }
+   * </code>
+   * @returns {object}
+   * @method mapComponentsForFlexRequest
+   */
+  mapComponentsForFlexRequest: function() {
+    var components = {};
+    this.get('model.components').forEach(function(component) {
+      components[component.get('name')] = {
+        instanceCount: component.get('defaultNumInstances')
+      }
+    });
+    return components;
+  },
+
+  /**
+   * Do request to <strong>delete</strong> current slider's app
    * @return {$.ajax}
    * @method destroy
    */

http://git-wip-us.apache.org/repos/asf/ambari/blob/53e3d8dd/contrib/views/slider/src/main/resources/ui/app/helpers/ajax.js
----------------------------------------------------------------------
diff --git a/contrib/views/slider/src/main/resources/ui/app/helpers/ajax.js b/contrib/views/slider/src/main/resources/ui/app/helpers/ajax.js
index 05e78db..66b97bd 100644
--- a/contrib/views/slider/src/main/resources/ui/app/helpers/ajax.js
+++ b/contrib/views/slider/src/main/resources/ui/app/helpers/ajax.js
@@ -56,6 +56,9 @@ var urls = {
   'createNewApp': {
     real: 'apps',
     mock: '',
+    headers: {
+      "Content-Type": "text/plain; charset=utf-8"
+    },
     format: function(data) {
       return {
         type: 'POST',
@@ -72,6 +75,33 @@ var urls = {
         method: 'DELETE'
       }
     }
+  },
+
+  'changeAppState': {
+    real: 'apps/{id}',
+    mock: '',
+    headers: {
+      "Content-Type": "text/plain; charset=utf-8"
+    },
+    format: function(data) {
+      return {
+        method: 'PUT',
+        data: JSON.stringify(data.data)
+      }
+    }
+  },
+  'flexApp': {
+    real: 'apps/{id}',
+    mock: '',
+    headers: {
+      "Content-Type": "text/plain; charset=utf-8"
+    },
+    format: function(data) {
+      return {
+        method: 'PUT',
+        data: JSON.stringify(data.data)
+      }
+    }
   }
 };
 /**
@@ -110,7 +140,7 @@ var formatRequest = function (data) {
     type: this.type || 'GET',
     dataType: 'json',
     async: true,
-    headers: this.headers || {accepts: "application/json; charset=utf-8"}
+    headers: this.headers || {Accept: "application/json; charset=utf-8"}
   };
   if (App.get('testMode')) {
     opt.url = formatUrl(this.mock ? this.mock : '', data);

http://git-wip-us.apache.org/repos/asf/ambari/blob/53e3d8dd/contrib/views/slider/src/main/resources/ui/app/initialize.js
----------------------------------------------------------------------
diff --git a/contrib/views/slider/src/main/resources/ui/app/initialize.js b/contrib/views/slider/src/main/resources/ui/app/initialize.js
index 73f4c6f..cc22ba2 100755
--- a/contrib/views/slider/src/main/resources/ui/app/initialize.js
+++ b/contrib/views/slider/src/main/resources/ui/app/initialize.js
@@ -102,4 +102,11 @@ folderOrder.forEach(function(folder) {
   }).forEach(function(module) {
     require(module);
   });
+});
+
+$.ajaxSetup({
+  cache : false,
+  headers : {
+    "X-Requested-By" : "X-Requested-By"
+  }
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/53e3d8dd/contrib/views/slider/src/main/resources/ui/app/routes/main.js
----------------------------------------------------------------------
diff --git a/contrib/views/slider/src/main/resources/ui/app/routes/main.js b/contrib/views/slider/src/main/resources/ui/app/routes/main.js
index 07babda..f875ffa 100644
--- a/contrib/views/slider/src/main/resources/ui/app/routes/main.js
+++ b/contrib/views/slider/src/main/resources/ui/app/routes/main.js
@@ -18,10 +18,6 @@
 
 App.IndexRoute = Ember.Route.extend({
 
-  model: function () {
-    return this.modelFor('sliderApps');
-  },
-
   redirect: function () {
     this.transitionTo('slider_apps');
   }
@@ -44,7 +40,7 @@ App.SliderAppsRoute = Ember.Route.extend({
 App.SliderAppRoute = Ember.Route.extend({
 
   model: function(params) {
-    return this.store.all('sliderApp', params.slider_app_id);
+    return this.store.find('sliderApp', params.slider_app_id);
   }
 
 });
\ No newline at end of file