TestCustomServiceOrchestrator.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. #!/usr/bin/env python
  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. import ConfigParser
  18. from multiprocessing.pool import ThreadPool
  19. import os
  20. import pprint
  21. from ambari_commons import shell
  22. from unittest import TestCase
  23. import threading
  24. import tempfile
  25. import time
  26. from threading import Thread
  27. from PythonExecutor import PythonExecutor
  28. from CustomServiceOrchestrator import CustomServiceOrchestrator
  29. from AmbariConfig import AmbariConfig
  30. from mock.mock import MagicMock, patch
  31. import StringIO
  32. import sys
  33. from AgentException import AgentException
  34. from FileCache import FileCache
  35. from LiveStatus import LiveStatus
  36. from BackgroundCommandExecutionHandle import BackgroundCommandExecutionHandle
  37. from ambari_agent.ActionQueue import ActionQueue
  38. from only_for_platform import get_platform, PLATFORM_WINDOWS
  39. class TestCustomServiceOrchestrator(TestCase):
  40. def setUp(self):
  41. # disable stdout
  42. out = StringIO.StringIO()
  43. sys.stdout = out
  44. # generate sample config
  45. tmpdir = tempfile.gettempdir()
  46. exec_tmp_dir = os.path.join(tmpdir, 'tmp')
  47. self.config = ConfigParser.RawConfigParser()
  48. self.config.add_section('agent')
  49. self.config.set('agent', 'prefix', tmpdir)
  50. self.config.set('agent', 'tmp_dir', exec_tmp_dir)
  51. self.config.set('agent', 'cache_dir', "/cachedir")
  52. self.config.add_section('python')
  53. self.config.set('python', 'custom_actions_dir', tmpdir)
  54. @patch.object(FileCache, "__init__")
  55. def test_add_reg_listener_to_controller(self, FileCache_mock):
  56. FileCache_mock.return_value = None
  57. dummy_controller = MagicMock()
  58. config = AmbariConfig().getConfig()
  59. tempdir = tempfile.gettempdir()
  60. config.set('agent', 'prefix', tempdir)
  61. CustomServiceOrchestrator(config, dummy_controller)
  62. self.assertTrue(dummy_controller.registration_listeners.append.called)
  63. @patch.object(CustomServiceOrchestrator, 'decompressClusterHostInfo')
  64. @patch("hostname.public_hostname")
  65. @patch("os.path.isfile")
  66. @patch("os.unlink")
  67. @patch.object(FileCache, "__init__")
  68. def test_dump_command_to_json(self, FileCache_mock, unlink_mock,
  69. isfile_mock, hostname_mock,
  70. decompress_cluster_host_info_mock):
  71. FileCache_mock.return_value = None
  72. hostname_mock.return_value = "test.hst"
  73. command = {
  74. 'commandType': 'EXECUTION_COMMAND',
  75. 'role': u'DATANODE',
  76. 'roleCommand': u'INSTALL',
  77. 'commandId': '1-1',
  78. 'taskId': 3,
  79. 'clusterName': u'cc',
  80. 'serviceName': u'HDFS',
  81. 'configurations':{'global' : {}},
  82. 'configurationTags':{'global' : { 'tag': 'v1' }},
  83. 'clusterHostInfo':{'namenode_host' : ['1'],
  84. 'slave_hosts' : ['0', '1'],
  85. 'all_hosts' : ['h1.hortonworks.com', 'h2.hortonworks.com'],
  86. 'all_ping_ports': ['8670:0,1']},
  87. 'hostLevelParams':{}
  88. }
  89. decompress_cluster_host_info_mock.return_value = {'namenode_host' : ['h2.hortonworks.com'],
  90. 'slave_hosts' : ['h1.hortonworks.com', 'h2.hortonworks.com'],
  91. 'all_hosts' : ['h1.hortonworks.com', 'h2.hortonworks.com'],
  92. 'all_ping_ports': ['8670', '8670']}
  93. config = AmbariConfig().getConfig()
  94. tempdir = tempfile.gettempdir()
  95. config.set('agent', 'prefix', tempdir)
  96. dummy_controller = MagicMock()
  97. orchestrator = CustomServiceOrchestrator(config, dummy_controller)
  98. isfile_mock.return_value = True
  99. # Test dumping EXECUTION_COMMAND
  100. json_file = orchestrator.dump_command_to_json(command)
  101. self.assertTrue(os.path.exists(json_file))
  102. self.assertTrue(os.path.getsize(json_file) > 0)
  103. if get_platform() != PLATFORM_WINDOWS:
  104. self.assertEqual(oct(os.stat(json_file).st_mode & 0777), '0600')
  105. self.assertTrue(json_file.endswith("command-3.json"))
  106. self.assertTrue(decompress_cluster_host_info_mock.called)
  107. os.unlink(json_file)
  108. # Test dumping STATUS_COMMAND
  109. command['commandType']='STATUS_COMMAND'
  110. decompress_cluster_host_info_mock.reset_mock()
  111. json_file = orchestrator.dump_command_to_json(command)
  112. self.assertTrue(os.path.exists(json_file))
  113. self.assertTrue(os.path.getsize(json_file) > 0)
  114. if get_platform() != PLATFORM_WINDOWS:
  115. self.assertEqual(oct(os.stat(json_file).st_mode & 0777), '0600')
  116. self.assertTrue(json_file.endswith("status_command.json"))
  117. self.assertFalse(decompress_cluster_host_info_mock.called)
  118. os.unlink(json_file)
  119. # Testing side effect of dump_command_to_json
  120. self.assertEquals(command['public_hostname'], "test.hst")
  121. self.assertTrue(unlink_mock.called)
  122. @patch("os.path.exists")
  123. @patch.object(FileCache, "__init__")
  124. def test_resolve_script_path(self, FileCache_mock, exists_mock):
  125. FileCache_mock.return_value = None
  126. dummy_controller = MagicMock()
  127. config = AmbariConfig().getConfig()
  128. orchestrator = CustomServiceOrchestrator(config, dummy_controller)
  129. # Testing existing path
  130. exists_mock.return_value = True
  131. path = orchestrator.\
  132. resolve_script_path(os.path.join("HBASE", "package"), os.path.join("scripts", "hbase_master.py"))
  133. self.assertEqual(os.path.join("HBASE", "package", "scripts", "hbase_master.py"), path)
  134. # Testing not existing path
  135. exists_mock.return_value = False
  136. try:
  137. orchestrator.resolve_script_path("/HBASE",
  138. os.path.join("scripts", "hbase_master.py"))
  139. self.fail('ExpectedException not thrown')
  140. except AgentException:
  141. pass # Expected
  142. @patch.object(CustomServiceOrchestrator, "resolve_script_path")
  143. @patch.object(CustomServiceOrchestrator, "resolve_hook_script_path")
  144. @patch.object(FileCache, "get_host_scripts_base_dir")
  145. @patch.object(FileCache, "get_service_base_dir")
  146. @patch.object(FileCache, "get_hook_base_dir")
  147. @patch.object(CustomServiceOrchestrator, "dump_command_to_json")
  148. @patch.object(PythonExecutor, "run_file")
  149. @patch.object(FileCache, "__init__")
  150. def test_runCommand(self, FileCache_mock,
  151. run_file_mock, dump_command_to_json_mock,
  152. get_hook_base_dir_mock, get_service_base_dir_mock,
  153. get_host_scripts_base_dir_mock,
  154. resolve_hook_script_path_mock,
  155. resolve_script_path_mock):
  156. FileCache_mock.return_value = None
  157. command = {
  158. 'role' : 'REGION_SERVER',
  159. 'hostLevelParams' : {
  160. 'stack_name' : 'HDP',
  161. 'stack_version' : '2.0.7',
  162. 'jdk_location' : 'some_location'
  163. },
  164. 'commandParams': {
  165. 'script_type': 'PYTHON',
  166. 'script': 'scripts/hbase_regionserver.py',
  167. 'command_timeout': '600',
  168. 'service_package_folder' : 'HBASE'
  169. },
  170. 'taskId' : '3',
  171. 'roleCommand': 'INSTALL'
  172. }
  173. get_host_scripts_base_dir_mock.return_value = "/host_scripts"
  174. get_service_base_dir_mock.return_value = "/basedir/"
  175. resolve_script_path_mock.return_value = "/basedir/scriptpath"
  176. resolve_hook_script_path_mock.return_value = \
  177. ('/hooks_dir/prefix-command/scripts/hook.py',
  178. '/hooks_dir/prefix-command')
  179. dummy_controller = MagicMock()
  180. orchestrator = CustomServiceOrchestrator(self.config, dummy_controller)
  181. unix_process_id = 111
  182. orchestrator.commands_in_progress = {command['taskId']: unix_process_id}
  183. get_hook_base_dir_mock.return_value = "/hooks/"
  184. # normal run case
  185. run_file_mock.return_value = {
  186. 'stdout' : 'sss',
  187. 'stderr' : 'eee',
  188. 'exitcode': 0,
  189. }
  190. ret = orchestrator.runCommand(command, "out.txt", "err.txt")
  191. self.assertEqual(ret['exitcode'], 0)
  192. self.assertTrue(run_file_mock.called)
  193. self.assertEqual(run_file_mock.call_count, 3)
  194. run_file_mock.reset_mock()
  195. # Case when we force another command
  196. run_file_mock.return_value = {
  197. 'stdout' : 'sss',
  198. 'stderr' : 'eee',
  199. 'exitcode': 0,
  200. }
  201. ret = orchestrator.runCommand(command, "out.txt", "err.txt",
  202. forced_command_name=CustomServiceOrchestrator.COMMAND_NAME_STATUS)
  203. ## Check that override_output_files was true only during first call
  204. self.assertEquals(run_file_mock.call_args_list[0][0][10], True)
  205. self.assertEquals(run_file_mock.call_args_list[1][0][10], False)
  206. self.assertEquals(run_file_mock.call_args_list[2][0][10], False)
  207. ## Check that forced_command_name was taken into account
  208. self.assertEqual(run_file_mock.call_args_list[0][0][1][0],
  209. CustomServiceOrchestrator.COMMAND_NAME_STATUS)
  210. run_file_mock.reset_mock()
  211. # unknown script type case
  212. command['commandParams']['script_type'] = "SOME_TYPE"
  213. ret = orchestrator.runCommand(command, "out.txt", "err.txt")
  214. self.assertEqual(ret['exitcode'], 1)
  215. self.assertFalse(run_file_mock.called)
  216. self.assertTrue("Unknown script type" in ret['stdout'])
  217. #By default returns empty dictionary
  218. self.assertEqual(ret['structuredOut'], '{}')
  219. pass
  220. @patch("ambari_commons.shell.kill_process_with_children")
  221. @patch.object(CustomServiceOrchestrator, "resolve_script_path")
  222. @patch.object(CustomServiceOrchestrator, "resolve_hook_script_path")
  223. @patch.object(FileCache, "get_host_scripts_base_dir")
  224. @patch.object(FileCache, "get_service_base_dir")
  225. @patch.object(FileCache, "get_hook_base_dir")
  226. @patch.object(CustomServiceOrchestrator, "dump_command_to_json")
  227. @patch.object(PythonExecutor, "run_file")
  228. @patch.object(FileCache, "__init__")
  229. def test_cancel_command(self, FileCache_mock,
  230. run_file_mock, dump_command_to_json_mock,
  231. get_hook_base_dir_mock, get_service_base_dir_mock,
  232. get_host_scripts_base_dir_mock,
  233. resolve_hook_script_path_mock, resolve_script_path_mock,
  234. kill_process_with_children_mock):
  235. FileCache_mock.return_value = None
  236. command = {
  237. 'role' : 'REGION_SERVER',
  238. 'hostLevelParams' : {
  239. 'stack_name' : 'HDP',
  240. 'stack_version' : '2.0.7',
  241. 'jdk_location' : 'some_location'
  242. },
  243. 'commandParams': {
  244. 'script_type': 'PYTHON',
  245. 'script': 'scripts/hbase_regionserver.py',
  246. 'command_timeout': '600',
  247. 'service_package_folder' : 'HBASE'
  248. },
  249. 'taskId' : '3',
  250. 'roleCommand': 'INSTALL'
  251. }
  252. get_host_scripts_base_dir_mock.return_value = "/host_scripts"
  253. get_service_base_dir_mock.return_value = "/basedir/"
  254. resolve_script_path_mock.return_value = "/basedir/scriptpath"
  255. resolve_hook_script_path_mock.return_value = \
  256. ('/hooks_dir/prefix-command/scripts/hook.py',
  257. '/hooks_dir/prefix-command')
  258. dummy_controller = MagicMock()
  259. orchestrator = CustomServiceOrchestrator(self.config, dummy_controller)
  260. unix_process_id = 111
  261. orchestrator.commands_in_progress = {command['taskId']: unix_process_id}
  262. get_hook_base_dir_mock.return_value = "/hooks/"
  263. run_file_mock_return_value = {
  264. 'stdout' : 'killed',
  265. 'stderr' : 'killed',
  266. 'exitcode': 1,
  267. }
  268. def side_effect(*args, **kwargs):
  269. time.sleep(0.2)
  270. return run_file_mock_return_value
  271. run_file_mock.side_effect = side_effect
  272. _, out = tempfile.mkstemp()
  273. _, err = tempfile.mkstemp()
  274. pool = ThreadPool(processes=1)
  275. async_result = pool.apply_async(orchestrator.runCommand, (command, out, err))
  276. time.sleep(0.1)
  277. orchestrator.cancel_command(command['taskId'], 'reason')
  278. ret = async_result.get()
  279. self.assertEqual(ret['exitcode'], 1)
  280. self.assertEquals(ret['stdout'], 'killed\nCommand aborted. reason')
  281. self.assertEquals(ret['stderr'], 'killed\nCommand aborted. reason')
  282. self.assertTrue(kill_process_with_children_mock.called)
  283. self.assertFalse(command['taskId'] in orchestrator.commands_in_progress.keys())
  284. self.assertTrue(os.path.exists(out))
  285. self.assertTrue(os.path.exists(err))
  286. try:
  287. os.remove(out)
  288. os.remove(err)
  289. except:
  290. pass
  291. from ambari_agent.StackVersionsFileHandler import StackVersionsFileHandler
  292. @patch("ambari_commons.shell.kill_process_with_children")
  293. @patch.object(FileCache, "__init__")
  294. @patch.object(CustomServiceOrchestrator, "resolve_script_path")
  295. @patch.object(CustomServiceOrchestrator, "resolve_hook_script_path")
  296. @patch.object(StackVersionsFileHandler, "read_stack_version")
  297. def test_cancel_backgound_command(self, read_stack_version_mock, resolve_hook_script_path_mock, resolve_script_path_mock, FileCache_mock,
  298. kill_process_with_children_mock):
  299. FileCache_mock.return_value = None
  300. FileCache_mock.cache_dir = MagicMock()
  301. resolve_hook_script_path_mock.return_value = None
  302. # shell.kill_process_with_children = MagicMock()
  303. dummy_controller = MagicMock()
  304. cfg = AmbariConfig().getConfig()
  305. cfg.set('agent', 'tolerate_download_failures', 'true')
  306. cfg.set('agent', 'prefix', '.')
  307. cfg.set('agent', 'cache_dir', 'background_tasks')
  308. actionQueue = ActionQueue(cfg, dummy_controller)
  309. dummy_controller.actionQueue = actionQueue
  310. orchestrator = CustomServiceOrchestrator(cfg, dummy_controller)
  311. orchestrator.file_cache = MagicMock()
  312. def f (a, b):
  313. return ""
  314. orchestrator.file_cache.get_service_base_dir = f
  315. actionQueue.customServiceOrchestrator = orchestrator
  316. import TestActionQueue
  317. import copy
  318. TestActionQueue.patch_output_file(orchestrator.python_executor)
  319. orchestrator.python_executor.prepare_process_result = MagicMock()
  320. orchestrator.dump_command_to_json = MagicMock()
  321. lock = threading.RLock()
  322. complete_done = threading.Condition(lock)
  323. complete_was_called = {}
  324. def command_complete_w(process_condenced_result, handle):
  325. with lock:
  326. complete_was_called['visited']= ''
  327. complete_done.wait(3)
  328. actionQueue.on_background_command_complete_callback = TestActionQueue.wraped(actionQueue.on_background_command_complete_callback, command_complete_w, None)
  329. execute_command = copy.deepcopy(TestActionQueue.TestActionQueue.background_command)
  330. actionQueue.put([execute_command])
  331. actionQueue.processBackgroundQueueSafeEmpty()
  332. time.sleep(.1)
  333. orchestrator.cancel_command(19,'')
  334. self.assertTrue(kill_process_with_children_mock.called)
  335. kill_process_with_children_mock.assert_called_with(33)
  336. with lock:
  337. complete_done.notifyAll()
  338. with lock:
  339. self.assertTrue(complete_was_called.has_key('visited'))
  340. time.sleep(.1)
  341. runningCommand = actionQueue.commandStatuses.get_command_status(19)
  342. self.assertTrue(runningCommand is not None)
  343. self.assertEqual(runningCommand['status'], ActionQueue.FAILED_STATUS)
  344. @patch.object(CustomServiceOrchestrator, "dump_command_to_json")
  345. @patch.object(PythonExecutor, "run_file")
  346. @patch.object(FileCache, "__init__")
  347. @patch.object(FileCache, "get_custom_actions_base_dir")
  348. def test_runCommand_custom_action(self, get_custom_actions_base_dir_mock,
  349. FileCache_mock,
  350. run_file_mock, dump_command_to_json_mock):
  351. FileCache_mock.return_value = None
  352. get_custom_actions_base_dir_mock.return_value = "some path"
  353. _, script = tempfile.mkstemp()
  354. command = {
  355. 'role' : 'any',
  356. 'commandParams': {
  357. 'script_type': 'PYTHON',
  358. 'script': 'some_custom_action.py',
  359. 'command_timeout': '600',
  360. 'jdk_location' : 'some_location'
  361. },
  362. 'taskId' : '3',
  363. 'roleCommand': 'ACTIONEXECUTE'
  364. }
  365. dummy_controller = MagicMock()
  366. orchestrator = CustomServiceOrchestrator(self.config, dummy_controller)
  367. unix_process_id = 111
  368. orchestrator.commands_in_progress = {command['taskId']: unix_process_id}
  369. # normal run case
  370. run_file_mock.return_value = {
  371. 'stdout' : 'sss',
  372. 'stderr' : 'eee',
  373. 'exitcode': 0,
  374. }
  375. ret = orchestrator.runCommand(command, "out.txt", "err.txt")
  376. self.assertEqual(ret['exitcode'], 0)
  377. self.assertTrue(run_file_mock.called)
  378. # Hoooks are not supported for custom actions,
  379. # that's why run_file() should be called only once
  380. self.assertEqual(run_file_mock.call_count, 1)
  381. @patch("os.path.isfile")
  382. @patch.object(FileCache, "__init__")
  383. def test_resolve_hook_script_path(self, FileCache_mock, isfile_mock):
  384. FileCache_mock.return_value = None
  385. dummy_controller = MagicMock()
  386. orchestrator = CustomServiceOrchestrator(self.config, dummy_controller)
  387. # Testing None param
  388. res1 = orchestrator.resolve_hook_script_path(None, "prefix", "command",
  389. "script_type")
  390. self.assertEqual(res1, None)
  391. # Testing existing hook script
  392. isfile_mock.return_value = True
  393. res2 = orchestrator.resolve_hook_script_path("hooks_dir", "prefix", "command",
  394. "script_type")
  395. self.assertEqual(res2, (os.path.join('hooks_dir', 'prefix-command', 'scripts', 'hook.py'),
  396. os.path.join('hooks_dir', 'prefix-command')))
  397. # Testing not existing hook script
  398. isfile_mock.return_value = False
  399. res3 = orchestrator.resolve_hook_script_path("hooks_dir", "prefix", "command",
  400. "script_type")
  401. self.assertEqual(res3, None)
  402. @patch.object(CustomServiceOrchestrator, "runCommand")
  403. @patch.object(FileCache, "__init__")
  404. def test_requestComponentStatus(self, FileCache_mock, runCommand_mock):
  405. FileCache_mock.return_value = None
  406. status_command = {
  407. "serviceName" : 'HDFS',
  408. "commandType" : "STATUS_COMMAND",
  409. "clusterName" : "",
  410. "componentName" : "DATANODE",
  411. 'configurations':{}
  412. }
  413. dummy_controller = MagicMock()
  414. orchestrator = CustomServiceOrchestrator(self.config, dummy_controller)
  415. # Test alive case
  416. runCommand_mock.return_value = {
  417. "exitcode" : 0
  418. }
  419. status = orchestrator.requestComponentStatus(status_command)
  420. self.assertEqual(runCommand_mock.return_value, status)
  421. # Test dead case
  422. runCommand_mock.return_value = {
  423. "exitcode" : 1
  424. }
  425. status = orchestrator.requestComponentStatus(status_command)
  426. self.assertEqual(runCommand_mock.return_value, status)
  427. @patch.object(CustomServiceOrchestrator, "runCommand")
  428. @patch.object(FileCache, "__init__")
  429. def test_requestComponentSecurityState(self, FileCache_mock, runCommand_mock):
  430. FileCache_mock.return_value = None
  431. status_command = {
  432. "serviceName" : 'HDFS',
  433. "commandType" : "STATUS_COMMAND",
  434. "clusterName" : "",
  435. "componentName" : "DATANODE",
  436. 'configurations':{}
  437. }
  438. dummy_controller = MagicMock()
  439. orchestrator = CustomServiceOrchestrator(self.config, dummy_controller)
  440. # Test securityState
  441. runCommand_mock.return_value = {
  442. 'exitcode' : 0,
  443. 'structuredOut' : {'securityState': 'UNSECURED'}
  444. }
  445. status = orchestrator.requestComponentSecurityState(status_command)
  446. self.assertEqual('UNSECURED', status)
  447. # Test case where exit code indicates failure
  448. runCommand_mock.return_value = {
  449. "exitcode" : 1
  450. }
  451. status = orchestrator.requestComponentSecurityState(status_command)
  452. self.assertEqual('UNKNOWN', status)
  453. @patch.object(FileCache, "__init__")
  454. def test_requestComponentSecurityState_realFailure(self, FileCache_mock):
  455. '''
  456. Tests the case where the CustomServiceOrchestrator attempts to call a service's security_status
  457. method, but fails to do so because the script or method was not found.
  458. :param FileCache_mock:
  459. :return:
  460. '''
  461. FileCache_mock.return_value = None
  462. status_command = {
  463. "serviceName" : 'BOGUS_SERVICE',
  464. "commandType" : "STATUS_COMMAND",
  465. "clusterName" : "",
  466. "componentName" : "DATANODE",
  467. 'configurations':{}
  468. }
  469. dummy_controller = MagicMock()
  470. orchestrator = CustomServiceOrchestrator(self.config, dummy_controller)
  471. status = orchestrator.requestComponentSecurityState(status_command)
  472. self.assertEqual('UNKNOWN', status)
  473. @patch.object(CustomServiceOrchestrator, "dump_command_to_json")
  474. @patch.object(FileCache, "__init__")
  475. @patch.object(FileCache, "get_custom_actions_base_dir")
  476. def test_runCommand_background_action(self, get_custom_actions_base_dir_mock,
  477. FileCache_mock,
  478. dump_command_to_json_mock):
  479. FileCache_mock.return_value = None
  480. get_custom_actions_base_dir_mock.return_value = "some path"
  481. _, script = tempfile.mkstemp()
  482. command = {
  483. 'role' : 'any',
  484. 'commandParams': {
  485. 'script_type': 'PYTHON',
  486. 'script': 'some_custom_action.py',
  487. 'command_timeout': '600',
  488. 'jdk_location' : 'some_location'
  489. },
  490. 'taskId' : '13',
  491. 'roleCommand': 'ACTIONEXECUTE',
  492. 'commandType': 'BACKGROUND_EXECUTION_COMMAND',
  493. '__handle': BackgroundCommandExecutionHandle({'taskId': '13'}, 13,
  494. MagicMock(), MagicMock())
  495. }
  496. dummy_controller = MagicMock()
  497. orchestrator = CustomServiceOrchestrator(self.config, dummy_controller)
  498. import TestActionQueue
  499. TestActionQueue.patch_output_file(orchestrator.python_executor)
  500. orchestrator.python_executor.condenseOutput = MagicMock()
  501. orchestrator.dump_command_to_json = MagicMock()
  502. ret = orchestrator.runCommand(command, "out.txt", "err.txt")
  503. self.assertEqual(ret['exitcode'], 777)
  504. def tearDown(self):
  505. # enable stdout
  506. sys.stdout = sys.__stdout__