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 <[email protected]> Authored: Tue May 27 13:13:24 2014 -0700 Committer: Srimanth Gunturi <[email protected]> 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>
