Repository: ambari Updated Branches: refs/heads/trunk e837d4f08 -> b8388e12b
http://git-wip-us.apache.org/repos/asf/ambari/blob/b8388e12/ambari-server/src/test/python/TestBootstrap.py.orig ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/python/TestBootstrap.py.orig b/ambari-server/src/test/python/TestBootstrap.py.orig new file mode 100644 index 0000000..792d99d --- /dev/null +++ b/ambari-server/src/test/python/TestBootstrap.py.orig @@ -0,0 +1,879 @@ +''' +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +''' + +from stacks.utils.RMFTestCase import * +import bootstrap +import time +import subprocess +import os +import logging +import tempfile +import pprint + +from ambari_commons.os_check import OSCheck +from bootstrap import PBootstrap, Bootstrap, BootstrapDefault, SharedState, HostLog, SCP, SSH +from unittest import TestCase +from subprocess import Popen +from bootstrap import AMBARI_PASSPHRASE_VAR_NAME +from mock.mock import MagicMock, call +from mock.mock import patch +from mock.mock import create_autospec +from only_for_platform import not_for_platform, os_distro_value, PLATFORM_WINDOWS + +@not_for_platform(PLATFORM_WINDOWS) +class TestBootstrap(TestCase): + + def setUp(self): + logging.basicConfig(level=logging.ERROR) + + + def test_getRemoteName(self): + shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "centos6", None, "8440", "root") + res = bootstrap_obj = Bootstrap("hostname", shared_state) + utime1 = 1234 + utime2 = 12345 + bootstrap_obj.getUtime = MagicMock(return_value=utime1) + remote1 = bootstrap_obj.getRemoteName("/tmp/setupAgent.sh") + self.assertEquals(remote1, "/tmp/setupAgent{0}.sh".format(utime1)) + + bootstrap_obj.getUtime.return_value=utime2 + remote1 = bootstrap_obj.getRemoteName("/tmp/setupAgent.sh") + self.assertEquals(remote1, "/tmp/setupAgent{0}.sh".format(utime1)) + + remote2 = bootstrap_obj.getRemoteName("/tmp/host_pass") + self.assertEquals(remote2, "/tmp/host_pass{0}".format(utime2)) + + + # TODO: Test bootstrap timeout + + # TODO: test_return_error_message_for_missing_sudo_package + + def test_getAmbariPort(self): + shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "centos6", + None, "8440", "root") + bootstrap_obj = Bootstrap("hostname", shared_state) + self.assertEquals(bootstrap_obj.getAmbariPort(),"8440") + shared_state.server_port = None + bootstrap_obj = Bootstrap("hostname", shared_state) + self.assertEquals(bootstrap_obj.getAmbariPort(),"null") + + + @patch.object(subprocess, "Popen") + @patch("sys.stderr") + @patch("sys.exit") + @patch.object(PBootstrap, "run") + @patch("os.path.dirname") + @patch("os.path.realpath") + 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", \ + "centos6", "1.1.1", "8440", "root", "passwordfile"]) + self.assertTrue(run_mock.called) + run_mock.reset_mock() + bootstrap.main(["bootstrap.py", "hostname,hostname2", "/tmp/bootstrap", "root", "sshkey_file", "setupAgent.py", "ambariServer", \ + "centos6", "1.1.1", "8440", "root", None]) + self.assertTrue(run_mock.called) + run_mock.reset_mock() + def side_effect(retcode): + raise Exception(retcode, "sys.exit") + exit_mock.side_effect = side_effect + try: + bootstrap.main(["bootstrap.py","hostname,hostname2", "/tmp/bootstrap"]) + self.fail("sys.exit(2)") + except Exception: + # Expected + pass + self.assertTrue(exit_mock.called) + + + @patch("os.environ") + def test_getRunSetupWithPasswordCommand(self, environ_mock): + shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "centos6", + None, "8440", "root") + environ_mock.__getitem__.return_value = "TEST_PASSPHRASE" + bootstrap_obj = Bootstrap("hostname", shared_state) + utime = 1234 + bootstrap_obj.getUtime = MagicMock(return_value=utime) + ret = bootstrap_obj.getRunSetupWithPasswordCommand("hostname") + expected = "sudo -S python /var/lib/ambari-agent/data/tmp/setupAgent{0}.py hostname TEST_PASSPHRASE " \ + "ambariServer root 8440 < /var/lib/ambari-agent/data/tmp/host_pass{0}".format(utime) + self.assertEquals(ret, expected) + + + def test_generateRandomFileName(self): + shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "centos6", + None, "8440", "root") + bootstrap_obj = Bootstrap("hostname", shared_state) + self.assertTrue(bootstrap_obj.generateRandomFileName(None) == bootstrap_obj.getUtime()) + + + + @patch.object(OSCheck, "is_redhat_family") + @patch.object(OSCheck, "is_suse_family") + def test_getRepoDir(self, is_suse_family, is_redhat_family): + shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "centos6", + None, "8440", "root") + bootstrap_obj = Bootstrap("hostname", shared_state) + # Suse + is_redhat_family.return_value = False + is_suse_family.return_value = True + res = bootstrap_obj.getRepoDir() + self.assertEquals(res, "/etc/zypp/repos.d") + # non-Suse + is_suse_family.return_value = False + is_redhat_family.return_value = True + res = bootstrap_obj.getRepoDir() + self.assertEquals(res, "/etc/yum.repos.d") + + def test_getSetupScript(self): + shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "centos6", + None, "8440", "root") + bootstrap_obj = Bootstrap("hostname", shared_state) + self.assertEquals(bootstrap_obj.shared_state.script_dir, "scriptDir") + + + def test_run_setup_agent_command_ends_with_project_version(self): + os.environ[AMBARI_PASSPHRASE_VAR_NAME] = "" + version = "1.1.1" + shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "centos6", + version, "8440", "root") + bootstrap_obj = Bootstrap("hostname", shared_state) + runSetupCommand = bootstrap_obj.getRunSetupCommand("hostname") + self.assertTrue(runSetupCommand.endswith(version + " 8440")) + + + def test_agent_setup_command_without_project_version(self): + os.environ[AMBARI_PASSPHRASE_VAR_NAME] = "" + version = None + shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "centos6", + version, "8440", "root") + bootstrap_obj = Bootstrap("hostname", shared_state) + runSetupCommand = bootstrap_obj.getRunSetupCommand("hostname") + self.assertTrue(runSetupCommand.endswith(" 8440")) + + + # TODO: test_os_check_fail_fails_bootstrap_execution + + + def test_host_log(self): + tmp_file, tmp_filename = tempfile.mkstemp() + dummy_log = HostLog(tmp_filename) + # First write to log + dummy_log.write("a\nb\nc") + # Read it + with open(tmp_filename) as f: + s = f.read() + etalon = "a\nb\nc\n" + self.assertEquals(s, etalon) + # Next write + dummy_log.write("Yet another string") + # Read it + with open(tmp_filename) as f: + s = f.read() + etalon = "a\nb\nc\nYet another string\n" + self.assertEquals(s, etalon) + # Should not append line end if it already exists + dummy_log.write("line break->\n") + # Read it + with open(tmp_filename) as f: + s = f.read() + etalon = "a\nb\nc\nYet another string\nline break->\n" + self.assertEquals(s, etalon) + # Cleanup + os.unlink(tmp_filename) + + + @patch("subprocess.Popen") + def test_SCP(self, popenMock): + params = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "centos6", + "1.2.1", "8440", "root") + host_log_mock = MagicMock() + log = {'text': ""} + def write_side_effect(text): + log['text'] = log['text'] + text + + host_log_mock.write.side_effect = write_side_effect + scp = SCP(params.user, params.sshkey_file, "dummy-host", "src/file", + "dst/file", params.bootdir, host_log_mock) + log_sample = "log_sample" + error_sample = "error_sample" + # Successful run + process = MagicMock() + popenMock.return_value = process + process.communicate.return_value = (log_sample, error_sample) + process.returncode = 0 + + retcode = scp.run() + + self.assertTrue(popenMock.called) + self.assertTrue(log_sample in log['text']) + self.assertTrue(error_sample in log['text']) + command_str = str(popenMock.call_args[0][0]) + self.assertEquals(command_str, "['scp', '-r', '-o', 'ConnectTimeout=60', '-o', " + "'BatchMode=yes', '-o', 'StrictHostKeyChecking=no', '-i', 'sshkey_file'," + " 'src/file', 'root@dummy-host:dst/file']") + self.assertEqual(retcode["exitstatus"], 0) + + log['text'] = "" + #unsuccessfull run + process.returncode = 1 + + retcode = scp.run() + + self.assertTrue(log_sample in log['text']) + self.assertTrue(error_sample in log['text']) + self.assertEqual(retcode["exitstatus"], 1) + + + @patch("subprocess.Popen") + def test_SSH(self, popenMock): + params = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "centos6", + "1.2.1", "8440", "root") + host_log_mock = MagicMock() + log = {'text': ""} + def write_side_effect(text): + log['text'] = log['text'] + text + + host_log_mock.write.side_effect = write_side_effect + ssh = SSH(params.user, params.sshkey_file, "dummy-host", "dummy-command", + params.bootdir, host_log_mock) + log_sample = "log_sample" + error_sample = "error_sample" + # Successful run + process = MagicMock() + popenMock.return_value = process + process.communicate.return_value = (log_sample, error_sample) + process.returncode = 0 + + retcode = ssh.run() + + self.assertTrue(popenMock.called) + self.assertTrue(log_sample in log['text']) + self.assertTrue(error_sample in log['text']) + command_str = str(popenMock.call_args[0][0]) + self.assertEquals(command_str, "['ssh', '-o', 'ConnectTimeOut=60', '-o', " + "'StrictHostKeyChecking=no', '-o', 'BatchMode=yes', '-tt', '-i', " + "'sshkey_file', 'root@dummy-host', 'dummy-command']") + self.assertEqual(retcode["exitstatus"], 0) + + log['text'] = "" + #unsuccessfull run + process.returncode = 1 + + retcode = ssh.run() + + self.assertTrue(log_sample in log['text']) + self.assertTrue(error_sample in log['text']) + self.assertEqual(retcode["exitstatus"], 1) + + log['text'] = "" + # unsuccessful run with error message + process.returncode = 1 + + dummy_error_message = "dummy_error_message" + ssh = SSH(params.user, params.sshkey_file, "dummy-host", "dummy-command", + params.bootdir, host_log_mock, errorMessage= dummy_error_message) + retcode = ssh.run() + + self.assertTrue(log_sample in log['text']) + self.assertTrue(error_sample in log['text']) + self.assertTrue(dummy_error_message in log['text']) + self.assertEqual(retcode["exitstatus"], 1) + + + def test_getOsCheckScript(self): + shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "centos6", + None, "8440", "root") + bootstrap_obj = Bootstrap("hostname", shared_state) + ocs = bootstrap_obj.getOsCheckScript() + self.assertEquals(ocs, "scriptDir/os_check_type.py") + + + @patch.object(BootstrapDefault, "getRemoteName") + def test_getOsCheckScriptRemoteLocation(self, getRemoteName_mock): + shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "centos6", + None, "8440", "root") + bootstrap_obj = Bootstrap("hostname", shared_state) + v = "/tmp/os_check_type1374259902.py" + getRemoteName_mock.return_value = v + ocs = bootstrap_obj.getOsCheckScriptRemoteLocation() + self.assertEquals(ocs, v) + + + @patch.object(BootstrapDefault, "is_suse") + def test_getRepoFile(self, is_suse_mock): + shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "centos6", + None, "8440", "root") + bootstrap_obj = Bootstrap("hostname", shared_state) + is_suse_mock.return_value = False + rf = bootstrap_obj.getRepoFile() + self.assertEquals(rf, "/etc/yum.repos.d/ambari.repo") + + + @patch.object(SSH, "__init__") + @patch.object(SSH, "run") + @patch.object(HostLog, "write") + def test_createTargetDir(self, write_mock, run_mock, + init_mock): + shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "centos6", + None, "8440", "root") + bootstrap_obj = Bootstrap("hostname", shared_state) + expected = 42 + init_mock.return_value = None + run_mock.return_value = expected + res = bootstrap_obj.createTargetDir() + self.assertEquals(res, expected) + command = str(init_mock.call_args[0][3]) + self.assertEqual(command, + "sudo mkdir -p /var/lib/ambari-agent/data/tmp ; " + "sudo chown -R root /var/lib/ambari-agent/data/tmp ; " + "sudo chmod 755 /var/lib/ambari-agent ; " + "sudo chmod 755 /var/lib/ambari-agent/data ; " + "sudo chmod 777 /var/lib/ambari-agent/data/tmp") + + @patch.object(BootstrapDefault, "getOsCheckScript") + @patch.object(BootstrapDefault, "getOsCheckScriptRemoteLocation") + @patch.object(SCP, "__init__") + @patch.object(SCP, "run") + @patch.object(HostLog, "write") + def test_copyOsCheckScript(self, write_mock, run_mock, init_mock, + getOsCheckScriptRemoteLocation_mock, getOsCheckScript_mock): + shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "centos6", + None, "8440", "root") + bootstrap_obj = Bootstrap("hostname", shared_state) + getOsCheckScript_mock.return_value = "OsCheckScript" + getOsCheckScriptRemoteLocation_mock.return_value = "OsCheckScriptRemoteLocation" + expected = 42 + init_mock.return_value = None + run_mock.return_value = expected + res = bootstrap_obj.copyOsCheckScript() + self.assertEquals(res, expected) + input_file = str(init_mock.call_args[0][3]) + remote_file = str(init_mock.call_args[0][4]) + self.assertEqual(input_file, "OsCheckScript") + self.assertEqual(remote_file, "OsCheckScriptRemoteLocation") + + + @patch.object(BootstrapDefault, "getRemoteName") + @patch.object(BootstrapDefault, "hasPassword") + @patch.object(OSCheck, "is_suse_family") + @patch.object(OSCheck, "is_ubuntu_family") + @patch.object(OSCheck, "is_redhat_family") + 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", + "setupAgentFile", "ambariServer", "centos6", + None, "8440", "root") + is_redhat_family.return_value = True + is_ubuntu_family.return_value = False + is_suse_family.return_value = False + bootstrap_obj = Bootstrap("hostname", shared_state) + # Without password + hasPassword_mock.return_value = False + getRemoteName_mock.return_value = "RemoteName" + rf = bootstrap_obj.getMoveRepoFileCommand("target") + self.assertEquals(rf, "sudo mv RemoteName target/ambari.repo") + # With password + hasPassword_mock.return_value = True + getRemoteName_mock.return_value = "RemoteName" + rf = bootstrap_obj.getMoveRepoFileCommand("target") + self.assertEquals(rf, "sudo -S mv RemoteName target/ambari.repo < RemoteName") + + @patch("os.path.exists") + @patch.object(OSCheck, "is_suse_family") + @patch.object(OSCheck, "is_ubuntu_family") + @patch.object(OSCheck, "is_redhat_family") + @patch.object(BootstrapDefault, "getMoveRepoFileCommand") + @patch.object(BootstrapDefault, "getRepoDir") + @patch.object(BootstrapDefault, "getRepoFile") + @patch.object(BootstrapDefault, "getRemoteName") + @patch.object(SCP, "__init__") + @patch.object(SCP, "run") + @patch.object(SSH, "__init__") + @patch.object(SSH, "run") + @patch.object(HostLog, "write") + def test_copyNeededFiles(self, write_mock, ssh_run_mock, ssh_init_mock, + scp_run_mock, scp_init_mock, + getRemoteName_mock, getRepoFile_mock, getRepoDir, + getMoveRepoFileCommand, is_redhat_family, is_ubuntu_family, is_suse_family, + os_path_exists_mock): + # + # Ambari repo file exists + # + def os_path_exists_side_effect(*args, **kwargs): + if args[0] == getRepoFile_mock(): + return True + else: + return False + + os_path_exists_mock.side_effect = os_path_exists_side_effect + os_path_exists_mock.return_value = None + + shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "centos6", + None, "8440", "root") + is_redhat_family.return_value = True + is_ubuntu_family.return_value = False + is_suse_family.return_value = False + bootstrap_obj = Bootstrap("hostname", shared_state) + getMoveRepoFileCommand.return_value = "MoveRepoFileCommand" + getRepoDir.return_value = "RepoDir" + getRemoteName_mock.return_value = "RemoteName" + getRepoFile_mock.return_value = "RepoFile" + expected1 = {"exitstatus": 42, "log": "log42", "errormsg": "errorMsg"} + expected2 = {"exitstatus": 17, "log": "log17", "errormsg": "errorMsg"} + expected3 = {"exitstatus": 1, "log": "log1", "errormsg": "errorMsg"} + expected4 = {"exitstatus": 17, "log": "log17", "errormsg": "errorMsg"} + scp_init_mock.return_value = None + ssh_init_mock.return_value = None + # Testing max retcode return + scp_run_mock.side_effect = [expected1, expected3] + ssh_run_mock.side_effect = [expected2, expected4] + res = bootstrap_obj.copyNeededFiles() + 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]) + self.assertEqual(input_file, "setupAgentFile") + self.assertEqual(remote_file, "RemoteName") + command = str(ssh_init_mock.call_args[0][3]) + self.assertEqual(command, "sudo chmod 644 RepoFile") + # Another order + expected1 = {"exitstatus": 0, "log": "log0", "errormsg": "errorMsg"} + expected2 = {"exitstatus": 17, "log": "log17", "errormsg": "errorMsg"} + expected3 = {"exitstatus": 1, "log": "log1", "errormsg": "errorMsg"} + expected4 = {"exitstatus": 17, "log": "log17", "errormsg": "errorMsg"} + scp_run_mock.side_effect = [expected1, expected3] + ssh_run_mock.side_effect = [expected2, expected4] + res = bootstrap_obj.copyNeededFiles() + self.assertEquals(res, expected2["exitstatus"]) + # yet another order + expected1 = {"exitstatus": 33, "log": "log33", "errormsg": "errorMsg"} + expected2 = {"exitstatus": 17, "log": "log17", "errormsg": "errorMsg"} + expected3 = {"exitstatus": 42, "log": "log42", "errormsg": "errorMsg"} + expected4 = {"exitstatus": 17, "log": "log17", "errormsg": "errorMsg"} + scp_run_mock.side_effect = [expected1, expected3] + ssh_run_mock.side_effect = [expected2, expected4] + res = bootstrap_obj.copyNeededFiles() + self.assertEquals(res, expected3["exitstatus"]) + + # + #Ambari repo file does not exist + # + os_path_exists_mock.side_effect = None + os_path_exists_mock.return_value = False + + #Expectations: + # SSH will not be called at all + # SCP will be called once for copying the setup script file + scp_run_mock.reset_mock() + ssh_run_mock.reset_mock() + expectedResult = {"exitstatus": 33, "log": "log33", "errormsg": "errorMsg"} + scp_run_mock.side_effect = [expectedResult] + res = bootstrap_obj.copyNeededFiles() + self.assertFalse(ssh_run_mock.called) + self.assertEquals(res, expectedResult["exitstatus"]) + + @patch.object(BootstrapDefault, "getOsCheckScriptRemoteLocation") + @patch.object(SSH, "__init__") + @patch.object(SSH, "run") + @patch.object(HostLog, "write") + def test_runOsCheckScript(self, write_mock, run_mock, + init_mock, getOsCheckScriptRemoteLocation_mock): + shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "centos6", + None, "8440", "root") + bootstrap_obj = Bootstrap("hostname", shared_state) + getOsCheckScriptRemoteLocation_mock.return_value = "OsCheckScriptRemoteLocation" + expected = 42 + init_mock.return_value = None + run_mock.return_value = expected + res = bootstrap_obj.runOsCheckScript() + self.assertEquals(res, expected) + command = str(init_mock.call_args[0][3]) + self.assertEqual(command, + "chmod a+x OsCheckScriptRemoteLocation && " + "env PYTHONPATH=$PYTHONPATH:/var/lib/ambari-agent/data/tmp OsCheckScriptRemoteLocation centos6") + + + @patch.object(SSH, "__init__") + @patch.object(BootstrapDefault, "getRunSetupCommand") + @patch.object(SSH, "run") + @patch.object(HostLog, "write") + def test_runSetupAgent(self, write_mock, run_mock, + getRunSetupCommand_mock, init_mock): + shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "centos6", + None, "8440", "root") + bootstrap_obj = Bootstrap("hostname", shared_state) + getRunSetupCommand_mock.return_value = "RunSetupCommand" + expected = 42 + init_mock.return_value = None + run_mock.return_value = expected + res = bootstrap_obj.runSetupAgent() + self.assertEquals(res, expected) + command = str(init_mock.call_args[0][3]) + self.assertEqual(command, "RunSetupCommand") + + + @patch.object(BootstrapDefault, "hasPassword") + @patch.object(BootstrapDefault, "getRunSetupWithPasswordCommand") + @patch.object(BootstrapDefault, "getRunSetupWithoutPasswordCommand") + def test_getRunSetupCommand(self, getRunSetupWithoutPasswordCommand_mock, + getRunSetupWithPasswordCommand_mock, + hasPassword_mock): + shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "centos6", + None, "8440", "root") + bootstrap_obj = Bootstrap("hostname", shared_state) + # With password + hasPassword_mock.return_value = True + getRunSetupWithPasswordCommand_mock.return_value = "RunSetupWithPasswordCommand" + getRunSetupWithoutPasswordCommand_mock.return_value = "RunSetupWithoutPasswordCommand" + res = bootstrap_obj.getRunSetupCommand("dummy-host") + self.assertEqual(res, "RunSetupWithPasswordCommand") + # Without password + hasPassword_mock.return_value = False + res = bootstrap_obj.getRunSetupCommand("dummy-host") + self.assertEqual(res, "RunSetupWithoutPasswordCommand") + + + @patch.object(HostLog, "write") + def test_createDoneFile(self, write_mock): + tmp_dir = tempfile.gettempdir() + shared_state = SharedState("root", "sshkey_file", "scriptDir", tmp_dir, + "setupAgentFile", "ambariServer", "centos6", + None, "8440", "root") + bootstrap_obj = Bootstrap("hostname", shared_state) + done_file = os.path.join(tmp_dir, "hostname.done") + expected = 42 + bootstrap_obj.createDoneFile(expected) + with open(done_file) as df: + res = df.read() + self.assertEqual(res, str(expected)) + os.unlink(done_file) + + @patch.object(OSCheck, "is_suse_family") + @patch.object(OSCheck, "is_ubuntu_family") + @patch.object(OSCheck, "is_redhat_family") + @patch.object(SSH, "__init__") + @patch.object(SSH, "run") + @patch.object(HostLog, "write") + 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", + "setupAgentFile", "ambariServer", "centos6", + None, "8440", "root") + bootstrap_obj = Bootstrap("hostname", shared_state) + expected = 42 + init_mock.return_value = None + run_mock.return_value = expected + is_redhat_family.return_value = True + is_ubuntu_family.return_value = False + is_suse_family.return_value = False + res = bootstrap_obj.checkSudoPackage() + self.assertEquals(res, expected) + command = str(init_mock.call_args[0][3]) + self.assertEqual(command, "rpm -qa | grep -e '^sudo\-'") + + @patch.object(OSCheck, "is_suse_family") + @patch.object(OSCheck, "is_ubuntu_family") + @patch.object(OSCheck, "is_redhat_family") + @patch.object(SSH, "__init__") + @patch.object(SSH, "run") + @patch.object(HostLog, "write") + def test_checkSudoPackageUbuntu(self, write_mock, run_mock, init_mock, + is_redhat_family, is_ubuntu_family, is_suse_family): + shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "ubuntu12", + None, "8440", "root") + is_redhat_family.return_value = False + is_ubuntu_family.return_value = True + is_suse_family.return_value = False + bootstrap_obj = Bootstrap("hostname", shared_state) + expected = 42 + init_mock.return_value = None + run_mock.return_value = expected + res = bootstrap_obj.checkSudoPackage() + self.assertEquals(res, expected) + command = str(init_mock.call_args[0][3]) + self.assertEqual(command, "dpkg --get-selections|grep -e '^sudo\s*install'") + + + @patch.object(SSH, "__init__") + @patch.object(SSH, "run") + @patch.object(HostLog, "write") + @patch.object(BootstrapDefault, "getPasswordFile") + def test_deletePasswordFile(self, getPasswordFile_mock, write_mock, run_mock, + init_mock): + shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "centos6", + None, "8440", "root") + bootstrap_obj = Bootstrap("hostname", shared_state) + expected = 42 + getPasswordFile_mock.return_value = "PasswordFile" + init_mock.return_value = None + run_mock.return_value = expected + res = bootstrap_obj.deletePasswordFile() + self.assertEquals(res, expected) + command = str(init_mock.call_args[0][3]) + self.assertEqual(command, "rm PasswordFile") + + + @patch.object(BootstrapDefault, "getPasswordFile") + @patch.object(SCP, "__init__") + @patch.object(SCP, "run") + @patch.object(SSH, "__init__") + @patch.object(SSH, "run") + @patch.object(HostLog, "write") + def test_copyPasswordFile(self, write_mock, ssh_run_mock, + ssh_init_mock, scp_run_mock, + scp_init_mock, getPasswordFile_mock): + shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "centos6", + None, "8440", "root", password_file="PasswordFile") + bootstrap_obj = Bootstrap("hostname", shared_state) + getPasswordFile_mock.return_value = "PasswordFile" + # Testing max retcode return + expected1 = {"exitstatus": 42, "log": "log42", "errormsg": "errorMsg"} + expected2 = {"exitstatus": 17, "log": "log17", "errormsg": "errorMsg"} + scp_init_mock.return_value = None + scp_run_mock.return_value = expected1 + ssh_init_mock.return_value = None + ssh_run_mock.return_value = expected2 + res = bootstrap_obj.copyPasswordFile() + 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]) + self.assertEqual(input_file, "PasswordFile") + self.assertEqual(remote_file, "PasswordFile") + command = str(ssh_init_mock.call_args[0][3]) + self.assertEqual(command, "chmod 600 PasswordFile") + # Another order + expected1 = {"exitstatus": 0, "log": "log0", "errormsg": "errorMsg"} + expected2 = {"exitstatus": 17, "log": "log17", "errormsg": "errorMsg"} + scp_run_mock.return_value = expected1 + ssh_run_mock.return_value = expected2 + + + @patch.object(SSH, "__init__") + @patch.object(SSH, "run") + @patch.object(HostLog, "write") + @patch.object(BootstrapDefault, "getPasswordFile") + def test_changePasswordFileModeOnHost(self, getPasswordFile_mock, write_mock, + run_mock, init_mock): + shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "centos6", + None, "8440", "root") + bootstrap_obj = Bootstrap("hostname", shared_state) + expected = 42 + getPasswordFile_mock.return_value = "PasswordFile" + init_mock.return_value = None + run_mock.return_value = expected + res = bootstrap_obj.changePasswordFileModeOnHost() + self.assertEquals(res, expected) + command = str(init_mock.call_args[0][3]) + self.assertEqual(command, "chmod 600 PasswordFile") + + + @patch.object(HostLog, "write") + def test_try_to_execute(self, write_mock): + expected = 43 + shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "centos6", + None, "8440", "root") + bootstrap_obj = Bootstrap("hostname", shared_state) + # Normal case + def act_normal_return_int(): + return 43 + ret = bootstrap_obj.try_to_execute(act_normal_return_int) + self.assertEqual(ret["exitstatus"], expected) + self.assertFalse(write_mock.called) + write_mock.reset_mock() + def act_normal_return(): + return {"exitstatus": 43} + ret = bootstrap_obj.try_to_execute(act_normal_return) + self.assertEqual(ret["exitstatus"], expected) + self.assertFalse(write_mock.called) + write_mock.reset_mock() + # Exception scenario + def act(): + raise IOError() + ret = bootstrap_obj.try_to_execute(act) + self.assertEqual(ret["exitstatus"], 177) + self.assertTrue(write_mock.called) + + + @patch.object(BootstrapDefault, "try_to_execute") + @patch.object(BootstrapDefault, "hasPassword") + @patch.object(BootstrapDefault, "createDoneFile") + @patch.object(HostLog, "write") + @patch("logging.warn") + @patch("logging.error") + def test_run(self, error_mock, warn_mock, write_mock, createDoneFile_mock, + hasPassword_mock, try_to_execute_mock): + shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "centos6", + None, "8440", "root") + bootstrap_obj = Bootstrap("hostname", shared_state) + # Testing workflow without password + bootstrap_obj.copied_password_file = False + hasPassword_mock.return_value = False + try_to_execute_mock.return_value = {"exitstatus": 0, "log":"log0", "errormsg":"errormsg0"} + bootstrap_obj.run() + self.assertEqual(try_to_execute_mock.call_count, 7) # <- Adjust if changed + self.assertTrue(createDoneFile_mock.called) + self.assertEqual(bootstrap_obj.getStatus()["return_code"], 0) + + try_to_execute_mock.reset_mock() + createDoneFile_mock.reset_mock() + # Testing workflow with password + bootstrap_obj.copied_password_file = True + hasPassword_mock.return_value = True + try_to_execute_mock.return_value = {"exitstatus": 0, "log":"log0", "errormsg":"errormsg0"} + bootstrap_obj.run() + self.assertEqual(try_to_execute_mock.call_count, 10) # <- Adjust if changed + self.assertTrue(createDoneFile_mock.called) + self.assertEqual(bootstrap_obj.getStatus()["return_code"], 0) + + error_mock.reset_mock() + write_mock.reset_mock() + try_to_execute_mock.reset_mock() + createDoneFile_mock.reset_mock() + # Testing workflow when some action failed before copying password + bootstrap_obj.copied_password_file = False + hasPassword_mock.return_value = False + try_to_execute_mock.side_effect = [{"exitstatus": 0, "log":"log0", "errormsg":"errormsg0"}, {"exitstatus": 1, "log":"log1", "errormsg":"errormsg1"}] + bootstrap_obj.run() + self.assertEqual(try_to_execute_mock.call_count, 2) # <- Adjust if changed + self.assertTrue("ERROR" in error_mock.call_args[0][0]) + self.assertTrue("ERROR" in write_mock.call_args[0][0]) + self.assertTrue(createDoneFile_mock.called) + self.assertEqual(bootstrap_obj.getStatus()["return_code"], 1) + + try_to_execute_mock.reset_mock() + createDoneFile_mock.reset_mock() + # Testing workflow when some action failed after copying password + bootstrap_obj.copied_password_file = True + hasPassword_mock.return_value = True + try_to_execute_mock.side_effect = [{"exitstatus": 0, "log":"log0", "errormsg":"errormsg0"}, {"exitstatus": 42, "log":"log42", "errormsg":"errormsg42"}, {"exitstatus": 0, "log":"log0", "errormsg":"errormsg0"}] + bootstrap_obj.run() + self.assertEqual(try_to_execute_mock.call_count, 3) # <- Adjust if changed + self.assertTrue(createDoneFile_mock.called) + self.assertEqual(bootstrap_obj.getStatus()["return_code"], 42) + + error_mock.reset_mock() + write_mock.reset_mock() + try_to_execute_mock.reset_mock() + createDoneFile_mock.reset_mock() + # Testing workflow when some action failed after copying password and + # removing password failed too + bootstrap_obj.copied_password_file = True + hasPassword_mock.return_value = True + try_to_execute_mock.side_effect = [{"exitstatus": 0, "log":"log0", "errormsg":"errormsg0"}, {"exitstatus": 17, "log":"log17", "errormsg":"errormsg17"}, {"exitstatus": 19, "log":"log19", "errormsg":"errormsg19"}] + bootstrap_obj.run() + self.assertEqual(try_to_execute_mock.call_count, 3) # <- Adjust if changed + self.assertTrue("ERROR" in write_mock.call_args_list[0][0][0]) + self.assertTrue("ERROR" in error_mock.call_args[0][0]) + self.assertTrue("WARNING" in write_mock.call_args_list[1][0][0]) + self.assertTrue("WARNING" in warn_mock.call_args[0][0]) + self.assertTrue(createDoneFile_mock.called) + self.assertEqual(bootstrap_obj.getStatus()["return_code"], 17) + + + @patch.object(BootstrapDefault, "createDoneFile") + @patch.object(HostLog, "write") + def test_interruptBootstrap(self, write_mock, createDoneFile_mock): + shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "centos6", + None, "8440", "root") + bootstrap_obj = Bootstrap("hostname", shared_state) + bootstrap_obj.interruptBootstrap() + self.assertTrue(createDoneFile_mock.called) + + + @patch("time.sleep") + @patch("time.time") + @patch("logging.warn") + @patch("logging.info") + @patch.object(BootstrapDefault, "start") + @patch.object(BootstrapDefault, "interruptBootstrap") + @patch.object(BootstrapDefault, "getStatus") + def test_PBootstrap(self, getStatus_mock, interruptBootstrap_mock, start_mock, + info_mock, warn_mock, time_mock, sleep_mock): + shared_state = SharedState("root", "sshkey_file", "scriptDir", "bootdir", + "setupAgentFile", "ambariServer", "centos6", + None, "8440", "root") + n = 180 + time = 100500 + time_mock.return_value = time + hosts = [] + for i in range(0, n): + hosts.append("host" + str(i)) + # Testing normal case + getStatus_mock.return_value = {"return_code": 0, + "start_time": time + 999} + pbootstrap_obj = PBootstrap(hosts, shared_state) + pbootstrap_obj.run() + self.assertEqual(start_mock.call_count, n) + self.assertEqual(interruptBootstrap_mock.call_count, 0) + + start_mock.reset_mock() + getStatus_mock.reset_mock() + # Testing case of timeout + def fake_return_code_generator(): + call_number = 0 + while True: + call_number += 1 + if call_number % 5 != 0: # ~80% of hosts finish successfully + yield 0 + else: + yield None + + def fake_start_time_generator(): + while True: + yield time - bootstrap.HOST_BOOTSTRAP_TIMEOUT - 1 + + return_code_generator = fake_return_code_generator() + start_time_generator = fake_start_time_generator() + + def status_get_item_mock(item): + if item == "return_code": + return return_code_generator.next() + elif item == "start_time": + return start_time_generator.next() + + dict_mock = MagicMock() + dict_mock.__getitem__.side_effect = status_get_item_mock + getStatus_mock.return_value = dict_mock + + pbootstrap_obj.run() + self.assertEqual(start_mock.call_count, n) + self.assertEqual(interruptBootstrap_mock.call_count, n / 5) +
