1
0

__init__.py 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. # -*- coding: utf-8 -*-
  2. '''
  3. Set up the Salt multimaster test suite
  4. '''
  5. # Import Python libs
  6. from __future__ import absolute_import, print_function
  7. import copy
  8. import logging
  9. import os
  10. import shutil
  11. import stat
  12. import sys
  13. import threading
  14. import time
  15. # Import salt tests support dirs
  16. from tests.support.paths import (
  17. ENGINES_DIR,
  18. FILES,
  19. INTEGRATION_TEST_DIR,
  20. LOG_HANDLERS_DIR,
  21. SCRIPT_DIR,
  22. TMP,
  23. )
  24. from tests.support.runtests import RUNTIME_VARS
  25. from tests.support.parser import PNUM, print_header
  26. from tests.support.processes import start_daemon
  27. # Import Salt libs
  28. from tests.integration import (
  29. SocketServerRequestHandler,
  30. TestDaemon,
  31. TestDaemonStartFailed,
  32. ThreadedSocketServer,
  33. get_unused_localhost_port,
  34. )
  35. import salt.config
  36. import salt.log.setup as salt_log_setup
  37. from salt.utils.immutabletypes import freeze
  38. from salt.utils.verify import verify_env
  39. # Import salt tests support libs
  40. from tests.support.processes import SaltMaster, SaltMinion
  41. log = logging.getLogger(__name__)
  42. SALT_LOG_PORT = get_unused_localhost_port()
  43. class MultimasterTestDaemon(TestDaemon):
  44. '''
  45. Set up the master and minion daemons, and run related cases
  46. '''
  47. def __enter__(self):
  48. '''
  49. Start a master and minion
  50. '''
  51. # Setup the multiprocessing logging queue listener
  52. salt_log_setup.setup_multiprocessing_logging_listener(
  53. self.mm_master_opts
  54. )
  55. # Set up PATH to mockbin
  56. self._enter_mockbin()
  57. self.master_targets = [self.mm_master_opts, self.mm_sub_master_opts]
  58. self.minion_targets = set(['minion', 'sub_minion'])
  59. if self.parser.options.transport == 'zeromq':
  60. self.start_zeromq_daemons()
  61. elif self.parser.options.transport == 'raet':
  62. self.start_raet_daemons()
  63. elif self.parser.options.transport == 'tcp':
  64. self.start_tcp_daemons()
  65. self.pre_setup_minions()
  66. self.setup_minions()
  67. #if getattr(self.parser.options, 'ssh', False):
  68. #self.prep_ssh()
  69. self.wait_for_minions(time.time(), self.MINIONS_CONNECT_TIMEOUT)
  70. if self.parser.options.sysinfo:
  71. try:
  72. print_header(
  73. '~~~~~~~ Versions Report ', inline=True,
  74. width=getattr(self.parser.options, 'output_columns', PNUM)
  75. )
  76. except TypeError:
  77. print_header('~~~~~~~ Versions Report ', inline=True)
  78. print('\n'.join(salt.version.versions_report()))
  79. try:
  80. print_header(
  81. '~~~~~~~ Minion Grains Information ', inline=True,
  82. width=getattr(self.parser.options, 'output_columns', PNUM)
  83. )
  84. except TypeError:
  85. print_header('~~~~~~~ Minion Grains Information ', inline=True)
  86. grains = self.client.cmd('minion', 'grains.items')
  87. minion_opts = self.mm_minion_opts.copy()
  88. minion_opts['color'] = self.parser.options.no_colors is False
  89. salt.output.display_output(grains, 'grains', minion_opts)
  90. try:
  91. print_header(
  92. '=', sep='=', inline=True,
  93. width=getattr(self.parser.options, 'output_columns', PNUM)
  94. )
  95. except TypeError:
  96. print_header('', sep='=', inline=True)
  97. try:
  98. return self
  99. finally:
  100. self.post_setup_minions()
  101. def __exit__(self, type, value, traceback):
  102. '''
  103. Kill the minion and master processes
  104. '''
  105. try:
  106. if hasattr(self.sub_minion_process, 'terminate'):
  107. self.sub_minion_process.terminate()
  108. else:
  109. log.error('self.sub_minion_process can\'t be terminate.')
  110. except AttributeError:
  111. pass
  112. try:
  113. if hasattr(self.minion_process, 'terminate'):
  114. self.minion_process.terminate()
  115. else:
  116. log.error('self.minion_process can\'t be terminate.')
  117. except AttributeError:
  118. pass
  119. try:
  120. if hasattr(self.sub_master_process, 'terminate'):
  121. self.sub_master_process.terminate()
  122. else:
  123. log.error('self.sub_master_process can\'t be terminate.')
  124. except AttributeError:
  125. pass
  126. try:
  127. if hasattr(self.master_process, 'terminate'):
  128. self.master_process.terminate()
  129. else:
  130. log.error('self.master_process can\'t be terminate.')
  131. except AttributeError:
  132. pass
  133. self._exit_mockbin()
  134. self._exit_ssh()
  135. # Shutdown the multiprocessing logging queue listener
  136. salt_log_setup.shutdown_multiprocessing_logging()
  137. salt_log_setup.shutdown_multiprocessing_logging_listener(daemonizing=True)
  138. # Shutdown the log server
  139. self.log_server.shutdown()
  140. self.log_server.server_close()
  141. self.log_server_process.join()
  142. def start_zeromq_daemons(self):
  143. '''
  144. Fire up the daemons used for zeromq tests
  145. '''
  146. self.log_server = ThreadedSocketServer(('localhost', SALT_LOG_PORT), SocketServerRequestHandler)
  147. self.log_server_process = threading.Thread(target=self.log_server.serve_forever)
  148. self.log_server_process.start()
  149. try:
  150. sys.stdout.write(
  151. ' * {LIGHT_YELLOW}Starting salt-master ... {ENDC}'.format(**self.colors)
  152. )
  153. sys.stdout.flush()
  154. self.master_process = start_daemon(
  155. daemon_name='salt-master',
  156. daemon_id=self.mm_master_opts['id'],
  157. daemon_log_prefix='salt-master/{}'.format(self.mm_master_opts['id']),
  158. daemon_cli_script_name='master',
  159. daemon_config=self.mm_master_opts,
  160. daemon_config_dir=RUNTIME_VARS.TMP_MM_CONF_DIR,
  161. daemon_class=SaltMaster,
  162. bin_dir_path=SCRIPT_DIR,
  163. fail_hard=True,
  164. start_timeout=120)
  165. sys.stdout.write(
  166. '\r{0}\r'.format(
  167. ' ' * getattr(self.parser.options, 'output_columns', PNUM)
  168. )
  169. )
  170. sys.stdout.write(
  171. ' * {LIGHT_GREEN}Starting salt-master ... STARTED!\n{ENDC}'.format(**self.colors)
  172. )
  173. sys.stdout.flush()
  174. except (RuntimeWarning, RuntimeError):
  175. sys.stdout.write(
  176. '\r{0}\r'.format(
  177. ' ' * getattr(self.parser.options, 'output_columns', PNUM)
  178. )
  179. )
  180. sys.stdout.write(
  181. ' * {LIGHT_RED}Starting salt-master ... FAILED!\n{ENDC}'.format(**self.colors)
  182. )
  183. sys.stdout.flush()
  184. raise TestDaemonStartFailed()
  185. # Clone the master key to sub-master's pki dir
  186. for keyfile in ('master.pem', 'master.pub'):
  187. shutil.copyfile(
  188. os.path.join(self.mm_master_opts['pki_dir'], keyfile),
  189. os.path.join(self.mm_sub_master_opts['pki_dir'], keyfile)
  190. )
  191. try:
  192. sys.stdout.write(
  193. ' * {LIGHT_YELLOW}Starting second salt-master ... {ENDC}'.format(**self.colors)
  194. )
  195. sys.stdout.flush()
  196. self.sub_master_process = start_daemon(
  197. daemon_name='sub salt-master',
  198. daemon_id=self.mm_master_opts['id'],
  199. daemon_log_prefix='sub-salt-master/{}'.format(self.mm_sub_master_opts['id']),
  200. daemon_cli_script_name='master',
  201. daemon_config=self.mm_sub_master_opts,
  202. daemon_config_dir=RUNTIME_VARS.TMP_MM_SUB_CONF_DIR,
  203. daemon_class=SaltMaster,
  204. bin_dir_path=SCRIPT_DIR,
  205. fail_hard=True,
  206. start_timeout=120)
  207. sys.stdout.write(
  208. '\r{0}\r'.format(
  209. ' ' * getattr(self.parser.options, 'output_columns', PNUM)
  210. )
  211. )
  212. sys.stdout.write(
  213. ' * {LIGHT_GREEN}Starting second salt-master ... STARTED!\n{ENDC}'.format(**self.colors)
  214. )
  215. sys.stdout.flush()
  216. except (RuntimeWarning, RuntimeError):
  217. sys.stdout.write(
  218. '\r{0}\r'.format(
  219. ' ' * getattr(self.parser.options, 'output_columns', PNUM)
  220. )
  221. )
  222. sys.stdout.write(
  223. ' * {LIGHT_RED}Starting second salt-master ... FAILED!\n{ENDC}'.format(**self.colors)
  224. )
  225. sys.stdout.flush()
  226. raise TestDaemonStartFailed()
  227. try:
  228. sys.stdout.write(
  229. ' * {LIGHT_YELLOW}Starting salt-minion ... {ENDC}'.format(**self.colors)
  230. )
  231. sys.stdout.flush()
  232. self.minion_process = start_daemon(
  233. daemon_name='salt-minion',
  234. daemon_id=self.mm_master_opts['id'],
  235. daemon_log_prefix='salt-minion/{}'.format(self.mm_minion_opts['id']),
  236. daemon_cli_script_name='minion',
  237. daemon_config=self.mm_minion_opts,
  238. daemon_config_dir=RUNTIME_VARS.TMP_MM_CONF_DIR,
  239. daemon_class=SaltMinion,
  240. bin_dir_path=SCRIPT_DIR,
  241. fail_hard=True,
  242. start_timeout=120)
  243. sys.stdout.write(
  244. '\r{0}\r'.format(
  245. ' ' * getattr(self.parser.options, 'output_columns', PNUM)
  246. )
  247. )
  248. sys.stdout.write(
  249. ' * {LIGHT_GREEN}Starting salt-minion ... STARTED!\n{ENDC}'.format(**self.colors)
  250. )
  251. sys.stdout.flush()
  252. except (RuntimeWarning, RuntimeError):
  253. sys.stdout.write(
  254. '\r{0}\r'.format(
  255. ' ' * getattr(self.parser.options, 'output_columns', PNUM)
  256. )
  257. )
  258. sys.stdout.write(
  259. ' * {LIGHT_RED}Starting salt-minion ... FAILED!\n{ENDC}'.format(**self.colors)
  260. )
  261. sys.stdout.flush()
  262. raise TestDaemonStartFailed()
  263. try:
  264. sys.stdout.write(
  265. ' * {LIGHT_YELLOW}Starting sub salt-minion ... {ENDC}'.format(**self.colors)
  266. )
  267. sys.stdout.flush()
  268. self.sub_minion_process = start_daemon(
  269. daemon_name='sub salt-minion',
  270. daemon_id=self.mm_master_opts['id'],
  271. daemon_log_prefix='sub-salt-minion/{}'.format(self.mm_sub_minion_opts['id']),
  272. daemon_cli_script_name='minion',
  273. daemon_config=self.mm_sub_minion_opts,
  274. daemon_config_dir=RUNTIME_VARS.TMP_MM_SUB_CONF_DIR,
  275. daemon_class=SaltMinion,
  276. bin_dir_path=SCRIPT_DIR,
  277. fail_hard=True,
  278. start_timeout=120)
  279. sys.stdout.write(
  280. '\r{0}\r'.format(
  281. ' ' * getattr(self.parser.options, 'output_columns', PNUM)
  282. )
  283. )
  284. sys.stdout.write(
  285. ' * {LIGHT_GREEN}Starting sub salt-minion ... STARTED!\n{ENDC}'.format(**self.colors)
  286. )
  287. sys.stdout.flush()
  288. except (RuntimeWarning, RuntimeError):
  289. sys.stdout.write(
  290. '\r{0}\r'.format(
  291. ' ' * getattr(self.parser.options, 'output_columns', PNUM)
  292. )
  293. )
  294. sys.stdout.write(
  295. ' * {LIGHT_RED}Starting sub salt-minion ... FAILED!\n{ENDC}'.format(**self.colors)
  296. )
  297. sys.stdout.flush()
  298. raise TestDaemonStartFailed()
  299. start_tcp_daemons = start_zeromq_daemons
  300. def wait_for_minions(self, start, timeout, sleep=5):
  301. '''
  302. Ensure all minions and masters (including sub-masters) are connected.
  303. '''
  304. success = [False] * len(self.master_targets)
  305. while True:
  306. for num, client in enumerate(self.clients):
  307. if success[num]:
  308. continue
  309. try:
  310. ret = self.client.run_job('*', 'test.ping')
  311. except salt.exceptions.SaltClientError:
  312. ret = None
  313. if ret and 'minions' not in ret:
  314. continue
  315. if ret and sorted(ret['minions']) == sorted(self.minion_targets):
  316. success[num] = True
  317. continue
  318. if all(success):
  319. break
  320. if time.time() - start >= timeout:
  321. raise RuntimeError("Ping Minions Failed")
  322. time.sleep(sleep)
  323. @property
  324. def clients(self):
  325. '''
  326. Return a local client which will be used for example to ping and sync
  327. the test minions.
  328. This client is defined as a class attribute because its creation needs
  329. to be deferred to a latter stage. If created it on `__enter__` like it
  330. previously was, it would not receive the master events.
  331. '''
  332. if 'runtime_clients' not in RUNTIME_VARS.RUNTIME_CONFIGS:
  333. clients = []
  334. for master_opts in self.master_targets:
  335. clients.append(salt.client.get_local_client(mopts=master_opts))
  336. RUNTIME_VARS.RUNTIME_CONFIGS['runtime_clients'] = clients
  337. return RUNTIME_VARS.RUNTIME_CONFIGS['runtime_clients']
  338. @property
  339. def client(self):
  340. return self.clients[0]
  341. @classmethod
  342. def transplant_configs(cls, transport='zeromq'):
  343. os.makedirs(RUNTIME_VARS.TMP_MM_CONF_DIR)
  344. os.makedirs(RUNTIME_VARS.TMP_MM_SUB_CONF_DIR)
  345. print(' * Transplanting multimaster configuration files to \'{0}\''.format(
  346. RUNTIME_VARS.TMP_CONF_DIR))
  347. tests_known_hosts_file = os.path.join(RUNTIME_VARS.TMP_CONF_DIR, 'salt_ssh_known_hosts')
  348. # Primary master in multimaster environment
  349. master_opts = salt.config._read_conf_file(os.path.join(RUNTIME_VARS.CONF_DIR, 'master'))
  350. master_opts.update(salt.config._read_conf_file(os.path.join(RUNTIME_VARS.CONF_DIR,
  351. 'mm_master')))
  352. master_opts['known_hosts_file'] = tests_known_hosts_file
  353. master_opts['cachedir'] = os.path.join(TMP, 'rootdir_multimaster', 'cache')
  354. master_opts['user'] = RUNTIME_VARS.RUNNING_TESTS_USER
  355. master_opts['config_dir'] = RUNTIME_VARS.TMP_MM_CONF_DIR
  356. master_opts['root_dir'] = os.path.join(TMP, 'rootdir-multimaster')
  357. master_opts['pki_dir'] = os.path.join(TMP, 'rootdir-multimaster', 'pki', 'master')
  358. file_tree = {
  359. 'root_dir': os.path.join(FILES, 'pillar', 'base', 'file_tree'),
  360. 'follow_dir_links': False,
  361. 'keep_newline': True,
  362. }
  363. master_opts['ext_pillar'].append({'file_tree': file_tree})
  364. # Secondary master in multimaster environment
  365. sub_master_opts = salt.config._read_conf_file(os.path.join(RUNTIME_VARS.CONF_DIR, 'master'))
  366. sub_master_opts.update(salt.config._read_conf_file(os.path.join(RUNTIME_VARS.CONF_DIR,
  367. 'mm_sub_master')))
  368. sub_master_opts['known_hosts_file'] = tests_known_hosts_file
  369. sub_master_opts['cachedir'] = os.path.join(TMP, 'rootdir-sub-multimaster', 'cache')
  370. sub_master_opts['user'] = RUNTIME_VARS.RUNNING_TESTS_USER
  371. sub_master_opts['config_dir'] = RUNTIME_VARS.TMP_MM_SUB_CONF_DIR
  372. sub_master_opts['root_dir'] = os.path.join(TMP, 'rootdir-sub-multimaster')
  373. sub_master_opts['pki_dir'] = os.path.join(TMP, 'rootdir-sub-multimaster', 'pki', 'master')
  374. sub_master_opts['ext_pillar'].append({'file_tree': copy.deepcopy(file_tree)})
  375. # Under windows we can't seem to properly create a virtualenv off of another
  376. # virtualenv, we can on linux but we will still point to the virtualenv binary
  377. # outside the virtualenv running the test suite, if that's the case.
  378. try:
  379. real_prefix = sys.real_prefix
  380. # The above attribute exists, this is a virtualenv
  381. if salt.utils.is_windows():
  382. virtualenv_binary = os.path.join(real_prefix, 'Scripts', 'virtualenv.exe')
  383. else:
  384. # We need to remove the virtualenv from PATH or we'll get the virtualenv binary
  385. # from within the virtualenv, we don't want that
  386. path = os.environ.get('PATH')
  387. if path is not None:
  388. path_items = path.split(os.pathsep)
  389. for item in path_items[:]:
  390. if item.startswith(sys.base_prefix):
  391. path_items.remove(item)
  392. os.environ['PATH'] = os.pathsep.join(path_items)
  393. virtualenv_binary = salt.utils.which('virtualenv')
  394. if path is not None:
  395. # Restore previous environ PATH
  396. os.environ['PATH'] = path
  397. if not virtualenv_binary.startswith(real_prefix):
  398. virtualenv_binary = None
  399. if virtualenv_binary and not os.path.exists(virtualenv_binary):
  400. # It doesn't exist?!
  401. virtualenv_binary = None
  402. except AttributeError:
  403. # We're not running inside a virtualenv
  404. virtualenv_binary = None
  405. # This minion connects to both masters
  406. minion_opts = salt.config._read_conf_file(os.path.join(RUNTIME_VARS.CONF_DIR, 'minion'))
  407. minion_opts.update(salt.config._read_conf_file(os.path.join(RUNTIME_VARS.CONF_DIR,
  408. 'mm_minion')))
  409. minion_opts['cachedir'] = os.path.join(TMP, 'rootdir-multimaster', 'cache')
  410. minion_opts['user'] = RUNTIME_VARS.RUNNING_TESTS_USER
  411. minion_opts['config_dir'] = RUNTIME_VARS.TMP_MM_CONF_DIR
  412. minion_opts['root_dir'] = os.path.join(TMP, 'rootdir-multimaster')
  413. minion_opts['pki_dir'] = os.path.join(TMP, 'rootdir-multimaster', 'pki', 'minion')
  414. minion_opts['hosts.file'] = os.path.join(TMP, 'rootdir', 'hosts')
  415. minion_opts['aliases.file'] = os.path.join(TMP, 'rootdir', 'aliases')
  416. if virtualenv_binary:
  417. minion_opts['venv_bin'] = virtualenv_binary
  418. # This sub_minion also connects to both masters
  419. sub_minion_opts = salt.config._read_conf_file(os.path.join(RUNTIME_VARS.CONF_DIR, 'sub_minion'))
  420. sub_minion_opts.update(salt.config._read_conf_file(os.path.join(RUNTIME_VARS.CONF_DIR,
  421. 'mm_sub_minion')))
  422. sub_minion_opts['cachedir'] = os.path.join(TMP, 'rootdir-sub-multimaster', 'cache')
  423. sub_minion_opts['user'] = RUNTIME_VARS.RUNNING_TESTS_USER
  424. sub_minion_opts['config_dir'] = RUNTIME_VARS.TMP_MM_SUB_CONF_DIR
  425. sub_minion_opts['root_dir'] = os.path.join(TMP, 'rootdir-sub-multimaster')
  426. sub_minion_opts['pki_dir'] = os.path.join(TMP, 'rootdir-sub-multimaster', 'pki', 'minion')
  427. sub_minion_opts['hosts.file'] = os.path.join(TMP, 'rootdir', 'hosts')
  428. sub_minion_opts['aliases.file'] = os.path.join(TMP, 'rootdir', 'aliases')
  429. if virtualenv_binary:
  430. sub_minion_opts['venv_bin'] = virtualenv_binary
  431. if transport == 'raet':
  432. master_opts['transport'] = 'raet'
  433. master_opts['raet_port'] = 64506
  434. sub_master_opts['transport'] = 'raet'
  435. sub_master_opts['raet_port'] = 64556
  436. minion_opts['transport'] = 'raet'
  437. minion_opts['raet_port'] = 64510
  438. sub_minion_opts['transport'] = 'raet'
  439. sub_minion_opts['raet_port'] = 64520
  440. # syndic_master_opts['transport'] = 'raet'
  441. if transport == 'tcp':
  442. master_opts['transport'] = 'tcp'
  443. sub_master_opts['transport'] = 'tcp'
  444. minion_opts['transport'] = 'tcp'
  445. sub_minion_opts['transport'] = 'tcp'
  446. # Set up config options that require internal data
  447. master_opts['pillar_roots'] = sub_master_opts['pillar_roots'] = {
  448. 'base': [
  449. RUNTIME_VARS.TMP_PILLAR_TREE,
  450. os.path.join(FILES, 'pillar', 'base'),
  451. ]
  452. }
  453. minion_opts['pillar_roots'] = {
  454. 'base': [
  455. RUNTIME_VARS.TMP_PILLAR_TREE,
  456. os.path.join(FILES, 'pillar', 'base'),
  457. ]
  458. }
  459. master_opts['file_roots'] = sub_master_opts['file_roots'] = {
  460. 'base': [
  461. os.path.join(FILES, 'file', 'base'),
  462. # Let's support runtime created files that can be used like:
  463. # salt://my-temp-file.txt
  464. RUNTIME_VARS.TMP_STATE_TREE
  465. ],
  466. # Alternate root to test __env__ choices
  467. 'prod': [
  468. os.path.join(FILES, 'file', 'prod'),
  469. RUNTIME_VARS.TMP_PRODENV_STATE_TREE
  470. ]
  471. }
  472. minion_opts['file_roots'] = {
  473. 'base': [
  474. os.path.join(FILES, 'file', 'base'),
  475. # Let's support runtime created files that can be used like:
  476. # salt://my-temp-file.txt
  477. RUNTIME_VARS.TMP_STATE_TREE
  478. ],
  479. # Alternate root to test __env__ choices
  480. 'prod': [
  481. os.path.join(FILES, 'file', 'prod'),
  482. RUNTIME_VARS.TMP_PRODENV_STATE_TREE
  483. ]
  484. }
  485. master_opts.setdefault('reactor', []).append(
  486. {
  487. 'salt/minion/*/start': [
  488. os.path.join(FILES, 'reactor-sync-minion.sls')
  489. ],
  490. }
  491. )
  492. for opts_dict in (master_opts, sub_master_opts):
  493. if 'ext_pillar' not in opts_dict:
  494. opts_dict['ext_pillar'] = []
  495. if salt.utils.platform.is_windows():
  496. opts_dict['ext_pillar'].append(
  497. {'cmd_yaml': 'type {0}'.format(os.path.join(FILES, 'ext.yaml'))})
  498. else:
  499. opts_dict['ext_pillar'].append(
  500. {'cmd_yaml': 'cat {0}'.format(os.path.join(FILES, 'ext.yaml'))})
  501. # all read, only owner write
  502. autosign_file_permissions = stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | stat.S_IWUSR
  503. for opts_dict in (master_opts, sub_master_opts):
  504. # We need to copy the extension modules into the new master root_dir or
  505. # it will be prefixed by it
  506. new_extension_modules_path = os.path.join(opts_dict['root_dir'], 'extension_modules')
  507. if not os.path.exists(new_extension_modules_path):
  508. shutil.copytree(
  509. os.path.join(
  510. INTEGRATION_TEST_DIR, 'files', 'extension_modules'
  511. ),
  512. new_extension_modules_path
  513. )
  514. opts_dict['extension_modules'] = os.path.join(opts_dict['root_dir'], 'extension_modules')
  515. # Copy the autosign_file to the new master root_dir
  516. new_autosign_file_path = os.path.join(opts_dict['root_dir'], 'autosign_file')
  517. shutil.copyfile(
  518. os.path.join(INTEGRATION_TEST_DIR, 'files', 'autosign_file'),
  519. new_autosign_file_path
  520. )
  521. os.chmod(new_autosign_file_path, autosign_file_permissions)
  522. # Point the config values to the correct temporary paths
  523. for name in ('hosts', 'aliases'):
  524. optname = '{0}.file'.format(name)
  525. optname_path = os.path.join(TMP, name)
  526. master_opts[optname] = optname_path
  527. sub_master_opts[optname] = optname_path
  528. minion_opts[optname] = optname_path
  529. sub_minion_opts[optname] = optname_path
  530. master_opts['runtests_conn_check_port'] = get_unused_localhost_port()
  531. sub_master_opts['runtests_conn_check_port'] = get_unused_localhost_port()
  532. minion_opts['runtests_conn_check_port'] = get_unused_localhost_port()
  533. sub_minion_opts['runtests_conn_check_port'] = get_unused_localhost_port()
  534. for conf in (master_opts, sub_master_opts, minion_opts, sub_minion_opts):
  535. if 'engines' not in conf:
  536. conf['engines'] = []
  537. conf['engines'].append({'salt_runtests': {}})
  538. if 'engines_dirs' not in conf:
  539. conf['engines_dirs'] = []
  540. conf['engines_dirs'].insert(0, ENGINES_DIR)
  541. if 'log_handlers_dirs' not in conf:
  542. conf['log_handlers_dirs'] = []
  543. conf['log_handlers_dirs'].insert(0, LOG_HANDLERS_DIR)
  544. conf['runtests_log_port'] = SALT_LOG_PORT
  545. conf['runtests_log_level'] = os.environ.get('TESTS_MIN_LOG_LEVEL_NAME') or 'debug'
  546. # ----- Transcribe Configuration ---------------------------------------------------------------------------->
  547. computed_config = copy.deepcopy(master_opts)
  548. with salt.utils.files.fopen(os.path.join(RUNTIME_VARS.TMP_MM_CONF_DIR, 'master'), 'w') as wfh:
  549. salt.utils.yaml.safe_dump(copy.deepcopy(master_opts), wfh, default_flow_style=False)
  550. with salt.utils.files.fopen(os.path.join(RUNTIME_VARS.TMP_MM_SUB_CONF_DIR, 'master'), 'w') as wfh:
  551. salt.utils.yaml.safe_dump(copy.deepcopy(sub_master_opts), wfh, default_flow_style=False)
  552. with salt.utils.files.fopen(os.path.join(RUNTIME_VARS.TMP_MM_CONF_DIR, 'minion'), 'w') as wfh:
  553. salt.utils.yaml.safe_dump(copy.deepcopy(minion_opts), wfh, default_flow_style=False)
  554. with salt.utils.files.fopen(os.path.join(RUNTIME_VARS.TMP_MM_SUB_CONF_DIR, 'minion'), 'w') as wfh:
  555. salt.utils.yaml.safe_dump(copy.deepcopy(sub_minion_opts), wfh, default_flow_style=False)
  556. # <---- Transcribe Configuration -----------------------------------------------------------------------------
  557. # ----- Verify Environment ---------------------------------------------------------------------------------->
  558. master_opts = salt.config.master_config(os.path.join(RUNTIME_VARS.TMP_MM_CONF_DIR, 'master'))
  559. sub_master_opts = salt.config.master_config(os.path.join(RUNTIME_VARS.TMP_MM_SUB_CONF_DIR, 'master'))
  560. minion_opts = salt.config.minion_config(os.path.join(RUNTIME_VARS.TMP_MM_CONF_DIR, 'minion'))
  561. sub_minion_opts = salt.config.minion_config(os.path.join(RUNTIME_VARS.TMP_MM_SUB_CONF_DIR, 'minion'))
  562. RUNTIME_VARS.RUNTIME_CONFIGS['mm_master'] = freeze(master_opts)
  563. RUNTIME_VARS.RUNTIME_CONFIGS['mm_sub_master'] = freeze(sub_master_opts)
  564. RUNTIME_VARS.RUNTIME_CONFIGS['mm_minion'] = freeze(minion_opts)
  565. RUNTIME_VARS.RUNTIME_CONFIGS['mm_sub_minion'] = freeze(sub_minion_opts)
  566. verify_env([os.path.join(master_opts['pki_dir'], 'minions'),
  567. os.path.join(master_opts['pki_dir'], 'minions_pre'),
  568. os.path.join(master_opts['pki_dir'], 'minions_rejected'),
  569. os.path.join(master_opts['pki_dir'], 'minions_denied'),
  570. os.path.join(master_opts['cachedir'], 'jobs'),
  571. os.path.join(master_opts['cachedir'], 'raet'),
  572. os.path.join(master_opts['root_dir'], 'cache', 'tokens'),
  573. os.path.join(master_opts['pki_dir'], 'accepted'),
  574. os.path.join(master_opts['pki_dir'], 'rejected'),
  575. os.path.join(master_opts['pki_dir'], 'pending'),
  576. os.path.join(master_opts['cachedir'], 'raet'),
  577. os.path.join(sub_master_opts['pki_dir'], 'minions'),
  578. os.path.join(sub_master_opts['pki_dir'], 'minions_pre'),
  579. os.path.join(sub_master_opts['pki_dir'], 'minions_rejected'),
  580. os.path.join(sub_master_opts['pki_dir'], 'minions_denied'),
  581. os.path.join(sub_master_opts['cachedir'], 'jobs'),
  582. os.path.join(sub_master_opts['cachedir'], 'raet'),
  583. os.path.join(sub_master_opts['root_dir'], 'cache', 'tokens'),
  584. os.path.join(sub_master_opts['pki_dir'], 'accepted'),
  585. os.path.join(sub_master_opts['pki_dir'], 'rejected'),
  586. os.path.join(sub_master_opts['pki_dir'], 'pending'),
  587. os.path.join(sub_master_opts['cachedir'], 'raet'),
  588. os.path.join(minion_opts['pki_dir'], 'accepted'),
  589. os.path.join(minion_opts['pki_dir'], 'rejected'),
  590. os.path.join(minion_opts['pki_dir'], 'pending'),
  591. os.path.join(minion_opts['cachedir'], 'raet'),
  592. os.path.join(sub_minion_opts['pki_dir'], 'accepted'),
  593. os.path.join(sub_minion_opts['pki_dir'], 'rejected'),
  594. os.path.join(sub_minion_opts['pki_dir'], 'pending'),
  595. os.path.join(sub_minion_opts['cachedir'], 'raet'),
  596. os.path.dirname(master_opts['log_file']),
  597. minion_opts['extension_modules'],
  598. sub_minion_opts['extension_modules'],
  599. sub_minion_opts['pki_dir'],
  600. master_opts['sock_dir'],
  601. sub_master_opts['sock_dir'],
  602. sub_minion_opts['sock_dir'],
  603. minion_opts['sock_dir'],
  604. ],
  605. RUNTIME_VARS.RUNNING_TESTS_USER,
  606. root_dir=master_opts['root_dir'],
  607. )
  608. cls.mm_master_opts = master_opts
  609. cls.mm_sub_master_opts = sub_master_opts
  610. cls.mm_minion_opts = minion_opts
  611. cls.mm_sub_minion_opts = sub_minion_opts
  612. # <---- Verify Environment -----------------------------------------------------------------------------------
  613. @classmethod
  614. def config_location(cls):
  615. return (RUNTIME_VARS.TMP_MM_CONF_DIR, RUNTIME_VARS.TMP_MM_SUB_CONF_DIR)