ticket47560_test.py 10 KB

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