test_blackout.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. # -*- coding: utf-8 -*-
  2. """
  3. Tests for minion blackout
  4. """
  5. from __future__ import absolute_import
  6. import logging
  7. import os
  8. import textwrap
  9. import time
  10. import pytest
  11. import salt.utils.files
  12. from tests.support.case import ModuleCase
  13. from tests.support.runtests import RUNTIME_VARS
  14. log = logging.getLogger(__name__)
  15. @pytest.mark.windows_whitelisted
  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. @pytest.mark.slow_test(seconds=240) # Test takes >120 and <=240 seconds
  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. @pytest.mark.slow_test(seconds=240) # Test takes >120 and <=240 seconds
  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. @pytest.mark.slow_test(seconds=240) # Test takes >120 and <=240 seconds
  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)