1
0

test_blackout.py 5.6 KB

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