ticket47560_test.py 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. import os
  2. import sys
  3. import time
  4. import ldap
  5. import logging
  6. import socket
  7. import time
  8. import logging
  9. import pytest
  10. from lib389 import DirSrv, Entry, tools
  11. from lib389.tools import DirSrvTools
  12. from lib389._constants import *
  13. from lib389.properties import *
  14. from constants import *
  15. log = logging.getLogger(__name__)
  16. installation_prefix = None
  17. class TopologyStandalone(object):
  18. def __init__(self, standalone):
  19. standalone.open()
  20. self.standalone = standalone
  21. @pytest.fixture(scope="module")
  22. def topology(request):
  23. '''
  24. This fixture is used to standalone topology for the 'module'.
  25. At the beginning, It may exists a standalone instance.
  26. It may also exists a backup for the standalone instance.
  27. Principle:
  28. If standalone instance exists:
  29. restart it
  30. If backup of standalone exists:
  31. create/rebind to standalone
  32. restore standalone instance from backup
  33. else:
  34. Cleanup everything
  35. remove instance
  36. remove backup
  37. Create instance
  38. Create backup
  39. '''
  40. global installation_prefix
  41. if installation_prefix:
  42. args_instance[SER_DEPLOYED_DIR] = installation_prefix
  43. standalone = DirSrv(verbose=False)
  44. # Args for the standalone instance
  45. args_instance[SER_HOST] = HOST_STANDALONE
  46. args_instance[SER_PORT] = PORT_STANDALONE
  47. args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
  48. args_standalone = args_instance.copy()
  49. standalone.allocate(args_standalone)
  50. # Get the status of the backups
  51. backup_standalone = standalone.checkBackupFS()
  52. # Get the status of the instance and restart it if it exists
  53. instance_standalone = standalone.exists()
  54. if instance_standalone:
  55. # assuming the instance is already stopped, just wait 5 sec max
  56. standalone.stop(timeout=5)
  57. standalone.start(timeout=10)
  58. if backup_standalone:
  59. # The backup exist, assuming it is correct
  60. # we just re-init the instance with it
  61. if not instance_standalone:
  62. standalone.create()
  63. # Used to retrieve configuration information (dbdir, confdir...)
  64. standalone.open()
  65. # restore standalone instance from backup
  66. standalone.stop(timeout=10)
  67. standalone.restoreFS(backup_standalone)
  68. standalone.start(timeout=10)
  69. else:
  70. # We should be here only in two conditions
  71. # - This is the first time a test involve standalone instance
  72. # - Something weird happened (instance/backup destroyed)
  73. # so we discard everything and recreate all
  74. # Remove the backup. So even if we have a specific backup file
  75. # (e.g backup_standalone) we clear backup that an instance may have created
  76. if backup_standalone:
  77. standalone.clearBackupFS()
  78. # Remove the instance
  79. if instance_standalone:
  80. standalone.delete()
  81. # Create the instance
  82. standalone.create()
  83. # Used to retrieve configuration information (dbdir, confdir...)
  84. standalone.open()
  85. # Time to create the backups
  86. standalone.stop(timeout=10)
  87. standalone.backupfile = standalone.backupFS()
  88. standalone.start(timeout=10)
  89. #
  90. # Here we have standalone instance up and running
  91. # Either coming from a backup recovery
  92. # or from a fresh (re)init
  93. # Time to return the topology
  94. return TopologyStandalone(standalone)
  95. def test_ticket47560(topology):
  96. """
  97. This test case does the following:
  98. SETUP
  99. - Create entry cn=group,SUFFIX
  100. - Create entry cn=member,SUFFIX
  101. - Update 'cn=member,SUFFIX' to add "memberOf: cn=group,SUFFIX"
  102. - Enable Memberof Plugins
  103. # Here the cn=member entry has a 'memberOf' but
  104. # cn=group entry does not contain 'cn=member' in its member
  105. TEST CASE
  106. - start the fixupmemberof task
  107. - read the cn=member entry
  108. - check 'memberOf is now empty
  109. TEARDOWN
  110. - Delete entry cn=group,SUFFIX
  111. - Delete entry cn=member,SUFFIX
  112. - Disable Memberof Plugins
  113. """
  114. def _enable_disable_mbo(value):
  115. """
  116. Enable or disable mbo plugin depending on 'value' ('on'/'off')
  117. """
  118. # enable/disable the mbo plugin
  119. if value != 'on':
  120. value = 'off'
  121. log.debug("-------------> _enable_disable_mbo(%s)" % value)
  122. MEMBEROF_PLUGIN_DN = 'cn=MemberOf Plugin,cn=plugins,cn=config'
  123. replace = [(ldap.MOD_REPLACE, 'nsslapd-pluginEnabled', value)]
  124. topology.standalone.modify_s(MEMBEROF_PLUGIN_DN, replace)
  125. topology.standalone.stop(timeout=120)
  126. time.sleep(1)
  127. topology.standalone.start(timeout=120)
  128. time.sleep(3)
  129. # need to reopen a connection toward the instance
  130. topology.standalone.open()
  131. def _test_ticket47560_setup():
  132. """
  133. - Create entry cn=group,SUFFIX
  134. - Create entry cn=member,SUFFIX
  135. - Update 'cn=member,SUFFIX' to add "memberOf: cn=group,SUFFIX"
  136. - Enable Memberof Plugins
  137. """
  138. log.debug( "-------- > _test_ticket47560_setup\n")
  139. #
  140. # By default the memberof plugin is disabled create
  141. # - create a group entry
  142. # - create a member entry
  143. # - set the member entry as memberof the group entry
  144. #
  145. entry = Entry(group_DN)
  146. entry.setValues('objectclass', 'top', 'groupOfNames', 'inetUser')
  147. entry.setValues('cn', 'group')
  148. try:
  149. topology.standalone.add_s(entry)
  150. except ldap.ALREADY_EXISTS:
  151. log.debug( "Entry %s already exists" % (group_DN))
  152. entry = Entry(member_DN)
  153. entry.setValues('objectclass', 'top', 'person', 'organizationalPerson', 'inetorgperson', 'inetUser')
  154. entry.setValues('uid', 'member')
  155. entry.setValues('cn', 'member')
  156. entry.setValues('sn', 'member')
  157. try:
  158. topology.standalone.add_s(entry)
  159. except ldap.ALREADY_EXISTS:
  160. log.debug( "Entry %s already exists" % (member_DN))
  161. replace = [(ldap.MOD_REPLACE, 'memberof', group_DN)]
  162. topology.standalone.modify_s(member_DN, replace)
  163. #
  164. # enable the memberof plugin and restart the instance
  165. #
  166. _enable_disable_mbo('on')
  167. #
  168. # check memberof attribute is still present
  169. #
  170. filt = 'uid=member'
  171. ents = topology.standalone.search_s(member_DN, ldap.SCOPE_BASE, filt)
  172. assert len(ents) == 1
  173. ent = ents[0]
  174. #print ent
  175. value = ent.getValue('memberof')
  176. #print "memberof: %s" % (value)
  177. assert value == group_DN
  178. def _test_ticket47560_teardown():
  179. """
  180. - Delete entry cn=group,SUFFIX
  181. - Delete entry cn=member,SUFFIX
  182. - Disable Memberof Plugins
  183. """
  184. log.debug( "-------- > _test_ticket47560_teardown\n")
  185. # remove the entries group_DN and member_DN
  186. try:
  187. topology.standalone.delete_s(group_DN)
  188. except:
  189. log.warning("Entry %s fail to delete" % (group_DN))
  190. try:
  191. topology.standalone.delete_s(member_DN)
  192. except:
  193. log.warning("Entry %s fail to delete" % (member_DN))
  194. #
  195. # disable the memberof plugin and restart the instance
  196. #
  197. _enable_disable_mbo('off')
  198. group_DN = "cn=group,%s" % (SUFFIX)
  199. member_DN = "uid=member,%s" % (SUFFIX)
  200. #
  201. # Initialize the test case
  202. #
  203. _test_ticket47560_setup()
  204. #
  205. # start the test
  206. # - start the fixup task
  207. # - check the entry is fixed (no longer memberof the group)
  208. #
  209. log.debug( "-------- > Start ticket tests\n")
  210. filt = 'uid=member'
  211. ents = topology.standalone.search_s(member_DN, ldap.SCOPE_BASE, filt)
  212. assert len(ents) == 1
  213. ent = ents[0]
  214. log.debug( "Unfixed entry %r\n" % ent)
  215. # run the fixup task
  216. topology.standalone.fixupMemberOf(SUFFIX, verbose=False)
  217. ents = topology.standalone.search_s(member_DN, ldap.SCOPE_BASE, filt)
  218. assert len(ents) == 1
  219. ent = ents[0]
  220. log.debug( "Fixed entry %r\n" % ent)
  221. if ent.getValue('memberof') == group_DN:
  222. log.warning("Error the fixupMemberOf did not fix %s" % (member_DN))
  223. result_successful = False
  224. else:
  225. result_successful = True
  226. #
  227. # cleanup up the test case
  228. #
  229. _test_ticket47560_teardown()
  230. assert result_successful == True
  231. def test_ticket47560_final(topology):
  232. topology.standalone.stop(timeout=10)
  233. def run_isolated():
  234. '''
  235. run_isolated is used to run these test cases independently of a test scheduler (xunit, py.test..)
  236. To run isolated without py.test, you need to
  237. - edit this file and comment '@pytest.fixture' line before 'topology' function.
  238. - set the installation prefix
  239. - run this program
  240. '''
  241. global installation_prefix
  242. installation_prefix = None
  243. topo = topology(True)
  244. test_ticket47560(topo)
  245. test_ticket47560_final(topo)
  246. if __name__ == '__main__':
  247. run_isolated()