TestHostCleanup.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. #!/usr/bin/env python2.6
  2. '''
  3. Licensed to the Apache Software Foundation (ASF) under one
  4. or more contributor license agreements. See the NOTICE file
  5. distributed with this work for additional information
  6. regarding copyright ownership. The ASF licenses this file
  7. to you under the Apache License, Version 2.0 (the
  8. "License"); you may not use this file except in compliance
  9. with the License. You may obtain a copy of the License at
  10. http://www.apache.org/licenses/LICENSE-2.0
  11. Unless required by applicable law or agreed to in writing, software
  12. distributed under the License is distributed on an "AS IS" BASIS,
  13. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. See the License for the specific language governing permissions and
  15. limitations under the License.
  16. '''
  17. from unittest import TestCase
  18. import unittest
  19. from mock.mock import patch, MagicMock, call, create_autospec
  20. from ambari_agent import HostCleanup
  21. import StringIO
  22. import sys
  23. import tempfile
  24. import os.path
  25. import optparse
  26. import logging
  27. PACKAGE_SECTION = "packages"
  28. PACKAGE_KEY = "pkg_list"
  29. USER_SECTION = "users"
  30. USER_KEY = "usr_list"
  31. REPO_SECTION = "repositories"
  32. REPOS_KEY = "pkg_list"
  33. DIR_SECTION = "directories"
  34. DIR_KEY = "dir_list"
  35. PROCESS_SECTION = "processes"
  36. PROCESS_KEY = "proc_list"
  37. ALT_SECTION = "alternatives"
  38. ALT_KEYS = ["symlink_list", "target_list"]
  39. ALT_ERASE_CMD = "alternatives --remove {0} {1}"
  40. class TestHostCleanup(TestCase):
  41. def setUp(self):
  42. HostCleanup.logger = MagicMock()
  43. self.hostcleanup = HostCleanup.HostCleanup()
  44. # disable stdout
  45. out = StringIO.StringIO()
  46. sys.stdout = out
  47. def tearDown(self):
  48. # enable stdout
  49. sys.stdout = sys.__stdout__
  50. def test_read_host_check_file_with_content(self):
  51. out = StringIO.StringIO()
  52. sys.stdout = out
  53. tmpfile = tempfile.mktemp()
  54. f = open(tmpfile,'w')
  55. fileContent = """[processes]
  56. proc_list = 323,434
  57. [users]
  58. usr_list = rrdcached,ambari-qa,hive,oozie,hbase,hcat,mysql,mapred,hdfs,zookeeper,sqoop,nagios
  59. [repositories]
  60. repo_list = HDP-1.3.0,HDP-epel
  61. [directories]
  62. dir_list = /etc/hadoop,/etc/hbase,/etc/hcatalog,/tmp/hive,/tmp/nagios,/var/nagios
  63. [alternatives]
  64. symlink_list = hcatalog-conf,hadoop-default,hadoop-log,oozie-conf
  65. target_list = /etc/hcatalog/conf.dist,/usr/share/man/man1/hadoop.1.gz,/etc/oozie/conf.dist,/usr/lib/hadoop
  66. [packages]
  67. pkg_list = sqoop.noarch,hadoop-libhdfs.x86_64,rrdtool.x86_64,ganglia-gmond.x86_64
  68. [metadata]
  69. created = 2013-07-02 20:39:22.162757"""
  70. f.write(fileContent)
  71. f.close()
  72. propMap = self.hostcleanup.read_host_check_file(tmpfile)
  73. self.assertTrue("323" in propMap["processes"])
  74. self.assertTrue("mysql" in propMap["users"])
  75. self.assertTrue("HDP-epel" in propMap["repositories"])
  76. self.assertTrue("/etc/hadoop" in propMap["directories"])
  77. self.assertTrue("hcatalog-conf" in propMap["alternatives"]["symlink_list"])
  78. self.assertTrue("/etc/oozie/conf.dist" in propMap["alternatives"]["target_list"])
  79. self.assertTrue("hadoop-libhdfs.x86_64" in propMap["packages"])
  80. sys.stdout = sys.__stdout__
  81. class HostCleanupOptions:
  82. def __init__(self, outputfile, inputfile, skip, verbose):
  83. self.outputfile = outputfile
  84. self.inputfile = inputfile
  85. self.skip = skip
  86. self.verbose = False
  87. @patch.object(logging.FileHandler, 'setFormatter')
  88. @patch.object(HostCleanup.HostCleanup,'read_host_check_file')
  89. @patch.object(logging,'basicConfig')
  90. @patch.object(logging, 'FileHandler')
  91. @patch.object(optparse.OptionParser, 'parse_args')
  92. def test_options(self, parser_mock, file_handler_mock, logging_mock, read_host_check_file_mock, set_formatter_mock):
  93. parser_mock.return_value = (TestHostCleanup.HostCleanupOptions('/someoutputfile', '/someinputfile', '', False), [])
  94. file_handler_mock.return_value = logging.FileHandler('') # disable creating real file
  95. HostCleanup.main()
  96. # test --out
  97. file_handler_mock.assert_called_with('/someoutputfile')
  98. # test --skip
  99. self.assertEquals([''],HostCleanup.SKIP_LIST)
  100. #test --verbose
  101. logging_mock.assert_called_with(level=logging.INFO)
  102. # test --in
  103. read_host_check_file_mock.assert_called_with('/someinputfile')
  104. @patch.object(HostCleanup.HostCleanup, 'do_erase_alternatives')
  105. @patch.object(HostCleanup.HostCleanup, 'find_repo_files_for_repos')
  106. @patch.object(HostCleanup.HostCleanup, 'get_os_type')
  107. @patch.object(HostCleanup.HostCleanup, 'do_kill_processes')
  108. @patch.object(HostCleanup.HostCleanup, 'do_erase_files_silent')
  109. @patch.object(HostCleanup.HostCleanup, 'do_erase_dir_silent')
  110. @patch.object(HostCleanup.HostCleanup, 'do_delete_users')
  111. @patch.object(HostCleanup.HostCleanup, 'do_erase_packages')
  112. def test_do_cleanup_all(self, do_erase_packages_method, do_delete_users_method,
  113. do_erase_dir_silent_method,
  114. do_erase_files_silent_method, do_kill_processes_method,
  115. get_os_type_method, find_repo_files_for_repos_method,
  116. do_erase_alternatives_method):
  117. global SKIP_LIST
  118. oldSkipList = HostCleanup.SKIP_LIST
  119. HostCleanup.SKIP_LIST = []
  120. out = StringIO.StringIO()
  121. sys.stdout = out
  122. propertyMap = {PACKAGE_SECTION:['abcd', 'pqrst'], USER_SECTION:['abcd', 'pqrst'],
  123. REPO_SECTION:['abcd', 'pqrst'], DIR_SECTION:['abcd', 'pqrst'],
  124. PROCESS_SECTION:['abcd', 'pqrst'],
  125. ALT_SECTION:{ALT_KEYS[0]:['alt1','alt2'], ALT_KEYS[1]:[
  126. 'dir1']}}
  127. get_os_type_method.return_value = 'redhat'
  128. find_repo_files_for_repos_method.return_value = ['abcd', 'pqrst']
  129. self.hostcleanup.do_cleanup(propertyMap)
  130. self.assertTrue(do_delete_users_method.called)
  131. self.assertTrue(do_erase_dir_silent_method.called)
  132. self.assertTrue(do_erase_files_silent_method.called)
  133. self.assertTrue(do_erase_packages_method.called)
  134. self.assertTrue(do_kill_processes_method.called)
  135. self.assertTrue(do_erase_alternatives_method.called)
  136. do_erase_dir_silent_method.assert_called_once_with(['abcd', 'pqrst'])
  137. do_erase_packages_method.assert_called_once_with(['abcd', 'pqrst'])
  138. do_erase_files_silent_method.assert_called_once_with(['abcd', 'pqrst'])
  139. do_delete_users_method.assert_called_once_with(['abcd', 'pqrst'])
  140. do_kill_processes_method.assert_called_once_with(['abcd', 'pqrst'])
  141. do_erase_alternatives_method.assert_called_once_with({ALT_KEYS[0]:['alt1',
  142. 'alt2'], ALT_KEYS[1]:['dir1']})
  143. HostCleanup.SKIP_LIST = oldSkipList
  144. sys.stdout = sys.__stdout__
  145. @patch.object(HostCleanup.HostCleanup, 'do_erase_alternatives')
  146. @patch.object(HostCleanup.HostCleanup, 'find_repo_files_for_repos')
  147. @patch.object(HostCleanup.HostCleanup, 'get_os_type')
  148. @patch.object(HostCleanup.HostCleanup, 'do_kill_processes')
  149. @patch.object(HostCleanup.HostCleanup, 'do_erase_files_silent')
  150. @patch.object(HostCleanup.HostCleanup, 'do_erase_dir_silent')
  151. @patch.object(HostCleanup.HostCleanup, 'do_delete_users')
  152. @patch.object(HostCleanup.HostCleanup, 'do_erase_packages')
  153. def test_do_cleanup_default(self, do_erase_packages_method, do_delete_users_method,
  154. do_erase_dir_silent_method,
  155. do_erase_files_silent_method, do_kill_processes_method,
  156. get_os_type_method, find_repo_files_for_repos_method,
  157. do_erase_alternatives_method):
  158. out = StringIO.StringIO()
  159. sys.stdout = out
  160. propertyMap = {PACKAGE_SECTION:['abcd', 'pqrst'], USER_SECTION:['abcd', 'pqrst'],
  161. REPO_SECTION:['abcd', 'pqrst'], DIR_SECTION:['abcd', 'pqrst'],
  162. PROCESS_SECTION:['abcd', 'pqrst'],
  163. ALT_SECTION:{ALT_KEYS[0]:['alt1','alt2'], ALT_KEYS[1]:[
  164. 'dir1']}}
  165. get_os_type_method.return_value = 'redhat'
  166. find_repo_files_for_repos_method.return_value = ['abcd', 'pqrst']
  167. self.hostcleanup.do_cleanup(propertyMap)
  168. self.assertFalse(do_delete_users_method.called)
  169. self.assertTrue(do_erase_dir_silent_method.called)
  170. self.assertTrue(do_erase_files_silent_method.called)
  171. self.assertTrue(do_erase_packages_method.called)
  172. self.assertTrue(do_kill_processes_method.called)
  173. self.assertTrue(do_erase_alternatives_method.called)
  174. sys.stdout = sys.__stdout__
  175. @patch.object(HostCleanup.HostCleanup, 'find_repo_files_for_repos')
  176. @patch.object(HostCleanup.HostCleanup, 'get_os_type')
  177. @patch.object(HostCleanup.HostCleanup, 'do_kill_processes')
  178. @patch.object(HostCleanup.HostCleanup, 'do_erase_files_silent')
  179. @patch.object(HostCleanup.HostCleanup, 'do_erase_dir_silent')
  180. @patch.object(HostCleanup.HostCleanup, 'do_delete_users')
  181. @patch.object(HostCleanup.HostCleanup, 'do_erase_packages')
  182. def test_do_cleanup_with_skip(self, do_erase_packages_method,
  183. do_delete_users_method,
  184. do_erase_dir_silent_method,
  185. do_erase_files_silent_method, do_kill_processes_method,
  186. get_os_type_method, find_repo_files_for_repos_method):
  187. out = StringIO.StringIO()
  188. sys.stdout = out
  189. propertyMap = {PACKAGE_SECTION:['abcd', 'pqrst'], USER_SECTION:['abcd', 'pqrst'],
  190. REPO_SECTION:['abcd', 'pqrst'], DIR_SECTION:['abcd', 'pqrst'],
  191. PROCESS_SECTION:['abcd', 'pqrst']}
  192. get_os_type_method.return_value = 'redhat'
  193. find_repo_files_for_repos_method.return_value = ['abcd', 'pqrst']
  194. HostCleanup.SKIP_LIST = [PACKAGE_SECTION, REPO_SECTION]
  195. self.hostcleanup.do_cleanup(propertyMap)
  196. self.assertTrue(do_delete_users_method.called)
  197. self.assertTrue(do_erase_dir_silent_method.called)
  198. self.assertFalse(do_erase_files_silent_method.called)
  199. self.assertFalse(do_erase_packages_method.called)
  200. self.assertTrue(do_kill_processes_method.called)
  201. do_erase_dir_silent_method.assert_called_once_with(['abcd', 'pqrst'])
  202. do_delete_users_method.assert_called_once_with(['abcd', 'pqrst'])
  203. do_kill_processes_method.assert_called_once_with(['abcd', 'pqrst'])
  204. sys.stdout = sys.__stdout__
  205. @patch("ConfigParser.RawConfigParser")
  206. @patch("__builtin__.open")
  207. def test_read_host_check_file(self, openMock, readMock):
  208. out = StringIO.StringIO()
  209. sys.stdout = out
  210. f = MagicMock()
  211. openMock.return_value = f
  212. propertyMap = self.hostcleanup.read_host_check_file('test')
  213. self.assertTrue(openMock.called)
  214. self.assertTrue(readMock.called)
  215. self.assertTrue(propertyMap.has_key(PACKAGE_SECTION))
  216. self.assertTrue(propertyMap.has_key(REPO_SECTION))
  217. self.assertTrue(propertyMap.has_key(USER_SECTION))
  218. self.assertTrue(propertyMap.has_key(DIR_SECTION))
  219. self.assertTrue(propertyMap.has_key(PROCESS_SECTION))
  220. sys.stdout = sys.__stdout__
  221. @patch.object(HostCleanup.HostCleanup, 'run_os_command')
  222. @patch.object(HostCleanup.HostCleanup, 'get_os_type')
  223. def test_do_earse_packages(self, get_os_type_method, run_os_command_method):
  224. out = StringIO.StringIO()
  225. sys.stdout = out
  226. get_os_type_method.return_value = 'redhat'
  227. run_os_command_method.return_value = (0, 'success', 'success')
  228. retval = self.hostcleanup.do_erase_packages(['abcd', 'wxyz'])
  229. self.assertTrue(get_os_type_method.called)
  230. self.assertTrue(run_os_command_method.called)
  231. run_os_command_method.assert_called_with("yum erase -y {0}".format(' '
  232. .join(['abcd', 'wxyz'])))
  233. self.assertEquals(0, retval)
  234. get_os_type_method.reset()
  235. run_os_command_method.reset()
  236. get_os_type_method.return_value = 'suse'
  237. run_os_command_method.return_value = (0, 'success', 'success')
  238. retval = self.hostcleanup.do_erase_packages(['abcd', 'wxyz'])
  239. self.assertTrue(get_os_type_method.called)
  240. self.assertTrue(run_os_command_method.called)
  241. run_os_command_method.assert_called_with("zypper -n -q remove {0}"
  242. .format(' '.join(['abcd', 'wxyz'])))
  243. self.assertEquals(0, retval)
  244. sys.stdout = sys.__stdout__
  245. @patch.object(HostCleanup.HostCleanup, 'get_files_in_dir')
  246. @patch.object(HostCleanup.HostCleanup, 'get_os_type')
  247. def test_find_repo_files_for_repos(self, get_os_type_method,
  248. get_files_in_dir_method):
  249. out = StringIO.StringIO()
  250. sys.stdout = out
  251. tmpfile = tempfile.mktemp()
  252. fileContent = """[###]
  253. [aass]
  254. [$$]
  255. 444]saas[333
  256. 1122[naas]2222
  257. name=sd des derft 3.1
  258. """
  259. with open(tmpfile,'w') as file:
  260. file.write(fileContent)
  261. get_os_type_method.return_value = 'redhat'
  262. get_files_in_dir_method.return_value = [ tmpfile ]
  263. repoFiles = self.hostcleanup.find_repo_files_for_repos(['aass'])
  264. self.assertTrue(get_files_in_dir_method.called)
  265. self.assertTrue(get_os_type_method.called)
  266. self.assertEquals(repoFiles, [ tmpfile ])
  267. repoFiles = self.hostcleanup.find_repo_files_for_repos(['sd des derft 3.1'])
  268. self.assertTrue(get_files_in_dir_method.called)
  269. self.assertTrue(get_os_type_method.called)
  270. self.assertEquals(repoFiles, [ tmpfile ])
  271. repoFiles = self.hostcleanup.find_repo_files_for_repos(['sd des derft 3.1', 'aass'])
  272. self.assertEquals(repoFiles, [ tmpfile ])
  273. repoFiles = self.hostcleanup.find_repo_files_for_repos(['saas'])
  274. self.assertEquals(repoFiles, [])
  275. repoFiles = self.hostcleanup.find_repo_files_for_repos([''])
  276. self.assertEquals(repoFiles, [])
  277. sys.stdout = sys.__stdout__
  278. @patch.object(HostCleanup.HostCleanup, 'run_os_command')
  279. @patch.object(HostCleanup.HostCleanup, 'do_erase_dir_silent')
  280. @patch.object(HostCleanup.HostCleanup, 'get_alternatives_desc')
  281. def test_do_erase_alternatives(self, get_alternatives_desc_mock,
  282. do_erase_dir_silent_mock, run_os_command_mock):
  283. out = StringIO.StringIO()
  284. sys.stdout = out
  285. get_alternatives_desc_mock.return_value = 'somepath to alternative\n'
  286. run_os_command_mock.return_value = (0, None, None)
  287. alt_map = {ALT_KEYS[0]:['alt1'], ALT_KEYS[1]:['dir1']}
  288. self.hostcleanup.do_erase_alternatives(alt_map)
  289. self.assertTrue(get_alternatives_desc_mock.called)
  290. get_alternatives_desc_mock.called_once_with('alt1')
  291. self.assertTrue(run_os_command_mock.called)
  292. run_os_command_mock.called_once_with(ALT_ERASE_CMD.format('alt1', 'somepath'))
  293. self.assertTrue(do_erase_dir_silent_mock.called)
  294. do_erase_dir_silent_mock.called_once_with(['dir1'])
  295. sys.stdout = sys.__stdout__
  296. if __name__ == "__main__":
  297. unittest.main(verbosity=2)