Browse Source

AMBARI-5696. Usability: performing connectivity checks against an external database.(vbrodetskyi)

Vitaly Brodetskyi 11 years ago
parent
commit
c8e86f8ffd

+ 6 - 2
ambari-agent/src/main/python/ambari_agent/CustomServiceOrchestrator.py

@@ -79,7 +79,10 @@ class CustomServiceOrchestrator():
       script_type = command['commandParams']['script_type']
       script = command['commandParams']['script']
       timeout = int(command['commandParams']['command_timeout'])
-      server_url_prefix = command['hostLevelParams']['jdk_location']
+      if 'hostLevelParams' in command and 'jdk_location' in command['hostLevelParams']:
+        server_url_prefix = command['hostLevelParams']['jdk_location']
+      else:
+        server_url_prefix = command['commandParams']['jdk_location']
       task_id = "status"
       try:
         task_id = command['taskId']
@@ -208,7 +211,8 @@ class CustomServiceOrchestrator():
       file_path = os.path.join(self.tmp_dir, "status_command.json")
     else:
       task_id = command['taskId']
-      command['clusterHostInfo'] = self.decompressClusterHostInfo(command['clusterHostInfo'])
+      if 'clusterHostInfo' in command and command['clusterHostInfo']:
+        command['clusterHostInfo'] = self.decompressClusterHostInfo(command['clusterHostInfo'])
       file_path = os.path.join(self.tmp_dir, "command-{0}.json".format(task_id))
     # Json may contain passwords, that's why we need proper permissions
     if os.path.isfile(file_path):

+ 1 - 3
ambari-agent/src/test/python/ambari_agent/TestCustomServiceOrchestrator.py

@@ -239,13 +239,11 @@ class TestCustomServiceOrchestrator(TestCase):
     _, script = tempfile.mkstemp()
     command = {
       'role' : 'any',
-      'hostLevelParams' : {
-        'jdk_location' : 'some_location'
-      },
       'commandParams': {
         'script_type': 'PYTHON',
         'script': 'some_custom_action.py',
         'command_timeout': '600',
+        'jdk_location' : 'some_location'
       },
       'taskId' : '3',
       'roleCommand': 'ACTIONEXECUTE'

+ 6 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/RootServiceResponseFactory.java

@@ -23,6 +23,8 @@ import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JDK_LOCATION;
+
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.ObjectNotFoundException;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
@@ -44,6 +46,9 @@ public class RootServiceResponseFactory extends
   
   @Inject
   private AmbariMetaInfo ambariMetaInfo;
+
+  @Inject
+  private AmbariManagementController managementController;
   
   
   @Override
@@ -152,6 +157,7 @@ public class RootServiceResponseFactory extends
       switch (component) {
       case AMBARI_SERVER:
         response = configs.getAmbariProperties();
+        response.put(JDK_LOCATION, managementController.getJdkResourceUrl());
         break;
 
       default:

+ 86 - 0
ambari-server/src/main/python/ambari-server.py

@@ -363,6 +363,8 @@ ORACLE_UPGRADE_STACK_ARGS = "-S -L '{0}/{1}@(description=(address=(protocol=TCP)
 
 JDBC_PATTERNS = {"oracle": "*ojdbc*.jar", "mysql": "*mysql*.jar"}
 DATABASE_FULL_NAMES = {"oracle": "Oracle", "mysql": "MySQL", "postgres": "PostgreSQL"}
+JDBC_DB_OPTION_VALUES = ["postgresql", "mysql", "oracle"]
+JDBC_DB_DEFAULT_DRIVER = {"postgresql" : "postgresql-jdbc.jar", "mysql" : "mysql-connector-java.jar", "oracle" : "ojdbc6.jar"}
 ORACLE_DB_ID_TYPES = ["Service Name", "SID"]
 
 
@@ -2162,11 +2164,21 @@ def check_jdbc_drivers(args):
       print_error_msg("There is no value for " + RESOURCES_DIR_PROPERTY + "in " + AMBARI_PROPERTIES_FILE)
       return -1
 
+    db_name = DATABASE_FULL_NAMES[args.dbms].lower()
+    jdbc_symlink = os.path.join(resources_dir, db_name + "-jdbc-driver.jar")
+    db_default_driver_path = os.path.join(JAVA_SHARE_PATH, JDBC_DB_DEFAULT_DRIVER[db_name])
+
+    if os.path.lexists(jdbc_symlink):
+      os.remove(jdbc_symlink)
+
     copy_status = copy_files(result, resources_dir)
 
     if not copy_status == 0:
       raise FatalException(-1, "Failed to copy JDBC drivers to server resources")
 
+    if db_default_driver_path in result:
+      os.symlink(os.path.join(resources_dir, JDBC_DB_DEFAULT_DRIVER[db_name]), jdbc_symlink)
+
   return 0
 
 
@@ -2214,6 +2226,10 @@ def setup(args):
   print 'Checking iptables...'
   check_iptables()
 
+  # proceed jdbc properties if they were set
+  if args.jdbc_driver is not None and args.jdbc_db is not None:
+    proceedJDBCProperties(args)
+
   print 'Checking JDK...'
   try:
     download_jdk(args)
@@ -2281,6 +2297,45 @@ def setup(args):
     check_jdbc_drivers(args)
 
 
+def proceedJDBCProperties(args):
+  if not os.path.isfile(args.jdbc_driver):
+    err = "File {0} does not exist!".format(args.jdbc_driver)
+    raise FatalException(1, err)
+
+  if args.jdbc_db not in JDBC_DB_OPTION_VALUES:
+    err = "Unsupported database name {0}. Please see help for more information.".format(args.jdbc_db)
+    raise FatalException(1, err)
+
+  properties = get_ambari_properties()
+  if properties == -1:
+    err = "Error getting ambari properties"
+    raise FatalException(-1, err)
+  conf_file = properties.fileName
+
+  try:
+    resources_dir = properties[RESOURCES_DIR_PROPERTY]
+  except (KeyError), e:
+    err = 'Property ' + str(e) + ' is not defined at ' + conf_file
+    raise FatalException(1, err)
+
+  symlink_name = args.jdbc_db + "-jdbc-driver.jar"
+  jdbc_symlink = os.path.join(resources_dir, symlink_name)
+
+  if os.path.lexists(jdbc_symlink):
+    os.remove(jdbc_symlink)
+
+  try:
+    shutil.copy(args.jdbc_driver, resources_dir)
+  except Exception, e:
+    err = "Can not copy file {0} to {1} due to: {2} . Please check file " \
+          "permissions and free disk space.".format(args.jdbc_driver, resources_dir, e.message)
+    raise FatalException(1, err)
+
+  path, jdbc_name = os.path.split(args.jdbc_driver)
+
+  os.symlink(os.path.join(resources_dir,jdbc_name), jdbc_symlink)
+
+
 #
 # Resets the Ambari Server.
 #
@@ -2759,6 +2814,28 @@ def upgrade(args):
   # local repo
   upgrade_local_repo(args)
 
+  # create jdbc symlinks if jdbc drivers are available in resources
+  properties = get_ambari_properties()
+  if properties == -1:
+    err = "Error getting ambari properties"
+    print_error_msg(err)
+    raise FatalException(-1, err)
+  conf_file = properties.fileName
+
+  try:
+    resources_dir = properties[RESOURCES_DIR_PROPERTY]
+  except (KeyError), e:
+    err = 'Property ' + str(e) + ' is not defined at ' + conf_file
+    raise FatalException(1, err)
+
+  for db_name in list(JDBC_DB_DEFAULT_DRIVER):
+    if os.path.isfile(os.path.join(resources_dir, JDBC_DB_DEFAULT_DRIVER[db_name])):
+      symlink_name = db_name + "-jdbc-driver.jar"
+      jdbc_symlink = os.path.join(resources_dir, symlink_name)
+      if os.path.lexists(jdbc_symlink):
+        os.remove(jdbc_symlink)
+      os.symlink(os.path.join(resources_dir,JDBC_DB_DEFAULT_DRIVER[db_name]), jdbc_symlink)
+
 
 #
 # The Ambari Server status.
@@ -4051,6 +4128,10 @@ def main():
   parser.add_option('--databasepassword', default=None, help="Database user password", dest="database_password")
   parser.add_option('--sidorsname', default="sname", help="Oracle database identifier type, Service ID/Service "
                                                          "Name sid|sname", dest="sid_or_sname")
+  parser.add_option('--jdbc-driver', default=None, help="Path to jdbc driver. Used only in pair with --jdbc-db. ",
+                    dest="jdbc_driver")
+  parser.add_option('--jdbc-db', default=None, help="Database name [postgresql/mysql/oracle]. Used only in pair with " \
+                    "--jdbc-driver", dest="jdbc_db")
   (options, args) = parser.parse_args()
 
   # set verbose
@@ -4118,6 +4199,11 @@ def main():
       parser.print_help()
       parser.error("Incorrect database port " + options.database_port)
 
+  # jdbc driver and db options validation
+  if options.jdbc_driver is None and options.jdbc_db is not None:
+    parser.error("Option --jdbc-db is used only in pair with --jdbc-driver.")
+  elif options.jdbc_driver is not None and options.jdbc_db is None:
+    parser.error("Option --jdbc-driver is used only in pair with --jdbc-db.")
 
   if options.sid_or_sname.lower() not in ["sid", "sname"]:
     print "WARNING: Valid values for sid_or_sname are 'sid' or 'sname'. Use 'sid' if the db identifier type is " \

+ 61 - 20
ambari-server/src/main/resources/custom_actions/check_host.py

@@ -24,20 +24,24 @@ import os
 import subprocess
 import socket
 
-from resource_management import Script, Execute
+from resource_management import Script, Execute, format
 
 CHECK_JAVA_HOME = "java_home_check"
 CHECK_DB_CONNECTION = "db_connection_check"
 CHECK_HOST_RESOLUTION = "host_resolution_check"
 
-DB_NAME_MYSQL = "mysql"
-DB_NAME_ORACLE = "oracle"
-DB_NAME_POSTGRESQL = "postgresql"
+DB_MYSQL = "mysql"
+DB_ORACLE = "oracle"
+DB_POSTGRESQL = "postgresql"
 
 JDBC_DRIVER_MYSQL = "com.mysql.jdbc.Driver"
 JDBC_DRIVER_ORACLE = "oracle.jdbc.driver.OracleDriver"
 JDBC_DRIVER_POSTGRESQL = "org.postgresql.Driver"
 
+JDBC_DRIVER_SYMLINK_MYSQL = "mysql-jdbc-driver.jar"
+JDBC_DRIVER_SYMLINK_ORACLE = "oracle-jdbc-driver.jar"
+JDBC_DRIVER_SYMLINK_POSTGRESQL = "postgresql-jdbc-driver.jar"
+
 
 class CheckHost(Script):
   def actionexecute(self, env):
@@ -79,7 +83,9 @@ class CheckHost(Script):
 
   def execute_java_home_available_check(self, config):
     print "Java home check started."
-    java64_home = config['hostLevelParams']['java_home']
+    java64_home = config['commandParams']['java_home']
+
+    print "Java home to check: " + java64_home
   
     if not os.path.isfile(os.path.join(java64_home, "bin", "java")):
       print "Java home doesn't exist!"
@@ -96,31 +102,65 @@ class CheckHost(Script):
   
     # initialize needed data
   
-    ambari_server_hostname = config['clusterHostInfo']['ambari_server_host']
+    ambari_server_hostname = config['commandParams']['ambari_server_host']
     check_db_connection_jar_name = "DBConnectionVerification.jar"
-    jdk_location = config['hostLevelParams']['jdk_location']
-    java64_home = config['hostLevelParams']['java_home']
+    jdk_location = config['commandParams']['jdk_location']
+    java64_home = config['commandParams']['java_home']
     db_name = config['commandParams']['db_name']
-  
-    if db_name == DB_NAME_MYSQL:
-      jdbc_url = config['hostLevelParams']['mysql_jdbc_url']
+
+    if db_name == DB_MYSQL:
+      jdbc_url = jdk_location + JDBC_DRIVER_SYMLINK_MYSQL
       jdbc_driver = JDBC_DRIVER_MYSQL
-    elif db_name == DB_NAME_ORACLE:
-      jdbc_url = config['hostLevelParams']['oracle_jdbc_url']
+      jdbc_name = JDBC_DRIVER_SYMLINK_MYSQL
+    elif db_name == DB_ORACLE:
+      jdbc_url = jdk_location + JDBC_DRIVER_SYMLINK_ORACLE
       jdbc_driver = JDBC_DRIVER_ORACLE
-    elif db_name == DB_NAME_POSTGRESQL:
-      jdbc_url = config['hostLevelParams']['postgresql_jdbc_url']
+      jdbc_name = JDBC_DRIVER_SYMLINK_ORACLE
+    elif db_name == DB_POSTGRESQL:
+      jdbc_url = jdk_location + JDBC_DRIVER_SYMLINK_POSTGRESQL
       jdbc_driver = JDBC_DRIVER_POSTGRESQL
+      jdbc_name = JDBC_DRIVER_SYMLINK_POSTGRESQL
   
-    path, jdbc_name = os.path.split(jdbc_url)
     db_connection_url = config['commandParams']['db_connection_url']
     user_name = config['commandParams']['user_name']
     user_passwd = config['commandParams']['user_passwd']
   
     environment = { "no_proxy": format("{ambari_server_hostname}") }
-  
+    artifact_dir = "/tmp/HDP-artifacts/"
+    jdk_name = config['commandParams']['jdk_name']
+    jdk_curl_target = format("{artifact_dir}/{jdk_name}")
+    java_exec = os.path.join(java64_home, "bin","java")
+    java_dir = os.path.dirname(java64_home)
+
     # download DBConnectionVerification.jar from ambari-server resources
-  
+
+    if not os.path.isfile(java_exec):
+      try:
+        Execute(format("mkdir -p {artifact_dir} ; curl -kf "
+                "--retry 10 {jdk_location}/{jdk_name} -o {jdk_curl_target}"),
+                path = ["/bin","/usr/bin/"],
+                environment = environment)
+      except Exception, e:
+        message = "Error downloading JDK from Ambari Server resources. Check network access to " \
+                  "Ambari Server.\n" + str(e)
+        print message
+        db_connection_check_structured_output = {"exit_code" : "1", "message": message}
+        return db_connection_check_structured_output
+
+      if jdk_name.endswith(".bin"):
+        install_cmd = format("mkdir -p {java_dir} ; chmod +x {jdk_curl_target}; cd {java_dir} ; echo A | " \
+                           "{jdk_curl_target} -noregister > /dev/null 2>&1")
+      elif jdk_name.endswith(".gz"):
+        install_cmd = format("mkdir -p {java_dir} ; cd {java_dir} ; tar -xf {jdk_curl_target} > /dev/null 2>&1")
+
+      try:
+        Execute(install_cmd, path = ["/bin","/usr/bin/"])
+      except Exception, e:
+        message = "Error installing java.\n" + str(e)
+        print message
+        db_connection_check_structured_output = {"exit_code" : "1", "message": message}
+        return db_connection_check_structured_output
+
     try:
       cmd = format("/bin/sh -c 'cd /usr/lib/ambari-agent/ && curl -kf "
                    "--retry 5 {jdk_location}{check_db_connection_jar_name} "
@@ -140,7 +180,8 @@ class CheckHost(Script):
                    "--retry 5 {jdbc_url} -o {jdbc_name}'")
       Execute(cmd, not_if=format("[ -f /usr/lib/ambari-agent/{jdbc_name}]"), environment = environment)
     except Exception, e:
-      message = "Error downloading JDBC connector from Ambari Server resources. Check network access to " \
+      message = "Error downloading JDBC connector from Ambari Server resources. Confirm you ran ambari-server setup to " \
+                "install JDBC connector. Use \"ambari-server --help\" for more information. Check network access to " \
                 "Ambari Server.\n" + str(e)
       print message
       db_connection_check_structured_output = {"exit_code" : "1", "message": message}
@@ -166,7 +207,7 @@ class CheckHost(Script):
     if process.returncode == 0:
       db_connection_check_structured_output = {"exit_code" : "0", "message": "DB connection check completed successfully!" }
     else:
-      db_connection_check_structured_output = {"exit_code" : "1", "message":  stdoutdata }
+      db_connection_check_structured_output = {"exit_code" : "1", "message":  stdoutdata + stderrdata }
   
     return db_connection_check_structured_output
   

+ 3 - 0
ambari-server/src/main/resources/stacks/HDP/1.3.2/hooks/before-START/scripts/params.py

@@ -84,6 +84,9 @@ server_db_name = config['hostLevelParams']['db_name']
 db_driver_filename = config['hostLevelParams']['db_driver_filename']
 oracle_driver_url = config['hostLevelParams']['oracle_jdbc_url']
 mysql_driver_url = config['hostLevelParams']['mysql_jdbc_url']
+ambari_server_resources = config['hostLevelParams']['jdk_location']
+oracle_driver_symlink_url = format("{ambari_server_resources}oracle-jdbc-driver.jar")
+mysql_driver_symlink_url = format("{ambari_server_resources}mysql-jdbc-driver.jar")
 
 ambari_db_rca_url = config['hostLevelParams']['ambari_db_rca_url']
 ambari_db_rca_driver = config['hostLevelParams']['ambari_db_rca_driver']

+ 2 - 2
ambari-server/src/main/resources/stacks/HDP/1.3.2/hooks/before-START/scripts/shared_initialization.py

@@ -93,11 +93,11 @@ def setup_database():
   }
   if params.server_db_name == 'oracle' and params.oracle_driver_url != "":
     db_driver_dload_cmd = format(
-      "curl -kf --retry 5 {oracle_driver_url}"
+      "curl -kf --retry 5 {oracle_driver_symlink_url}"
       " -o {hadoop_lib_home}/{db_driver_filename}")
   elif params.server_db_name == 'mysql' and params.mysql_driver_url != "":
     db_driver_dload_cmd = format(
-      "curl -kf --retry 5 {mysql_driver_url} "
+      "curl -kf --retry 5 {mysql_driver_symlink_url} "
       "-o {hadoop_lib_home}/{db_driver_filename}")
 
   if db_driver_dload_cmd:

+ 4 - 1
ambari-server/src/main/resources/stacks/HDP/1.3.2/services/HIVE/package/scripts/params.py

@@ -37,10 +37,13 @@ hive_lib = '/usr/lib/hive/lib/'
 hive_jdbc_driver = config['configurations']['hive-site']['javax.jdo.option.ConnectionDriverName']
 if hive_jdbc_driver == "com.mysql.jdbc.Driver":
   jdbc_jar_name = "mysql-connector-java.jar"
+  jdbc_symlink_name = "mysql-jdbc-driver.jar"
 elif hive_jdbc_driver == "org.postgresql.Driver":
   jdbc_jar_name = "postgresql-jdbc.jar"
+  jdbc_symlink_name = "postgresql-jdbc-driver.jar"
 elif hive_jdbc_driver == "oracle.jdbc.driver.OracleDriver":
   jdbc_jar_name = "ojdbc6.jar"
+  jdbc_symlink_name = "oracle-jdbc-driver.jar"
 
 check_db_connection_jar_name = "DBConnectionVerification.jar"
 check_db_connection_jar = format("/usr/lib/ambari-agent/{check_db_connection_jar_name}")
@@ -92,7 +95,7 @@ artifact_dir = "/tmp/HDP-artifacts/"
 target = format("{hive_lib}/{jdbc_jar_name}")
 
 jdk_location = config['hostLevelParams']['jdk_location']
-driver_curl_source = format("{jdk_location}/{jdbc_jar_name}")
+driver_curl_source = format("{jdk_location}/{jdbc_symlink_name}")
 
 start_hiveserver2_path = "/tmp/start_hiveserver2_script"
 start_metastore_path = "/tmp/start_metastore_script"

+ 3 - 0
ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/before-START/scripts/params.py

@@ -85,6 +85,9 @@ server_db_name = config['hostLevelParams']['db_name']
 db_driver_filename = config['hostLevelParams']['db_driver_filename']
 oracle_driver_url = config['hostLevelParams']['oracle_jdbc_url']
 mysql_driver_url = config['hostLevelParams']['mysql_jdbc_url']
+ambari_server_resources = config['hostLevelParams']['jdk_location']
+oracle_driver_symlink_url = format("{ambari_server_resources}oracle-jdbc-driver.jar")
+mysql_driver_symlink_url = format("{ambari_server_resources}mysql-jdbc-driver.jar")
 
 ambari_db_rca_url = config['hostLevelParams']['ambari_db_rca_url'][0]
 ambari_db_rca_driver = config['hostLevelParams']['ambari_db_rca_driver'][0]

+ 2 - 2
ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/before-START/scripts/shared_initialization.py

@@ -98,11 +98,11 @@ def setup_database():
   if params.server_db_name == 'oracle' and params.oracle_driver_url != "":
     db_driver_dload_cmd = format(
       "curl -kf \
-      --retry 5 {oracle_driver_url} -o {hadoop_lib_home}/{db_driver_filename}",)
+      --retry 5 {oracle_driver_symlink_url} -o {hadoop_lib_home}/{db_driver_filename}",)
   elif params.server_db_name == 'mysql' and params.mysql_driver_url != "":
     db_driver_dload_cmd = format(
       "curl -kf \
-      --retry 5 {mysql_driver_url} -o {hadoop_lib_home}/{db_driver_filename}")
+      --retry 5 {mysql_driver_symlink_url} -o {hadoop_lib_home}/{db_driver_filename}")
 
   if db_driver_dload_cmd:
     Execute(db_driver_dload_cmd,

+ 4 - 1
ambari-server/src/main/resources/stacks/HDP/2.0.6/services/HIVE/package/scripts/params.py

@@ -38,10 +38,13 @@ hive_lib = '/usr/lib/hive/lib/'
 hive_jdbc_driver = config['configurations']['hive-site']['javax.jdo.option.ConnectionDriverName']
 if hive_jdbc_driver == "com.mysql.jdbc.Driver":
   jdbc_jar_name = "mysql-connector-java.jar"
+  jdbc_symlink_name = "mysql-jdbc-driver.jar"
 elif hive_jdbc_driver == "org.postgresql.Driver":
   jdbc_jar_name = "postgresql-jdbc.jar"
+  jdbc_symlink_name = "postgresql-jdbc-driver.jar"
 elif hive_jdbc_driver == "oracle.jdbc.driver.OracleDriver":
   jdbc_jar_name = "ojdbc6.jar"
+  jdbc_symlink_name = "oracle-jdbc-driver.jar"
 
 check_db_connection_jar_name = "DBConnectionVerification.jar"
 check_db_connection_jar = format("/usr/lib/ambari-agent/{check_db_connection_jar_name}")
@@ -95,7 +98,7 @@ artifact_dir = "/tmp/HDP-artifacts/"
 target = format("{hive_lib}/{jdbc_jar_name}")
 
 jdk_location = config['hostLevelParams']['jdk_location']
-driver_curl_source = format("{jdk_location}/{jdbc_jar_name}")
+driver_curl_source = format("{jdk_location}/{jdbc_symlink_name}")
 
 start_hiveserver2_path = "/tmp/start_hiveserver2_script"
 start_metastore_path = "/tmp/start_metastore_script"

+ 26 - 31
ambari-server/src/test/java/org/apache/ambari/server/controller/RootServiceResponseFactoryTest.java

@@ -20,51 +20,37 @@ package org.apache.ambari.server.controller;
 
 import java.util.Collections;
 import java.util.Set;
+
 import org.apache.ambari.server.ObjectNotFoundException;
-import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.RootServiceResponseFactory.Components;
+import org.apache.ambari.server.orm.GuiceJpaInitializer;
 import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
 import org.junit.Before;
 import org.junit.Test;
 
-import com.google.inject.AbstractModule;
 import com.google.inject.Guice;
 import com.google.inject.Inject;
 import com.google.inject.Injector;
 
 import static junit.framework.Assert.assertTrue;
 import static junit.framework.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 
 public class RootServiceResponseFactoryTest {
 
-  private AbstractRootServiceResponseFactory responseFactory;
+  @Inject
+  private RootServiceResponseFactory responseFactory;
   private Injector injector;
   
   @Inject
   Configuration configs;
-  
-  @Inject
-  AmbariMetaInfo ambariMetaInfo;
-  
-  public class MockModule extends AbstractModule {
-    
-    @Override
-    protected void configure() {
-      AmbariMetaInfo ambariMetaInfo = mock(AmbariMetaInfo.class);
-      bind(AmbariMetaInfo.class).toInstance(ambariMetaInfo);
-    }
-  }
+
   
   @Before
   public void setUp() throws Exception{
-    injector = Guice.createInjector(new InMemoryDefaultTestModule(), new MockModule());
+    injector = Guice.createInjector(new InMemoryDefaultTestModule());
+    injector.getInstance(GuiceJpaInitializer.class);
     injector.injectMembers(this);
-    responseFactory = injector.getInstance(RootServiceResponseFactory.class);
-    
-    when(ambariMetaInfo.getServerVersion()).thenReturn("1.2.3");
   }
 
   @Test
@@ -142,16 +128,21 @@ public class RootServiceResponseFactoryTest {
           RootServiceResponseFactory.Services.AMBARI.getComponents()[i];
 
       if (component.name().equals(
-          RootServiceResponseFactory.Components.AMBARI_SERVER.name()))
-        assertTrue(rootServiceComponents
-            .contains(new RootServiceComponentResponse(component.name(),
-                ambariMetaInfo.getServerVersion(),
-                configs.getAmbariProperties())));
-      else
+          RootServiceResponseFactory.Components.AMBARI_SERVER.name())) {
+         for (RootServiceComponentResponse response : rootServiceComponents) {
+           if (response.getComponentName().equals(RootServiceResponseFactory.Components.AMBARI_SERVER.name())) {
+             assertEquals(response.getComponentVersion(), "1.3.0");
+             assertEquals(response.getProperties().size(), 1);
+             assertTrue(response.getProperties().containsKey("jdk_location"));
+             assertEquals(response.getProperties().get("jdk_location"), "http://localhost:8080/resources/");
+           }
+         }
+      } else {
         assertTrue(rootServiceComponents
             .contains(new RootServiceComponentResponse(component.name(),
                 RootServiceResponseFactory.NOT_APPLICABLE,
                 Collections.<String, String> emptyMap())));
+      }
     }
 
     // Request existent service name, existent component name
@@ -162,10 +153,14 @@ public class RootServiceResponseFactoryTest {
                 .name());
     rootServiceComponents = responseFactory.getRootServiceComponents(request);
     assertEquals(1, rootServiceComponents.size());
-    assertTrue(rootServiceComponents.contains(new RootServiceComponentResponse(
-        RootServiceResponseFactory.Services.AMBARI.getComponents()[0].name(),
-        ambariMetaInfo.getServerVersion(),
-        configs.getAmbariProperties())));
+    for (RootServiceComponentResponse response : rootServiceComponents) {
+      if (response.getComponentName().equals(RootServiceResponseFactory.Services.AMBARI.getComponents()[0].name())) {
+        assertEquals(response.getComponentVersion(), "1.3.0");
+        assertEquals(response.getProperties().size(), 1);
+        assertTrue(response.getProperties().containsKey("jdk_location"));
+        assertEquals(response.getProperties().get("jdk_location"), "http://localhost:8080/resources/");
+      }
+    }
     
     // Request existent service name, and component, not belongs to requested service
     request =

+ 159 - 5
ambari-server/src/test/python/TestAmbariServer.py

@@ -30,6 +30,7 @@ import datetime
 import operator
 import json
 import platform
+import shutil
 from pwd import getpwnam
 from ambari_server.resourceFilesKeeper import ResourceFilesKeeper, KeeperException
 
@@ -2214,6 +2215,7 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV
     self.assertEqual(result, "two")
 
   @patch("os.path.exists")
+  @patch("os.path.isfile")
   @patch.object(ambari_server, "remove_file")
   @patch.object(ambari_server, "is_jdbc_user_changed")
   @patch.object(ambari_server, 'verify_setup_allowed')
@@ -2236,10 +2238,11 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV
                  setup_remote_db_mock, check_selinux_mock, check_jdbc_drivers_mock, check_ambari_user_mock,
                  check_iptables_mock, check_postgre_up_mock, setup_db_mock, configure_postgres_mock,
                  download_jdk_mock, configure_os_settings_mock, get_YN_input,
-                 verify_setup_allowed_method, is_jdbc_user_changed_mock, remove_file_mock, exists_mock):
+                 verify_setup_allowed_method, is_jdbc_user_changed_mock, remove_file_mock, isfile_mock, exists_mock):
     args = MagicMock()
     failed = False
     get_YN_input.return_value = False
+    isfile_mock.return_value = False
     verify_setup_allowed_method.return_value = 0
     exists_mock.return_value = False
     remove_file_mock.return_value = 0
@@ -2288,6 +2291,8 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV
     configure_os_settings_mock.return_value = 0
     store_remote_properties_mock.return_value = 0
     store_local_properties_mock.return_value = 0
+    args.jdbc_driver= None
+    args.jdbc_db = None
 
     result = ambari_server.setup(args)
 
@@ -2891,7 +2896,105 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV
                                            ' > /var/log/ambari-server/ambari-server.out 2>&1')
 
 
+  @patch("os.path.isfile")
+  @patch.object(ambari_server, "get_ambari_properties")
+  @patch("os.path.lexists")
+  @patch("os.remove")
+  @patch("os.symlink")
+  @patch("shutil.copy")
+  def test_proceedJDBCProperties(self, copy_mock, os_symlink_mock, os_remove_mock, lexists_mock, get_ambari_properties_mock, isfile_mock):
+    args = MagicMock()
+
+    # test incorrect path to jdbc-driver
+    isfile_mock.return_value = False
+    args.jdbc_driver = "test jdbc"
+    fail = False
+
+    try:
+      ambari_server.proceedJDBCProperties(args)
+    except FatalException as e:
+      self.assertEquals("File test jdbc does not exist!", e.reason)
+      fail = True
+    self.assertTrue(fail)
+
+    # test incorrect jdbc-db
+    isfile_mock.return_value = True
+    args.jdbc_db = "incorrect db"
+    fail = False
+
+    try:
+      ambari_server.proceedJDBCProperties(args)
+    except FatalException as e:
+      self.assertEquals("Unsupported database name incorrect db. Please see help for more information.", e.reason)
+      fail = True
+    self.assertTrue(fail)
+
+    # test getAmbariProperties failed
+    args.jdbc_db = "mysql"
+    get_ambari_properties_mock.return_value = -1
+    fail = False
+
+    try:
+      ambari_server.proceedJDBCProperties(args)
+    except FatalException as e:
+      self.assertEquals("Error getting ambari properties", e.reason)
+      fail = True
+    self.assertTrue(fail)
+
+    # test get resource dir param failed
+    args.jdbc_db = "oracle"
+    p = MagicMock()
+    get_ambari_properties_mock.return_value = p
+    p.__getitem__.side_effect = KeyError("test exception")
+    fail = False
+
+    try:
+      ambari_server.proceedJDBCProperties(args)
+    except FatalException as e:
+      fail = True
+    self.assertTrue(fail)
+
+    # test copy jdbc failed and symlink exists
+    lexists_mock.return_value = True
+    args.jdbc_db = "postgresql"
+    get_ambari_properties_mock.return_value = MagicMock()
+    fail = False
+
+    def side_effect():
+      raise Exception(-1, "Failed to copy!")
+
+    copy_mock.side_effect = side_effect
+
+    try:
+      ambari_server.proceedJDBCProperties(args)
+    except FatalException as e:
+      fail = True
+    self.assertTrue(fail)
+    self.assertTrue(os_remove_mock.called)
+
+    # test success symlink creation
+    get_ambari_properties_mock.reset_mock()
+    os_remove_mock.reset_mock()
+    p = MagicMock()
+    get_ambari_properties_mock.return_value = p
+    p.__getitem__.side_effect = None
+    p.__getitem__.return_value = "somewhere"
+    copy_mock.reset_mock()
+    copy_mock.side_effect = None
+
+    ambari_server.proceedJDBCProperties(args)
+    self.assertTrue(os_remove_mock.called)
+    self.assertTrue(os_symlink_mock.called)
+    self.assertEquals(os_symlink_mock.call_args_list[0][0][0], os.path.join("somewhere","test jdbc"))
+    self.assertEquals(os_symlink_mock.call_args_list[0][0][1], os.path.join("somewhere","postgresql-jdbc-driver.jar"))
+
+
+
   @patch("__builtin__.open")
+  @patch("os.path.isfile")
+  @patch("os.path.lexists")
+  @patch("os.remove")
+  @patch("os.symlink")
   @patch.object(ambari_server.Properties, "store")
   @patch.object(ambari_server, "find_properties_file")
   @patch.object(ambari_server, "adjust_directory_permissions")
@@ -2909,13 +3012,15 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV
                    update_ambari_properties_mock, run_schema_upgrade_mock,
                    read_ambari_user_mock, print_warning_msg_mock,
                    adjust_directory_permissions_mock,
-                   find_properties_file_mock, properties_store_mock, open_mock):
+                   find_properties_file_mock, properties_store_mock,
+                   os_symlink_mock, os_remove_mock, lexists_mock, isfile_mock, open_mock):
 
     args = MagicMock()
     check_database_name_property_mock = MagicMock()
 
     update_ambari_properties_mock.return_value = 0
     run_schema_upgrade_mock.return_value = 0
+    isfile_mock.return_value = False
 
     # Testing call under non-root
     is_root_mock.return_value = False
@@ -2955,6 +3060,43 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV
     self.assertTrue(parse_properties_file_mock.called)
     self.assertTrue(run_schema_upgrade_mock.called)
 
+    # test getAmbariProperties failed
+    get_ambari_properties_mock.return_value = -1
+    fail = False
+
+    try:
+      ambari_server.upgrade(args)
+    except FatalException as e:
+      self.assertEquals("Error getting ambari properties", e.reason)
+      fail = True
+    self.assertTrue(fail)
+
+    # test get resource dir param failed
+    p = MagicMock()
+    get_ambari_properties_mock.reset_mock()
+    get_ambari_properties_mock.return_value = p
+    p.__getitem__.side_effect = ["something", KeyError("test exception")]
+    fail = False
+
+    try:
+      ambari_server.upgrade(args)
+    except FatalException as e:
+      fail = True
+    self.assertTrue(fail)
+
+    # test if some drivers are available in reources, and symlink available too
+    p.reset_mock()
+    p.__getitem__.side_effect = ["something", "resources"]
+    lexists_mock.return_value = True
+    isfile_mock.side_effect = [True, False, False]
+    ambari_server.upgrade(args)
+    self.assertTrue(os_remove_mock.called)
+    self.assertEquals(os_remove_mock.call_count, 1)
+    self.assertEquals(os_remove_mock.call_args[0][0], os.path.join("resources", "oracle-jdbc-driver.jar"))
+    self.assertEquals(os_symlink_mock.call_count, 1)
+    self.assertEquals(os_symlink_mock.call_args[0][0], os.path.join("resources","ojdbc6.jar"))
+    self.assertEquals(os_symlink_mock.call_args[0][1], os.path.join("resources","oracle-jdbc-driver.jar"))
+
 
   def test_print_info_msg(self):
     out = StringIO.StringIO()
@@ -3392,6 +3534,8 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV
                                      store_remote_properties_mock, get_db_cli_tool_mock, get_YN_input,
                                      exit_mock, verify_setup_allowed_method):
     args = MagicMock()
+    args.jdbc_driver= None
+    args.jdbc_db = None
     raw_input.return_value = ""
     is_root_mock.return_value = True
     is_local_db_mock.return_value = False
@@ -3643,8 +3787,12 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV
   @patch.object(ambari_server, "print_error_msg")
   @patch.object(ambari_server, "print_warning_msg")
   @patch('__builtin__.raw_input')
-  def test_check_jdbc_drivers(self, raw_input_mock, print_warning_msg, print_error_msg_mock, copy_files_mock,
-                              find_jdbc_driver_mock, get_ambari_properties_mock):
+  @patch("os.path.lexists")
+  @patch("os.remove")
+  @patch("os.symlink")
+  def test_check_jdbc_drivers(self,os_symlink_mock, os_remove_mock, lexists_mock,
+                              raw_input_mock, print_warning_msg, print_error_msg_mock,
+                              copy_files_mock, find_jdbc_driver_mock, get_ambari_properties_mock):
 
     out = StringIO.StringIO()
     sys.stdout = out
@@ -3652,7 +3800,7 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV
     args = MagicMock()
 
     # Check positive scenario
-    drivers_list = ['driver_file']
+    drivers_list = ['driver_file',os.path.join(os.sep,'usr','share','java','ojdbc6.jar')]
     resources_dir = '/tmp'
 
     get_ambari_properties_mock.return_value = {ambari_server.RESOURCES_DIR_PROPERTY: resources_dir}
@@ -3660,9 +3808,13 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV
     copy_files_mock.return_value = 0
 
     args.dbms = "oracle"
+    lexists_mock.return_value = True
 
     rcode = ambari_server.check_jdbc_drivers(args)
 
+    self.assertEquals(os_symlink_mock.call_count, 1)
+    self.assertEquals(os_symlink_mock.call_args_list[0][0][0], os.path.join(os.sep,'tmp','ojdbc6.jar'))
+    self.assertEquals(os_symlink_mock.call_args_list[0][0][1], os.path.join(os.sep,'tmp','oracle-jdbc-driver.jar'))
     self.assertEqual(0, rcode)
     copy_files_mock.assert_called_with(drivers_list, resources_dir)
 
@@ -4595,6 +4747,8 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV
     args.database_name = new_db
     args.database_username = "user"
     args.database_password = "password"
+    args.jdbc_driver= None
+    args.jdbc_db = None
 
     tempdir = tempfile.gettempdir()
     prop_file = os.path.join(tempdir, "ambari.properties")

+ 122 - 1
ambari-server/src/test/python/TestCheckHost.py

@@ -22,13 +22,134 @@ import os
 import socket
 from resource_management import Script,ConfigDictionary
 from mock.mock import patch
+from mock.mock import MagicMock
 from unittest import TestCase
 
 check_host = __import__('check_host')
 from check_host import CheckHost
 
 class TestCheckHost(TestCase):
-  
+
+  @patch("os.path.isfile")
+  @patch.object(Script, 'get_config')
+  @patch("resource_management.libraries.script.Script.put_structured_out")
+  def testJavaHomeAvailableCheck(self, structured_out_mock, mock_config, os_isfile_mock):
+    # test, java home exists
+    os_isfile_mock.return_value = True
+    mock_config.return_value = {"commandParams" : {"check_execute_list" : "java_home_check",
+                                                   "java_home" : "test_java_home"}}
+
+    checkHost = CheckHost()
+    checkHost.actionexecute(None)
+
+    self.assertEquals(os_isfile_mock.call_args[0][0], 'test_java_home/bin/java')
+    self.assertEquals(structured_out_mock.call_args[0][0], {'java_home_check': {'message': 'Java home exists!',
+                                                                                'exit_code': '0'}})
+    # test, java home doesn't exist
+    os_isfile_mock.reset_mock()
+    os_isfile_mock.return_value = False
+
+    checkHost.actionexecute(None)
+
+    self.assertEquals(os_isfile_mock.call_args[0][0], 'test_java_home/bin/java')
+    self.assertEquals(structured_out_mock.call_args[0][0], {'java_home_check': {"message": "Java home doesn't exist!",
+                                                                                "exit_code" : "1"}})
+
+
+  @patch.object(Script, 'get_config')
+  @patch("check_host.Execute")
+  @patch("resource_management.libraries.script.Script.put_structured_out")
+  @patch("subprocess.Popen")
+  @patch("check_host.format")
+  @patch("os.path.isfile")
+  def testDBConnectionCheck(self, isfile_mock, format_mock, popenMock, structured_out_mock, execute_mock, mock_config):
+    # test, download DBConnectionVerification.jar failed
+    mock_config.return_value = {"commandParams" : {"check_execute_list" : "db_connection_check",
+                                                   "java_home" : "test_java_home",
+                                                   "ambari_server_host" : "test_host",
+                                                   "jdk_location" : "test_jdk_location",
+                                                   "db_name" : "mysql",
+                                                   "db_connection_url" : "test_db_connection_url",
+                                                   "user_name" : "test_user_name",
+                                                   "user_passwd" : "test_user_passwd",
+                                                   "jdk_name" : "test_jdk_name"}}
+
+    execute_mock.side_effect = Exception("test exception")
+    isfile_mock.return_value = True
+    checkHost = CheckHost()
+    checkHost.actionexecute(None)
+
+    self.assertEquals(structured_out_mock.call_args[0][0], {'db_connection_check': {'message': 'Error downloading ' \
+                     'DBConnectionVerification.jar from Ambari Server resources. Check network access to Ambari ' \
+                     'Server.\ntest exception', 'exit_code': '1'}})
+    self.assertEquals(format_mock.call_args_list[2][0][0], "/bin/sh -c 'cd /usr/lib/ambari-agent/ && curl -kf " \
+                      "--retry 5 {jdk_location}{check_db_connection_jar_name} -o {check_db_connection_jar_name}'")
+    self.assertEquals(format_mock.call_args_list[3][0][0], "[ -f /usr/lib/ambari-agent/{check_db_connection_jar_name}]")
+
+    # test, download jdbc driver failed
+    mock_config.return_value = {"commandParams" : {"check_execute_list" : "db_connection_check",
+                                                   "java_home" : "test_java_home",
+                                                   "ambari_server_host" : "test_host",
+                                                   "jdk_location" : "test_jdk_location",
+                                                   "db_name" : "oracle",
+                                                   "db_connection_url" : "test_db_connection_url",
+                                                   "user_name" : "test_user_name",
+                                                   "user_passwd" : "test_user_passwd",
+                                                   "jdk_name" : "test_jdk_name"}}
+    format_mock.reset_mock()
+    execute_mock.reset_mock()
+    p = MagicMock()
+    execute_mock.side_effect = [p, Exception("test exception")]
+
+    checkHost.actionexecute(None)
+
+    self.assertEquals(structured_out_mock.call_args[0][0], {'db_connection_check': {'message': 'Error downloading JDBC ' \
+                              'connector from Ambari Server resources. Confirm you ran ambari-server setup to ' \
+                              'install JDBC connector. Use "ambari-server --help" for more information. Check ' \
+                              'network access to Ambari Server.\ntest exception', 'exit_code': '1'}})
+    self.assertEquals(format_mock.call_args_list[4][0][0], "/bin/sh -c 'cd /usr/lib/ambari-agent/ && curl -kf " \
+                                                            "--retry 5 {jdbc_url} -o {jdbc_name}'")
+    self.assertEquals(format_mock.call_args_list[5][0][0], "[ -f /usr/lib/ambari-agent/{jdbc_name}]")
+
+    # test, no connection to remote db
+    mock_config.return_value = {"commandParams" : {"check_execute_list" : "db_connection_check",
+                                                   "java_home" : "test_java_home",
+                                                   "ambari_server_host" : "test_host",
+                                                   "jdk_location" : "test_jdk_location",
+                                                   "db_name" : "postgresql",
+                                                   "db_connection_url" : "test_db_connection_url",
+                                                   "user_name" : "test_user_name",
+                                                   "user_passwd" : "test_user_passwd",
+                                                   "jdk_name" : "test_jdk_name"}}
+    format_mock.reset_mock()
+    execute_mock.reset_mock()
+    execute_mock.side_effect = [p, p]
+    s = MagicMock()
+    s.communicate.return_value = ("test message", "")
+    s.returncode = 1
+    popenMock.return_value = s
+
+    checkHost.actionexecute(None)
+
+    self.assertEquals(structured_out_mock.call_args[0][0], {'db_connection_check': {'message': 'test message',
+                                                                                    'exit_code': '1'}})
+    self.assertEquals(format_mock.call_args[0][0],'{java64_home}/bin/java -cp /usr/lib/ambari-agent/{check_db_' \
+                                                'connection_jar_name}:/usr/lib/ambari-agent/{jdbc_name} org.' \
+                                                'apache.ambari.server.DBConnectionVerification {db_connection_url} ' \
+                                                '{user_name} {user_passwd!p} {jdbc_driver}')
+
+    # test, db connection success
+    execute_mock.reset_mock()
+    execute_mock.side_effect = [p, p]
+    s.returncode = 0
+
+    checkHost.actionexecute(None)
+
+    self.assertEquals(structured_out_mock.call_args[0][0], {'db_connection_check':
+                                        {'message': 'DB connection check completed successfully!', 'exit_code': '0'}})
+
+
+
   @patch("socket.gethostbyname")
   @patch.object(Script, 'get_config')
   @patch("resource_management.libraries.script.Script.put_structured_out")