You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by rl...@apache.org on 2017/06/14 21:19:42 UTC

[11/26] ambari git commit: AMBARI-20853. Service Advisor - Allow Service to define its Advisor Type as Python or Java (alejandro)

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/serviceadvisor/pom.xml
----------------------------------------------------------------------
diff --git a/serviceadvisor/pom.xml b/serviceadvisor/pom.xml
new file mode 100644
index 0000000..ecf6d8b
--- /dev/null
+++ b/serviceadvisor/pom.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <!-- Can compile this project independently, cd serviceadvisor ; mvn clean package install
+
+  To test independently without needing the rest of Ambari, simply compile and run as,
+  java -jar serviceadvisor-$VERSION.jar [ACTION] [HOSTS_FILE.json] [SERVICES_FILE.json]
+  -->
+  <groupId>serviceadvisor</groupId>
+  <artifactId>serviceadvisor</artifactId>
+  <name>Service Advisor</name>
+  <version>1.0.0.0-SNAPSHOT</version>
+  <description>Service Advisor</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven.plugins</groupId>
+      <artifactId>maven-assembly-plugin</artifactId>
+      <version>2.6</version>
+    </dependency>
+
+    <!-- Log Factory logging
+    The main class is expected to write to stdout and stderr appropriately.
+    -->
+    <dependency>
+      <groupId>commons-logging</groupId>
+      <artifactId>commons-logging</artifactId>
+      <version>1.2</version>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+      <version>1.7.20</version>
+    </dependency>
+      <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-lang3</artifactId>
+      <version>3.0</version>
+    </dependency>
+
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+      <version>2.4</version>
+    </dependency>
+  </dependencies>
+
+  <pluginRepositories>
+    <pluginRepository>
+      <id>oss.sonatype.org</id>
+      <name>OSS Sonatype Staging</name>
+      <url>https://oss.sonatype.org/content/groups/staging</url>
+    </pluginRepository>
+  </pluginRepositories>
+
+  <packaging>jar</packaging>
+  <!-- Run with mvn clean package .
+  Execute as, java -jar serviceadvisor-$VERSION.jar
+  -->
+  <build>
+    <plugins>
+      <!--
+      The next 2 plugins are to include the main class in the Jar and to create a single jar with all of the dependencies.
+      It conflicts with the maven-compiler-plugin since the jar created is different.
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <manifest>
+              <addClasspath>true</addClasspath>
+              <mainClass>org.apache.ambari.stackadvisor.StackAdvisor</mainClass>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-shade-plugin</artifactId>
+        <version>1.6</version>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>shade</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      -->
+      <plugin>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.2</version>
+        <configuration>
+          <source>1.7</source>
+          <target>1.7</target>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/serviceadvisor/src/main/java/org/apache/ambari/serviceadvisor/ServiceAdvisor.java
----------------------------------------------------------------------
diff --git a/serviceadvisor/src/main/java/org/apache/ambari/serviceadvisor/ServiceAdvisor.java b/serviceadvisor/src/main/java/org/apache/ambari/serviceadvisor/ServiceAdvisor.java
new file mode 100644
index 0000000..77c482a
--- /dev/null
+++ b/serviceadvisor/src/main/java/org/apache/ambari/serviceadvisor/ServiceAdvisor.java
@@ -0,0 +1,147 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.serviceadvisor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.lang3.EnumUtils;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * Class that can be called either through its jar or using its run method.
+ * The goal is to invoke a Service Advisor.
+ * Right now, it is backward compatible by invoking the python script and does not know which service is affected.
+ */
+public class ServiceAdvisor {
+  protected static Log LOG = LogFactory.getLog(ServiceAdvisor.class);
+
+  private static String USAGE = "Usage: java -jar serviceadvisor.jar [ACTION] [HOSTS_FILE.json] [SERVICES_FILE.json] [OUTPUT.txt] [ERRORS.txt]";
+  private static String PYTHON_STACK_ADVISOR_SCRIPT = "/var/lib/ambari-server/resources/scripts/stack_advisor.py";
+
+  /**
+   * Entry point for calling this class through its jar.
+   * @param args
+   */
+  public static void main(String[] args) {
+    if (args.length != 5) {
+      System.err.println(String.format("Wrong number of arguments. %s", USAGE));
+      System.exit(1);
+    }
+
+    String action = args[0];
+    String hostsFile = args[1];
+    String servicesFile = args[2];
+    String outputFile = args[3];
+    String errorFile = args[4];
+
+    int exitCode = run(action, hostsFile, servicesFile, outputFile, errorFile);
+    System.exit(exitCode);
+  }
+
+  public static int run(String action, String hostsFile, String servicesFile, String outputFile, String errorFile) {
+    LOG.info(String.format("ServiceAdvisor. Received arguments. Action: %s, Hosts File: %s, Services File: %s", action, hostsFile, servicesFile));
+    int returnCode = -1;
+
+    try {
+      ServiceAdvisorCommandType commandType = ServiceAdvisorCommandType.getEnum(action);
+
+      // TODO, load each Service's Service Advisor at Start Time and call it instead of Python command below.
+
+      ProcessBuilder builder = preparePythonShellCommand(commandType, hostsFile, servicesFile, outputFile, errorFile);
+      returnCode = launchProcess(builder);
+    } catch (IllegalArgumentException e) {
+      List<ServiceAdvisorCommandType> values = EnumUtils.getEnumList(ServiceAdvisorCommandType.class);
+      List<String> stringValues = new ArrayList<String>();
+      for (ServiceAdvisorCommandType value : values) {
+        stringValues.add(value.toString());
+      }
+      LOG.error("ServiceAdvisor. Illegal Argument. Action must be one of " + StringUtils.join(stringValues.toArray(), ", "));
+      return -1;
+    }  catch (Exception e) {
+      LOG.error("ServiceAdvisor. Failed with " + e.getMessage());
+      return -1;
+    }
+    return returnCode;
+  }
+
+  /**
+   * Generate a process to invoke a Python command for the old-style Stack Advisor.
+   * @param commandType Command Type
+   * @param hostsFile hosts.json file
+   * @param servicesFile services.json file
+   * @param outputFile output.txt
+   * @param errorFile error.txt
+   * @return Process that can launch.
+   */
+  private static ProcessBuilder preparePythonShellCommand(ServiceAdvisorCommandType commandType, String hostsFile, String servicesFile, String outputFile, String errorFile) {
+    List<String> builderParameters = new ArrayList<String>();
+
+    if (System.getProperty("os.name").contains("Windows")) {
+      builderParameters.add("cmd");
+      builderParameters.add("/c");
+    } else {
+      builderParameters.add("sh");
+      builderParameters.add("-c");
+    }
+
+    StringBuilder commandString = new StringBuilder();
+    commandString.append(PYTHON_STACK_ADVISOR_SCRIPT + " ");
+
+    commandString.append(commandType.toString()).append(" ");
+    commandString.append(hostsFile).append(" ");
+    commandString.append(servicesFile).append(" ");
+    commandString.append("1> ");
+    commandString.append(outputFile).append(" ");
+    commandString.append("2>");
+    commandString.append(errorFile).append(" ");
+
+    builderParameters.add(commandString.toString());
+
+    LOG.info("ServiceAdvisor. Python command is: " + builderParameters.toString());
+
+    return new ProcessBuilder(builderParameters);
+  }
+
+  /**
+   * Launch a process, wait for it to finish, and return its exit code.
+   * @param builder Process Builder
+   * @return Exit Code
+   * @throws Exception
+   */
+  private static int launchProcess(ProcessBuilder builder) throws Exception {
+    int exitCode = -1;
+    Process process = null;
+    try {
+      process = builder.start();
+      exitCode = process.waitFor();
+    } catch (Exception ioe) {
+      String message = "Error executing Service Advisor: ";
+      LOG.error(message, ioe);
+      throw new Exception(message + ioe.getMessage());
+    } finally {
+      if (process != null) {
+        process.destroy();
+      }
+    }
+    return exitCode;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/serviceadvisor/src/main/java/org/apache/ambari/serviceadvisor/ServiceAdvisorCommandType.java
----------------------------------------------------------------------
diff --git a/serviceadvisor/src/main/java/org/apache/ambari/serviceadvisor/ServiceAdvisorCommandType.java b/serviceadvisor/src/main/java/org/apache/ambari/serviceadvisor/ServiceAdvisorCommandType.java
new file mode 100644
index 0000000..f067668
--- /dev/null
+++ b/serviceadvisor/src/main/java/org/apache/ambari/serviceadvisor/ServiceAdvisorCommandType.java
@@ -0,0 +1,63 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.ambari.serviceadvisor;
+
+
+// TODO, use this class instead of org.apache.ambari.server.api.services.stackadvisor.commands.StackAdvisorCommandType
+public enum ServiceAdvisorCommandType {
+
+  RECOMMEND_COMPONENT_LAYOUT("recommend-component-layout"),
+
+  VALIDATE_COMPONENT_LAYOUT("validate-component-layout"),
+
+  RECOMMEND_CONFIGURATIONS("recommend-configurations"),
+
+  RECOMMEND_CONFIGURATION_DEPENDENCIES("recommend-configuration-dependencies"),
+
+  VALIDATE_CONFIGURATIONS("validate-configurations");
+  private final String name;
+
+  private ServiceAdvisorCommandType(String name) {
+    this.name = name;
+  }
+
+  public String getValue() {
+    return this.name.toLowerCase();
+  }
+
+  @Override
+  public String toString() {
+    return this.name;
+  }
+
+  /**
+   * Instead of Enum.valueOf("value"), use this method instead to map the string to the correct Enum.
+   * @param name Name with lowercase and dashes.
+   * @return Enum that matches the string.
+   */
+  public static ServiceAdvisorCommandType getEnum(String name) {
+    for (ServiceAdvisorCommandType v : values()) {
+      if (v.getValue().equalsIgnoreCase(name.replace("_", "-"))) {
+        return v;
+      }
+    }
+    throw new IllegalArgumentException();
+  }
+}
\ No newline at end of file