blob: d8004cad599f7b898c3ea8def98f728ce206d6e3 [file] [log] [blame]
#!/usr/bin/env python2.6
'''
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 unittest import TestCase
import unittest
from mock.mock import patch, Mock, MagicMock, call, create_autospec
from ambari_agent import HostCleanup
import StringIO
import sys
import tempfile
import os.path
import optparse
import logging
PACKAGE_SECTION = "packages"
PACKAGE_KEY = "pkg_list"
USER_SECTION = "users"
USER_KEY = "usr_list"
REPO_SECTION = "repositories"
REPOS_KEY = "pkg_list"
DIR_SECTION = "directories"
DIR_KEY = "dir_list"
PROCESS_SECTION = "processes"
PROCESS_KEY = "proc_list"
ALT_SECTION = "alternatives"
ALT_KEYS = ["symlink_list", "target_list"]
ALT_ERASE_CMD = "alternatives --remove {0} {1}"
USER_HOMEDIR_SECTION = "usr_homedir"
class TestHostCleanup(TestCase):
def setUp(self):
HostCleanup.logger = MagicMock()
self.hostcleanup = HostCleanup.HostCleanup()
# disable stdout
out = StringIO.StringIO()
sys.stdout = out
def tearDown(self):
# enable stdout
sys.stdout = sys.__stdout__
@patch("os.listdir", create=True, autospec=True)
def test_read_host_check_file_with_content(self, os_listdir_mock):
out = StringIO.StringIO()
sys.stdout = out
tmpfile = tempfile.mktemp()
f = open(tmpfile,'w')
fileContent = """[processes]
proc_list = 323,434
[users]
usr_list = rrdcached,ambari-qa,hive,oozie,hbase,hcat,mysql,mapred,hdfs,zookeeper,sqoop,nagios
[repositories]
repo_list = HDP-1.3.0,HDP-epel
[directories]
dir_list = /etc/hadoop,/etc/hbase,/etc/hcatalog,/tmp/hive,/tmp/nagios,/var/nagios
[alternatives]
symlink_list = hcatalog-conf,hadoop-default,hadoop-log,oozie-conf
target_list = /etc/hcatalog/conf.dist,/usr/share/man/man1/hadoop.1.gz,/etc/oozie/conf.dist,/usr/lib/hadoop
[packages]
pkg_list = sqoop.noarch,hadoop-libhdfs.x86_64,rrdtool.x86_64,ganglia-gmond.x86_64
[metadata]
created = 2013-07-02 20:39:22.162757"""
f.write(fileContent)
f.close()
os_listdir_mock.return_value = ['111']
tf2 = tempfile.mktemp()
f2 = open(tf2,'w')
f2.write('java_home|hadoop')
f2.close()
with patch('os.path.join') as patch_join_mock:
patch_join_mock.return_value = f2.name
propMap = self.hostcleanup.read_host_check_file(tmpfile)
self.assertTrue(111 in propMap["processes"])
self.assertTrue("mysql" in propMap["users"])
self.assertTrue("HDP-epel" in propMap["repositories"])
self.assertTrue("/etc/hadoop" in propMap["directories"])
self.assertTrue("hcatalog-conf" in propMap["alternatives"]["symlink_list"])
self.assertTrue("/etc/oozie/conf.dist" in propMap["alternatives"]["target_list"])
self.assertTrue("hadoop-libhdfs.x86_64" in propMap["packages"])
sys.stdout = sys.__stdout__
class HostCleanupOptions:
def __init__(self, outputfile, inputfile, skip, verbose, silent, java_home):
self.outputfile = outputfile
self.inputfile = inputfile
self.skip = skip
self.verbose = verbose
self.silent = silent
self.java_home = java_home
@patch.object(HostCleanup, 'get_YN_input')
@patch.object(HostCleanup.HostCleanup, 'do_cleanup')
@patch.object(HostCleanup.HostCleanup, 'is_current_user_root')
@patch.object(logging.FileHandler, 'setFormatter')
@patch.object(HostCleanup.HostCleanup,'read_host_check_file')
@patch.object(logging,'basicConfig')
@patch.object(logging, 'FileHandler')
@patch.object(optparse.OptionParser, 'parse_args')
def test_options(self, parser_mock, file_handler_mock, logging_mock, read_host_check_file_mock,
set_formatter_mock, user_root_mock, do_cleanup_mock, get_yn_input_mock):
parser_mock.return_value = (TestHostCleanup.HostCleanupOptions('/someoutputfile', '/someinputfile', '', False,
False, 'java_home'), [])
file_handler_mock.return_value = logging.FileHandler('') # disable creating real file
user_root_mock.return_value = True
get_yn_input_mock.return_value = True
HostCleanup.main()
# test --out
file_handler_mock.assert_called_with('/someoutputfile')
# test --skip
self.assertEquals([''],HostCleanup.SKIP_LIST)
#test --verbose
logging_mock.assert_called_with(level=logging.INFO)
# test --in
read_host_check_file_mock.assert_called_with('/someinputfile')
self.assertTrue(get_yn_input_mock.called)
@patch.object(HostCleanup, 'get_YN_input')
@patch.object(HostCleanup.HostCleanup, 'do_cleanup')
@patch.object(HostCleanup.HostCleanup, 'is_current_user_root')
@patch.object(logging.FileHandler, 'setFormatter')
@patch.object(HostCleanup.HostCleanup,'read_host_check_file')
@patch.object(logging,'basicConfig')
@patch.object(logging, 'FileHandler')
@patch.object(optparse.OptionParser, 'parse_args')
def test_options_silent(self, parser_mock, file_handler_mock, logging_mock, read_host_check_file_mock,
set_formatter_mock, user_root_mock, do_cleanup_mock, get_yn_input_mock):
parser_mock.return_value = (TestHostCleanup.HostCleanupOptions('/someoutputfile', '/someinputfile', '', False,
True, 'java_home'), [])
file_handler_mock.return_value = logging.FileHandler('') # disable creating real file
user_root_mock.return_value = True
get_yn_input_mock.return_value = True
HostCleanup.main()
# test --out
file_handler_mock.assert_called_with('/someoutputfile')
# test --skip
self.assertEquals([''],HostCleanup.SKIP_LIST)
#test --verbose
logging_mock.assert_called_with(level=logging.INFO)
# test --in
read_host_check_file_mock.assert_called_with('/someinputfile')
self.assertFalse(get_yn_input_mock.called)
@patch.object(HostCleanup.HostCleanup, 'do_erase_alternatives')
@patch.object(HostCleanup.HostCleanup, 'find_repo_files_for_repos')
@patch.object(HostCleanup.HostCleanup, 'get_os_type')
@patch.object(HostCleanup.HostCleanup, 'do_kill_processes')
@patch.object(HostCleanup.HostCleanup, 'do_erase_files_silent')
@patch.object(HostCleanup.HostCleanup, 'do_erase_dir_silent')
@patch.object(HostCleanup.HostCleanup, 'do_delete_users')
@patch.object(HostCleanup.HostCleanup, 'do_erase_packages')
def test_do_cleanup_all(self, do_erase_packages_method, do_delete_users_method,
do_erase_dir_silent_method,
do_erase_files_silent_method, do_kill_processes_method,
get_os_type_method, find_repo_files_for_repos_method,
do_erase_alternatives_method):
out = StringIO.StringIO()
sys.stdout = out
propertyMap = {PACKAGE_SECTION:['abcd', 'pqrst'], USER_SECTION:['abcd', 'pqrst'],
REPO_SECTION:['abcd', 'pqrst'], DIR_SECTION:['abcd', 'pqrst'],
PROCESS_SECTION:['abcd', 'pqrst'],
ALT_SECTION:{ALT_KEYS[0]:['alt1','alt2'], ALT_KEYS[1]:[
'dir1']}, USER_HOMEDIR_SECTION:['decf']}
get_os_type_method.return_value = 'redhat'
find_repo_files_for_repos_method.return_value = ['abcd', 'pqrst']
self.hostcleanup.do_cleanup(propertyMap)
self.assertTrue(do_delete_users_method.called)
self.assertTrue(do_erase_dir_silent_method.called)
self.assertTrue(do_erase_files_silent_method.called)
self.assertTrue(do_erase_packages_method.called)
self.assertTrue(do_kill_processes_method.called)
self.assertTrue(do_erase_alternatives_method.called)
calls = [call(['decf']), call(['abcd', 'pqrst'])]
do_erase_dir_silent_method.assert_has_calls(calls)
do_erase_packages_method.assert_called_once_with(['abcd', 'pqrst'])
do_erase_files_silent_method.assert_called_once_with(['abcd', 'pqrst'])
do_delete_users_method.assert_called_once_with(['abcd', 'pqrst'])
do_kill_processes_method.assert_called_once_with(['abcd', 'pqrst'])
do_erase_alternatives_method.assert_called_once_with({ALT_KEYS[0]:['alt1',
'alt2'], ALT_KEYS[1]:['dir1']})
sys.stdout = sys.__stdout__
@patch.object(HostCleanup.HostCleanup, 'do_delete_by_owner')
@patch.object(HostCleanup.HostCleanup, 'get_user_ids')
@patch.object(HostCleanup.HostCleanup, 'do_erase_alternatives')
@patch.object(HostCleanup.HostCleanup, 'find_repo_files_for_repos')
@patch.object(HostCleanup.HostCleanup, 'get_os_type')
@patch.object(HostCleanup.HostCleanup, 'do_kill_processes')
@patch.object(HostCleanup.HostCleanup, 'do_erase_files_silent')
@patch.object(HostCleanup.HostCleanup, 'do_erase_dir_silent')
@patch.object(HostCleanup.HostCleanup, 'do_delete_users')
@patch.object(HostCleanup.HostCleanup, 'do_erase_packages')
def test_do_cleanup_default(self, do_erase_packages_method, do_delete_users_method,
do_erase_dir_silent_method,
do_erase_files_silent_method, do_kill_processes_method,
get_os_type_method, find_repo_files_for_repos_method,
do_erase_alternatives_method, get_user_ids_method,
do_delete_by_owner_method):
global SKIP_LIST
oldSkipList = HostCleanup.SKIP_LIST
HostCleanup.SKIP_LIST = ["users"]
out = StringIO.StringIO()
sys.stdout = out
propertyMap = {PACKAGE_SECTION:['abcd', 'pqrst'], USER_SECTION:['abcd', 'pqrst'],
REPO_SECTION:['abcd', 'pqrst'], DIR_SECTION:['abcd', 'pqrst'],
PROCESS_SECTION:['abcd', 'pqrst'],
ALT_SECTION:{ALT_KEYS[0]:['alt1','alt2'], ALT_KEYS[1]:[
'dir1']}}
get_os_type_method.return_value = 'redhat'
find_repo_files_for_repos_method.return_value = ['abcd', 'pqrst']
self.hostcleanup.do_cleanup(propertyMap)
self.assertFalse(do_delete_by_owner_method.called)
self.assertFalse(get_user_ids_method.called)
self.assertFalse(do_delete_users_method.called)
self.assertTrue(do_erase_dir_silent_method.called)
self.assertTrue(do_erase_files_silent_method.called)
self.assertTrue(do_erase_packages_method.called)
self.assertTrue(do_kill_processes_method.called)
self.assertTrue(do_erase_alternatives_method.called)
HostCleanup.SKIP_LIST = oldSkipList
sys.stdout = sys.__stdout__
@patch.object(HostCleanup.HostCleanup, 'find_repo_files_for_repos')
@patch.object(HostCleanup.HostCleanup, 'get_os_type')
@patch.object(HostCleanup.HostCleanup, 'do_kill_processes')
@patch.object(HostCleanup.HostCleanup, 'do_erase_files_silent')
@patch.object(HostCleanup.HostCleanup, 'do_erase_dir_silent')
@patch.object(HostCleanup.HostCleanup, 'do_delete_users')
@patch.object(HostCleanup.HostCleanup, 'do_erase_packages')
def test_do_cleanup_with_skip(self, do_erase_packages_method,
do_delete_users_method,
do_erase_dir_silent_method,
do_erase_files_silent_method, do_kill_processes_method,
get_os_type_method, find_repo_files_for_repos_method):
out = StringIO.StringIO()
sys.stdout = out
propertyMap = {PACKAGE_SECTION:['abcd', 'pqrst'], USER_SECTION:['abcd', 'pqrst'],
REPO_SECTION:['abcd', 'pqrst'], DIR_SECTION:['abcd', 'pqrst'],
PROCESS_SECTION:['abcd', 'pqrst']}
get_os_type_method.return_value = 'redhat'
find_repo_files_for_repos_method.return_value = ['abcd', 'pqrst']
HostCleanup.SKIP_LIST = [PACKAGE_SECTION, REPO_SECTION]
self.hostcleanup.do_cleanup(propertyMap)
self.assertTrue(do_delete_users_method.called)
self.assertTrue(do_erase_dir_silent_method.called)
self.assertFalse(do_erase_files_silent_method.called)
self.assertFalse(do_erase_packages_method.called)
self.assertTrue(do_kill_processes_method.called)
calls = [call(None), call(['abcd', 'pqrst'])]
do_erase_dir_silent_method.assert_has_calls(calls)
do_delete_users_method.assert_called_once_with(['abcd', 'pqrst'])
do_kill_processes_method.assert_called_once_with(['abcd', 'pqrst'])
sys.stdout = sys.__stdout__
@patch.object(HostCleanup.HostCleanup, 'do_erase_dir_silent')
@patch("os.stat")
@patch("os.path.join")
@patch("os.listdir")
def test_do_delete_by_owner(self, listdir_mock, join_mock, stat_mock, do_erase_dir_silent_method):
listdir_mock.return_value = ["k", "j"]
join_mock.return_value = "path"
response = MagicMock()
response.st_uid = 1
stat_mock.return_value = response
self.hostcleanup.do_delete_by_owner([1, 2], ["a"])
self.assertTrue(do_erase_dir_silent_method.called)
calls = [call(["path"]), call(["path"])]
do_erase_dir_silent_method.assert_has_calls(calls)
@patch.object(HostCleanup.HostCleanup, 'run_os_command')
def test_do_delete_users(self, run_os_command_mock):
run_os_command_mock.return_value = (1, "", "")
self.hostcleanup.do_delete_users(["a", "b"])
self.assertTrue(run_os_command_mock.called)
calls = [call('userdel -rf a'), call('userdel -rf b'), call('groupdel hadoop')]
run_os_command_mock.assert_has_calls(calls)
@patch("ConfigParser.RawConfigParser")
@patch("__builtin__.open")
@patch("os.listdir", create=True, autospec=True)
def test_read_host_check_file(self, os_listdir_mock, openMock, readMock):
out = StringIO.StringIO()
sys.stdout = out
f = MagicMock()
openRead = MagicMock()
openRead.read.return_value = 'java_home|hadoop'
openMock.side_effect = [f, openRead]
os_listdir_mock.return_value = ['111']
propertyMap = self.hostcleanup.read_host_check_file('test')
self.assertTrue(openMock.called)
self.assertTrue(readMock.called)
self.assertTrue(propertyMap.has_key(PACKAGE_SECTION))
self.assertTrue(propertyMap.has_key(REPO_SECTION))
self.assertTrue(propertyMap.has_key(USER_SECTION))
self.assertTrue(propertyMap.has_key(DIR_SECTION))
self.assertTrue(propertyMap.has_key(PROCESS_SECTION))
self.assertEquals(propertyMap[PROCESS_SECTION][0], 111)
sys.stdout = sys.__stdout__
@patch.object(HostCleanup.HostCleanup, 'run_os_command')
@patch.object(HostCleanup.HostCleanup, 'get_os_type')
def test_do_earse_packages(self, get_os_type_method, run_os_command_method):
out = StringIO.StringIO()
sys.stdout = out
get_os_type_method.return_value = 'redhat'
run_os_command_method.return_value = (0, 'success', 'success')
retval = self.hostcleanup.do_erase_packages(['abcd', 'wxyz'])
self.assertTrue(get_os_type_method.called)
self.assertTrue(run_os_command_method.called)
run_os_command_method.assert_called_with("yum erase -y {0}".format(' '
.join(['abcd', 'wxyz'])))
self.assertEquals(0, retval)
get_os_type_method.reset()
run_os_command_method.reset()
get_os_type_method.return_value = 'suse'
run_os_command_method.return_value = (0, 'success', 'success')
retval = self.hostcleanup.do_erase_packages(['abcd', 'wxyz'])
self.assertTrue(get_os_type_method.called)
self.assertTrue(run_os_command_method.called)
run_os_command_method.assert_called_with("zypper -n -q remove {0}"
.format(' '.join(['abcd', 'wxyz'])))
self.assertEquals(0, retval)
sys.stdout = sys.__stdout__
@patch.object(HostCleanup.HostCleanup, 'get_files_in_dir')
@patch.object(HostCleanup.HostCleanup, 'get_os_type')
def test_find_repo_files_for_repos(self, get_os_type_method,
get_files_in_dir_method):
out = StringIO.StringIO()
sys.stdout = out
tmpfile = tempfile.mktemp()
fileContent = """[###]
[aass]
[$$]
444]saas[333
1122[naas]2222
name=sd des derft 3.1
"""
with open(tmpfile,'w') as file:
file.write(fileContent)
get_os_type_method.return_value = 'redhat'
get_files_in_dir_method.return_value = [ tmpfile ]
repoFiles = self.hostcleanup.find_repo_files_for_repos(['aass'])
self.assertTrue(get_files_in_dir_method.called)
self.assertTrue(get_os_type_method.called)
self.assertEquals(repoFiles, [ tmpfile ])
repoFiles = self.hostcleanup.find_repo_files_for_repos(['sd des derft 3.1'])
self.assertTrue(get_files_in_dir_method.called)
self.assertTrue(get_os_type_method.called)
self.assertEquals(repoFiles, [ tmpfile ])
repoFiles = self.hostcleanup.find_repo_files_for_repos(['sd des derft 3.1', 'aass'])
self.assertEquals(repoFiles, [ tmpfile ])
repoFiles = self.hostcleanup.find_repo_files_for_repos(['saas'])
self.assertEquals(repoFiles, [])
repoFiles = self.hostcleanup.find_repo_files_for_repos([''])
self.assertEquals(repoFiles, [])
sys.stdout = sys.__stdout__
@patch.object(HostCleanup.HostCleanup, 'run_os_command')
@patch.object(HostCleanup.HostCleanup, 'do_erase_dir_silent')
@patch.object(HostCleanup.HostCleanup, 'get_alternatives_desc')
def test_do_erase_alternatives(self, get_alternatives_desc_mock,
do_erase_dir_silent_mock, run_os_command_mock):
out = StringIO.StringIO()
sys.stdout = out
get_alternatives_desc_mock.return_value = 'somepath to alternative\n'
run_os_command_mock.return_value = (0, None, None)
alt_map = {ALT_KEYS[0]:['alt1'], ALT_KEYS[1]:['dir1']}
self.hostcleanup.do_erase_alternatives(alt_map)
self.assertTrue(get_alternatives_desc_mock.called)
get_alternatives_desc_mock.called_once_with('alt1')
self.assertTrue(run_os_command_mock.called)
run_os_command_mock.called_once_with(ALT_ERASE_CMD.format('alt1', 'somepath'))
self.assertTrue(do_erase_dir_silent_mock.called)
do_erase_dir_silent_mock.called_once_with(['dir1'])
sys.stdout = sys.__stdout__
if __name__ == "__main__":
unittest.main()