test_blackout.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. """
  2. Tests for minion blackout
  3. """
  4. import logging
  5. import os
  6. import textwrap
  7. import time
  8. import pytest
  9. import salt.utils.files
  10. from tests.support.case import ModuleCase
  11. from tests.support.helpers import slowTest
  12. from tests.support.runtests import RUNTIME_VARS
  13. log = logging.getLogger(__name__)
  14. @pytest.mark.windows_whitelisted
  15. @pytest.mark.usefixtures("salt_sub_minion")
  16. class MinionBlackoutTestCase(ModuleCase):
  17. """
  18. Test minion blackout functionality
  19. """
  20. @classmethod
  21. def setUpClass(cls):
  22. cls.top_pillar = os.path.join(RUNTIME_VARS.TMP_PILLAR_TREE, "top.sls")
  23. cls.blackout_pillar = os.path.join(RUNTIME_VARS.TMP_PILLAR_TREE, "blackout.sls")
  24. @classmethod
  25. def tearDownClass(cls):
  26. if os.path.exists(cls.top_pillar):
  27. os.unlink(cls.top_pillar)
  28. del cls.top_pillar
  29. if os.path.exists(cls.blackout_pillar):
  30. os.unlink(cls.blackout_pillar)
  31. del cls.blackout_pillar
  32. def setUp(self):
  33. with salt.utils.files.fopen(self.top_pillar, "w") as wfh:
  34. wfh.write(
  35. textwrap.dedent(
  36. """\
  37. base:
  38. '*':
  39. - blackout
  40. """
  41. )
  42. )
  43. with salt.utils.files.fopen(self.blackout_pillar, "w") as wfh:
  44. wfh.write("minion_blackout: False")
  45. self.addCleanup(self.cleanup_blackout_pillar)
  46. def tearDown(self):
  47. self.end_blackout()
  48. # Be sure to also refresh the sub_minion pillar
  49. self.run_function("saltutil.refresh_pillar", minion_tgt="sub_minion")
  50. timeout = 120
  51. if not self.wait_for_blackout(end=True, tgt="sub_minion", timeout=timeout):
  52. raise Exception(
  53. "Minion did not exit blackout mode after {} seconds".format(timeout)
  54. )
  55. self.wait_for_all_jobs()
  56. def cleanup_blackout_pillar(self):
  57. if os.path.exists(self.top_pillar):
  58. os.unlink(self.top_pillar)
  59. if os.path.exists(self.blackout_pillar):
  60. os.unlink(self.blackout_pillar)
  61. def begin_blackout(self, blackout_data="minion_blackout: True"):
  62. """
  63. setup minion blackout mode
  64. """
  65. log.info("Entering minion blackout...")
  66. self.wait_for_all_jobs()
  67. with salt.utils.files.fopen(self.blackout_pillar, "w") as wfh:
  68. wfh.write(blackout_data)
  69. ret = self.run_function("saltutil.refresh_pillar", timeout=30)
  70. timeout = 120
  71. if not self.wait_for_blackout(timeout=timeout):
  72. raise Exception(
  73. "Minion did not enter blackout mode after {} seconds".format(timeout)
  74. )
  75. log.info("Entered minion blackout.")
  76. def wait_for_blackout(self, end=False, tgt="minion", timeout=120, sleep=0.3):
  77. """
  78. Wait for blackout mode to start or end.
  79. """
  80. start = time.time()
  81. while time.time() - start <= timeout:
  82. ret = self.run_function(
  83. "pillar.get", minion_tgt=tgt, arg=["minion_blackout"], timeout=30,
  84. )
  85. if end:
  86. if str(ret).find("Minion in blackout mode") == -1:
  87. return True
  88. else:
  89. if str(ret).find("Minion in blackout mode") != -1:
  90. return True
  91. time.sleep(sleep)
  92. return False
  93. def end_blackout(self):
  94. """
  95. takedown minion blackout mode
  96. """
  97. log.info("Exiting minion blackout...")
  98. with salt.utils.files.fopen(self.blackout_pillar, "w") as wfh:
  99. wfh.write("minion_blackout: False\n")
  100. self.run_function("saltutil.refresh_pillar")
  101. timeout = 120
  102. if not self.wait_for_blackout(end=True, timeout=timeout):
  103. raise Exception(
  104. "Minion did not exit blackout mode after {} seconds".format(timeout)
  105. )
  106. self.wait_for_all_jobs()
  107. log.info("Exited minion blackout.")
  108. @slowTest
  109. def test_blackout(self):
  110. """
  111. Test that basic minion blackout functionality works
  112. """
  113. try:
  114. self.begin_blackout()
  115. blackout_ret = self.run_function("test.ping")
  116. self.assertIn("Minion in blackout mode.", blackout_ret)
  117. finally:
  118. self.end_blackout()
  119. ret = self.run_function("test.ping")
  120. self.assertEqual(ret, True)
  121. @slowTest
  122. def test_blackout_whitelist(self):
  123. """
  124. Test that minion blackout whitelist works
  125. """
  126. self.begin_blackout(
  127. textwrap.dedent(
  128. """\
  129. minion_blackout: True
  130. minion_blackout_whitelist:
  131. - test.ping
  132. - test.fib
  133. """
  134. )
  135. )
  136. ping_ret = self.run_function("test.ping")
  137. self.assertEqual(ping_ret, True)
  138. fib_ret = self.run_function("test.fib", [7])
  139. self.assertTrue(isinstance(fib_ret, list))
  140. self.assertEqual(fib_ret[0], 13)
  141. @slowTest
  142. def test_blackout_nonwhitelist(self):
  143. """
  144. Test that minion refuses to run non-whitelisted functions during
  145. blackout whitelist
  146. """
  147. self.begin_blackout(
  148. textwrap.dedent(
  149. """\
  150. minion_blackout: True
  151. minion_blackout_whitelist:
  152. - test.ping
  153. - test.fib
  154. """
  155. )
  156. )
  157. state_ret = self.run_function("state.apply")
  158. self.assertIn("Minion in blackout mode.", state_ret)
  159. cloud_ret = self.run_function("cloud.query", ["list_nodes_full"])
  160. self.assertIn("Minion in blackout mode.", cloud_ret)