Repository: ambari
Updated Branches:
  refs/heads/trunk cc82fec86 -> 8eead1491


AMBARI-18637: Management pack purge option should warn user and ask for 
confirmation before purging (jluniya)


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

Branch: refs/heads/trunk
Commit: 8eead14916ddd86658c488dd07f9432dadcc2331
Parents: cc82fec
Author: Jayush Luniya <[email protected]>
Authored: Tue Oct 25 22:20:45 2016 +0900
Committer: Jayush Luniya <[email protected]>
Committed: Tue Oct 25 22:20:45 2016 +0900

----------------------------------------------------------------------
 .../server/checks/MpackInstallChecker.java      | 240 +++++++++++++++++++
 .../main/python/ambari_server/setupMpacks.py    | 106 +++++++-
 .../server/checks/MpackInstallCheckerTest.java  | 124 ++++++++++
 ambari-server/src/test/python/TestMpacks.py     |  61 ++++-
 4 files changed, 522 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/8eead149/ambari-server/src/main/java/org/apache/ambari/server/checks/MpackInstallChecker.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/checks/MpackInstallChecker.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/checks/MpackInstallChecker.java
new file mode 100644
index 0000000..d80f123
--- /dev/null
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/checks/MpackInstallChecker.java
@@ -0,0 +1,240 @@
+/*
+ * 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.server.checks;
+
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.persist.PersistService;
+
+import org.apache.ambari.server.audit.AuditLoggerModule;
+import org.apache.ambari.server.controller.ControllerModule;
+import org.apache.ambari.server.orm.DBAccessor;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.DefaultParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+
+/**
+ * Mpack Install Checker
+ */
+public class MpackInstallChecker {
+
+  private static final String MPACK_STACKS_ARG = "mpack-stacks";
+
+  private static final Logger LOG = LoggerFactory.getLogger
+      (MpackInstallChecker.class);
+
+  private PersistService persistService;
+  private DBAccessor dbAccessor;
+  private Injector injector;
+  private Connection connection;
+
+  private boolean errorsFound = false;
+
+  private static Options getOptions() {
+    Options options = new Options();
+    options.addOption(Option.builder().longOpt(MPACK_STACKS_ARG).desc(
+        "List of stacks defined in the management 
pack").required().type(String.class).hasArg().valueSeparator(' ').build());
+    return options;
+  }
+
+  private static MpackContext processArguments(String... args) {
+    CommandLineParser cmdLineParser = new DefaultParser();
+    HelpFormatter formatter = new HelpFormatter();
+    MpackContext ctx = null;
+
+    try {
+      CommandLine line = cmdLineParser.parse(getOptions(), args);
+      String mpackStacksStr = (String) 
line.getParsedOptionValue(MPACK_STACKS_ARG);
+      HashSet<String> stacksInMpack = new 
HashSet<>(Arrays.asList(mpackStacksStr.split(",")));
+      ctx = new MpackContext(stacksInMpack);
+    } catch (Exception exp) {
+      System.err.println("Parsing failed. Reason: " + exp.getMessage());
+      LOG.error("Parsing failed. Reason: ", exp);
+      System.exit(1);
+    }
+    return ctx;
+  }
+
+  public boolean isErrorsFound() {
+    return errorsFound;
+  }
+
+  @Inject
+  public MpackInstallChecker(DBAccessor dbAccessor,
+      Injector injector,
+      PersistService persistService) {
+    this.dbAccessor = dbAccessor;
+    this.injector = injector;
+    this.persistService = persistService;
+  }
+
+  /**
+   * Extension of audit logger module
+   */
+  public static class MpackCheckerAuditModule extends AuditLoggerModule {
+
+    public MpackCheckerAuditModule() throws Exception {
+    }
+
+    @Override
+    protected void configure() {
+      super.configure();
+    }
+  }
+
+  public void startPersistenceService() {
+    persistService.start();
+  }
+
+  public void stopPersistenceService() {
+    persistService.stop();
+  }
+
+  public Connection getConnection() {
+    if (connection == null) {
+      if (dbAccessor == null) {
+        dbAccessor = injector.getInstance(DBAccessor.class);
+      }
+      connection = dbAccessor.getConnection();
+    }
+    return connection;
+  }
+
+  /**
+   * Check if any clusters are deployed with a stack that is not included in 
the management pack
+   * @param stacksInMpack List of stacks included in the management pack
+   */
+  public void checkClusters(HashSet<String> stacksInMpack) {
+
+    ResultSet rs = null;
+    Statement statement = null;
+    Map<String, Map<String, String>>  clusterStackInfo = new HashMap<>();
+    String GET_STACK_NAME_VERSION_QUERY = "select c.cluster_name, 
s.stack_name, s.stack_version from clusters c " +
+        "join stack s on c.desired_stack_id = s.stack_id";
+
+    Connection conn = getConnection();
+    try {
+      statement = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, 
ResultSet.CONCUR_UPDATABLE);
+      rs = statement.executeQuery(GET_STACK_NAME_VERSION_QUERY);
+      if (rs != null) {
+        while (rs.next()) {
+          Map<String, String> stackInfoMap = new HashMap<>();
+          stackInfoMap.put(rs.getString("stack_name"), 
rs.getString("stack_version"));
+          clusterStackInfo.put(rs.getString("cluster_name"), stackInfoMap);
+        }
+      }
+
+      for (Map.Entry<String, Map<String, String>> clusterStackInfoEntry : 
clusterStackInfo.entrySet()) {
+        String clusterName = clusterStackInfoEntry.getKey();
+        Map<String, String> stackInfo = clusterStackInfoEntry.getValue();
+        String stackName = stackInfo.keySet().iterator().next();
+        String stackVersion = stackInfo.get(stackName);
+        if(!stacksInMpack.contains(stackName)) {
+          String errorMsg = String.format("This Ambari instance is already 
managing the cluster %s that has the " +
+              "%s-%s stack installed on it. The management pack you are 
attempting to install only contains stack " +
+              "definitions for %s. Since this management pack does not contain 
a stack that has already being " +
+              "deployed by Ambari, the --purge option would cause your 
existing Ambari installation to be unusable. " +
+              "Due to that we cannot install this management pack.",
+              clusterName, stackName, stackVersion, stacksInMpack.toString());
+          LOG.error(errorMsg);
+          System.err.println(errorMsg);
+          errorsFound = true;
+        }
+      }
+    } catch (SQLException e) {
+      System.err.println("SQL Exception occured during check for validating 
installed clusters. Reason: " + e.getMessage());
+      LOG.error("SQL Exception occured during check for validating installed 
clusters. Reason: ", e);
+      errorsFound = true;
+    } finally {
+      if (rs != null) {
+        try {
+          rs.close();
+        } catch (SQLException e) {
+          System.err.println("SQL Exception occurred during result set closing 
procedure. Reason: " +  e.getMessage());
+          LOG.error("SQL Exception occurred during result set closing 
procedure. Reason: " , e);
+          errorsFound = true;
+        }
+      }
+      if (statement != null) {
+        try {
+          statement.close();
+        } catch (SQLException e) {
+          System.err.println("SQL Exception occurred during statement closing 
procedure. Reason: " + e.getMessage());
+          LOG.error("SQL Exception occurred during statement closing 
procedure. Reason: ", e);
+          errorsFound = true;
+        }
+      }
+    }
+  }
+
+  /**
+   * Main method for management pack installation checker
+   */
+  public static void main(String[] args) throws Exception {
+
+    Injector injector = Guice.createInjector(new ControllerModule(), new 
MpackCheckerAuditModule());
+    MpackInstallChecker mpackInstallChecker = 
injector.getInstance(MpackInstallChecker.class);
+    MpackContext mpackContext = processArguments(args);
+
+    mpackInstallChecker.startPersistenceService();
+
+    mpackInstallChecker.checkClusters(mpackContext.getStacksInMpack());
+
+    mpackInstallChecker.stopPersistenceService();
+
+    if(mpackInstallChecker.isErrorsFound()) {
+      LOG.error("Mpack installation checker failed!");
+      System.err.println("Mpack installation checker failed!");
+      System.exit(1);
+    } else {
+      LOG.info("No errors found");
+      System.out.println("No errors found");
+    }
+  }
+
+  /**
+   * Context object that encapsulates values passed in as arguments to the 
{@link MpackInstallChecker} class.
+   */
+  private static class MpackContext {
+    private HashSet<String> stacksInMpack;
+
+    public MpackContext(HashSet<String> stacksInMpack) {
+      this.stacksInMpack = stacksInMpack;
+    }
+
+    public HashSet<String> getStacksInMpack() {
+      return stacksInMpack;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/8eead149/ambari-server/src/main/python/ambari_server/setupMpacks.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/python/ambari_server/setupMpacks.py 
b/ambari-server/src/main/python/ambari_server/setupMpacks.py
index 4ffeb42..f0c4f86 100644
--- a/ambari-server/src/main/python/ambari_server/setupMpacks.py
+++ b/ambari-server/src/main/python/ambari_server/setupMpacks.py
@@ -24,17 +24,27 @@ import json
 import ast
 import logging
 
+from ambari_server.serverClassPath import ServerClassPath
+
 from ambari_commons.exceptions import FatalException
 from ambari_commons.inet_utils import download_file
-from ambari_commons.logging_utils import print_info_msg, print_error_msg
+from ambari_commons.logging_utils import print_info_msg, print_error_msg, 
print_warning_msg
 from ambari_commons.os_utils import copy_file, run_os_command
 from ambari_server.serverConfiguration import get_ambari_properties, 
get_ambari_version, get_stack_location, \
-  get_common_services_location, get_mpacks_staging_location, 
get_server_temp_location, get_extension_location
+  get_common_services_location, get_mpacks_staging_location, 
get_server_temp_location, get_extension_location, \
+  get_java_exe_path, read_ambari_user, parse_properties_file, 
JDBC_DATABASE_PROPERTY
+from ambari_server.setupSecurity import ensure_can_start_under_current_user, 
generate_env
+from ambari_server.setupActions import INSTALL_MPACK_ACTION, 
UPGRADE_MPACK_ACTION
+from ambari_server.userInput import get_YN_input
+from ambari_server.dbConfiguration import ensure_jdbc_driver_is_installed, 
LINUX_DBMS_KEYS_LIST
 
 from resource_management.core import sudo
 from resource_management.libraries.functions.tar_archive import 
extract_archive, get_archive_root_dir
 from resource_management.libraries.functions.version import compare_versions
-from ambari_server.setupActions import INSTALL_MPACK_ACTION, 
UPGRADE_MPACK_ACTION
+
+
+MPACK_INSTALL_CHECKER_CMD = "{0} -cp {1} " + \
+                            
"org.apache.ambari.server.checks.MpackInstallChecker --mpack-stacks {2}"
 
 logger = logging.getLogger(__name__)
 
@@ -57,6 +67,11 @@ SERVICE_DEFINITIONS_ARTIFACT_NAME = "service-definitions"
 EXTENSION_DEFINITIONS_ARTIFACT_NAME = "extension-definitions"
 STACK_ADDON_SERVICE_DEFINITIONS_ARTIFACT_NAME = 
"stack-addon-service-definitions"
 
+RESOURCE_FRIENDLY_NAMES = {
+  STACK_DEFINITIONS_RESOURCE_NAME : "stack definitions",
+  SERVICE_DEFINITIONS_RESOURCE_NAME: "service definitions",
+  MPACKS_RESOURCE_NAME: "management packs"
+}
 
 class _named_dict(dict):
   """
@@ -236,6 +251,85 @@ def remove_symlinks(stack_location, 
service_definitions_location, staged_mpack_d
           print_info_msg("Removing symlink {0}".format(dir))
           sudo.unlink(dir)
 
+def run_mpack_install_checker(options, mpack_stacks):
+  """
+  Run MpackInstallChecker to validate that there is no cluster deployed with a 
stack that is not included in the management pack
+  :param options: Options passed
+  :param mpack_stacks: List of stacks included in the management pack
+  :return: Output of MpackInstallChecker
+  """
+  properties = get_ambari_properties()
+  database_type = properties[JDBC_DATABASE_PROPERTY]
+  jdk_path = get_java_exe_path()
+
+  if not jdk_path or not database_type:
+    # Ambari Server has not been setup, so no cluster would be present
+    return (0, "", "")
+
+  parse_properties_file(options)
+  options.database_index = 
LINUX_DBMS_KEYS_LIST.index(properties[JDBC_DATABASE_PROPERTY])
+  ensure_jdbc_driver_is_installed(options, properties)
+
+  serverClassPath = ServerClassPath(properties, options)
+  class_path = serverClassPath.get_full_ambari_classpath_escaped_for_shell()
+
+  command = MPACK_INSTALL_CHECKER_CMD.format(jdk_path, class_path, 
",".join(mpack_stacks))
+
+  ambari_user = read_ambari_user()
+  current_user = ensure_can_start_under_current_user(ambari_user)
+  environ = generate_env(options, ambari_user, current_user)
+
+  return run_os_command(command, env=environ)
+
+
+def validate_purge(options, purge_list, mpack_dir, mpack_metadata, 
replay_mode=False):
+  """
+  Validate purge options
+  :param purge_list: List of resources to purge
+  :param mpack_metadata: Management pack metadata
+  :param replay_mode: Flag to indicate if purging in replay mode
+  """
+  # Get ambari mpacks config properties
+  stack_location, extension_location, service_definitions_location, 
mpacks_staging_location = get_mpack_properties()
+
+  if not purge_list:
+    return
+
+  if STACK_DEFINITIONS_RESOURCE_NAME in purge_list:
+    mpack_stacks = []
+    for artifact in mpack_metadata.artifacts:
+      if artifact.type == STACK_DEFINITIONS_ARTIFACT_NAME:
+        artifact_source_dir = os.path.join(mpack_dir, artifact.source_dir)
+        for file in sorted(os.listdir(artifact_source_dir)):
+          if os.path.isdir(os.path.join(artifact_source_dir, file)):
+            stack_name = file
+            mpack_stacks.append(stack_name)
+    if not mpack_stacks:
+      # Don't purge stacks accidentally when installing add-on mpacks
+      err = "The management pack you are attempting to install does not 
contain {0}. Since this management pack " \
+            "does not contain a stack, the --purge option with 
--purge-list={1} would cause your existing Ambari " \
+            "installation to be unusable. Due to that we cannot install this 
management pack.".format(
+          RESOURCE_FRIENDLY_NAMES[STACK_DEFINITIONS_ARTIFACT_NAME], purge_list)
+      print_error_msg(err)
+      raise FatalException(1, err)
+    else:
+      # Valid that there are no clusters deployed with a stack that is not 
included in the management pack
+      (retcode, stdout, stderr) = run_mpack_install_checker(options, 
mpack_stacks)
+      if retcode > 0:
+        print_error_msg(stderr)
+        raise FatalException(1, stderr)
+
+  if not replay_mode:
+    purge_resources = set((v) for k, v in RESOURCE_FRIENDLY_NAMES.iteritems() 
if k in purge_list)
+    warn_msg = "CAUTION: You have specified the --purge option with 
--purge-list={0}. " \
+               "This will replace all existing {1} currently installed.\n" \
+               "Are you absolutely sure you want to perform the purge 
[yes/no]? (no)".format(
+        purge_list, ", ".join(purge_resources))
+    okToPurge = get_YN_input(warn_msg, False)
+    if not okToPurge:
+      err = "Management pack installation cancelled by user"
+      raise FatalException(1, err)
+
 def purge_stacks_and_mpacks(purge_list, replay_mode=False):
   """
   Purge all stacks and management packs
@@ -464,7 +558,7 @@ def uninstall_mpack(mpack_name, mpack_version):
 def validate_mpack_prerequisites(mpack_metadata):
   """
   Validate management pack prerequisites
-  :param mpack_name: Management pack metadata
+  :param mpack_metadata: Management pack metadata
   """
   # Get ambari config properties
   properties = get_ambari_properties()
@@ -547,7 +641,9 @@ def _install_mpack(options, replay_mode=False, 
is_upgrade=False):
 
   # Purge previously installed stacks and management packs
   if options.purge and options.purge_list:
-    purge_stacks_and_mpacks(options.purge_list.split(","), replay_mode)
+    purge_resources = options.purge_list.split(",")
+    validate_purge(options, purge_resources, tmp_root_dir, mpack_metadata, 
replay_mode)
+    purge_stacks_and_mpacks(purge_resources, replay_mode)
 
   # Get ambari mpack properties
   stack_location, extension_location, service_definitions_location, 
mpacks_staging_location = get_mpack_properties()

http://git-wip-us.apache.org/repos/asf/ambari/blob/8eead149/ambari-server/src/test/java/org/apache/ambari/server/checks/MpackInstallCheckerTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/checks/MpackInstallCheckerTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/checks/MpackInstallCheckerTest.java
new file mode 100644
index 0000000..634fe70
--- /dev/null
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/checks/MpackInstallCheckerTest.java
@@ -0,0 +1,124 @@
+/*
+ * 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.server.checks;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import junit.framework.Assert;
+import org.apache.ambari.server.orm.DBAccessor;
+import org.apache.ambari.server.stack.StackManagerFactory;
+import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.stack.OsFamily;
+import org.easymock.EasyMockSupport;
+import org.junit.Test;
+import com.google.inject.persist.PersistService;
+import javax.persistence.EntityManager;
+import static org.easymock.EasyMock.expect;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.util.HashSet;
+
+/**
+ * Unit tests for {@link MpackInstallChecker}
+ */
+public class MpackInstallCheckerTest {
+
+  @Test
+  public void testCheckValidClusters() throws Exception {
+
+    EasyMockSupport easyMockSupport = new EasyMockSupport();
+    final Connection mockConnection = 
easyMockSupport.createNiceMock(Connection.class);
+    final Statement mockStatement = 
easyMockSupport.createNiceMock(Statement.class);
+    final ResultSet stackResultSet = 
easyMockSupport.createNiceMock(ResultSet.class);
+
+    final DBAccessor mockDBDbAccessor = 
easyMockSupport.createNiceMock(DBAccessor.class);
+    final PersistService mockPersistService = 
easyMockSupport.createNiceMock(PersistService.class);
+    final Injector mockInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(DBAccessor.class).toInstance(mockDBDbAccessor);
+        bind(PersistService.class).toInstance(mockPersistService);
+      }
+    });
+
+    MpackInstallChecker mpackInstallChecker = 
mockInjector.getInstance(MpackInstallChecker.class);
+
+    HashSet<String> stacksInMpack = new HashSet<>();
+    stacksInMpack.add("HDF");
+
+    expect(mpackInstallChecker.getConnection()).andReturn(mockConnection);
+    expect(mockConnection.createStatement(
+        ResultSet.TYPE_SCROLL_SENSITIVE, 
ResultSet.CONCUR_UPDATABLE)).andReturn(mockStatement);
+    expect(mockStatement.executeQuery("select c.cluster_name, s.stack_name, 
s.stack_version from clusters c " +
+        "join stack s on c.desired_stack_id = 
s.stack_id")).andReturn(stackResultSet);
+    expect(stackResultSet.next()).andReturn(true);
+    expect(stackResultSet.getString("stack_name")).andReturn("HDF");
+    expect(stackResultSet.getString("stack_version")).andReturn("2.0");
+    expect(stackResultSet.getString("cluster_name")).andReturn("cl1");
+
+    easyMockSupport.replayAll();
+    mpackInstallChecker.checkClusters(stacksInMpack);
+    easyMockSupport.verifyAll();
+
+    Assert.assertFalse("No errors should have been triggered.", 
mpackInstallChecker.isErrorsFound());
+  }
+
+  @Test
+  public void testCheckInvalidClusters() throws Exception {
+
+    EasyMockSupport easyMockSupport = new EasyMockSupport();
+    final Connection mockConnection = 
easyMockSupport.createNiceMock(Connection.class);
+    final Statement mockStatement = 
easyMockSupport.createNiceMock(Statement.class);
+    final ResultSet stackResultSet = 
easyMockSupport.createNiceMock(ResultSet.class);
+
+    final DBAccessor mockDBDbAccessor = 
easyMockSupport.createNiceMock(DBAccessor.class);
+    final PersistService mockPersistService = 
easyMockSupport.createNiceMock(PersistService.class);
+    final Injector mockInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(DBAccessor.class).toInstance(mockDBDbAccessor);
+        bind(PersistService.class).toInstance(mockPersistService);
+      }
+    });
+    MpackInstallChecker mpackInstallChecker = 
mockInjector.getInstance(MpackInstallChecker.class);
+
+    HashSet<String> stacksInMpack = new HashSet<>();
+    stacksInMpack.add("HDF");
+
+    expect(mpackInstallChecker.getConnection()).andReturn(mockConnection);
+    expect(mockConnection.createStatement(
+        ResultSet.TYPE_SCROLL_SENSITIVE, 
ResultSet.CONCUR_UPDATABLE)).andReturn(mockStatement);
+    expect(mockStatement.executeQuery("select c.cluster_name, s.stack_name, 
s.stack_version from clusters c " +
+        "join stack s on c.desired_stack_id = 
s.stack_id")).andReturn(stackResultSet);
+    expect(stackResultSet.next()).andReturn(true);
+    expect(stackResultSet.getString("stack_name")).andReturn("HDP");
+    expect(stackResultSet.getString("stack_version")).andReturn("2.5");
+    expect(stackResultSet.getString("cluster_name")).andReturn("cl1");
+
+    easyMockSupport.replayAll();
+    mpackInstallChecker.checkClusters(stacksInMpack);
+    easyMockSupport.verifyAll();
+
+    Assert.assertTrue("Installing HDF mpack on HDP cluster with purge option 
should have triggered an error.",
+        mpackInstallChecker.isErrorsFound());
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/8eead149/ambari-server/src/test/python/TestMpacks.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/python/TestMpacks.py 
b/ambari-server/src/test/python/TestMpacks.py
index d0ef461..d935b5a 100644
--- a/ambari-server/src/test/python/TestMpacks.py
+++ b/ambari-server/src/test/python/TestMpacks.py
@@ -48,8 +48,8 @@ with patch.object(platform, "linux_distribution", 
return_value = MagicMock(retur
                 serverConfiguration.search_file = _search_file
 
 from ambari_server.setupMpacks import install_mpack, upgrade_mpack, 
replay_mpack_logs, \
-  purge_stacks_and_mpacks, STACK_DEFINITIONS_RESOURCE_NAME, 
SERVICE_DEFINITIONS_RESOURCE_NAME, \
-  MPACKS_RESOURCE_NAME
+  purge_stacks_and_mpacks, validate_purge, read_mpack_metadata, \
+  STACK_DEFINITIONS_RESOURCE_NAME, SERVICE_DEFINITIONS_RESOURCE_NAME, 
MPACKS_RESOURCE_NAME
 
 with patch.object(os, "geteuid", new=MagicMock(return_value=0)):
   from resource_management.core import sudo
@@ -63,7 +63,8 @@ def get_configs():
     serverConfiguration.COMMON_SERVICES_PATH_PROPERTY : 
"/var/lib/ambari-server/resources/common-services",
     serverConfiguration.EXTENSION_PATH_PROPERTY : 
"/var/lib/ambari-server/resources/extensions",
     serverConfiguration.MPACKS_STAGING_PATH_PROPERTY : mpacks_directory,
-    serverConfiguration.SERVER_TMP_DIR_PROPERTY : "/tmp"
+    serverConfiguration.SERVER_TMP_DIR_PROPERTY : "/tmp",
+    serverConfiguration.JDBC_DATABASE_PROPERTY: "postgres"
   }
   return configs
 
@@ -95,6 +96,57 @@ class TestMpacks(TestCase):
       fail = True
     self.assertTrue(fail)
 
+  @patch("ambari_server.setupMpacks.get_YN_input")
+  @patch("ambari_server.setupMpacks.run_mpack_install_checker")
+  def test_validate_purge(self, run_mpack_install_checker_mock, 
get_YN_input_mock):
+    options = self._create_empty_options_mock()
+    options.purge = True
+    purge_list = options.purge_list.split(',')
+    mpack_staging_dir = 
configs[serverConfiguration.MPACKS_STAGING_PATH_PROPERTY]
+    mpack_dir = os.path.join(mpack_staging_dir, "mystack-ambari-mpack-1.0.0.0")
+    mpack_metadata = read_mpack_metadata(mpack_dir)
+    replay_mode = False
+    run_mpack_install_checker_mock.return_value = (0, "No errors found", "")
+    get_YN_input_mock.return_value = True
+
+    fail = False
+    try:
+      validate_purge(options, purge_list, mpack_dir, mpack_metadata, 
replay_mode)
+    except FatalException as e:
+      # Unexpected failure
+      fail = True
+    self.assertFalse(fail)
+
+    get_YN_input_mock.return_value = False
+    fail = False
+    try:
+      validate_purge(options, purge_list, mpack_dir, mpack_metadata, 
replay_mode)
+    except FatalException as e:
+      # Expected failure
+      fail = True
+    self.assertTrue(fail)
+
+    get_YN_input_mock.return_value = True
+    fail = False
+    run_mpack_install_checker_mock.return_value = (1, "", "Mpack installation 
checker failed!")
+    try:
+      validate_purge(options, purge_list, mpack_dir, mpack_metadata, 
replay_mode)
+    except FatalException as e:
+      # Expected failure
+      fail = True
+    self.assertTrue(fail)
+
+    fail = False
+    mpack_dir = os.path.join(mpack_staging_dir, 
"myservice-ambari-mpack-1.0.0.0")
+    mpack_metadata = read_mpack_metadata(mpack_dir)
+    run_mpack_install_checker_mock.return_value = (0, "No errors found", "")
+    try:
+      validate_purge(options, purge_list, mpack_dir, mpack_metadata, 
replay_mode)
+    except FatalException as e:
+      # Expected failure
+      fail = True
+    self.assertTrue(fail)
+
   @patch("os.path.exists")
   @patch("ambari_server.setupMpacks.get_ambari_properties")
   def test_purge_stacks_and_mpacks(self, get_ambari_version_mock, 
os_path_exists_mock):
@@ -188,7 +240,8 @@ class TestMpacks(TestCase):
   @patch("ambari_server.setupMpacks.expand_mpack")
   @patch("ambari_server.setupMpacks.download_mpack")
   @patch("ambari_server.setupMpacks.run_os_command")
-  def test_install_stack_mpack(self, run_os_command_mock, download_mpack_mock, 
expand_mpack_mock, purge_stacks_and_mpacks_mock,
+  @patch("ambari_server.setupMpacks.validate_purge")
+  def test_install_stack_mpack(self, validate_purge_mock, run_os_command_mock, 
download_mpack_mock, expand_mpack_mock, purge_stacks_and_mpacks_mock,
                                      add_replay_log_mock, 
get_ambari_properties_mock, get_ambari_version_mock,
                                      create_symlink_mock, os_mkdir_mock, 
shutil_move_mock, os_path_exists_mock):
     options = self._create_empty_options_mock()

Reply via email to