test_dynamic_plugins.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. '''
  2. Created on Dec 09, 2014
  3. @author: mreynolds
  4. '''
  5. import os
  6. import sys
  7. import time
  8. import ldap
  9. import ldap.sasl
  10. import logging
  11. import socket
  12. import pytest
  13. import plugin_tests
  14. import stress_tests
  15. from lib389 import DirSrv, Entry, tools, tasks
  16. from lib389.tools import DirSrvTools
  17. from lib389._constants import *
  18. from lib389.properties import *
  19. from lib389.tasks import *
  20. from constants import *
  21. log = logging.getLogger(__name__)
  22. installation_prefix = None
  23. class TopologyStandalone(object):
  24. def __init__(self, standalone):
  25. standalone.open()
  26. self.standalone = standalone
  27. @pytest.fixture(scope="module")
  28. def topology(request):
  29. '''
  30. This fixture is used to standalone topology for the 'module'.
  31. At the beginning, It may exists a standalone instance.
  32. It may also exists a backup for the standalone instance.
  33. Principle:
  34. If standalone instance exists:
  35. restart it
  36. If backup of standalone exists:
  37. create/rebind to standalone
  38. restore standalone instance from backup
  39. else:
  40. Cleanup everything
  41. remove instance
  42. remove backup
  43. Create instance
  44. Create backup
  45. '''
  46. global installation_prefix
  47. if installation_prefix:
  48. args_instance[SER_DEPLOYED_DIR] = installation_prefix
  49. standalone = DirSrv(verbose=False)
  50. # Args for the standalone instance
  51. args_instance[SER_HOST] = HOST_STANDALONE
  52. args_instance[SER_PORT] = PORT_STANDALONE
  53. args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
  54. args_standalone = args_instance.copy()
  55. standalone.allocate(args_standalone)
  56. # Get the status of the backups
  57. backup_standalone = standalone.checkBackupFS()
  58. # Get the status of the instance and restart it if it exists
  59. instance_standalone = standalone.exists()
  60. if instance_standalone:
  61. # assuming the instance is already stopped, just wait 5 sec max
  62. standalone.stop(timeout=5)
  63. standalone.start(timeout=10)
  64. if backup_standalone:
  65. # The backup exist, assuming it is correct
  66. # we just re-init the instance with it
  67. if not instance_standalone:
  68. standalone.create()
  69. # Used to retrieve configuration information (dbdir, confdir...)
  70. standalone.open()
  71. # restore standalone instance from backup
  72. standalone.stop(timeout=10)
  73. standalone.restoreFS(backup_standalone)
  74. standalone.start(timeout=10)
  75. else:
  76. # We should be here only in two conditions
  77. # - This is the first time a test involve standalone instance
  78. # - Something weird happened (instance/backup destroyed)
  79. # so we discard everything and recreate all
  80. # Remove the backup. So even if we have a specific backup file
  81. # (e.g backup_standalone) we clear backup that an instance may have created
  82. if backup_standalone:
  83. standalone.clearBackupFS()
  84. # Remove the instance
  85. if instance_standalone:
  86. standalone.delete()
  87. # Create the instance
  88. standalone.create()
  89. # Used to retrieve configuration information (dbdir, confdir...)
  90. standalone.open()
  91. # Time to create the backups
  92. standalone.stop(timeout=10)
  93. standalone.backupfile = standalone.backupFS()
  94. standalone.start(timeout=10)
  95. #
  96. # Here we have standalone instance up and running
  97. # Either coming from a backup recovery
  98. # or from a fresh (re)init
  99. # Time to return the topology
  100. return TopologyStandalone(standalone)
  101. def test_dynamic_plugins(topology):
  102. """
  103. Test Dynamic Plugins - exercise each plugin and its main features, while
  104. changing the configuration without restarting the server.
  105. Need to test: functionality, stability, and stress.
  106. Functionality - Make sure that as configuration changes are made they take
  107. effect immediately. Cross plugin interaction (e.g. automember/memberOf)
  108. needs to tested, as well as plugin tasks. Need to test plugin
  109. config validation(dependencies, etc).
  110. Memory Corruption - Restart the plugins many times, and in different orders and test
  111. functionality, and stability. This will excerise the internal
  112. plugin linked lists, dse callabcks, and task handlers.
  113. Stress - Put the server under some type of load that is using a particular
  114. plugin for each operation, and then make changes to that plugin.
  115. The new changes should take effect, and the server should not crash.
  116. """
  117. ############################################################################
  118. # Test plugin functionality
  119. ############################################################################
  120. # First enable dynamic plugins
  121. try:
  122. topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-dynamic-plugins', 'on')])
  123. except ldap.LDAPError, e:
  124. ldap.error('Failed to enable dynamic plugin!' + e.message['desc'])
  125. assert False
  126. log.info('#####################################################')
  127. log.info('Testing Dynamic Plugins Functionality...')
  128. log.info('#####################################################\n')
  129. plugin_tests.test_all_plugins(topology.standalone)
  130. log.info('#####################################################')
  131. log.info('Successfully Tested Dynamic Plugins Functionality.')
  132. log.info('#####################################################\n')
  133. ############################################################################
  134. # Test the stability by exercising the internal lists, callabcks, and task handlers
  135. ############################################################################
  136. log.info('#####################################################')
  137. log.info('Testing Dynamic Plugins for Memory Corruption...')
  138. log.info('#####################################################\n')
  139. prev_plugin_test = None
  140. prev_prev_plugin_test = None
  141. for plugin_test in plugin_tests.func_tests:
  142. #
  143. # Restart the plugin several times (and prev plugins) - work that linked list
  144. #
  145. plugin_test(topology.standalone, "restart")
  146. if prev_prev_plugin_test:
  147. prev_prev_plugin_test(topology.standalone, "restart")
  148. plugin_test(topology.standalone, "restart")
  149. if prev_plugin_test:
  150. prev_plugin_test(topology.standalone, "restart")
  151. plugin_test(topology.standalone, "restart")
  152. # Now run the functional test
  153. plugin_test(topology.standalone)
  154. # Set the previous tests
  155. if prev_plugin_test:
  156. prev_prev_plugin_test = prev_plugin_test
  157. prev_plugin_test = plugin_test
  158. log.info('#####################################################')
  159. log.info('Successfully Tested Dynamic Plugins for Memory Corruption.')
  160. log.info('#####################################################\n')
  161. ############################################################################
  162. # Stress two plugins while restarting it, and while restarting other plugins.
  163. # The goal is to not crash, and have the plugins work after stressing it.
  164. ############################################################################
  165. log.info('#####################################################')
  166. log.info('Stressing Dynamic Plugins...')
  167. log.info('#####################################################\n')
  168. # Configure the plugins
  169. stress_tests.configureMO(topology.standalone)
  170. stress_tests.configureRI(topology.standalone)
  171. # Launch three new threads to add a bunch of users
  172. add_users = stress_tests.AddUsers(topology.standalone, 'user', True)
  173. add_users.start()
  174. add_users2 = stress_tests.AddUsers(topology.standalone, 'entry', True)
  175. add_users2.start()
  176. add_users3 = stress_tests.AddUsers(topology.standalone, 'person', True)
  177. add_users3.start()
  178. time.sleep(1)
  179. # While we are adding users restart the MO plugin
  180. topology.standalone.plugins.disable(name=PLUGIN_MEMBER_OF)
  181. topology.standalone.plugins.enable(name=PLUGIN_MEMBER_OF)
  182. time.sleep(3)
  183. topology.standalone.plugins.disable(name=PLUGIN_MEMBER_OF)
  184. time.sleep(1)
  185. topology.standalone.plugins.enable(name=PLUGIN_MEMBER_OF)
  186. # Restart idle plugin
  187. topology.standalone.plugins.disable(name=PLUGIN_LINKED_ATTRS)
  188. topology.standalone.plugins.enable(name=PLUGIN_LINKED_ATTRS)
  189. # Wait for the 'adding' threads to complete
  190. add_users.join()
  191. add_users2.join()
  192. add_users3.join()
  193. # Now launch three threads to delete the users, and restart both the MO and RI plugins
  194. del_users = stress_tests.DelUsers(topology.standalone, 'user')
  195. del_users.start()
  196. del_users2 = stress_tests.DelUsers(topology.standalone, 'entry')
  197. del_users2.start()
  198. del_users3 = stress_tests.DelUsers(topology.standalone, 'person')
  199. del_users3.start()
  200. time.sleep(1)
  201. # Restart the both the MO and RI plugins during these deletes
  202. topology.standalone.plugins.disable(name=PLUGIN_REFER_INTEGRITY)
  203. topology.standalone.plugins.disable(name=PLUGIN_MEMBER_OF)
  204. topology.standalone.plugins.enable(name=PLUGIN_MEMBER_OF)
  205. topology.standalone.plugins.enable(name=PLUGIN_REFER_INTEGRITY)
  206. time.sleep(3)
  207. topology.standalone.plugins.disable(name=PLUGIN_REFER_INTEGRITY)
  208. time.sleep(1)
  209. topology.standalone.plugins.disable(name=PLUGIN_MEMBER_OF)
  210. time.sleep(1)
  211. topology.standalone.plugins.enable(name=PLUGIN_MEMBER_OF)
  212. time.sleep(1)
  213. topology.standalone.plugins.enable(name=PLUGIN_REFER_INTEGRITY)
  214. # Restart idle plugin
  215. topology.standalone.plugins.disable(name=PLUGIN_LINKED_ATTRS)
  216. topology.standalone.plugins.enable(name=PLUGIN_LINKED_ATTRS)
  217. # Wait for the 'deleting' threads to complete
  218. del_users.join()
  219. del_users2.join()
  220. del_users3.join()
  221. # Now make sure both the MO and RI plugins still work
  222. plugin_tests.func_tests[8](topology.standalone) # RI plugin
  223. plugin_tests.func_tests[5](topology.standalone) # MO plugin
  224. log.info('#####################################################')
  225. log.info('Successfully Stressed Dynamic Plugins.')
  226. log.info('#####################################################\n')
  227. ############################################################################
  228. # We made it to the end!
  229. ############################################################################
  230. log.info('#####################################################')
  231. log.info('#####################################################')
  232. log.info("Dynamic Plugins Testsuite: Completed Successfully!")
  233. log.info('#####################################################')
  234. log.info('#####################################################')
  235. def test_dynamic_plugins_final(topology):
  236. topology.standalone.stop(timeout=10)
  237. def run_isolated():
  238. '''
  239. run_isolated is used to run these test cases independently of a test scheduler (xunit, py.test..)
  240. To run isolated without py.test, you need to
  241. - edit this file and comment '@pytest.fixture' line before 'topology' function.
  242. - set the installation prefix
  243. - run this program
  244. '''
  245. global installation_prefix
  246. installation_prefix = None
  247. topo = topology(True)
  248. test_dynamic_plugins(topo)
  249. if __name__ == '__main__':
  250. run_isolated()