ticket47931_test.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. import threading
  2. import pytest
  3. from lib389.tasks import *
  4. from lib389.utils import *
  5. from lib389.topologies import topology_st
  6. logging.getLogger(__name__).setLevel(logging.DEBUG)
  7. log = logging.getLogger(__name__)
  8. installation1_prefix = None
  9. SECOND_SUFFIX = "dc=deadlock"
  10. SECOND_BACKEND = "deadlock"
  11. RETROCL_PLUGIN_DN = ('cn=' + PLUGIN_RETRO_CHANGELOG + ',cn=plugins,cn=config')
  12. MEMBEROF_PLUGIN_DN = ('cn=' + PLUGIN_MEMBER_OF + ',cn=plugins,cn=config')
  13. GROUP_DN = ("cn=group," + DEFAULT_SUFFIX)
  14. MEMBER_DN_COMP = "uid=member"
  15. TIME_OUT = 5
  16. class modifySecondBackendThread(threading.Thread):
  17. def __init__(self, inst, timeout):
  18. threading.Thread.__init__(self)
  19. self.daemon = True
  20. self.inst = inst
  21. self.timeout = timeout
  22. def run(self):
  23. conn = self.inst.openConnection()
  24. conn.set_option(ldap.OPT_TIMEOUT, self.timeout)
  25. log.info('Modify second suffix...')
  26. for x in range(0, 5000):
  27. try:
  28. conn.modify_s(SECOND_SUFFIX,
  29. [(ldap.MOD_REPLACE,
  30. 'description',
  31. 'new description')])
  32. except ldap.LDAPError as e:
  33. log.fatal('Failed to modify second suffix - error: %s' %
  34. (e.message['desc']))
  35. assert False
  36. conn.close()
  37. log.info('Finished modifying second suffix')
  38. def test_ticket47931(topology_st):
  39. """Test Retro Changelog and MemberOf deadlock fix.
  40. Verification steps:
  41. - Enable retro cl and memberOf.
  42. - Create two backends: A & B.
  43. - Configure retrocl scoping for backend A.
  44. - Configure memberOf plugin for uniquemember
  45. - Create group in backend A.
  46. - In parallel, add members to the group on A, and make modifications
  47. to entries in backend B.
  48. - Make sure the server does not hang during the updates to both
  49. backends.
  50. """
  51. # Enable dynamic plugins to make plugin configuration easier
  52. try:
  53. topology_st.standalone.modify_s(DN_CONFIG,
  54. [(ldap.MOD_REPLACE,
  55. 'nsslapd-dynamic-plugins',
  56. 'on')])
  57. except ldap.LDAPError as e:
  58. ldap.error('Failed to enable dynamic plugins! ' + e.message['desc'])
  59. assert False
  60. # Enable the plugins
  61. topology_st.standalone.plugins.enable(name=PLUGIN_MEMBER_OF)
  62. topology_st.standalone.plugins.enable(name=PLUGIN_RETRO_CHANGELOG)
  63. # Create second backend
  64. topology_st.standalone.backend.create(SECOND_SUFFIX, {BACKEND_NAME: SECOND_BACKEND})
  65. topology_st.standalone.mappingtree.create(SECOND_SUFFIX, bename=SECOND_BACKEND)
  66. # Create the root node of the second backend
  67. try:
  68. topology_st.standalone.add_s(Entry((SECOND_SUFFIX,
  69. {'objectclass': 'top domain'.split(),
  70. 'dc': 'deadlock'})))
  71. except ldap.LDAPError as e:
  72. log.fatal('Failed to create suffix entry: error ' + e.message['desc'])
  73. assert False
  74. # Configure retrocl scope
  75. try:
  76. topology_st.standalone.modify_s(RETROCL_PLUGIN_DN,
  77. [(ldap.MOD_REPLACE,
  78. 'nsslapd-include-suffix',
  79. DEFAULT_SUFFIX)])
  80. except ldap.LDAPError as e:
  81. ldap.error('Failed to configure retrocl plugin: ' + e.message['desc'])
  82. assert False
  83. # Configure memberOf group attribute
  84. try:
  85. topology_st.standalone.modify_s(MEMBEROF_PLUGIN_DN,
  86. [(ldap.MOD_REPLACE,
  87. 'memberofgroupattr',
  88. 'uniquemember')])
  89. except ldap.LDAPError as e:
  90. log.fatal('Failed to configure memberOf plugin: error ' + e.message['desc'])
  91. assert False
  92. # Create group
  93. try:
  94. topology_st.standalone.add_s(Entry((GROUP_DN,
  95. {'objectclass': 'top extensibleObject'.split(),
  96. 'cn': 'group'})))
  97. except ldap.LDAPError as e:
  98. log.fatal('Failed to add grouo: error ' + e.message['desc'])
  99. assert False
  100. # Create 1500 entries (future members of the group)
  101. for idx in range(1, 1500):
  102. try:
  103. USER_DN = ("uid=member%d,%s" % (idx, DEFAULT_SUFFIX))
  104. topology_st.standalone.add_s(Entry((USER_DN,
  105. {'objectclass': 'top extensibleObject'.split(),
  106. 'uid': 'member%d' % (x)})))
  107. except ldap.LDAPError as e:
  108. log.fatal('Failed to add user (%s): error %s' % (USER_DN, e.message['desc']))
  109. assert False
  110. # Modify second backend (separate thread)
  111. mod_backend_thrd = modifySecondBackendThread(topology_st.standalone, TIME_OUT)
  112. mod_backend_thrd.start()
  113. # Add members to the group - set timeout
  114. log.info('Adding members to the group...')
  115. topology_st.standalone.set_option(ldap.OPT_TIMEOUT, TIME_OUT)
  116. for idx in range(1, 1500):
  117. try:
  118. MEMBER_VAL = ("uid=member%d,%s" % (idx, DEFAULT_SUFFIX))
  119. topology_st.standalone.modify_s(GROUP_DN,
  120. [(ldap.MOD_ADD,
  121. 'uniquemember',
  122. MEMBER_VAL)])
  123. except ldap.TIMEOUT:
  124. log.fatal('Deadlock! Bug verification failed.')
  125. assert False
  126. except ldap.LDAPError as e:
  127. log.fatal('Failed to update group(not a deadlock) member (%s) - error: %s' %
  128. (MEMBER_VAL, e.message['desc']))
  129. assert False
  130. log.info('Finished adding members to the group.')
  131. # Wait for the thread to finish
  132. mod_backend_thrd.join()
  133. # No timeout, test passed!
  134. log.info('Test complete\n')
  135. if __name__ == '__main__':
  136. # Run isolated
  137. # -s for DEBUG mode
  138. CURRENT_FILE = os.path.realpath(__file__)
  139. pytest.main("-s %s" % CURRENT_FILE)