Преглед изворни кода

https://issues.apache.org/jira/browse/AMBARI-13450. AMBARI-13450 Bootstrap Cluster via different SSH Port Number (Selim Ozcan via aonishuk)

Andrew Onishuk пре 9 година
родитељ
комит
39c04ac9b4

+ 18 - 10
ambari-server/src/main/java/org/apache/ambari/server/bootstrap/BSRunner.java

@@ -41,6 +41,7 @@ class BSRunner extends Thread {
   private static Log LOG = LogFactory.getLog(BSRunner.class);
   private static Log LOG = LogFactory.getLog(BSRunner.class);
 
 
   private static final String DEFAULT_USER = "root";
   private static final String DEFAULT_USER = "root";
+  private static final String DEFAULT_SSHPORT = "22";
 
 
   private  boolean finished = false;
   private  boolean finished = false;
   private SshHostInfo sshHostInfo;
   private SshHostInfo sshHostInfo;
@@ -164,7 +165,13 @@ class BSRunner extends Thread {
     if (user == null || user.isEmpty()) {
     if (user == null || user.isEmpty()) {
       user = DEFAULT_USER;
       user = DEFAULT_USER;
     }
     }
-    String command[] = new String[12];
+
+    String sshPort = sshHostInfo.getSshPort();
+    if(sshPort == null || sshPort.isEmpty()){
+       sshPort = DEFAULT_SSHPORT;
+    }
+
+    String command[] = new String[13];
     BSStat stat = BSStat.RUNNING;
     BSStat stat = BSStat.RUNNING;
     String scriptlog = "";
     String scriptlog = "";
     try {
     try {
@@ -194,14 +201,15 @@ class BSRunner extends Thread {
       command[1] = hostString;
       command[1] = hostString;
       command[2] = this.requestIdDir.toString();
       command[2] = this.requestIdDir.toString();
       command[3] = user;
       command[3] = user;
-      command[4] = this.sshKeyFile.toString();
-      command[5] = this.agentSetupScript.toString();
-      command[6] = this.ambariHostname;
-      command[7] = this.clusterOsFamily;
-      command[8] = this.projectVersion;
-      command[9] = this.serverPort+"";
-      command[10] = userRunAs;
-      command[11] = (this.passwordFile==null) ? "null" : this.passwordFile.toString();
+      command[4] = sshPort;
+      command[5] = this.sshKeyFile.toString();
+      command[6] = this.agentSetupScript.toString();
+      command[7] = this.ambariHostname;
+      command[8] = this.clusterOsFamily;
+      command[9] = this.projectVersion;
+      command[10] = this.serverPort+"";
+      command[11] = userRunAs;
+      command[12] = (this.passwordFile==null) ? "null" : this.passwordFile.toString();
 
 
       Map<String, String> envVariables = new HashMap<String, String>();
       Map<String, String> envVariables = new HashMap<String, String>();
 
 
@@ -218,7 +226,7 @@ class BSRunner extends Thread {
       }
       }
 
 
       LOG.info("Host= " + hostString + " bs=" + this.bsScript + " requestDir=" +
       LOG.info("Host= " + hostString + " bs=" + this.bsScript + " requestDir=" +
-          requestIdDir + " user=" + user + " keyfile=" + this.sshKeyFile +
+          requestIdDir + " user=" + user + " sshPort=" + sshPort + " keyfile=" + this.sshKeyFile +
           " passwordFile " + this.passwordFile + " server=" + this.ambariHostname +
           " passwordFile " + this.passwordFile + " server=" + this.ambariHostname +
           " version=" + projectVersion + " serverPort=" + this.serverPort + " userRunAs=" + userRunAs);
           " version=" + projectVersion + " serverPort=" + this.serverPort + " userRunAs=" + userRunAs);
 
 

+ 7 - 0
ambari-server/src/main/java/org/apache/ambari/server/bootstrap/SshHostInfo.java

@@ -48,6 +48,9 @@ public class SshHostInfo {
   @XmlElement
   @XmlElement
   private String user;
   private String user;
 
 
+  @XmlElement
+  private String sshPort;
+
   @XmlElement
   @XmlElement
   private String password;
   private String password;
   
   
@@ -86,6 +89,10 @@ public class SshHostInfo {
     this.user = user;
     this.user = user;
   }
   }
 
 
+  public String getSshPort(){ return sshPort; }
+
+  public void setSshPort(String sshPort){ this.sshPort = sshPort; }
+
   public String getPassword() {
   public String getPassword() {
     return password;
     return password;
   }
   }

+ 35 - 31
ambari-server/src/main/python/bootstrap.py

@@ -74,8 +74,9 @@ class HostLog:
 class SCP:
 class SCP:
   """ SCP implementation that is thread based. The status can be returned using
   """ SCP implementation that is thread based. The status can be returned using
    status val """
    status val """
-  def __init__(self, user, sshkey_file, host, inputFile, remote, bootdir, host_log):
+  def __init__(self, user, sshPort, sshkey_file, host, inputFile, remote, bootdir, host_log):
     self.user = user
     self.user = user
+    self.sshPort = sshPort
     self.sshkey_file = sshkey_file
     self.sshkey_file = sshkey_file
     self.host = host
     self.host = host
     self.inputFile = inputFile
     self.inputFile = inputFile
@@ -90,7 +91,7 @@ class SCP:
                   "-r",
                   "-r",
                   "-o", "ConnectTimeout=60",
                   "-o", "ConnectTimeout=60",
                   "-o", "BatchMode=yes",
                   "-o", "BatchMode=yes",
-                  "-o", "StrictHostKeyChecking=no",
+                  "-o", "StrictHostKeyChecking=no", "-P", self.sshPort,
                   "-i", self.sshkey_file, self.inputFile, self.user + "@" +
                   "-i", self.sshkey_file, self.inputFile, self.user + "@" +
                                                          self.host + ":" + self.remote]
                                                          self.host + ":" + self.remote]
     if DEBUG:
     if DEBUG:
@@ -111,8 +112,9 @@ class SCP:
 
 
 class SSH:
 class SSH:
   """ Ssh implementation of this """
   """ Ssh implementation of this """
-  def __init__(self, user, sshkey_file, host, command, bootdir, host_log, errorMessage = None):
+  def __init__(self, user, sshPort, sshkey_file, host, command, bootdir, host_log, errorMessage = None):
     self.user = user
     self.user = user
+    self.sshPort = sshPort
     self.sshkey_file = sshkey_file
     self.sshkey_file = sshkey_file
     self.host = host
     self.host = host
     self.command = command
     self.command = command
@@ -128,7 +130,7 @@ class SSH:
                   "-o", "StrictHostKeyChecking=no",
                   "-o", "StrictHostKeyChecking=no",
                   "-o", "BatchMode=yes",
                   "-o", "BatchMode=yes",
                   "-tt", # Should prevent "tput: No value for $TERM and no -T specified" warning
                   "-tt", # Should prevent "tput: No value for $TERM and no -T specified" warning
-                  "-i", self.sshkey_file,
+                  "-i", self.sshkey_file, "-p", self.sshPort,
                   self.user + "@" + self.host, self.command]
                   self.user + "@" + self.host, self.command]
     if DEBUG:
     if DEBUG:
       self.host_log.write("Running ssh command " + ' '.join(sshcommand))
       self.host_log.write("Running ssh command " + ' '.join(sshcommand))
@@ -454,7 +456,7 @@ class BootstrapDefault(Bootstrap):
     params = self.shared_state
     params = self.shared_state
     self.host_log.write("==========================\n")
     self.host_log.write("==========================\n")
     self.host_log.write("Copying OS type check script...")
     self.host_log.write("Copying OS type check script...")
-    scp = SCP(params.user, params.sshkey_file, self.host, fileToCopy,
+    scp = SCP(params.user, params.sshPort, params.sshkey_file, self.host, fileToCopy,
               target, params.bootdir, self.host_log)
               target, params.bootdir, self.host_log)
     result = scp.run()
     result = scp.run()
     self.host_log.write("\n")
     self.host_log.write("\n")
@@ -467,7 +469,7 @@ class BootstrapDefault(Bootstrap):
     params = self.shared_state
     params = self.shared_state
     self.host_log.write("==========================\n")
     self.host_log.write("==========================\n")
     self.host_log.write("Copying common functions script...")
     self.host_log.write("Copying common functions script...")
-    scp = SCP(params.user, params.sshkey_file, self.host, fileToCopy,
+    scp = SCP(params.user, params.sshPort, params.sshkey_file, self.host, fileToCopy,
               target, params.bootdir, self.host_log)
               target, params.bootdir, self.host_log)
     result = scp.run()
     result = scp.run()
     self.host_log.write("\n")
     self.host_log.write("\n")
@@ -507,7 +509,7 @@ class BootstrapDefault(Bootstrap):
     if (os.path.exists(fileToCopy)):
     if (os.path.exists(fileToCopy)):
       self.host_log.write("==========================\n")
       self.host_log.write("==========================\n")
       self.host_log.write("Copying repo file to 'tmp' folder...")
       self.host_log.write("Copying repo file to 'tmp' folder...")
-      scp = SCP(params.user, params.sshkey_file, self.host, fileToCopy,
+      scp = SCP(params.user, params.sshPort, params.sshkey_file, self.host, fileToCopy,
                 target, params.bootdir, self.host_log)
                 target, params.bootdir, self.host_log)
       retcode1 = scp.run()
       retcode1 = scp.run()
       self.host_log.write("\n")
       self.host_log.write("\n")
@@ -517,7 +519,7 @@ class BootstrapDefault(Bootstrap):
       self.host_log.write("Moving file to repo dir...")
       self.host_log.write("Moving file to repo dir...")
       targetDir = self.getRepoDir()
       targetDir = self.getRepoDir()
       command = self.getMoveRepoFileCommand(targetDir)
       command = self.getMoveRepoFileCommand(targetDir)
-      ssh = SSH(params.user, params.sshkey_file, self.host, command,
+      ssh = SSH(params.user, params.sshPort, params.sshkey_file, self.host, command,
                 params.bootdir, self.host_log)
                 params.bootdir, self.host_log)
       retcode2 = ssh.run()
       retcode2 = ssh.run()
       self.host_log.write("\n")
       self.host_log.write("\n")
@@ -526,7 +528,7 @@ class BootstrapDefault(Bootstrap):
       self.host_log.write("==========================\n")
       self.host_log.write("==========================\n")
       self.host_log.write("Changing permissions for ambari.repo...")
       self.host_log.write("Changing permissions for ambari.repo...")
       command = self.getRepoFileChmodCommand()
       command = self.getRepoFileChmodCommand()
-      ssh = SSH(params.user, params.sshkey_file, self.host, command,
+      ssh = SSH(params.user, params.sshPort, params.sshkey_file, self.host, command,
                 params.bootdir, self.host_log)
                 params.bootdir, self.host_log)
       retcode4 = ssh.run()
       retcode4 = ssh.run()
       self.host_log.write("\n")
       self.host_log.write("\n")
@@ -536,7 +538,7 @@ class BootstrapDefault(Bootstrap):
         self.host_log.write("==========================\n")
         self.host_log.write("==========================\n")
         self.host_log.write("Update apt cache of repository...")
         self.host_log.write("Update apt cache of repository...")
         command = self.getAptUpdateCommand()
         command = self.getAptUpdateCommand()
-        ssh = SSH(params.user, params.sshkey_file, self.host, command,
+        ssh = SSH(params.user, params.sshPort, params.sshkey_file, self.host, command,
                   params.bootdir, self.host_log)
                   params.bootdir, self.host_log)
         retcode2 = ssh.run()
         retcode2 = ssh.run()
         self.host_log.write("\n")
         self.host_log.write("\n")
@@ -554,7 +556,7 @@ class BootstrapDefault(Bootstrap):
     self.host_log.write("Copying setup script file...")
     self.host_log.write("Copying setup script file...")
     fileToCopy = params.setup_agent_file
     fileToCopy = params.setup_agent_file
     target = self.getRemoteName(self.SETUP_SCRIPT_FILENAME)
     target = self.getRemoteName(self.SETUP_SCRIPT_FILENAME)
-    scp = SCP(params.user, params.sshkey_file, self.host, fileToCopy,
+    scp = SCP(params.user, params.sshPort, params.sshkey_file, self.host, fileToCopy,
               target, params.bootdir, self.host_log)
               target, params.bootdir, self.host_log)
     retcode3 = scp.run()
     retcode3 = scp.run()
     self.host_log.write("\n")
     self.host_log.write("\n")
@@ -600,7 +602,7 @@ class BootstrapDefault(Bootstrap):
               (self.getOsCheckScriptRemoteLocation(),
               (self.getOsCheckScriptRemoteLocation(),
                PYTHON_ENV, self.getOsCheckScriptRemoteLocation(), params.cluster_os_type)
                PYTHON_ENV, self.getOsCheckScriptRemoteLocation(), params.cluster_os_type)
 
 
-    ssh = SSH(params.user, params.sshkey_file, self.host, command,
+    ssh = SSH(params.user, params.sshPort, params.sshkey_file, self.host, command,
               params.bootdir, self.host_log)
               params.bootdir, self.host_log)
     retcode = ssh.run()
     retcode = ssh.run()
     self.host_log.write("\n")
     self.host_log.write("\n")
@@ -615,7 +617,7 @@ class BootstrapDefault(Bootstrap):
       command = "dpkg --get-selections|grep -e '^sudo\s*install'"
       command = "dpkg --get-selections|grep -e '^sudo\s*install'"
     else:
     else:
       command = "rpm -qa | grep -e '^sudo\-'"
       command = "rpm -qa | grep -e '^sudo\-'"
-    ssh = SSH(params.user, params.sshkey_file, self.host, command,
+    ssh = SSH(params.user, params.sshPort, params.sshkey_file, self.host, command,
               params.bootdir, self.host_log,
               params.bootdir, self.host_log,
               errorMessage="Error: Sudo command is not available. "
               errorMessage="Error: Sudo command is not available. "
                            "Please install the sudo command.")
                            "Please install the sudo command.")
@@ -627,7 +629,7 @@ class BootstrapDefault(Bootstrap):
     # Copy the password file
     # Copy the password file
     self.host_log.write("Copying password file to 'tmp' folder...")
     self.host_log.write("Copying password file to 'tmp' folder...")
     params = self.shared_state
     params = self.shared_state
-    scp = SCP(params.user, params.sshkey_file, self.host, params.password_file,
+    scp = SCP(params.user, params.sshPort, params.sshkey_file, self.host, params.password_file,
               self.getPasswordFile(), params.bootdir, self.host_log)
               self.getPasswordFile(), params.bootdir, self.host_log)
     retcode1 = scp.run()
     retcode1 = scp.run()
 
 
@@ -636,7 +638,7 @@ class BootstrapDefault(Bootstrap):
     # Change password file mode to 600
     # Change password file mode to 600
     self.host_log.write("Changing password file mode...")
     self.host_log.write("Changing password file mode...")
     command = "chmod 600 " + self.getPasswordFile()
     command = "chmod 600 " + self.getPasswordFile()
-    ssh = SSH(params.user, params.sshkey_file, self.host, command,
+    ssh = SSH(params.user, params.sshPort, params.sshkey_file, self.host, command,
               params.bootdir, self.host_log)
               params.bootdir, self.host_log)
     retcode2 = ssh.run()
     retcode2 = ssh.run()
 
 
@@ -648,7 +650,7 @@ class BootstrapDefault(Bootstrap):
     self.host_log.write("Changing password file mode...")
     self.host_log.write("Changing password file mode...")
     params = self.shared_state
     params = self.shared_state
     command = "chmod 600 " + self.getPasswordFile()
     command = "chmod 600 " + self.getPasswordFile()
-    ssh = SSH(params.user, params.sshkey_file, self.host, command,
+    ssh = SSH(params.user, params.sshPort, params.sshkey_file, self.host, command,
               params.bootdir, self.host_log)
               params.bootdir, self.host_log)
     retcode = ssh.run()
     retcode = ssh.run()
     self.host_log.write("Change password file mode on host finished")
     self.host_log.write("Change password file mode on host finished")
@@ -659,7 +661,7 @@ class BootstrapDefault(Bootstrap):
     self.host_log.write("Deleting password file...")
     self.host_log.write("Deleting password file...")
     params = self.shared_state
     params = self.shared_state
     command = "rm " + self.getPasswordFile()
     command = "rm " + self.getPasswordFile()
-    ssh = SSH(params.user, params.sshkey_file, self.host, command,
+    ssh = SSH(params.user, params.sshPort, params.sshkey_file, self.host, command,
               params.bootdir, self.host_log)
               params.bootdir, self.host_log)
     retcode = ssh.run()
     retcode = ssh.run()
     self.host_log.write("Deleting password file finished")
     self.host_log.write("Deleting password file finished")
@@ -675,7 +677,7 @@ class BootstrapDefault(Bootstrap):
     command = "sudo mkdir -p {0} ; sudo chown -R {1} {0} ; sudo chmod 755 {3} ; sudo chmod 755 {2} ; sudo chmod 777 {0}".format(
     command = "sudo mkdir -p {0} ; sudo chown -R {1} {0} ; sudo chmod 755 {3} ; sudo chmod 755 {2} ; sudo chmod 777 {0}".format(
       self.TEMP_FOLDER, quote_bash_args(params.user), DEFAULT_AGENT_DATA_FOLDER, DEFAULT_AGENT_LIB_FOLDER)
       self.TEMP_FOLDER, quote_bash_args(params.user), DEFAULT_AGENT_DATA_FOLDER, DEFAULT_AGENT_LIB_FOLDER)
 
 
-    ssh = SSH(params.user, params.sshkey_file, self.host, command,
+    ssh = SSH(params.user, params.sshPort, params.sshkey_file, self.host, command,
               params.bootdir, self.host_log)
               params.bootdir, self.host_log)
     retcode = ssh.run()
     retcode = ssh.run()
     self.host_log.write("\n")
     self.host_log.write("\n")
@@ -692,7 +694,7 @@ class BootstrapDefault(Bootstrap):
     self.host_log.write("==========================\n")
     self.host_log.write("==========================\n")
     self.host_log.write("Running setup agent script...")
     self.host_log.write("Running setup agent script...")
     command = self.getRunSetupCommand(self.host)
     command = self.getRunSetupCommand(self.host)
-    ssh = SSH(params.user, params.sshkey_file, self.host, command,
+    ssh = SSH(params.user, params.sshPort, params.sshkey_file, self.host, command,
               params.bootdir, self.host_log)
               params.bootdir, self.host_log)
     retcode = ssh.run()
     retcode = ssh.run()
     self.host_log.write("\n")
     self.host_log.write("\n")
@@ -791,11 +793,12 @@ class PBootstrap:
 
 
 
 
 class SharedState:
 class SharedState:
-  def __init__(self, user, sshkey_file, script_dir, boottmpdir, setup_agent_file,
+  def __init__(self, user, sshPort, sshkey_file, script_dir, boottmpdir, setup_agent_file,
                ambari_server, cluster_os_type, ambari_version, server_port,
                ambari_server, cluster_os_type, ambari_version, server_port,
                user_run_as, password_file = None):
                user_run_as, password_file = None):
     self.hostlist_to_remove_password_file = None
     self.hostlist_to_remove_password_file = None
     self.user = user
     self.user = user
+    self.sshPort = sshPort
     self.sshkey_file = sshkey_file
     self.sshkey_file = sshkey_file
     self.bootdir = boottmpdir
     self.bootdir = boottmpdir
     self.script_dir = script_dir
     self.script_dir = script_dir
@@ -817,7 +820,7 @@ def main(argv=None):
   onlyargs = argv[1:]
   onlyargs = argv[1:]
   if len(onlyargs) < 3:
   if len(onlyargs) < 3:
     sys.stderr.write("Usage: <comma separated hosts> "
     sys.stderr.write("Usage: <comma separated hosts> "
-                     "<tmpdir for storage> <user> <sshkey_file> <agent setup script>"
+                     "<tmpdir for storage> <user> <sshPort> <sshkey_file> <agent setup script>"
                      " <ambari-server name> <cluster os type> <ambari version> <ambari port> <user_run_as> <passwordFile>\n")
                      " <ambari-server name> <cluster os type> <ambari version> <ambari port> <user_run_as> <passwordFile>\n")
     sys.exit(2)
     sys.exit(2)
     pass
     pass
@@ -827,14 +830,15 @@ def main(argv=None):
   hostList = onlyargs[0].split(",")
   hostList = onlyargs[0].split(",")
   bootdir =  onlyargs[1]
   bootdir =  onlyargs[1]
   user = onlyargs[2]
   user = onlyargs[2]
-  sshkey_file = onlyargs[3]
-  setupAgentFile = onlyargs[4]
-  ambariServer = onlyargs[5]
-  cluster_os_type = onlyargs[6]
-  ambariVersion = onlyargs[7]
-  server_port = onlyargs[8]
-  user_run_as = onlyargs[9]
-  passwordFile = onlyargs[10]
+  sshPort = onlyargs[3]
+  sshkey_file = onlyargs[4]
+  setupAgentFile = onlyargs[5]
+  ambariServer = onlyargs[6]
+  cluster_os_type = onlyargs[7]
+  ambariVersion = onlyargs[8]
+  server_port = onlyargs[9]
+  user_run_as = onlyargs[10]
+  passwordFile = onlyargs[11]
 
 
   if not OSCheck.is_windows_family():
   if not OSCheck.is_windows_family():
     # ssh doesn't like open files
     # ssh doesn't like open files
@@ -845,10 +849,10 @@ def main(argv=None):
 
 
   logging.info("BootStrapping hosts " + pprint.pformat(hostList) +
   logging.info("BootStrapping hosts " + pprint.pformat(hostList) +
                " using " + scriptDir + " cluster primary OS: " + cluster_os_type +
                " using " + scriptDir + " cluster primary OS: " + cluster_os_type +
-               " with user '" + user + "' sshKey File " + sshkey_file + " password File " + passwordFile +\
+               " with user '" + user + "'with ssh Port '" + sshPort + "' sshKey File " + sshkey_file + " password File " + passwordFile +\
                " using tmp dir " + bootdir + " ambari: " + ambariServer +"; server_port: " + server_port +\
                " using tmp dir " + bootdir + " ambari: " + ambariServer +"; server_port: " + server_port +\
                "; ambari version: " + ambariVersion+"; user_run_as: " + user_run_as)
                "; ambari version: " + ambariVersion+"; user_run_as: " + user_run_as)
-  sharedState = SharedState(user, sshkey_file, scriptDir, bootdir, setupAgentFile,
+  sharedState = SharedState(user, sshPort, sshkey_file, scriptDir, bootdir, setupAgentFile,
                        ambariServer, cluster_os_type, ambariVersion,
                        ambariServer, cluster_os_type, ambariVersion,
                        server_port, user_run_as, passwordFile)
                        server_port, user_run_as, passwordFile)
   pbootstrap = PBootstrap(hostList, sharedState)
   pbootstrap = PBootstrap(hostList, sharedState)

+ 51 - 51
ambari-server/src/test/python/TestBootstrap.py

@@ -43,7 +43,7 @@ class TestBootstrap(TestCase):
 
 
 
 
   def test_getRemoteName(self):
   def test_getRemoteName(self):
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                       "setupAgentFile", "ambariServer", "centos6", None, "8440", "root")
                       "setupAgentFile", "ambariServer", "centos6", None, "8440", "root")
     res = bootstrap_obj = Bootstrap("hostname", shared_state)
     res = bootstrap_obj = Bootstrap("hostname", shared_state)
     utime1 = 1234
     utime1 = 1234
@@ -65,7 +65,7 @@ class TestBootstrap(TestCase):
   # TODO: test_return_error_message_for_missing_sudo_package
   # TODO: test_return_error_message_for_missing_sudo_package
 
 
   def test_getAmbariPort(self):
   def test_getAmbariPort(self):
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                "setupAgentFile", "ambariServer", "centos6",
                                "setupAgentFile", "ambariServer", "centos6",
                                None, "8440", "root")
                                None, "8440", "root")
     bootstrap_obj = Bootstrap("hostname", shared_state)
     bootstrap_obj = Bootstrap("hostname", shared_state)
@@ -82,11 +82,11 @@ class TestBootstrap(TestCase):
   @patch("os.path.dirname")
   @patch("os.path.dirname")
   @patch("os.path.realpath")
   @patch("os.path.realpath")
   def test_bootstrap_main(self, dirname_mock, realpath_mock, run_mock, exit_mock, stderr_mock, subprocess_Popen_mock):
   def test_bootstrap_main(self, dirname_mock, realpath_mock, run_mock, exit_mock, stderr_mock, subprocess_Popen_mock):
-    bootstrap.main(["bootstrap.py", "hostname,hostname2", "/tmp/bootstrap", "root", "sshkey_file", "setupAgent.py", "ambariServer", \
+    bootstrap.main(["bootstrap.py", "hostname,hostname2", "/tmp/bootstrap", "root", "123", "sshkey_file", "setupAgent.py", "ambariServer", \
                     "centos6", "1.1.1", "8440", "root", "passwordfile"])
                     "centos6", "1.1.1", "8440", "root", "passwordfile"])
     self.assertTrue(run_mock.called)
     self.assertTrue(run_mock.called)
     run_mock.reset_mock()
     run_mock.reset_mock()
-    bootstrap.main(["bootstrap.py", "hostname,hostname2", "/tmp/bootstrap", "root", "sshkey_file", "setupAgent.py", "ambariServer", \
+    bootstrap.main(["bootstrap.py", "hostname,hostname2", "/tmp/bootstrap", "root", "123", "sshkey_file", "setupAgent.py", "ambariServer", \
                     "centos6", "1.1.1", "8440", "root", None])
                     "centos6", "1.1.1", "8440", "root", None])
     self.assertTrue(run_mock.called)
     self.assertTrue(run_mock.called)
     run_mock.reset_mock()
     run_mock.reset_mock()
@@ -104,7 +104,7 @@ class TestBootstrap(TestCase):
 
 
   @patch("os.environ")
   @patch("os.environ")
   def test_getRunSetupWithPasswordCommand(self, environ_mock):
   def test_getRunSetupWithPasswordCommand(self, environ_mock):
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                "setupAgentFile", "ambariServer", "centos6",
                                "setupAgentFile", "ambariServer", "centos6",
                                None, "8440", "root")
                                None, "8440", "root")
     environ_mock.__getitem__.return_value = "TEST_PASSPHRASE"
     environ_mock.__getitem__.return_value = "TEST_PASSPHRASE"
@@ -118,7 +118,7 @@ class TestBootstrap(TestCase):
 
 
 
 
   def test_generateRandomFileName(self):
   def test_generateRandomFileName(self):
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                "setupAgentFile", "ambariServer", "centos6",
                                "setupAgentFile", "ambariServer", "centos6",
                                None, "8440", "root")
                                None, "8440", "root")
     bootstrap_obj = Bootstrap("hostname", shared_state)
     bootstrap_obj = Bootstrap("hostname", shared_state)
@@ -129,7 +129,7 @@ class TestBootstrap(TestCase):
   @patch.object(OSCheck, "is_redhat_family")
   @patch.object(OSCheck, "is_redhat_family")
   @patch.object(OSCheck, "is_suse_family")
   @patch.object(OSCheck, "is_suse_family")
   def test_getRepoDir(self, is_suse_family, is_redhat_family):
   def test_getRepoDir(self, is_suse_family, is_redhat_family):
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                "setupAgentFile", "ambariServer", "centos6",
                                "setupAgentFile", "ambariServer", "centos6",
                                None, "8440", "root")
                                None, "8440", "root")
     bootstrap_obj = Bootstrap("hostname", shared_state)
     bootstrap_obj = Bootstrap("hostname", shared_state)
@@ -145,7 +145,7 @@ class TestBootstrap(TestCase):
     self.assertEquals(res, "/etc/yum.repos.d")
     self.assertEquals(res, "/etc/yum.repos.d")
 
 
   def test_getSetupScript(self):
   def test_getSetupScript(self):
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                "setupAgentFile", "ambariServer", "centos6",
                                "setupAgentFile", "ambariServer", "centos6",
                                None, "8440", "root")
                                None, "8440", "root")
     bootstrap_obj = Bootstrap("hostname", shared_state)
     bootstrap_obj = Bootstrap("hostname", shared_state)
@@ -155,7 +155,7 @@ class TestBootstrap(TestCase):
   def test_run_setup_agent_command_ends_with_project_version(self):
   def test_run_setup_agent_command_ends_with_project_version(self):
     os.environ[AMBARI_PASSPHRASE_VAR_NAME] = ""
     os.environ[AMBARI_PASSPHRASE_VAR_NAME] = ""
     version = "1.1.1"
     version = "1.1.1"
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                "setupAgentFile", "ambariServer", "centos6",
                                "setupAgentFile", "ambariServer", "centos6",
                                version, "8440", "root")
                                version, "8440", "root")
     bootstrap_obj = Bootstrap("hostname", shared_state)
     bootstrap_obj = Bootstrap("hostname", shared_state)
@@ -166,7 +166,7 @@ class TestBootstrap(TestCase):
   def test_agent_setup_command_without_project_version(self):
   def test_agent_setup_command_without_project_version(self):
     os.environ[AMBARI_PASSPHRASE_VAR_NAME] = ""
     os.environ[AMBARI_PASSPHRASE_VAR_NAME] = ""
     version = None
     version = None
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                "setupAgentFile", "ambariServer", "centos6",
                                "setupAgentFile", "ambariServer", "centos6",
                                version, "8440", "root")
                                version, "8440", "root")
     bootstrap_obj = Bootstrap("hostname", shared_state)
     bootstrap_obj = Bootstrap("hostname", shared_state)
@@ -207,7 +207,7 @@ class TestBootstrap(TestCase):
 
 
   @patch("subprocess.Popen")
   @patch("subprocess.Popen")
   def test_SCP(self, popenMock):
   def test_SCP(self, popenMock):
-    params = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    params = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                   "setupAgentFile", "ambariServer", "centos6",
                                   "setupAgentFile", "ambariServer", "centos6",
                                   "1.2.1", "8440", "root")
                                   "1.2.1", "8440", "root")
     host_log_mock = MagicMock()
     host_log_mock = MagicMock()
@@ -216,7 +216,7 @@ class TestBootstrap(TestCase):
       log['text'] = log['text'] + text
       log['text'] = log['text'] + text
 
 
     host_log_mock.write.side_effect = write_side_effect
     host_log_mock.write.side_effect = write_side_effect
-    scp = SCP(params.user, params.sshkey_file, "dummy-host", "src/file",
+    scp = SCP(params.user, params.sshPort, params.sshkey_file, "dummy-host", "src/file",
               "dst/file", params.bootdir, host_log_mock)
               "dst/file", params.bootdir, host_log_mock)
     log_sample = "log_sample"
     log_sample = "log_sample"
     error_sample = "error_sample"
     error_sample = "error_sample"
@@ -233,7 +233,7 @@ class TestBootstrap(TestCase):
     self.assertTrue(error_sample in log['text'])
     self.assertTrue(error_sample in log['text'])
     command_str = str(popenMock.call_args[0][0])
     command_str = str(popenMock.call_args[0][0])
     self.assertEquals(command_str, "['scp', '-r', '-o', 'ConnectTimeout=60', '-o', "
     self.assertEquals(command_str, "['scp', '-r', '-o', 'ConnectTimeout=60', '-o', "
-        "'BatchMode=yes', '-o', 'StrictHostKeyChecking=no', '-i', 'sshkey_file',"
+        "'BatchMode=yes', '-o', 'StrictHostKeyChecking=no', '-P', '123', '-i', 'sshkey_file',"
         " 'src/file', 'root@dummy-host:dst/file']")
         " 'src/file', 'root@dummy-host:dst/file']")
     self.assertEqual(retcode["exitstatus"], 0)
     self.assertEqual(retcode["exitstatus"], 0)
 
 
@@ -250,7 +250,7 @@ class TestBootstrap(TestCase):
 
 
   @patch("subprocess.Popen")
   @patch("subprocess.Popen")
   def test_SSH(self, popenMock):
   def test_SSH(self, popenMock):
-    params = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    params = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                   "setupAgentFile", "ambariServer", "centos6",
                                   "setupAgentFile", "ambariServer", "centos6",
                                   "1.2.1", "8440", "root")
                                   "1.2.1", "8440", "root")
     host_log_mock = MagicMock()
     host_log_mock = MagicMock()
@@ -259,7 +259,7 @@ class TestBootstrap(TestCase):
       log['text'] = log['text'] + text
       log['text'] = log['text'] + text
 
 
     host_log_mock.write.side_effect = write_side_effect
     host_log_mock.write.side_effect = write_side_effect
-    ssh = SSH(params.user, params.sshkey_file, "dummy-host", "dummy-command",
+    ssh = SSH(params.user, params.sshPort, params.sshkey_file, "dummy-host", "dummy-command",
               params.bootdir, host_log_mock)
               params.bootdir, host_log_mock)
     log_sample = "log_sample"
     log_sample = "log_sample"
     error_sample = "error_sample"
     error_sample = "error_sample"
@@ -277,7 +277,7 @@ class TestBootstrap(TestCase):
     command_str = str(popenMock.call_args[0][0])
     command_str = str(popenMock.call_args[0][0])
     self.assertEquals(command_str, "['ssh', '-o', 'ConnectTimeOut=60', '-o', "
     self.assertEquals(command_str, "['ssh', '-o', 'ConnectTimeOut=60', '-o', "
             "'StrictHostKeyChecking=no', '-o', 'BatchMode=yes', '-tt', '-i', "
             "'StrictHostKeyChecking=no', '-o', 'BatchMode=yes', '-tt', '-i', "
-            "'sshkey_file', 'root@dummy-host', 'dummy-command']")
+            "'sshkey_file', '-p', '123', 'root@dummy-host', 'dummy-command']")
     self.assertEqual(retcode["exitstatus"], 0)
     self.assertEqual(retcode["exitstatus"], 0)
 
 
     log['text'] = ""
     log['text'] = ""
@@ -295,7 +295,7 @@ class TestBootstrap(TestCase):
     process.returncode = 1
     process.returncode = 1
 
 
     dummy_error_message = "dummy_error_message"
     dummy_error_message = "dummy_error_message"
-    ssh = SSH(params.user, params.sshkey_file, "dummy-host", "dummy-command",
+    ssh = SSH(params.user, params.sshPort, params.sshkey_file, "dummy-host", "dummy-command",
               params.bootdir, host_log_mock, errorMessage= dummy_error_message)
               params.bootdir, host_log_mock, errorMessage= dummy_error_message)
     retcode = ssh.run()
     retcode = ssh.run()
 
 
@@ -306,7 +306,7 @@ class TestBootstrap(TestCase):
 
 
 
 
   def test_getOsCheckScript(self):
   def test_getOsCheckScript(self):
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                "setupAgentFile", "ambariServer", "centos6",
                                "setupAgentFile", "ambariServer", "centos6",
                                None, "8440", "root")
                                None, "8440", "root")
     bootstrap_obj = Bootstrap("hostname", shared_state)
     bootstrap_obj = Bootstrap("hostname", shared_state)
@@ -316,7 +316,7 @@ class TestBootstrap(TestCase):
 
 
   @patch.object(BootstrapDefault, "getRemoteName")
   @patch.object(BootstrapDefault, "getRemoteName")
   def test_getOsCheckScriptRemoteLocation(self, getRemoteName_mock):
   def test_getOsCheckScriptRemoteLocation(self, getRemoteName_mock):
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                "setupAgentFile", "ambariServer", "centos6",
                                "setupAgentFile", "ambariServer", "centos6",
                                None, "8440", "root")
                                None, "8440", "root")
     bootstrap_obj = Bootstrap("hostname", shared_state)
     bootstrap_obj = Bootstrap("hostname", shared_state)
@@ -328,7 +328,7 @@ class TestBootstrap(TestCase):
 
 
   @patch.object(BootstrapDefault, "is_suse")
   @patch.object(BootstrapDefault, "is_suse")
   def test_getRepoFile(self, is_suse_mock):
   def test_getRepoFile(self, is_suse_mock):
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                "setupAgentFile", "ambariServer", "centos6",
                                "setupAgentFile", "ambariServer", "centos6",
                                None, "8440", "root")
                                None, "8440", "root")
     bootstrap_obj = Bootstrap("hostname", shared_state)
     bootstrap_obj = Bootstrap("hostname", shared_state)
@@ -342,7 +342,7 @@ class TestBootstrap(TestCase):
   @patch.object(HostLog, "write")
   @patch.object(HostLog, "write")
   def test_createTargetDir(self, write_mock, run_mock,
   def test_createTargetDir(self, write_mock, run_mock,
                             init_mock):
                             init_mock):
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                "setupAgentFile", "ambariServer", "centos6",
                                "setupAgentFile", "ambariServer", "centos6",
                                None, "8440", "root")
                                None, "8440", "root")
     bootstrap_obj = Bootstrap("hostname", shared_state)
     bootstrap_obj = Bootstrap("hostname", shared_state)
@@ -351,7 +351,7 @@ class TestBootstrap(TestCase):
     run_mock.return_value = expected
     run_mock.return_value = expected
     res = bootstrap_obj.createTargetDir()
     res = bootstrap_obj.createTargetDir()
     self.assertEquals(res, expected)
     self.assertEquals(res, expected)
-    command = str(init_mock.call_args[0][3])
+    command = str(init_mock.call_args[0][4])
     self.assertEqual(command,
     self.assertEqual(command,
                      "sudo mkdir -p /var/lib/ambari-agent/tmp ; "
                      "sudo mkdir -p /var/lib/ambari-agent/tmp ; "
                      "sudo chown -R root /var/lib/ambari-agent/tmp ; "
                      "sudo chown -R root /var/lib/ambari-agent/tmp ; "
@@ -366,7 +366,7 @@ class TestBootstrap(TestCase):
   @patch.object(HostLog, "write")
   @patch.object(HostLog, "write")
   def test_copyOsCheckScript(self, write_mock, run_mock, init_mock,
   def test_copyOsCheckScript(self, write_mock, run_mock, init_mock,
                     getOsCheckScriptRemoteLocation_mock, getOsCheckScript_mock):
                     getOsCheckScriptRemoteLocation_mock, getOsCheckScript_mock):
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                "setupAgentFile", "ambariServer", "centos6",
                                "setupAgentFile", "ambariServer", "centos6",
                                None, "8440", "root")
                                None, "8440", "root")
     bootstrap_obj = Bootstrap("hostname", shared_state)
     bootstrap_obj = Bootstrap("hostname", shared_state)
@@ -377,8 +377,8 @@ class TestBootstrap(TestCase):
     run_mock.return_value = expected
     run_mock.return_value = expected
     res = bootstrap_obj.copyOsCheckScript()
     res = bootstrap_obj.copyOsCheckScript()
     self.assertEquals(res, expected)
     self.assertEquals(res, expected)
-    input_file = str(init_mock.call_args[0][3])
-    remote_file = str(init_mock.call_args[0][4])
+    input_file = str(init_mock.call_args[0][4])
+    remote_file = str(init_mock.call_args[0][5])
     self.assertEqual(input_file, "OsCheckScript")
     self.assertEqual(input_file, "OsCheckScript")
     self.assertEqual(remote_file, "OsCheckScriptRemoteLocation")
     self.assertEqual(remote_file, "OsCheckScriptRemoteLocation")
 
 
@@ -389,7 +389,7 @@ class TestBootstrap(TestCase):
   @patch.object(OSCheck, "is_ubuntu_family")
   @patch.object(OSCheck, "is_ubuntu_family")
   @patch.object(OSCheck, "is_redhat_family")
   @patch.object(OSCheck, "is_redhat_family")
   def test_getRepoFile(self, is_redhat_family, is_ubuntu_family, is_suse_family, hasPassword_mock, getRemoteName_mock):
   def test_getRepoFile(self, is_redhat_family, is_ubuntu_family, is_suse_family, hasPassword_mock, getRemoteName_mock):
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                "setupAgentFile", "ambariServer", "centos6",
                                "setupAgentFile", "ambariServer", "centos6",
                                None, "8440", "root")
                                None, "8440", "root")
     is_redhat_family.return_value = True
     is_redhat_family.return_value = True
@@ -437,7 +437,7 @@ class TestBootstrap(TestCase):
     os_path_exists_mock.side_effect = os_path_exists_side_effect
     os_path_exists_mock.side_effect = os_path_exists_side_effect
     os_path_exists_mock.return_value = None
     os_path_exists_mock.return_value = None
 
 
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                "setupAgentFile", "ambariServer", "centos6",
                                "setupAgentFile", "ambariServer", "centos6",
                                None, "8440", "root")
                                None, "8440", "root")
     is_redhat_family.return_value = True
     is_redhat_family.return_value = True
@@ -459,11 +459,11 @@ class TestBootstrap(TestCase):
     ssh_run_mock.side_effect = [expected2, expected4]
     ssh_run_mock.side_effect = [expected2, expected4]
     res = bootstrap_obj.copyNeededFiles()
     res = bootstrap_obj.copyNeededFiles()
     self.assertEquals(res, expected1["exitstatus"])
     self.assertEquals(res, expected1["exitstatus"])
-    input_file = str(scp_init_mock.call_args[0][3])
-    remote_file = str(scp_init_mock.call_args[0][4])
+    input_file = str(scp_init_mock.call_args[0][4])
+    remote_file = str(scp_init_mock.call_args[0][5])
     self.assertEqual(input_file, "setupAgentFile")
     self.assertEqual(input_file, "setupAgentFile")
     self.assertEqual(remote_file, "RemoteName")
     self.assertEqual(remote_file, "RemoteName")
-    command = str(ssh_init_mock.call_args[0][3])
+    command = str(ssh_init_mock.call_args[0][4])
     self.assertEqual(command, "sudo chmod 644 RepoFile")
     self.assertEqual(command, "sudo chmod 644 RepoFile")
     # Another order
     # Another order
     expected1 = {"exitstatus": 0, "log": "log0", "errormsg": "errorMsg"}
     expected1 = {"exitstatus": 0, "log": "log0", "errormsg": "errorMsg"}
@@ -507,7 +507,7 @@ class TestBootstrap(TestCase):
   @patch.object(HostLog, "write")
   @patch.object(HostLog, "write")
   def test_runOsCheckScript(self, write_mock, run_mock,
   def test_runOsCheckScript(self, write_mock, run_mock,
                             init_mock, getOsCheckScriptRemoteLocation_mock):
                             init_mock, getOsCheckScriptRemoteLocation_mock):
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                "setupAgentFile", "ambariServer", "centos6",
                                "setupAgentFile", "ambariServer", "centos6",
                                None, "8440", "root")
                                None, "8440", "root")
     bootstrap_obj = Bootstrap("hostname", shared_state)
     bootstrap_obj = Bootstrap("hostname", shared_state)
@@ -517,7 +517,7 @@ class TestBootstrap(TestCase):
     run_mock.return_value = expected
     run_mock.return_value = expected
     res = bootstrap_obj.runOsCheckScript()
     res = bootstrap_obj.runOsCheckScript()
     self.assertEquals(res, expected)
     self.assertEquals(res, expected)
-    command = str(init_mock.call_args[0][3])
+    command = str(init_mock.call_args[0][4])
     self.assertEqual(command,
     self.assertEqual(command,
                      "chmod a+x OsCheckScriptRemoteLocation && "
                      "chmod a+x OsCheckScriptRemoteLocation && "
                      "env PYTHONPATH=$PYTHONPATH:/var/lib/ambari-agent/tmp OsCheckScriptRemoteLocation centos6")
                      "env PYTHONPATH=$PYTHONPATH:/var/lib/ambari-agent/tmp OsCheckScriptRemoteLocation centos6")
@@ -529,7 +529,7 @@ class TestBootstrap(TestCase):
   @patch.object(HostLog, "write")
   @patch.object(HostLog, "write")
   def test_runSetupAgent(self, write_mock, run_mock,
   def test_runSetupAgent(self, write_mock, run_mock,
                          getRunSetupCommand_mock, init_mock):
                          getRunSetupCommand_mock, init_mock):
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                "setupAgentFile", "ambariServer", "centos6",
                                "setupAgentFile", "ambariServer", "centos6",
                                None, "8440", "root")
                                None, "8440", "root")
     bootstrap_obj = Bootstrap("hostname", shared_state)
     bootstrap_obj = Bootstrap("hostname", shared_state)
@@ -539,7 +539,7 @@ class TestBootstrap(TestCase):
     run_mock.return_value = expected
     run_mock.return_value = expected
     res = bootstrap_obj.runSetupAgent()
     res = bootstrap_obj.runSetupAgent()
     self.assertEquals(res, expected)
     self.assertEquals(res, expected)
-    command = str(init_mock.call_args[0][3])
+    command = str(init_mock.call_args[0][4])
     self.assertEqual(command, "RunSetupCommand")
     self.assertEqual(command, "RunSetupCommand")
 
 
 
 
@@ -549,7 +549,7 @@ class TestBootstrap(TestCase):
   def test_getRunSetupCommand(self, getRunSetupWithoutPasswordCommand_mock,
   def test_getRunSetupCommand(self, getRunSetupWithoutPasswordCommand_mock,
                               getRunSetupWithPasswordCommand_mock,
                               getRunSetupWithPasswordCommand_mock,
                               hasPassword_mock):
                               hasPassword_mock):
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                "setupAgentFile", "ambariServer", "centos6",
                                "setupAgentFile", "ambariServer", "centos6",
                                None, "8440", "root")
                                None, "8440", "root")
     bootstrap_obj = Bootstrap("hostname", shared_state)
     bootstrap_obj = Bootstrap("hostname", shared_state)
@@ -568,7 +568,7 @@ class TestBootstrap(TestCase):
   @patch.object(HostLog, "write")
   @patch.object(HostLog, "write")
   def test_createDoneFile(self, write_mock):
   def test_createDoneFile(self, write_mock):
     tmp_dir = tempfile.gettempdir()
     tmp_dir = tempfile.gettempdir()
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", tmp_dir,
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", tmp_dir,
                                "setupAgentFile", "ambariServer", "centos6",
                                "setupAgentFile", "ambariServer", "centos6",
                                None, "8440", "root")
                                None, "8440", "root")
     bootstrap_obj = Bootstrap("hostname", shared_state)
     bootstrap_obj = Bootstrap("hostname", shared_state)
@@ -587,7 +587,7 @@ class TestBootstrap(TestCase):
   @patch.object(SSH, "run")
   @patch.object(SSH, "run")
   @patch.object(HostLog, "write")
   @patch.object(HostLog, "write")
   def test_checkSudoPackage(self, write_mock, run_mock, init_mock, is_redhat_family, is_ubuntu_family, is_suse_family):
   def test_checkSudoPackage(self, write_mock, run_mock, init_mock, is_redhat_family, is_ubuntu_family, is_suse_family):
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                "setupAgentFile", "ambariServer", "centos6",
                                "setupAgentFile", "ambariServer", "centos6",
                                None, "8440", "root")
                                None, "8440", "root")
     bootstrap_obj = Bootstrap("hostname", shared_state)
     bootstrap_obj = Bootstrap("hostname", shared_state)
@@ -599,7 +599,7 @@ class TestBootstrap(TestCase):
     is_suse_family.return_value = False
     is_suse_family.return_value = False
     res = bootstrap_obj.checkSudoPackage()
     res = bootstrap_obj.checkSudoPackage()
     self.assertEquals(res, expected)
     self.assertEquals(res, expected)
-    command = str(init_mock.call_args[0][3])
+    command = str(init_mock.call_args[0][4])
     self.assertEqual(command, "rpm -qa | grep -e '^sudo\-'")
     self.assertEqual(command, "rpm -qa | grep -e '^sudo\-'")
 
 
   @patch.object(OSCheck, "is_suse_family")
   @patch.object(OSCheck, "is_suse_family")
@@ -610,7 +610,7 @@ class TestBootstrap(TestCase):
   @patch.object(HostLog, "write")
   @patch.object(HostLog, "write")
   def test_checkSudoPackageUbuntu(self, write_mock, run_mock, init_mock,
   def test_checkSudoPackageUbuntu(self, write_mock, run_mock, init_mock,
                                   is_redhat_family, is_ubuntu_family, is_suse_family):
                                   is_redhat_family, is_ubuntu_family, is_suse_family):
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                "setupAgentFile", "ambariServer", "ubuntu12",
                                "setupAgentFile", "ambariServer", "ubuntu12",
                                None, "8440", "root")
                                None, "8440", "root")
     is_redhat_family.return_value = False
     is_redhat_family.return_value = False
@@ -622,7 +622,7 @@ class TestBootstrap(TestCase):
     run_mock.return_value = expected
     run_mock.return_value = expected
     res = bootstrap_obj.checkSudoPackage()
     res = bootstrap_obj.checkSudoPackage()
     self.assertEquals(res, expected)
     self.assertEquals(res, expected)
-    command = str(init_mock.call_args[0][3])
+    command = str(init_mock.call_args[0][4])
     self.assertEqual(command, "dpkg --get-selections|grep -e '^sudo\s*install'")
     self.assertEqual(command, "dpkg --get-selections|grep -e '^sudo\s*install'")
 
 
 
 
@@ -632,7 +632,7 @@ class TestBootstrap(TestCase):
   @patch.object(BootstrapDefault, "getPasswordFile")
   @patch.object(BootstrapDefault, "getPasswordFile")
   def test_deletePasswordFile(self, getPasswordFile_mock, write_mock, run_mock,
   def test_deletePasswordFile(self, getPasswordFile_mock, write_mock, run_mock,
                               init_mock):
                               init_mock):
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                "setupAgentFile", "ambariServer", "centos6",
                                "setupAgentFile", "ambariServer", "centos6",
                                None, "8440", "root")
                                None, "8440", "root")
     bootstrap_obj = Bootstrap("hostname", shared_state)
     bootstrap_obj = Bootstrap("hostname", shared_state)
@@ -642,7 +642,7 @@ class TestBootstrap(TestCase):
     run_mock.return_value = expected
     run_mock.return_value = expected
     res = bootstrap_obj.deletePasswordFile()
     res = bootstrap_obj.deletePasswordFile()
     self.assertEquals(res, expected)
     self.assertEquals(res, expected)
-    command = str(init_mock.call_args[0][3])
+    command = str(init_mock.call_args[0][4])
     self.assertEqual(command, "rm PasswordFile")
     self.assertEqual(command, "rm PasswordFile")
 
 
 
 
@@ -655,7 +655,7 @@ class TestBootstrap(TestCase):
   def test_copyPasswordFile(self, write_mock, ssh_run_mock,
   def test_copyPasswordFile(self, write_mock, ssh_run_mock,
                             ssh_init_mock, scp_run_mock,
                             ssh_init_mock, scp_run_mock,
                             scp_init_mock, getPasswordFile_mock):
                             scp_init_mock, getPasswordFile_mock):
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                "setupAgentFile", "ambariServer", "centos6",
                                "setupAgentFile", "ambariServer", "centos6",
                                None, "8440", "root", password_file="PasswordFile")
                                None, "8440", "root", password_file="PasswordFile")
     bootstrap_obj = Bootstrap("hostname", shared_state)
     bootstrap_obj = Bootstrap("hostname", shared_state)
@@ -669,11 +669,11 @@ class TestBootstrap(TestCase):
     ssh_run_mock.return_value = expected2
     ssh_run_mock.return_value = expected2
     res = bootstrap_obj.copyPasswordFile()
     res = bootstrap_obj.copyPasswordFile()
     self.assertEquals(res, expected1["exitstatus"])
     self.assertEquals(res, expected1["exitstatus"])
-    input_file = str(scp_init_mock.call_args[0][3])
+    input_file = str(scp_init_mock.call_args[0][4])
     remote_file = str(scp_init_mock.call_args[0][4])
     remote_file = str(scp_init_mock.call_args[0][4])
     self.assertEqual(input_file, "PasswordFile")
     self.assertEqual(input_file, "PasswordFile")
     self.assertEqual(remote_file, "PasswordFile")
     self.assertEqual(remote_file, "PasswordFile")
-    command = str(ssh_init_mock.call_args[0][3])
+    command = str(ssh_init_mock.call_args[0][4])
     self.assertEqual(command, "chmod 600 PasswordFile")
     self.assertEqual(command, "chmod 600 PasswordFile")
     # Another order
     # Another order
     expected1 = {"exitstatus": 0, "log": "log0", "errormsg": "errorMsg"}
     expected1 = {"exitstatus": 0, "log": "log0", "errormsg": "errorMsg"}
@@ -688,7 +688,7 @@ class TestBootstrap(TestCase):
   @patch.object(BootstrapDefault, "getPasswordFile")
   @patch.object(BootstrapDefault, "getPasswordFile")
   def test_changePasswordFileModeOnHost(self, getPasswordFile_mock, write_mock,
   def test_changePasswordFileModeOnHost(self, getPasswordFile_mock, write_mock,
                                         run_mock, init_mock):
                                         run_mock, init_mock):
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                "setupAgentFile", "ambariServer", "centos6",
                                "setupAgentFile", "ambariServer", "centos6",
                                None, "8440", "root")
                                None, "8440", "root")
     bootstrap_obj = Bootstrap("hostname", shared_state)
     bootstrap_obj = Bootstrap("hostname", shared_state)
@@ -698,14 +698,14 @@ class TestBootstrap(TestCase):
     run_mock.return_value = expected
     run_mock.return_value = expected
     res = bootstrap_obj.changePasswordFileModeOnHost()
     res = bootstrap_obj.changePasswordFileModeOnHost()
     self.assertEquals(res, expected)
     self.assertEquals(res, expected)
-    command = str(init_mock.call_args[0][3])
+    command = str(init_mock.call_args[0][4])
     self.assertEqual(command, "chmod 600 PasswordFile")
     self.assertEqual(command, "chmod 600 PasswordFile")
 
 
 
 
   @patch.object(HostLog, "write")
   @patch.object(HostLog, "write")
   def test_try_to_execute(self, write_mock):
   def test_try_to_execute(self, write_mock):
     expected = 43
     expected = 43
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                "setupAgentFile", "ambariServer", "centos6",
                                "setupAgentFile", "ambariServer", "centos6",
                                None, "8440", "root")
                                None, "8440", "root")
     bootstrap_obj = Bootstrap("hostname", shared_state)
     bootstrap_obj = Bootstrap("hostname", shared_state)
@@ -738,7 +738,7 @@ class TestBootstrap(TestCase):
   @patch("logging.error")
   @patch("logging.error")
   def test_run(self, error_mock, warn_mock, write_mock, createDoneFile_mock,
   def test_run(self, error_mock, warn_mock, write_mock, createDoneFile_mock,
                hasPassword_mock, try_to_execute_mock):
                hasPassword_mock, try_to_execute_mock):
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                "setupAgentFile", "ambariServer", "centos6",
                                "setupAgentFile", "ambariServer", "centos6",
                                None, "8440", "root")
                                None, "8440", "root")
     bootstrap_obj = Bootstrap("hostname", shared_state)
     bootstrap_obj = Bootstrap("hostname", shared_state)
@@ -810,7 +810,7 @@ class TestBootstrap(TestCase):
   @patch.object(BootstrapDefault, "createDoneFile")
   @patch.object(BootstrapDefault, "createDoneFile")
   @patch.object(HostLog, "write")
   @patch.object(HostLog, "write")
   def test_interruptBootstrap(self, write_mock, createDoneFile_mock):
   def test_interruptBootstrap(self, write_mock, createDoneFile_mock):
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                "setupAgentFile", "ambariServer", "centos6",
                                "setupAgentFile", "ambariServer", "centos6",
                                None, "8440", "root")
                                None, "8440", "root")
     bootstrap_obj = Bootstrap("hostname", shared_state)
     bootstrap_obj = Bootstrap("hostname", shared_state)
@@ -827,7 +827,7 @@ class TestBootstrap(TestCase):
   @patch.object(BootstrapDefault, "getStatus")
   @patch.object(BootstrapDefault, "getStatus")
   def test_PBootstrap(self, getStatus_mock, interruptBootstrap_mock, start_mock,
   def test_PBootstrap(self, getStatus_mock, interruptBootstrap_mock, start_mock,
                       info_mock, warn_mock, time_mock, sleep_mock):
                       info_mock, warn_mock, time_mock, sleep_mock):
-    shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir",
+    shared_state = SharedState("root", "123", "sshkey_file", "scriptDir", "bootdir",
                                "setupAgentFile", "ambariServer", "centos6",
                                "setupAgentFile", "ambariServer", "centos6",
                                None, "8440", "root")
                                None, "8440", "root")
     n = 180
     n = 180

+ 2 - 0
ambari-web/app/controllers/wizard.js

@@ -616,6 +616,7 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, App.ThemesMappingM
     sshKey: "", //string
     sshKey: "", //string
     bootRequestId: null, //string
     bootRequestId: null, //string
     sshUser: "root", //string
     sshUser: "root", //string
+    sshPort: "22",
     agentUser: "root" //string
     agentUser: "root" //string
   },
   },
 
 
@@ -628,6 +629,7 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, App.ThemesMappingM
     sshKey: "", //string
     sshKey: "", //string
     bootRequestId: null, //string
     bootRequestId: null, //string
     sshUser: "", //string
     sshUser: "", //string
+    sshPort: "22",
     agentUser: "" //string
     agentUser: "" //string
   },
   },
 
 

+ 22 - 3
ambari-web/app/controllers/wizard/step2_controller.js

@@ -93,6 +93,14 @@ App.WizardStep2Controller = Em.Controller.extend({
     return this.get('content.installOptions.sshUser');
     return this.get('content.installOptions.sshUser');
   }.property('content.installOptions.sshUser'),
   }.property('content.installOptions.sshUser'),
 
 
+  /**
+   * "Shortcut" to <code>content.installOptions.sshPort</code>
+   * @type {string}
+   */
+  sshPort: function () {
+    return this.get('content.installOptions.sshPort');
+  }.property('content.installOptions.sshPort'),
+
   /**
   /**
    * "Shortcut" to <code>content.installOptions.agentUser</code>
    * "Shortcut" to <code>content.installOptions.agentUser</code>
    * @type {string}
    * @type {string}
@@ -147,6 +155,17 @@ App.WizardStep2Controller = Em.Controller.extend({
     return null;
     return null;
   }.property('sshUser', 'useSSH', 'hasSubmitted', 'manualInstall'),
   }.property('sshUser', 'useSSH', 'hasSubmitted', 'manualInstall'),
 
 
+  /**
+   * Error-message if <code>sshPort</code> is empty, null otherwise
+   * @type {string|null}
+   */
+  sshPortError: function () {
+    if (this.get('manualInstall') === false && this.get('useSSH') && Em.isEmpty(this.get('sshPort').trim() ))  {
+      return Em.I18n.t('installer.step2.sshPort.required');
+    }
+    return null;
+  }.property('sshPort', 'useSSH', 'hasSubmitted', 'manualInstall'),
+
   /**
   /**
    * Error-message if <code>agentUser</code> is empty, null otherwise
    * Error-message if <code>agentUser</code> is empty, null otherwise
    * @type {string|null}
    * @type {string|null}
@@ -163,8 +182,8 @@ App.WizardStep2Controller = Em.Controller.extend({
    * @type {bool}
    * @type {bool}
    */
    */
   isSubmitDisabled: function () {
   isSubmitDisabled: function () {
-    return (this.get('hostsError') || this.get('sshKeyError') || this.get('sshUserError') || this.get('agentUserError'));
-  }.property('hostsError', 'sshKeyError', 'sshUserError', 'agentUserError'),
+    return (this.get('hostsError') || this.get('sshKeyError') || this.get('sshUserError') || this.get('sshPortError') || this.get('agentUserError'));
+  }.property('hostsError', 'sshKeyError', 'sshUserError', 'sshPortError', 'agentUserError'),
 
 
   installedHostNames: function () {
   installedHostNames: function () {
     var installedHostsName = [];
     var installedHostsName = [];
@@ -292,7 +311,7 @@ App.WizardStep2Controller = Em.Controller.extend({
       this.set('hostsError', Em.I18n.t('installer.step2.hostName.error.already_installed'));
       this.set('hostsError', Em.I18n.t('installer.step2.hostName.error.already_installed'));
     }
     }
 
 
-    if (this.get('hostsError') || this.get('sshUserError') || this.get('agentUserError') || this.get('sshKeyError')) {
+    if (this.get('hostsError') || this.get('sshUserError') || this.get('sshPortError') || this.get('agentUserError') || this.get('sshKeyError')) {
       return false;
       return false;
     }
     }
 
 

+ 2 - 0
ambari-web/app/controllers/wizard/step3_controller.js

@@ -278,6 +278,7 @@ App.WizardStep3Controller = Em.Controller.extend(App.ReloadPopupMixin, {
         'sshKey': this.get('content.installOptions.sshKey'),
         'sshKey': this.get('content.installOptions.sshKey'),
         'hosts': this.getBootstrapHosts(),
         'hosts': this.getBootstrapHosts(),
         'user': this.get('content.installOptions.sshUser'),
         'user': this.get('content.installOptions.sshUser'),
+        'sshPort': this.get('content.installOptions.sshPort'),
         'userRunAs': App.get('supports.customizeAgentUserAccount') ? this.get('content.installOptions.agentUser') : 'root'
         'userRunAs': App.get('supports.customizeAgentUserAccount') ? this.get('content.installOptions.agentUser') : 'root'
     });
     });
     App.router.get(this.get('content.controllerName')).launchBootstrap(bootStrapData, function (requestId) {
     App.router.get(this.get('content.controllerName')).launchBootstrap(bootStrapData, function (requestId) {
@@ -461,6 +462,7 @@ App.WizardStep3Controller = Em.Controller.extend(App.ReloadPopupMixin, {
         'sshKey': this.get('content.installOptions.sshKey'),
         'sshKey': this.get('content.installOptions.sshKey'),
         'hosts': hosts.mapProperty('name'),
         'hosts': hosts.mapProperty('name'),
         'user': this.get('content.installOptions.sshUser'),
         'user': this.get('content.installOptions.sshUser'),
+        'sshPort': this.get('content.installOptions.sshPort'),
         'userRunAs': App.get('supports.customizeAgentUserAccount') ? this.get('content.installOptions.agentUser') : 'root'
         'userRunAs': App.get('supports.customizeAgentUserAccount') ? this.get('content.installOptions.agentUser') : 'root'
       });
       });
     this.set('numPolls', 0);
     this.set('numPolls', 0);

+ 3 - 0
ambari-web/app/messages.js

@@ -586,6 +586,9 @@ Em.I18n.translations = {
   'installer.step2.sshUser.toolTip':'The user account used to install the Ambari Agent on the target host(s) via SSH. This user must be set up with passwordless SSH and sudo access on all the target host(s)',
   'installer.step2.sshUser.toolTip':'The user account used to install the Ambari Agent on the target host(s) via SSH. This user must be set up with passwordless SSH and sudo access on all the target host(s)',
   'installer.step2.sshUser.placeholder':'Enter user name',
   'installer.step2.sshUser.placeholder':'Enter user name',
   'installer.step2.sshUser.required':'User name is required',
   'installer.step2.sshUser.required':'User name is required',
+  'installer.step2.sshPort':'SSH Port Number',
+  'installer.step2.sshPort.toolTip':'SSH Port Number',
+  'installer.step2.sshPort.required':'SSH Port Number is required.',
   'installer.step2.agentUser':'Ambari Agent User Account',
   'installer.step2.agentUser':'Ambari Agent User Account',
   'installer.step2.agentUser.toolTip':'The user account used to run the Ambari Agent daemon on the target host(s). This user must be set up with passwordless sudo access on all the target host(s)',
   'installer.step2.agentUser.toolTip':'The user account used to run the Ambari Agent daemon on the target host(s). This user must be set up with passwordless sudo access on all the target host(s)',
   'installer.step2.bootStrap.error':'Errors were encountered while setting up Ambari Agents on the hosts.',
   'installer.step2.bootStrap.error':'Errors were encountered while setting up Ambari Agents on the hosts.',

+ 4 - 0
ambari-web/app/styles/application.less

@@ -719,6 +719,10 @@ h1 {
       margin-right: 10px;
       margin-right: 10px;
       padding-top: 5px;
       padding-top: 5px;
     }
     }
+    .ssh-port {
+      margin-right: 10px;
+      padding-top: 5px;
+    }
     #targetHosts {
     #targetHosts {
       .target-hosts-input {
       .target-hosts-input {
         padding-left: 18px;
         padding-left: 18px;

+ 12 - 0
ambari-web/app/templates/wizard/step2.hbs

@@ -90,6 +90,18 @@
               {{/if}}
               {{/if}}
             </div>
             </div>
           </div>
           </div>
+           <div class="row-fluid">
+                <label rel="tooltip" {{translateAttr title="installer.step2.sshPort.toolTip"}} class="ssh-port pull-left span4">
+                    {{t installer.step2.sshPort}}
+                </label>
+
+                <div {{bindAttr class="sshPortError:error :control-group"}}>
+                    {{view view.textFieldView valueBinding="content.installOptions.sshPort" isEnabledBinding="content.installOptions.useSsh" }}
+                    {{#if sshPortError}}
+                        <span class="help-inline">{{sshPortError}}</span>
+                    {{/if}}
+                </div>
+           </div>
           {{#if App.supports.customizeAgentUserAccount}}
           {{#if App.supports.customizeAgentUserAccount}}
             <div class="row-fluid">
             <div class="row-fluid">
               <label rel="tooltip" {{translateAttr title="installer.step2.agentUser.toolTip"}} class="ssh-user pull-left span4">
               <label rel="tooltip" {{translateAttr title="installer.step2.agentUser.toolTip"}} class="ssh-user pull-left span4">

+ 45 - 0
ambari-web/test/controllers/wizard/step2_test.js

@@ -29,21 +29,25 @@ describe('App.WizardStep2Controller', function () {
     {
     {
       manualInstall: false,
       manualInstall: false,
       user: '',
       user: '',
+      sshPort:'',
       e: ''
       e: ''
     },
     },
     {
     {
       manualInstall: true,
       manualInstall: true,
       user: '',
       user: '',
+      sshPort:'',
       e: null
       e: null
     },
     },
     {
     {
       manualInstall: true,
       manualInstall: true,
       user: 'nobody',
       user: 'nobody',
+      sshPort:'123',
       e: null
       e: null
     },
     },
     {
     {
       manualInstall: false,
       manualInstall: false,
       user: 'nobody',
       user: 'nobody',
+      sshPort:'123',
       e: null
       e: null
     }
     }
   ]);
   ]);
@@ -100,6 +104,15 @@ describe('App.WizardStep2Controller', function () {
     });
     });
   });
   });
 
 
+  describe('#sshPort', function() {
+      it('should be equal to content.installOptions.sshPort', function() {
+          var controller = App.WizardStep2Controller.create({content: {installOptions: {sshPort: '123'}}});
+          expect(controller.get('sshPort')).to.equal('123');
+          controller.set('content.installOptions.sshPort', '321');
+          expect(controller.get('sshPort')).to.equal('321');
+      });
+  });
+
   describe('#agentUser', function() {
   describe('#agentUser', function() {
     it('should be equal to content.installOptions.agentUser', function() {
     it('should be equal to content.installOptions.agentUser', function() {
       var controller = App.WizardStep2Controller.create({content: {installOptions: {agentUser: '123'}}});
       var controller = App.WizardStep2Controller.create({content: {installOptions: {agentUser: '123'}}});
@@ -285,6 +298,22 @@ describe('App.WizardStep2Controller', function () {
 
 
   });
   });
 
 
+  describe('#sshPortError', function () {
+
+      userErrorTests.forEach(function(test) {
+          it('', function() {
+              var controller = App.WizardStep2Controller.create({content: {installOptions: {manualInstall: test.manualInstall, sshPort: test.sshPort}}});
+              if(Em.isNone(test.e)) {
+                  expect(controller.get('sshPortError')).to.equal(null);
+              }
+              else {
+                  expect(controller.get('sshPortError').length).to.be.above(2);
+              }
+          });
+      });
+
+  });
+
   describe('#agentUserError', function () {
   describe('#agentUserError', function () {
 
 
     afterEach(function () {
     afterEach(function () {
@@ -379,6 +408,15 @@ describe('App.WizardStep2Controller', function () {
       expect(controller.evaluateStep()).to.equal(false);
       expect(controller.evaluateStep()).to.equal(false);
     });
     });
 
 
+    it('should return false if sshPortError is not empty', function () {
+        var controller = App.WizardStep2Controller.create({
+            hostNames: 'apache.ambari',
+            parseHostNamesAsPatternExpression: Em.K
+        });
+        controller.reopen({sshPortError: 'error'});
+        expect(controller.evaluateStep()).to.equal(false);
+    });
+
     it('should return false if agentUserError is not empty', function () {
     it('should return false if agentUserError is not empty', function () {
       var controller = App.WizardStep2Controller.create({
       var controller = App.WizardStep2Controller.create({
         hostNames: 'apache.ambari',
         hostNames: 'apache.ambari',
@@ -487,6 +525,7 @@ describe('App.WizardStep2Controller', function () {
       hostsError: '',
       hostsError: '',
       sshKeyError: '',
       sshKeyError: '',
       sshUserError: '',
       sshUserError: '',
+      sshPortError: '',
       agentUserError: ''
       agentUserError: ''
     });
     });
 
 
@@ -512,6 +551,12 @@ describe('App.WizardStep2Controller', function () {
       controller.set('sshUserError', '');
       controller.set('sshUserError', '');
       expect(controller.get('isSubmitDisabled').length).to.above(0);
       expect(controller.get('isSubmitDisabled').length).to.above(0);
     });
     });
+
+    it('should return value if sshPortError is not empty', function () {
+        controller.set('sshPortError', 'error');
+        controller.set('agentUserError', '');
+        expect(controller.get('isSubmitDisabled').length).to.above(0);
+    });
   });
   });
 
 
   describe('#installedHostsPopup', function() {
   describe('#installedHostsPopup', function() {

+ 4 - 0
ambari-web/test/controllers/wizard/step3_test.js

@@ -558,6 +558,7 @@ describe('App.WizardStep3Controller', function () {
             installOptions: {
             installOptions: {
               sshKey: 'key',
               sshKey: 'key',
               sshUser: 'root',
               sshUser: 'root',
+              sshPort: '123',
               agentUser: 'user'
               agentUser: 'user'
             },
             },
             hosts: { "host0": { "name": "host0" }, "host1": { "name": "host1" } }
             hosts: { "host0": { "name": "host0" }, "host1": { "name": "host1" } }
@@ -571,6 +572,7 @@ describe('App.WizardStep3Controller', function () {
           sshKey: 'key',
           sshKey: 'key',
           hosts: ['host0', 'host1'],
           hosts: ['host0', 'host1'],
           user: 'root',
           user: 'root',
+          sshPort: '123',
           userRunAs: item.userRunAs
           userRunAs: item.userRunAs
         }));
         }));
       });
       });
@@ -2410,6 +2412,7 @@ describe('App.WizardStep3Controller', function () {
           installOptions: {
           installOptions: {
             sshKey: 'key',
             sshKey: 'key',
             sshUser: 'root',
             sshUser: 'root',
+            sshPort: '123',
             agentUser: 'user'
             agentUser: 'user'
           },
           },
           hosts: { "host0": { "name": "host0" }, "host1": { "name": "host1" } },
           hosts: { "host0": { "name": "host0" }, "host1": { "name": "host1" } },
@@ -2436,6 +2439,7 @@ describe('App.WizardStep3Controller', function () {
           sshKey: 'key',
           sshKey: 'key',
           hosts: ['host0', 'host1'],
           hosts: ['host0', 'host1'],
           user: 'root',
           user: 'root',
+          sshPort: '123',
           userRunAs: item.userRunAs
           userRunAs: item.userRunAs
         }));
         }));
       });
       });