test_drones.py 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. # -*- coding: utf-8 -*-
  2. # vim: tabstop=4 shiftwidth=4 softtabstop=4
  3. # Copyright 2013, Red Hat, Inc.
  4. #
  5. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  6. # not use this file except in compliance with the License. You may obtain
  7. # a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing, software
  12. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  13. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  14. # License for the specific language governing permissions and limitations
  15. # under the License.
  16. import os
  17. import shutil
  18. import tempfile
  19. from unittest import TestCase
  20. from ..test_base import PackstackTestCaseMixin
  21. from packstack.installer.core.drones import *
  22. class SshTarballTransferMixinTestCase(PackstackTestCaseMixin, TestCase):
  23. def setUp(self):
  24. # Creating a temp directory that can be used by tests
  25. self.tempdir = tempfile.mkdtemp()
  26. def tearDown(self):
  27. # remove the temp directory
  28. # shutil.rmtree(self.tempdir)
  29. pass
  30. def setUp(self):
  31. self.tempdir = tempfile.mkdtemp()
  32. # prepare resource files
  33. res1path = os.path.join(self.tempdir, 'res1.txt')
  34. with open(res1path, 'w') as f:
  35. f.write('resource one')
  36. resdir = os.path.join(self.tempdir, 'resdir')
  37. os.mkdir(resdir)
  38. res2path = os.path.join(resdir, 'res2.txt')
  39. with open(res2path, 'w') as f:
  40. f.write('resource two')
  41. # prepare recipe files
  42. rec1path = os.path.join(self.tempdir, 'rec1.pp')
  43. with open(rec1path, 'w') as f:
  44. f.write('recipe one')
  45. recdir = os.path.join(self.tempdir, 'recdir')
  46. os.mkdir(recdir)
  47. rec2path = os.path.join(recdir, 'rec2.pp')
  48. with open(rec2path, 'w') as f:
  49. f.write('recipe two')
  50. # prepare class
  51. self.mixin = SshTarballTransferMixin()
  52. self.mixin.node = '127.0.0.1'
  53. self.mixin.resource_dir = os.path.join(self.tempdir, 'remote')
  54. self.mixin.recipe_dir = os.path.join(self.tempdir, 'remote',
  55. 'recipes')
  56. self.mixin.local_tmpdir = os.path.join(self.tempdir, 'loctmp')
  57. self.mixin.remote_tmpdir = os.path.join(self.tempdir, 'remtmp')
  58. self.mixin._resources = [(res1path, 'resources'),
  59. (resdir, 'resources')]
  60. self.mixin._recipes = {'one': [rec1path], 'two': [rec2path]}
  61. for i in (self.mixin.resource_dir, self.mixin.recipe_dir,
  62. self.mixin.local_tmpdir, self.mixin.remote_tmpdir):
  63. os.mkdir(i)
  64. def test_tarball_packing(self):
  65. """
  66. Tests packing of resources and recipes
  67. """
  68. # pack
  69. res_path = self.mixin._pack_resources()
  70. rec_path = self.mixin._pack_recipes()
  71. # unpack
  72. for pack_path in (res_path, rec_path):
  73. tarball = tarfile.open(pack_path)
  74. tarball.extractall(path=self.tempdir)
  75. # check content of files
  76. for path, content in [('resources/res1.txt', 'resource one'),
  77. ('resources/resdir/res2.txt', 'resource two'),
  78. ('recipes/rec1.pp', 'recipe one'),
  79. ('recipes/rec2.pp', 'recipe two')]:
  80. with open(os.path.join(self.tempdir, path)) as f:
  81. fcont = f.read()
  82. self.assertEqual(fcont, content)
  83. # clean for next test
  84. shutil.rmtree(os.path.join(self.tempdir, 'resources'))
  85. shutil.rmtree(os.path.join(self.tempdir, 'recipes'))
  86. '''
  87. # uncomment this test only on local machines
  88. def test_transfer(self):
  89. """
  90. Tests resources transfer if sshd to 127.0.0.1 is enabled.
  91. """
  92. remtmp = self.mixin.resource_dir
  93. server = utils.ScriptRunner('127.0.0.1')
  94. try:
  95. server.append('echo "test"')
  96. server.execute()
  97. except ScripRuntimeError:
  98. return
  99. # transfer
  100. self.mixin._copy_resources()
  101. self.mixin._copy_recipes()
  102. # check content of files
  103. for path, content in \
  104. [('resources/res1.txt', 'resource one'),
  105. ('resources/resdir/res2.txt', 'resource two'),
  106. ('recipes/rec1.pp', 'recipe one'),
  107. ('recipes/rec2.pp', 'recipe two')]:
  108. with open(os.path.join(remtmp, path)) as f:
  109. fcont = f.read()
  110. self.assertEqual(fcont, content)
  111. # clean for next test
  112. server = utils.ScriptRunner('127.0.0.1')
  113. server.append('rm -fr %s' % remtmp)
  114. server.execute()
  115. '''
  116. class FakeDroneObserver(DroneObserver):
  117. def __init__(self, *args, **kwargs):
  118. super(FakeDroneObserver, self).__init__(*args, **kwargs)
  119. self.log = []
  120. def applying(self, drone, recipe):
  121. """
  122. Drone is calling this method when it starts applying recipe.
  123. """
  124. self.log.append('applying:%s' % recipe)
  125. def checking(self, drone, recipe):
  126. """
  127. Drone is calling this method when it starts checking if recipe
  128. has been applied.
  129. """
  130. self.log.append('checking:%s' % recipe)
  131. def finished(self, drone, recipe):
  132. """
  133. Drone is calling this method when it's finished with recipe
  134. application.
  135. """
  136. # subclass must implement this method
  137. self.log.append('finished:%s' % recipe)
  138. class FakeDrone(Drone):
  139. def __init__(self, *args, **kwargs):
  140. super(FakeDrone, self).__init__(*args, **kwargs)
  141. self.log = []
  142. def _apply(self, recipe):
  143. self.log.append(recipe)
  144. def _finished(self, recipe):
  145. return True
  146. class DroneTestCase(PackstackTestCaseMixin, TestCase):
  147. def setUp(self):
  148. super(DroneTestCase, self).setUp()
  149. self.observer = FakeDroneObserver()
  150. self.drone = FakeDrone('127.0.0.1')
  151. self.drone.add_recipe('/some/recipe/path1.rec')
  152. self.drone.add_recipe('/some/recipe/path2.rec')
  153. self.drone.add_recipe('/some/recipe/path3a.rec', marker='test')
  154. self.drone.add_recipe('/some/recipe/path3b.rec', marker='test')
  155. self.drone.add_recipe('/some/recipe/path4a.rec', marker='next')
  156. self.drone.add_recipe('/some/recipe/path4b.rec', marker='next')
  157. self.drone.add_recipe('/some/recipe/path5.rec')
  158. def test_drone_behavior(self):
  159. """
  160. Tests Drone's recipe application order.
  161. """
  162. self.drone.log = []
  163. self.drone.apply()
  164. rdir = self.drone.recipe_dir
  165. recpaths = [os.path.join(rdir, os.path.basename(i))
  166. for i in self.drone.recipes]
  167. self.assertListEqual(self.drone.log, recpaths)
  168. def test_observer_behavior(self):
  169. """
  170. Tests DroneObserver calling.
  171. """
  172. self.drone.set_observer(self.observer)
  173. self.drone.apply()
  174. rdir = self.drone.recipe_dir.rstrip('/')
  175. first = ['applying:/some/recipe/path1.rec',
  176. 'checking:%s/path1.rec' % rdir,
  177. 'finished:%s/path1.rec' % rdir,
  178. 'applying:/some/recipe/path2.rec',
  179. 'checking:%s/path2.rec' % rdir,
  180. 'finished:%s/path2.rec' % rdir]
  181. last = ['applying:/some/recipe/path5.rec',
  182. 'checking:%s/path5.rec' % rdir,
  183. 'finished:%s/path5.rec' % rdir]
  184. self.assertListEqual(self.observer.log[:6], first)
  185. self.assertListEqual(self.observer.log[-3:], last)
  186. self.assertEqual(len(self.observer.log), 21)